+ testing. His efforts have contributed as much to TuxOnIce as any of the
+ names above.
diff --git a/MAINTAINERS b/MAINTAINERS
-index 8dca9d8..14c7e10 100644
+index 4f96ac8..21b92f2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -5038,6 +5038,13 @@ S: Maintained
+@@ -5259,6 +5259,13 @@ S: Maintained
F: drivers/tc/
F: include/linux/tc.h
M: Dario Ballabio <ballabio_dario@emc.com>
L: linux-scsi@vger.kernel.org
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
-index 5422169..33be4fa 100644
+index cb96cb2..2be8da2 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -396,6 +396,7 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
static int fixmaps;
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
-index a06e8d1..9a1fe4b 100644
+index f930787..869133f 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
-@@ -677,6 +677,7 @@ void machine_restart(char *cmd)
+@@ -693,6 +693,7 @@ void machine_restart(char *cmd)
{
machine_ops.restart(cmd);
}
void machine_halt(void)
{
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
-index 7e600c1..418725a 100644
+index dd38bfb..26b3bbf 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
-@@ -1284,6 +1284,7 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
+@@ -1274,6 +1274,7 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
*/
__flush_tlb_all();
}
#ifdef CONFIG_HIBERNATION
-@@ -1298,7 +1299,7 @@ bool kernel_page_present(struct page *page)
+@@ -1288,7 +1289,7 @@ bool kernel_page_present(struct page *page)
pte = lookup_address((unsigned long)page_address(page), &level);
return (pte_val(*pte) & _PAGE_PRESENT);
}
#endif /* CONFIG_DEBUG_PAGEALLOC */
diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
-index b3d20b9..cb13f39 100644
+index 8aa85f1..b22c157 100644
--- a/arch/x86/power/cpu.c
+++ b/arch/x86/power/cpu.c
@@ -111,9 +111,7 @@ void save_processor_state(void)
return (rdr->magic == RESTORE_MAGIC) ? 0 : -EINVAL;
}
+EXPORT_SYMBOL_GPL(arch_hibernation_header_restore);
+diff --git a/block/Makefile b/block/Makefile
+index ba74ca6..aa30a88 100644
+--- a/block/Makefile
++++ b/block/Makefile
+@@ -5,7 +5,7 @@
+ obj-$(CONFIG_BLOCK) := elevator.o blk-core.o blk-tag.o blk-sysfs.o \
+ blk-barrier.o blk-settings.o blk-ioc.o blk-map.o \
+ blk-exec.o blk-merge.o blk-softirq.o blk-timeout.o \
+- blk-iopoll.o ioctl.o genhd.o scsi_ioctl.o
++ blk-iopoll.o ioctl.o genhd.o scsi_ioctl.o uuid.o
+
+ obj-$(CONFIG_BLK_DEV_BSG) += bsg.o
+ obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o
+diff --git a/block/blk-core.c b/block/blk-core.c
+index 71da511..e338e9d 100644
+--- a/block/blk-core.c
++++ b/block/blk-core.c
+@@ -37,6 +37,9 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(block_remap);
+ EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_remap);
+ EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_complete);
+
++int trap_non_toi_io;
++EXPORT_SYMBOL_GPL(trap_non_toi_io);
++
+ static int __make_request(struct request_queue *q, struct bio *bio);
+
+ /*
+@@ -1555,6 +1558,9 @@ void submit_bio(int rw, struct bio *bio)
+
+ bio->bi_rw |= rw;
+
++ if (unlikely(trap_non_toi_io))
++ BUG_ON(!bio_rw_flagged(bio, BIO_RW_TUXONICE));
++
+ /*
+ * If it's a regular read/write or a barrier with data attached,
+ * go through the normal accounting stuff before submission.
+diff --git a/block/genhd.c b/block/genhd.c
+index 517e433..9a5fa6f 100644
+--- a/block/genhd.c
++++ b/block/genhd.c
+@@ -18,6 +18,8 @@
+ #include <linux/buffer_head.h>
+ #include <linux/mutex.h>
+ #include <linux/idr.h>
++#include <linux/ctype.h>
++#include <linux/uuid.h>
+
+ #include "blk.h"
+
+@@ -1274,3 +1276,30 @@ int invalidate_partition(struct gendisk *disk, int partno)
+ }
+
+ EXPORT_SYMBOL(invalidate_partition);
++
++dev_t blk_lookup_uuid(const char *uuid)
++{
++ dev_t devt = MKDEV(0, 0);
++ struct class_dev_iter iter;
++ struct device *dev;
++
++ class_dev_iter_init(&iter, &block_class, NULL, &disk_type);
++ while (!devt && (dev = class_dev_iter_next(&iter))) {
++ struct gendisk *disk = dev_to_disk(dev);
++ struct disk_part_iter piter;
++ struct hd_struct *part;
++
++ disk_part_iter_init(&piter, disk, DISK_PITER_INCL_PART0);
++
++ while ((part = disk_part_iter_next(&piter))) {
++ if (part_matches_uuid(part, uuid)) {
++ devt = part_devt(part);
++ break;
++ }
++ }
++ disk_part_iter_exit(&piter);
++ }
++ class_dev_iter_exit(&iter);
++ return devt;
++}
++EXPORT_SYMBOL_GPL(blk_lookup_uuid);
+diff --git a/block/uuid.c b/block/uuid.c
+new file mode 100644
+index 0000000..fefc3ed
+--- /dev/null
++++ b/block/uuid.c
+@@ -0,0 +1,366 @@
++#include <linux/blkdev.h>
++#include <linux/ctype.h>
++
++#if 0
++#define PRINTK(fmt, args...) printk(KERN_DEBUG fmt, ## args)
++#define PRINT_HEX_DUMP(v1, v2, v3, v4, v5, v6, v7, v8) \
++ print_hex_dump(v1, v2, v3, v4, v5, v6, v7, v8)
++#else
++#define PRINTK(fmt, args...)
++#define PRINT_HEX_DUMP(v1, v2, v3, v4, v5, v6, v7, v8)
++#endif
++
++/*
++ * Simple UUID translation
++ */
++
++struct uuid_info {
++ const char *name;
++ long bkoff;
++ unsigned sboff;
++ unsigned sig_len;
++ const char *magic;
++ int uuid_offset;
++};
++
++/*
++ * Based on libuuid's blkid_magic array. Note that I don't
++ * have uuid offsets for all of these yet - mssing ones are 0x0.
++ * Further information welcome.
++ *
++ * Rearranged by sector of fs signature for optimisation.
++ */
++static struct uuid_info uuid_list[] = {
++ { "oracleasm", 0, 32, 8, "ORCLDISK", 0x0 },
++ { "ntfs", 0, 3, 8, "NTFS ", 0x0 },
++ { "vfat", 0, 0x52, 5, "MSWIN", 0x0 },
++ { "vfat", 0, 0x52, 8, "FAT32 ", 0x0 },
++ { "vfat", 0, 0x36, 5, "MSDOS", 0x0 },
++ { "vfat", 0, 0x36, 8, "FAT16 ", 0x0 },
++ { "vfat", 0, 0x36, 8, "FAT12 ", 0x0 },
++ { "vfat", 0, 0, 1, "\353", 0x0 },
++ { "vfat", 0, 0, 1, "\351", 0x0 },
++ { "vfat", 0, 0x1fe, 2, "\125\252", 0x0 },
++ { "xfs", 0, 0, 4, "XFSB", 0x14 },
++ { "romfs", 0, 0, 8, "-rom1fs-", 0x0 },
++ { "bfs", 0, 0, 4, "\316\372\173\033", 0 },
++ { "cramfs", 0, 0, 4, "E=\315\050", 0x0 },
++ { "qnx4", 0, 4, 6, "QNX4FS", 0 },
++ { "crypt_LUKS", 0, 0, 6, "LUKS\xba\xbe", 0x0 },
++ { "squashfs", 0, 0, 4, "sqsh", 0 },
++ { "squashfs", 0, 0, 4, "hsqs", 0 },
++ { "ocfs", 0, 8, 9, "OracleCFS", 0x0 },
++ { "lvm2pv", 0, 0x018, 8, "LVM2 001", 0x0 },
++ { "sysv", 0, 0x3f8, 4, "\020~\030\375", 0 },
++ { "jbd", 1, 0x38, 2, "\123\357", 0x0 },
++ { "ext4dev", 1, 0x38, 2, "\123\357", 0x468 },
++ { "ext4", 1, 0x38, 2, "\123\357", 0x468 },
++ { "ext3", 1, 0x38, 2, "\123\357", 0x468 },
++ { "ext2", 1, 0x38, 2, "\123\357", 0x468 },
++ { "minix", 1, 0x10, 2, "\177\023", 0 },
++ { "minix", 1, 0x10, 2, "\217\023", 0 },
++ { "minix", 1, 0x10, 2, "\150\044", 0 },
++ { "minix", 1, 0x10, 2, "\170\044", 0 },
++ { "lvm2pv", 1, 0x018, 8, "LVM2 001", 0x0 },
++ { "vxfs", 1, 0, 4, "\365\374\001\245", 0 },
++ { "hfsplus", 1, 0, 2, "BD", 0x0 },
++ { "hfsplus", 1, 0, 2, "H+", 0x0 },
++ { "hfsplus", 1, 0, 2, "HX", 0x0 },
++ { "hfs", 1, 0, 2, "BD", 0x0 },
++ { "ocfs2", 1, 0, 6, "OCFSV2", 0x0 },
++ { "lvm2pv", 0, 0x218, 8, "LVM2 001", 0x0 },
++ { "lvm2pv", 1, 0x218, 8, "LVM2 001", 0x0 },
++ { "ocfs2", 2, 0, 6, "OCFSV2", 0x0 },
++ { "swap", 0, 0xff6, 10, "SWAP-SPACE", 0x40c },
++ { "swap", 0, 0xff6, 10, "SWAPSPACE2", 0x40c },
++ { "swsuspend", 0, 0xff6, 9, "S1SUSPEND", 0x40c },
++ { "swsuspend", 0, 0xff6, 9, "S2SUSPEND", 0x40c },
++ { "swsuspend", 0, 0xff6, 9, "ULSUSPEND", 0x40c },
++ { "ocfs2", 4, 0, 6, "OCFSV2", 0x0 },
++ { "ocfs2", 8, 0, 6, "OCFSV2", 0x0 },
++ { "hpfs", 8, 0, 4, "I\350\225\371", 0 },
++ { "reiserfs", 8, 0x34, 8, "ReIsErFs", 0x10054 },
++ { "reiserfs", 8, 20, 8, "ReIsErFs", 0x10054 },
++ { "zfs", 8, 0, 8, "\0\0\x02\xf5\xb0\x07\xb1\x0c", 0x0 },
++ { "zfs", 8, 0, 8, "\x0c\xb1\x07\xb0\xf5\x02\0\0", 0x0 },
++ { "ufs", 8, 0x55c, 4, "T\031\001\000", 0 },
++ { "swap", 0, 0x1ff6, 10, "SWAP-SPACE", 0x40c },
++ { "swap", 0, 0x1ff6, 10, "SWAPSPACE2", 0x40c },
++ { "swsuspend", 0, 0x1ff6, 9, "S1SUSPEND", 0x40c },
++ { "swsuspend", 0, 0x1ff6, 9, "S2SUSPEND", 0x40c },
++ { "swsuspend", 0, 0x1ff6, 9, "ULSUSPEND", 0x40c },
++ { "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", 0x10054 },
++ { "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", 0x10054 },
++ { "reiserfs", 64, 0x34, 8, "ReIsErFs", 0x10054 },
++ { "reiser4", 64, 0, 7, "ReIsEr4", 0x100544 },
++ { "gfs2", 64, 0, 4, "\x01\x16\x19\x70", 0x0 },
++ { "gfs", 64, 0, 4, "\x01\x16\x19\x70", 0x0 },
++ { "btrfs", 64, 0x40, 8, "_BHRfS_M", 0x0 },
++ { "swap", 0, 0x3ff6, 10, "SWAP-SPACE", 0x40c },
++ { "swap", 0, 0x3ff6, 10, "SWAPSPACE2", 0x40c },
++ { "swsuspend", 0, 0x3ff6, 9, "S1SUSPEND", 0x40c },
++ { "swsuspend", 0, 0x3ff6, 9, "S2SUSPEND", 0x40c },
++ { "swsuspend", 0, 0x3ff6, 9, "ULSUSPEND", 0x40c },
++ { "udf", 32, 1, 5, "BEA01", 0x0 },
++ { "udf", 32, 1, 5, "BOOT2", 0x0 },
++ { "udf", 32, 1, 5, "CD001", 0x0 },
++ { "udf", 32, 1, 5, "CDW02", 0x0 },
++ { "udf", 32, 1, 5, "NSR02", 0x0 },
++ { "udf", 32, 1, 5, "NSR03", 0x0 },
++ { "udf", 32, 1, 5, "TEA01", 0x0 },
++ { "iso9660", 32, 1, 5, "CD001", 0x0 },
++ { "iso9660", 32, 9, 5, "CDROM", 0x0 },
++ { "jfs", 32, 0, 4, "JFS1", 0x88 },
++ { "swap", 0, 0x7ff6, 10, "SWAP-SPACE", 0x40c },
++ { "swap", 0, 0x7ff6, 10, "SWAPSPACE2", 0x40c },
++ { "swsuspend", 0, 0x7ff6, 9, "S1SUSPEND", 0x40c },
++ { "swsuspend", 0, 0x7ff6, 9, "S2SUSPEND", 0x40c },
++ { "swsuspend", 0, 0x7ff6, 9, "ULSUSPEND", 0x40c },
++ { "swap", 0, 0xfff6, 10, "SWAP-SPACE", 0x40c },
++ { "swap", 0, 0xfff6, 10, "SWAPSPACE2", 0x40c },
++ { "swsuspend", 0, 0xfff6, 9, "S1SUSPEND", 0x40c },
++ { "swsuspend", 0, 0xfff6, 9, "S2SUSPEND", 0x40c },
++ { "swsuspend", 0, 0xfff6, 9, "ULSUSPEND", 0x40c },
++ { "zfs", 264, 0, 8, "\0\0\x02\xf5\xb0\x07\xb1\x0c", 0x0 },
++ { "zfs", 264, 0, 8, "\x0c\xb1\x07\xb0\xf5\x02\0\0", 0x0 },
++ { NULL, 0, 0, 0, NULL, 0x0 }
++};
++
++static void uuid_end_bio(struct bio *bio, int err)
++{
++ struct page *page = bio->bi_io_vec[0].bv_page;
++
++ BUG_ON(!test_bit(BIO_UPTODATE, &bio->bi_flags));
++
++ unlock_page(page);
++ bio_put(bio);
++}
++
++
++/**
++ * submit - submit BIO request
++ * @writing: READ or WRITE.
++ * @dev: The block device we're using.
++ * @first_block: The first sector we're using.
++ * @page: The page being used for I/O.
++ * @free_group: If writing, the group that was used in allocating the page
++ * and which will be used in freeing the page from the completion
++ * routine.
++ *
++ * Based on Patrick Mochell's pmdisk code from long ago: "Straight from the
++ * textbook - allocate and initialize the bio. If we're writing, make sure
++ * the page is marked as dirty. Then submit it and carry on."
++ *
++ * If we're just testing the speed of our own code, we fake having done all
++ * the hard work and all toi_end_bio immediately.
++ **/
++static struct page *read_bdev_sector(struct block_device *dev,
++ sector_t first_block)
++{
++ struct bio *bio = NULL;
++ struct page *page = alloc_page(GFP_KERNEL);
++
++ if (!page)
++ return NULL;
++
++ lock_page(page);
++
++ bio = bio_alloc(GFP_KERNEL, 1);
++ bio->bi_bdev = dev;
++ bio->bi_sector = first_block;
++ bio->bi_end_io = uuid_end_bio;
++
++ if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
++ printk(KERN_DEBUG "ERROR: adding page to bio at %lld\n",
++ (unsigned long long) first_block);
++ bio_put(bio);
++ __free_page(page);
++ printk(KERN_DEBUG "read_bdev_sector freed page %p (in error "
++ "path).\n", page);
++ return ERR_PTR(-EFAULT);
++ }
++
++ submit_bio(READ | (1 << BIO_RW_SYNCIO) |
++ (1 << BIO_RW_UNPLUG), bio);
++
++ wait_on_page_bit(page, PG_locked);
++ return page;
++}
++
++
++int part_matches_uuid(struct hd_struct *part, const char *uuid)
++{
++ struct block_device *bdev;
++ unsigned char *data = NULL;
++ struct page *data_page = NULL;
++
++ int dev_offset, pg_num, pg_off;
++ int uuid_pg_num, uuid_pg_off, i;
++ unsigned char *uuid_data = NULL;
++ struct page *uuid_data_page = NULL;
++
++ int last_pg_num = 0, last_uuid_pg_num = 0;
++ int result = 0;
++ char buf[50];
++
++ bdev = bdget(part_devt(part));
++
++ PRINTK("blkdev_get %p.\n", part);
++
++ if (blkdev_get(bdev, FMODE_READ)) {
++ PRINTK("blkdev_get failed.\n");
++ return 0;
++ }
++
++ if (!bdev->bd_disk) {
++ bdevname(bdev, buf);
++ PRINTK("bdev %s has no bd_disk.\n", buf);
++ goto out;
++ }
++
++ if (!bdev->bd_disk->queue) {
++ bdevname(bdev, buf);
++ PRINTK("bdev %s has no queue.\n", buf);
++ goto out;
++ }
++
++ PRINT_HEX_DUMP(KERN_EMERG, "part_matches_uuid looking for ",
++ DUMP_PREFIX_NONE, 16, 1, uuid, 16, 0);
++
++ for (i = 0; uuid_list[i].name; i++) {
++ struct uuid_info *dat = &uuid_list[i];
++ dev_offset = (dat->bkoff << 10) + dat->sboff;
++ pg_num = dev_offset >> 12;
++ pg_off = dev_offset & 0xfff;
++ uuid_pg_num = dat->uuid_offset >> 12;
++ uuid_pg_off = dat->uuid_offset & 0xfff;
++
++ if ((((pg_num + 1) << 3) - 1) > part->nr_sects >> 1)
++ continue;
++
++ if (!i || pg_num != last_pg_num) {
++ if (data_page)
++ __free_page(data_page);
++ data_page = read_bdev_sector(bdev, pg_num);
++ data = page_address(data_page);
++ }
++
++ last_pg_num = pg_num;
++
++ if (strncmp(&data[pg_off], dat->magic, dat->sig_len))
++ continue;
++
++ /* Does the UUID match? */
++ if (uuid_pg_num > part->nr_sects >> 3)
++ continue;
++
++ if (!uuid_data || uuid_pg_num != last_uuid_pg_num) {
++ if (uuid_data_page)
++ __free_page(uuid_data_page);
++ uuid_data_page = read_bdev_sector(bdev, uuid_pg_num);
++ uuid_data = page_address(uuid_data_page);
++ }
++
++ last_uuid_pg_num = uuid_pg_num;
++
++ PRINT_HEX_DUMP(KERN_EMERG, "part_matches_uuid considering ",
++ DUMP_PREFIX_NONE, 16, 1,
++ &uuid_data[uuid_pg_off], 16, 0);
++
++ if (!memcmp(&uuid_data[uuid_pg_off], uuid, 16)) {
++ PRINTK("We have a match.\n");
++ result = 1;
++ break;
++ }
++ }
++
++ if (data_page)
++ __free_page(data_page);
++
++ if (uuid_data_page)
++ __free_page(uuid_data_page);
++
++out:
++ blkdev_put(bdev, FMODE_READ);
++ return result;
++}
++
++int uuid_from_block_dev(struct block_device *bdev, char *uuid)
++{
++ unsigned char *data = NULL;
++ struct page *data_page = NULL;
++
++ int dev_offset, pg_num, pg_off;
++ int uuid_pg_num, uuid_pg_off, i;
++ unsigned char *uuid_data = NULL;
++ struct page *uuid_data_page = NULL;
++
++ int last_pg_num = 0, last_uuid_pg_num = 0;
++ int result = 1;
++ char buf[50];
++
++ bdevname(bdev, buf);
++
++ PRINTK(KERN_EMERG "uuid_from_block_dev looking for partition type "
++ "of %s.\n", buf);
++
++ for (i = 0; uuid_list[i].name; i++) {
++ struct uuid_info *dat = &uuid_list[i];
++ dev_offset = (dat->bkoff << 10) + dat->sboff;
++ pg_num = dev_offset >> 12;
++ pg_off = dev_offset & 0xfff;
++ uuid_pg_num = dat->uuid_offset >> 12;
++ uuid_pg_off = dat->uuid_offset & 0xfff;
++
++ if ((((pg_num + 1) << 3) - 1) > bdev->bd_part->nr_sects >> 1)
++ continue;
++
++ if (!i || pg_num != last_pg_num) {
++ if (data_page)
++ __free_page(data_page);
++ data_page = read_bdev_sector(bdev, pg_num);
++ data = page_address(data_page);
++ }
++
++ last_pg_num = pg_num;
++
++ if (strncmp(&data[pg_off], dat->magic, dat->sig_len))
++ continue;
++
++ /* UUID can't be off the end of the disk */
++ if (uuid_pg_num > bdev->bd_part->nr_sects >> 3)
++ continue;
++
++ PRINTK("This partition looks like %s.\n", dat->name);
++
++ if (!uuid_data || uuid_pg_num != last_uuid_pg_num) {
++ if (uuid_data_page)
++ __free_page(uuid_data_page);
++ uuid_data_page = read_bdev_sector(bdev, uuid_pg_num);
++ uuid_data = page_address(uuid_data_page);
++ }
++
++ last_uuid_pg_num = uuid_pg_num;
++
++ if (!uuid_pg_off) {
++ PRINTK("Don't know uuid offset for %s. Continuing the "
++ "search.\n", dat->name);
++ } else {
++ memcpy(uuid, &uuid_data[uuid_pg_off], 16);
++ PRINT_HEX_DUMP(KERN_EMERG, "uuid_from_block_dev "
++ "returning ", DUMP_PREFIX_NONE, 16, 1,
++ uuid, 16, 0);
++ result = 0;
++ break;
++ }
++ }
++
++ if (data_page)
++ __free_page(data_page);
++
++ if (uuid_data_page)
++ __free_page(uuid_data_page);
++
++ return result;
++}
++EXPORT_SYMBOL_GPL(uuid_from_block_dev);
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
-index 58a3e57..4b0c6cf 100644
+index 8aa2443..1e61592 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
-@@ -55,6 +55,7 @@ void device_pm_lock(void)
+@@ -66,6 +66,7 @@ void device_pm_lock(void)
{
mutex_lock(&dpm_list_mtx);
}
+EXPORT_SYMBOL_GPL(device_pm_lock);
/**
- * device_pm_unlock - unlock the list of active devices used by the PM core
-@@ -63,6 +64,7 @@ void device_pm_unlock(void)
+ * device_pm_unlock - Unlock the list of active devices used by the PM core.
+@@ -74,6 +75,7 @@ void device_pm_unlock(void)
{
mutex_unlock(&dpm_list_mtx);
}
+EXPORT_SYMBOL_GPL(device_pm_unlock);
/**
- * device_pm_add - add a device to the list of active devices
+ * device_pm_add - Add a device to the PM core's list of active devices.
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
-index 404f4c1..0988ad0 100644
+index 0c80c68..af032c1 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -188,6 +188,7 @@ int fg_console;
/*
* For each existing display, we have a pointer to console currently visible
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
-index ffe8f43..5e7dca6 100644
+index e9dbb48..db9bf9b 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -138,7 +138,8 @@ drm_gem_object_alloc(struct drm_device *dev, size_t size)
goto free;
diff --git a/drivers/md/md.c b/drivers/md/md.c
-index 9dd8720..88dc120 100644
+index b182f86..f9d7053 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
-@@ -6245,6 +6245,9 @@ void md_do_sync(mddev_t *mddev)
+@@ -6279,6 +6279,9 @@ void md_do_sync(mddev_t *mddev)
mddev->curr_resync = 2;
try_again:
if (kthread_should_stop()) {
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
goto skip;
-@@ -6266,6 +6269,10 @@ void md_do_sync(mddev_t *mddev)
+@@ -6300,6 +6303,10 @@ void md_do_sync(mddev_t *mddev)
* time 'round when curr_resync == 2
*/
continue;
/* We need to wait 'interruptible' so as not to
* contribute to the load average, and not to
* be caught by 'softlockup'
-@@ -6278,6 +6285,7 @@ void md_do_sync(mddev_t *mddev)
+@@ -6312,6 +6319,7 @@ void md_do_sync(mddev_t *mddev)
" share one or more physical units)\n",
desc, mdname(mddev), mdname(mddev2));
mddev_put(mddev2);
if (signal_pending(current))
flush_signals(current);
schedule();
-@@ -6384,6 +6392,9 @@ void md_do_sync(mddev_t *mddev)
+@@ -6418,6 +6426,9 @@ void md_do_sync(mddev_t *mddev)
|| kthread_should_stop());
}
if (kthread_should_stop())
goto interrupted;
-@@ -6428,6 +6439,9 @@ void md_do_sync(mddev_t *mddev)
+@@ -6462,6 +6473,9 @@ void md_do_sync(mddev_t *mddev)
last_mark = next;
}
if (kthread_should_stop())
goto interrupted;
diff --git a/fs/block_dev.c b/fs/block_dev.c
-index 94dfda2..8c1b98e 100644
+index 8bed055..3a49424 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
-@@ -327,6 +327,93 @@ int thaw_bdev(struct block_device *bdev, struct super_block *sb)
+@@ -334,6 +334,93 @@ out_unlock:
}
EXPORT_SYMBOL(thaw_bdev);
{
return block_write_full_page(page, blkdev_get_block, wbc);
diff --git a/fs/drop_caches.c b/fs/drop_caches.c
-index a2edb79..1d0444e 100644
+index 31f4b0e..ff7df7a 100644
--- a/fs/drop_caches.c
+++ b/fs/drop_caches.c
@@ -8,6 +8,7 @@
+EXPORT_SYMBOL_GPL(drop_pagecache);
int drop_caches_sysctl_handler(ctl_table *table, int write,
- struct file *file, void __user *buffer, size_t *length, loff_t *ppos)
+ void __user *buffer, size_t *length, loff_t *ppos)
diff --git a/fs/fuse/control.c b/fs/fuse/control.c
-index 99c99df..cadffd8 100644
+index 3773fd6..6272b60 100644
--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
-@@ -209,6 +209,7 @@ static void fuse_ctl_kill_sb(struct super_block *sb)
+@@ -341,6 +341,7 @@ static void fuse_ctl_kill_sb(struct super_block *sb)
static struct file_system_type fuse_ctl_fs_type = {
.owner = THIS_MODULE,
.name = "fusectl",
.kill_sb = fuse_ctl_kill_sb,
};
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
-index 6484eb7..5251799 100644
+index 51d9e33..12ad477 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -7,6 +7,7 @@
if (nbytes < sizeof(struct fuse_out_header))
return -EINVAL;
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
-index e703654..bfb0500 100644
+index 4787ae6..797b7dd 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -7,12 +7,14 @@
err = -EIO;
if (inode && get_node_id(inode) == FUSE_ROOT_ID)
goto out_iput;
-@@ -389,6 +398,8 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
+@@ -392,6 +401,8 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
if (IS_ERR(forget_req))
return PTR_ERR(forget_req);
req = fuse_get_req(fc);
err = PTR_ERR(req);
if (IS_ERR(req))
-@@ -482,6 +493,8 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
+@@ -485,6 +496,8 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
int err;
struct fuse_req *forget_req;
forget_req = fuse_get_req(fc);
if (IS_ERR(forget_req)) {
fuse_put_request(fc, req);
-@@ -584,7 +597,11 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
+@@ -587,7 +600,11 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
{
struct fuse_mkdir_in inarg;
struct fuse_conn *fc = get_fuse_conn(dir);
if (IS_ERR(req))
return PTR_ERR(req);
-@@ -608,7 +625,11 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry,
+@@ -611,7 +628,11 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry,
{
struct fuse_conn *fc = get_fuse_conn(dir);
unsigned len = strlen(link) + 1;
if (IS_ERR(req))
return PTR_ERR(req);
-@@ -625,7 +646,11 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
+@@ -628,7 +649,11 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
{
int err;
struct fuse_conn *fc = get_fuse_conn(dir);
if (IS_ERR(req))
return PTR_ERR(req);
-@@ -658,7 +683,11 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
+@@ -661,7 +686,11 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
{
int err;
struct fuse_conn *fc = get_fuse_conn(dir);
return PTR_ERR(req);
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
-index cbc4640..b99aa5c 100644
+index c18913a..0f7d313 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -7,11 +7,13 @@
req = fuse_get_req(fc);
if (IS_ERR(req))
return PTR_ERR(req);
-@@ -1408,6 +1429,8 @@ static int fuse_getlk(struct file *file, struct file_lock *fl)
+@@ -1409,6 +1430,8 @@ static int fuse_getlk(struct file *file, struct file_lock *fl)
struct fuse_lk_out outarg;
int err;
req = fuse_get_req(fc);
if (IS_ERR(req))
return PTR_ERR(req);
-@@ -1443,6 +1466,8 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
+@@ -1444,6 +1467,8 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
if (fl->fl_flags & FL_CLOSE)
return 0;
req = fuse_get_req(fc);
if (IS_ERR(req))
return PTR_ERR(req);
-@@ -1509,6 +1534,8 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block)
+@@ -1510,6 +1535,8 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block)
if (!inode->i_sb->s_bdev || fc->no_bmap)
return 0;
+ } \
+} while (0)
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
-index f91ccc4..8de2966 100644
+index 1a822ce..9b69d61 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
-@@ -991,7 +991,7 @@ static void fuse_kill_sb_anon(struct super_block *sb)
+@@ -1062,7 +1062,7 @@ static void fuse_kill_sb_anon(struct super_block *sb)
static struct file_system_type fuse_fs_type = {
.owner = THIS_MODULE,
.name = "fuse",
.get_sb = fuse_get_sb,
.kill_sb = fuse_kill_sb_anon,
};
-@@ -1023,7 +1023,7 @@ static struct file_system_type fuseblk_fs_type = {
+@@ -1094,7 +1094,7 @@ static struct file_system_type fuseblk_fs_type = {
.name = "fuseblk",
.get_sb = fuse_get_sb_blk,
.kill_sb = fuse_kill_sb_blk,
static inline int register_fuseblk(void)
diff --git a/fs/namei.c b/fs/namei.c
-index 1f13751..96fcd99 100644
+index d11f404..c665cb7 100644
--- a/fs/namei.c
+++ b/fs/namei.c
-@@ -2271,6 +2271,8 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry)
+@@ -2273,6 +2273,8 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry)
if (!dir->i_op->unlink)
return -EPERM;
mutex_lock(&dentry->d_inode->i_mutex);
diff --git a/fs/super.c b/fs/super.c
-index 2761d3e..6892dab 100644
+index 19eb70b..96cf7e6 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -42,6 +42,8 @@
/**
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
-index 334a359..c53ebd5 100644
+index 1feed71..23f2385 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
-@@ -211,6 +211,7 @@ unifdef-y += filter.h
+@@ -212,6 +212,7 @@ unifdef-y += filter.h
unifdef-y += flat.h
unifdef-y += futex.h
unifdef-y += fs.h
unifdef-y += gameport.h
unifdef-y += generic_serial.h
unifdef-y += hayesesp.h
+diff --git a/include/linux/bio.h b/include/linux/bio.h
+index 5be93f1..b9ce6fe 100644
+--- a/include/linux/bio.h
++++ b/include/linux/bio.h
+@@ -175,8 +175,11 @@ enum bio_rw_flags {
+ BIO_RW_META,
+ BIO_RW_DISCARD,
+ BIO_RW_NOIDLE,
++ BIO_RW_TUXONICE,
+ };
+
++extern int trap_non_toi_io;
++
+ /*
+ * First four bits must match between bio->bi_rw and rq->cmd_flags, make
+ * that explicit here.
diff --git a/include/linux/freezer.h b/include/linux/freezer.h
-index 5a361f8..c775cd1 100644
+index 5a361f8..a66f2a9 100644
--- a/include/linux/freezer.h
+++ b/include/linux/freezer.h
-@@ -121,6 +121,23 @@ static inline void set_freezable(void)
+@@ -121,6 +121,19 @@ static inline void set_freezable(void)
current->flags &= ~PF_NOFREEZE;
}
++extern int freezer_state;
+#define FREEZER_OFF 0
+#define FREEZER_FILESYSTEMS_FROZEN 1
+#define FREEZER_USERSPACE_FROZEN 2
+#define FREEZER_FULLY_ON 3
-+#ifdef CONFIG_PM_SLEEP
-+extern int freezer_state;
+
+static inline int freezer_is_on(void)
+{
+ return freezer_state == FREEZER_FULLY_ON;
+}
-+#else
-+static inline int freezer_is_on(void) { return 0; }
-+#endif
+
+extern void thaw_kernel_threads(void);
+
/*
* Tell the freezer that the current task should be frozen by it and that it
* should send a fake signal to the task to freeze it.
-@@ -172,6 +189,8 @@ static inline int freeze_processes(void) { BUG(); return 0; }
+@@ -172,6 +185,8 @@ static inline int freeze_processes(void) { BUG(); return 0; }
static inline void thaw_processes(void) {}
static inline int try_to_freeze(void) { return 0; }
static inline void freezer_do_not_count(void) {}
static inline void freezer_count(void) {}
diff --git a/include/linux/fs.h b/include/linux/fs.h
-index 73e9b64..78b2ef3 100644
+index 2620a8c..bd1c328 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -172,6 +172,7 @@ struct inodes_stat_t {
/*
* Note that nosuid etc flags are inode-specific: setting some file-system
-@@ -373,6 +377,7 @@ struct inodes_stat_t {
+@@ -377,6 +381,7 @@ struct inodes_stat_t {
#include <linux/capability.h>
#include <linux/semaphore.h>
#include <linux/fiemap.h>
#include <asm/atomic.h>
#include <asm/byteorder.h>
-@@ -1392,8 +1397,11 @@ enum {
+@@ -1393,8 +1398,11 @@ enum {
SB_FREEZE_TRANS = 2,
};
#define get_fs_excl() atomic_inc(¤t->fs_excl)
#define put_fs_excl() atomic_dec(¤t->fs_excl)
-@@ -1957,6 +1965,13 @@ extern struct super_block *freeze_bdev(struct block_device *);
+@@ -1955,6 +1963,13 @@ extern struct super_block *freeze_bdev(struct block_device *);
extern void emergency_thaw_all(void);
extern int thaw_bdev(struct block_device *bdev, struct super_block *sb);
extern int fsync_bdev(struct block_device *);
static inline void bd_forget(struct inode *inode) {}
static inline int sync_blockdev(struct block_device *bdev) { return 0; }
diff --git a/include/linux/mm.h b/include/linux/mm.h
-index 9a72cc7..ec0431d 100644
+index 24c3956..e935946 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
-@@ -103,6 +103,7 @@ extern unsigned int kobjsize(const void *objp);
- #define VM_MIXEDMAP 0x10000000 /* Can contain "struct page" and pure PFN pages */
- #define VM_SAO 0x20000000 /* Strong Access Ordering (powerpc) */
- #define VM_PFN_AT_MMAP 0x40000000 /* PFNMAP vma that is fully mapped at mmap time */
-+#define VM_ATOMIC_COPY 0x80000000 /* TuxOnIce should atomically copy */
+@@ -97,6 +97,7 @@ extern unsigned int kobjsize(const void *objp);
+ #define VM_HUGETLB 0x00400000 /* Huge TLB Page VM */
+ #define VM_NONLINEAR 0x00800000 /* Is non-linear (remap_file_pages) */
+ #define VM_MAPPED_COPY 0x01000000 /* T if mapped copy of data (nommu mmap) */
++#define VM_ATOMIC_COPY 0x01000000 /* TuxOnIce should atomically copy (mmu) */
+ #define VM_INSERTPAGE 0x02000000 /* The vma has had "vm_insert_page()" done on it */
+ #define VM_ALWAYSDUMP 0x04000000 /* Always include in core dumps */
- #ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */
- #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS
-@@ -1278,6 +1279,7 @@ int drop_caches_sysctl_handler(struct ctl_table *, int, struct file *,
+@@ -1290,6 +1291,7 @@ int drop_caches_sysctl_handler(struct ctl_table *, int,
void __user *, size_t *, loff_t *);
unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask,
unsigned long lru_pages);
#ifndef CONFIG_MMU
#define randomize_va_space 0
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
-index 5ba398e..f220828 100644
+index ab5d312..aee7b0f 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -24,6 +24,8 @@
#define MAX_LINKS 32
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
-index cd15df6..df6b587 100644
+index 5e781d8..a1c07f3 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
-@@ -312,4 +312,70 @@ static inline void register_nosave_region_late(unsigned long b, unsigned long e)
-
- extern struct mutex pm_mutex;
+@@ -329,4 +329,70 @@ static inline void unlock_system_sleep(void)
+ }
+ #endif
+enum {
+ TOI_CAN_HIBERNATE,
+#endif
#endif /* _LINUX_SUSPEND_H */
diff --git a/include/linux/swap.h b/include/linux/swap.h
-index 7c15334..779dcb1 100644
+index 4ec9001..12da629 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
-@@ -169,6 +169,7 @@ struct swap_list_t {
+@@ -191,6 +191,7 @@ struct swap_list_t {
extern unsigned long totalram_pages;
extern unsigned long totalreserve_pages;
extern unsigned int nr_free_buffer_pages(void);
extern unsigned int nr_free_pagecache_pages(void);
/* Definition of global_page_state not available yet */
+diff --git a/include/linux/uuid.h b/include/linux/uuid.h
+new file mode 100644
+index 0000000..a3f6a99
+--- /dev/null
++++ b/include/linux/uuid.h
+@@ -0,0 +1,8 @@
++#include <linux/device.h>
++
++struct hd_struct;
++struct block_device;
++
++int part_matches_uuid(struct hd_struct *part, const char *uuid);
++dev_t blk_lookup_uuid(const char *uuid);
++int uuid_from_block_dev(struct block_device *bdev, char *uuid);
diff --git a/init/do_mounts.c b/init/do_mounts.c
-index 093f659..cf1ef2b 100644
+index bb008d0..5273dc9 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -143,6 +143,7 @@ fail:
+
mount_root();
out:
- sys_mount(".", "/", NULL, MS_MOVE, NULL);
+ devtmpfs_mount("dev");
diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c
index 614241b..f3ea292 100644
--- a/init/do_mounts_initrd.c
sys_fchdir(old_fd);
sys_mount("/", ".", NULL, MS_MOVE, NULL);
diff --git a/init/main.c b/init/main.c
-index 11f4f14..cb63e56 100644
+index 4051d75..650828d 100644
--- a/init/main.c
+++ b/init/main.c
-@@ -115,6 +115,7 @@ extern void softirq_init(void);
+@@ -116,6 +116,7 @@ extern void softirq_init(void);
char __initdata boot_command_line[COMMAND_LINE_SIZE];
/* Untouched saved command line (eg. for /proc) */
char *saved_command_line;
static char *static_command_line;
diff --git a/kernel/cpu.c b/kernel/cpu.c
-index 8ce1004..853cf28 100644
+index 6ba0f1e..a633bac 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
-@@ -412,6 +412,7 @@ int disable_nonboot_cpus(void)
+@@ -413,6 +413,7 @@ int disable_nonboot_cpus(void)
stop_machine_destroy();
return error;
}
+EXPORT_SYMBOL_GPL(disable_nonboot_cpus);
- void __ref enable_nonboot_cpus(void)
+ void __weak arch_enable_nonboot_cpus_begin(void)
{
-@@ -436,6 +437,7 @@ void __ref enable_nonboot_cpus(void)
+@@ -451,6 +452,7 @@ void __ref enable_nonboot_cpus(void)
out:
cpu_maps_update_done();
}
static int alloc_frozen_cpus(void)
{
diff --git a/kernel/fork.c b/kernel/fork.c
-index e6c04d4..9f36327 100644
+index 166b8c4..8033d91 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
-@@ -83,6 +83,7 @@ int max_threads; /* tunable limit on nr_threads */
+@@ -85,6 +85,7 @@ int max_threads; /* tunable limit on nr_threads */
DEFINE_PER_CPU(unsigned long, process_counts) = 0;
__cacheline_aligned DEFINE_RWLOCK(tasklist_lock); /* outer */
int nr_processes(void)
{
diff --git a/kernel/kmod.c b/kernel/kmod.c
-index 385c31a..1ad9a46 100644
+index 9fcb53a..624929f 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
-@@ -318,6 +318,7 @@ int usermodehelper_disable(void)
+@@ -326,6 +326,7 @@ int usermodehelper_disable(void)
usermodehelper_disabled = 0;
return -EAGAIN;
}
/**
* usermodehelper_enable - allow new helpers to be started again
-@@ -326,6 +327,7 @@ void usermodehelper_enable(void)
+@@ -334,6 +335,7 @@ void usermodehelper_enable(void)
{
usermodehelper_disabled = 0;
}
static void helper_lock(void)
{
diff --git a/kernel/pid.c b/kernel/pid.c
-index 31310b5..f64b509 100644
+index d3f722d..291a7c3 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -382,6 +382,7 @@ struct task_struct *find_task_by_pid_ns(pid_t nr, struct pid_namespace *ns)
struct task_struct *find_task_by_vpid(pid_t vnr)
{
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
-index 72067cb..82cd2a1 100644
+index 91e09d3..21f1af0 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -38,6 +38,13 @@ config CAN_PM_TRACE
tristate "Advanced Power Management Emulation"
depends on PM && SYS_SUPPORTS_APM_EMULATION
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
-index c3b81c3..b5a36bc 100644
+index c3b81c3..982a589 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
-@@ -3,6 +3,28 @@ ifeq ($(CONFIG_PM_DEBUG),y)
+@@ -3,6 +3,35 @@ ifeq ($(CONFIG_PM_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
endif
-+tuxonice_core-y := tuxonice_modules.o tuxonice_sysfs.o tuxonice_highlevel.o \
-+ tuxonice_io.o tuxonice_pagedir.o tuxonice_prepare_image.o \
-+ tuxonice_extent.o tuxonice_pageflags.o tuxonice_ui.o \
-+ tuxonice_power_off.o tuxonice_atomic_copy.o
++tuxonice_core-y := tuxonice_modules.o
+
+obj-$(CONFIG_TOI) += tuxonice_builtin.o
+
+tuxonice_core-$(CONFIG_PM_DEBUG) += tuxonice_alloc.o
+
++# Compile these in after allocation debugging, if used.
++
++tuxonice_core-y += tuxonice_sysfs.o tuxonice_highlevel.o \
++ tuxonice_io.o tuxonice_pagedir.o tuxonice_prepare_image.o \
++ tuxonice_extent.o tuxonice_pageflags.o tuxonice_ui.o \
++ tuxonice_power_off.o tuxonice_atomic_copy.o
++
+tuxonice_core-$(CONFIG_TOI_CHECKSUM) += tuxonice_checksum.o
+
+tuxonice_core-$(CONFIG_NET) += tuxonice_storage.o tuxonice_netlink.o
+obj-$(CONFIG_TOI_CORE) += tuxonice_core.o
+obj-$(CONFIG_TOI_CRYPTO) += tuxonice_compress.o
+
-+obj-$(CONFIG_TOI_SWAP) += tuxonice_block_io.o tuxonice_swap.o
-+obj-$(CONFIG_TOI_FILE) += tuxonice_block_io.o tuxonice_file.o
++tuxonice_bio-y := tuxonice_bio_core.o tuxonice_bio_chains.o \
++ tuxonice_bio_signature.o
++
++obj-$(CONFIG_TOI_SWAP) += tuxonice_bio.o tuxonice_swap.o
++obj-$(CONFIG_TOI_FILE) += tuxonice_bio.o tuxonice_file.o
+obj-$(CONFIG_TOI_CLUSTER) += tuxonice_cluster.o
+
+obj-$(CONFIG_TOI_USERUI) += tuxonice_userui.o
obj-$(CONFIG_PM) += main.o
obj-$(CONFIG_PM_SLEEP) += console.o
obj-$(CONFIG_FREEZER) += process.o
+diff --git a/kernel/power/console.c b/kernel/power/console.c
+index 5187136..f4f8761 100644
+--- a/kernel/power/console.c
++++ b/kernel/power/console.c
+@@ -25,6 +25,7 @@ int pm_prepare_console(void)
+ kmsg_redirect = SUSPEND_CONSOLE;
+ return 0;
+ }
++EXPORT_SYMBOL_GPL(pm_prepare_console);
+
+ void pm_restore_console(void)
+ {
+@@ -33,4 +34,5 @@ void pm_restore_console(void)
+ kmsg_redirect = orig_kmsg;
+ }
+ }
++EXPORT_SYMBOL_GPL(pm_restore_console);
+ #endif
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
-index 81d2e74..3fc04ad 100644
+index 04a9e90..c35feb0 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -25,11 +25,12 @@
/**
* create_image - freeze devices that need to be frozen with interrupts
-@@ -491,6 +500,7 @@ int hibernation_platform_enter(void)
+@@ -495,6 +504,7 @@ int hibernation_platform_enter(void)
return error;
}
/**
* power_down - Shut the machine down for hibernation.
-@@ -542,6 +552,9 @@ int hibernate(void)
+@@ -546,6 +556,9 @@ int hibernate(void)
{
int error;
mutex_lock(&pm_mutex);
/* The snapshot device should not be opened while we're running */
if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
-@@ -619,11 +632,19 @@ int hibernate(void)
+@@ -626,11 +639,19 @@ int hibernate(void)
*
*/
/*
* If the user said "noresume".. bail out early.
*/
-@@ -947,6 +968,7 @@ static int __init resume_offset_setup(char *str)
+@@ -959,6 +980,7 @@ static int __init resume_offset_setup(char *str)
static int __init noresume_setup(char *str)
{
noresume = 1;
}
diff --git a/kernel/power/main.c b/kernel/power/main.c
-index f710e36..8f1b120 100644
+index 347d2cc..10e587f 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
-@@ -15,6 +15,7 @@
+@@ -16,6 +16,7 @@
#include "power.h"
DEFINE_MUTEX(pm_mutex);
unsigned int pm_flags;
EXPORT_SYMBOL(pm_flags);
-@@ -23,7 +24,8 @@ EXPORT_SYMBOL(pm_flags);
+@@ -24,7 +25,8 @@ EXPORT_SYMBOL(pm_flags);
/* Routines for PM-transition notifications */
int register_pm_notifier(struct notifier_block *nb)
{
-@@ -42,6 +44,7 @@ int pm_notifier_call_chain(unsigned long val)
+@@ -43,6 +45,7 @@ int pm_notifier_call_chain(unsigned long val)
return (blocking_notifier_call_chain(&pm_chain_head, val, NULL)
== NOTIFY_BAD) ? -EINVAL : 0;
}
#ifdef CONFIG_PM_DEBUG
int pm_test_level = TEST_NONE;
-@@ -109,6 +112,7 @@ power_attr(pm_test);
+@@ -110,6 +113,7 @@ power_attr(pm_test);
#endif /* CONFIG_PM_SLEEP */
struct kobject *power_kobj;
/**
* state - control system power state.
diff --git a/kernel/power/power.h b/kernel/power/power.h
-index 26d5a26..71469b4 100644
+index 46c5a26..d8c8f32 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -31,8 +31,12 @@ static inline char *check_image_kernel(struct swsusp_info *info)
+
+#define BM_END_OF_MAP (~0UL)
+
-+#define BM_BITS_PER_BLOCK (PAGE_SIZE << 3)
++#define BM_BITS_PER_BLOCK (PAGE_SIZE * BITS_PER_BYTE)
+
+struct bm_block {
+ struct list_head hook; /* hook into a list of bitmap blocks */
+ (int rw, struct toi_module_ops *owner, char *buffer, int buffer_size));
+#endif
diff --git a/kernel/power/process.c b/kernel/power/process.c
-index da2072d..9b31b2b 100644
+index cc2e553..5e1a845 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
-@@ -13,6 +13,13 @@
+@@ -14,6 +14,13 @@
#include <linux/module.h>
#include <linux/syscalls.h>
#include <linux/freezer.h>
/*
* Timeout for stopping processes
-@@ -86,7 +93,8 @@ static int try_to_freeze_tasks(bool sig_only)
+@@ -87,7 +94,8 @@ static int try_to_freeze_tasks(bool sig_only)
do_each_thread(g, p) {
task_lock(p);
if (freezing(p) && !freezer_should_skip(p))
cancel_freezing(p);
task_unlock(p);
} while_each_thread(g, p);
-@@ -106,17 +114,26 @@ int freeze_processes(void)
+@@ -107,17 +115,26 @@ int freeze_processes(void)
{
int error;
oom_killer_disable();
Exit:
-@@ -125,6 +142,7 @@ int freeze_processes(void)
+@@ -126,6 +143,7 @@ int freeze_processes(void)
return error;
}
static void thaw_tasks(bool nosig_only)
{
-@@ -148,12 +166,39 @@ static void thaw_tasks(bool nosig_only)
+@@ -149,12 +167,39 @@ static void thaw_tasks(bool nosig_only)
void thaw_processes(void)
{
+ */
+EXPORT_SYMBOL_GPL(thaw_kernel_threads);
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
-index 523a451..ecad28d 100644
+index 36cb168..7f6da8f 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -34,6 +34,8 @@
-#define BM_END_OF_MAP (~0UL)
-
--#define BM_BITS_PER_BLOCK (PAGE_SIZE << 3)
+-#define BM_BITS_PER_BLOCK (PAGE_SIZE * BITS_PER_BYTE)
-
-struct bm_block {
- struct list_head hook; /* hook into a list of bitmap blocks */
/**
* count_data_pages - compute the total number of saveable non-highmem
-@@ -1286,6 +1407,9 @@ asmlinkage int swsusp_save(void)
+@@ -1500,6 +1621,9 @@ asmlinkage int swsusp_save(void)
{
unsigned int nr_pages, nr_highmem;
printk(KERN_INFO "PM: Creating hibernation image: \n");
drain_local_pages(NULL);
-@@ -1326,14 +1450,14 @@ asmlinkage int swsusp_save(void)
+@@ -1540,14 +1664,14 @@ asmlinkage int swsusp_save(void)
}
#ifndef CONFIG_ARCH_HIBERNATION_HEADER
{
if (info->version_code != LINUX_VERSION_CODE)
return "kernel version";
-@@ -1347,6 +1471,7 @@ static char *check_image_kernel(struct swsusp_info *info)
+@@ -1561,6 +1685,7 @@ static char *check_image_kernel(struct swsusp_info *info)
return "machine";
return NULL;
}
#endif /* CONFIG_ARCH_HIBERNATION_HEADER */
unsigned long snapshot_get_image_size(void)
-@@ -1354,7 +1479,7 @@ unsigned long snapshot_get_image_size(void)
+@@ -1568,7 +1693,7 @@ unsigned long snapshot_get_image_size(void)
return nr_copy_pages + nr_meta_pages + 1;
}
{
memset(info, 0, sizeof(struct swsusp_info));
info->num_physpages = num_physpages;
-@@ -1364,6 +1489,7 @@ static int init_header(struct swsusp_info *info)
+@@ -1578,6 +1703,7 @@ static int init_header(struct swsusp_info *info)
info->size <<= PAGE_SHIFT;
return init_header_complete(info);
}
* suspend_finish - Do final work before exiting suspend sequence.
diff --git a/kernel/power/tuxonice.h b/kernel/power/tuxonice.h
new file mode 100644
-index 0000000..4ed1cd4
+index 0000000..2ab1c23
--- /dev/null
+++ b/kernel/power/tuxonice.h
-@@ -0,0 +1,213 @@
+@@ -0,0 +1,214 @@
+/*
+ * kernel/power/tuxonice.h
+ *
+#include "tuxonice_pageflags.h"
+#include "power.h"
+
-+#define TOI_CORE_VERSION "3.0.1"
++#define TOI_CORE_VERSION "3.0.99.32"
+
+#define MY_BOOT_KERNEL_DATA_VERSION 1
+
+extern int toi_launch_userspace_program(char *command, int channel_no,
+ enum umh_wait wait, int debug);
+
-+extern char *tuxonice_signature;
++extern char tuxonice_signature[9];
++extern int freezer_sync;
+#endif
diff --git a/kernel/power/tuxonice_alloc.c b/kernel/power/tuxonice_alloc.c
new file mode 100644
-index 0000000..0089ab8
+index 0000000..225a067
--- /dev/null
+++ b/kernel/power/tuxonice_alloc.c
-@@ -0,0 +1,288 @@
+@@ -0,0 +1,313 @@
+/*
+ * kernel/power/tuxonice_alloc.c
+ *
+#include "tuxonice_sysfs.h"
+#include "tuxonice.h"
+
-+#define TOI_ALLOC_PATHS 39
++#define TOI_ALLOC_PATHS 40
+
+static DEFINE_MUTEX(toi_alloc_mutex);
+
+static struct toi_module_ops toi_alloc_ops;
+
+static int toi_fail_num;
++static int trace_allocs;
+static atomic_t toi_alloc_count[TOI_ALLOC_PATHS],
+ toi_free_count[TOI_ALLOC_PATHS],
+ toi_test_count[TOI_ALLOC_PATHS],
+ "swap mark resume attempted buffer", /* 35 */
+ "cluster member",
+ "boot kernel data buffer",
-+ "setting swap signature"
++ "setting swap signature",
++ "block i/o bdev struct"
+};
+
+#define MIGHT_FAIL(FAIL_NUM, FAIL_VAL) \
+ if (unlikely(test_action_state(TOI_GET_MAX_MEM_ALLOCD))) {
+ mutex_lock(&toi_alloc_mutex);
+ toi_cur_allocd[fail_num]++;
-+ cur_allocd+= size;
++ cur_allocd += size;
+ if (unlikely(cur_allocd > max_allocd)) {
+ int i;
+
+{
+ BUG_ON(fail_num >= TOI_ALLOC_PATHS);
+ atomic_inc(&toi_free_count[fail_num]);
++ if (unlikely(atomic_read(&toi_free_count[fail_num]) >
++ atomic_read(&toi_alloc_count[fail_num])))
++ dump_stack();
+ if (unlikely(test_action_state(TOI_GET_MAX_MEM_ALLOCD))) {
+ mutex_lock(&toi_alloc_mutex);
-+ cur_allocd-= size;
++ cur_allocd -= size;
+ toi_cur_allocd[fail_num]--;
+ mutex_unlock(&toi_alloc_mutex);
+ }
+ result = kzalloc(size, flags);
+ if (toi_alloc_ops.enabled)
+ alloc_update_stats(fail_num, result, size);
++ if (fail_num == trace_allocs)
++ dump_stack();
+ return result;
+}
+EXPORT_SYMBOL_GPL(toi_kzalloc);
+ if (toi_alloc_ops.enabled)
+ alloc_update_stats(fail_num, (void *) result,
+ PAGE_SIZE << order);
++ if (fail_num == trace_allocs)
++ dump_stack();
+ return result;
+}
+EXPORT_SYMBOL_GPL(toi_get_free_pages);
+ result = alloc_page(mask);
+ if (toi_alloc_ops.enabled)
+ alloc_update_stats(fail_num, (void *) result, PAGE_SIZE);
++ if (fail_num == trace_allocs)
++ dump_stack();
+ return result;
+}
+EXPORT_SYMBOL_GPL(toi_alloc_page);
+{
+ unsigned long result;
+
++ if (fail_num == trace_allocs)
++ dump_stack();
+ if (toi_alloc_ops.enabled)
+ MIGHT_FAIL(fail_num, 0);
+ result = get_zeroed_page(mask);
+ if (toi_alloc_ops.enabled)
+ alloc_update_stats(fail_num, (void *) result, PAGE_SIZE);
++ if (fail_num == trace_allocs)
++ dump_stack();
+ return result;
+}
+EXPORT_SYMBOL_GPL(toi_get_zeroed_page);
+ if (arg && toi_alloc_ops.enabled)
+ free_update_stats(fail_num, size);
+
++ if (fail_num == trace_allocs)
++ dump_stack();
+ kfree(arg);
+}
+EXPORT_SYMBOL_GPL(toi_kfree);
+ if (virt && toi_alloc_ops.enabled)
+ free_update_stats(fail_num, PAGE_SIZE);
+
++ if (fail_num == trace_allocs)
++ dump_stack();
+ free_page(virt);
+}
+EXPORT_SYMBOL_GPL(toi_free_page);
+ if (page && toi_alloc_ops.enabled)
+ free_update_stats(fail_num, PAGE_SIZE);
+
++ if (fail_num == trace_allocs)
++ dump_stack();
+ __free_page(page);
+}
+EXPORT_SYMBOL_GPL(toi__free_page);
+ if (page && toi_alloc_ops.enabled)
+ free_update_stats(fail_num, PAGE_SIZE << order);
+
++ if (fail_num == trace_allocs)
++ dump_stack();
+ __free_pages(page, order);
+}
+
+ atomic_read(&toi_free_count[i])) {
+ if (!header_done) {
+ printk(KERN_INFO "Idx Allocs Frees Tests "
-+ " Fails Max Description\n");
++ " Fails Max Description\n");
+ header_done = 1;
+ }
+
+{
+ int i;
+
-+ if (starting_cycle && toi_alloc_ops.enabled) {
-+ for (i = 0; i < TOI_ALLOC_PATHS; i++) {
-+ atomic_set(&toi_alloc_count[i], 0);
-+ atomic_set(&toi_free_count[i], 0);
-+ atomic_set(&toi_test_count[i], 0);
-+ atomic_set(&toi_fail_count[i], 0);
-+ toi_cur_allocd[i] = 0;
-+ toi_max_allocd[i] = 0;
-+ };
-+ max_allocd = 0;
-+ cur_allocd = 0;
-+ }
++ if (!starting_cycle)
++ return 0;
++
++ for (i = 0; i < TOI_ALLOC_PATHS; i++) {
++ atomic_set(&toi_alloc_count[i], 0);
++ atomic_set(&toi_free_count[i], 0);
++ atomic_set(&toi_test_count[i], 0);
++ atomic_set(&toi_fail_count[i], 0);
++ toi_cur_allocd[i] = 0;
++ toi_max_allocd[i] = 0;
++ };
+
++ max_allocd = 0;
++ cur_allocd = 0;
+ return 0;
+}
+
+static struct toi_sysfs_data sysfs_params[] = {
+ SYSFS_INT("failure_test", SYSFS_RW, &toi_fail_num, 0, 99, 0, NULL),
++ SYSFS_INT("trace", SYSFS_RW, &trace_allocs, 0, TOI_ALLOC_PATHS, 0,
++ NULL),
+ SYSFS_BIT("find_max_mem_allocated", SYSFS_RW, &toi_bkd.toi_action,
+ TOI_GET_MAX_MEM_ALLOCD, 0),
+ SYSFS_INT("enabled", SYSFS_RW, &toi_alloc_ops.enabled, 0, 1, 0,
+int toi_alloc_init(void)
+{
+ int result = toi_register_module(&toi_alloc_ops);
-+ toi_alloc_ops.enabled = 0;
+ return result;
+}
+
+
+int toi_go_atomic(pm_message_t state, int toi_time);
+void toi_end_atomic(int stage, int toi_time, int error);
-diff --git a/kernel/power/tuxonice_block_io.c b/kernel/power/tuxonice_block_io.c
+diff --git a/kernel/power/tuxonice_bio.h b/kernel/power/tuxonice_bio.h
new file mode 100644
-index 0000000..aa7a9cd
+index 0000000..9b770d6
--- /dev/null
-+++ b/kernel/power/tuxonice_block_io.c
-@@ -0,0 +1,1343 @@
++++ b/kernel/power/tuxonice_bio.h
+@@ -0,0 +1,76 @@
+/*
-+ * kernel/power/tuxonice_block_io.c
++ * kernel/power/tuxonice_bio.h
+ *
+ * Copyright (C) 2004-2008 Nigel Cunningham (nigel at tuxonice net)
++ * Copyright (C) 2006 Red Hat, inc.
+ *
+ * Distributed under GPLv2.
+ *
-+ * This file contains block io functions for TuxOnIce. These are
-+ * used by the swapwriter and it is planned that they will also
-+ * be used by the NFSwriter.
-+ *
++ * This file contains declarations for functions exported from
++ * tuxonice_bio.c, which contains low level io functions.
+ */
+
-+#include <linux/blkdev.h>
-+#include <linux/syscalls.h>
-+#include <linux/suspend.h>
++#include <linux/buffer_head.h>
++#include "tuxonice_extent.h"
+
-+#include "tuxonice.h"
-+#include "tuxonice_sysfs.h"
-+#include "tuxonice_modules.h"
-+#include "tuxonice_prepare_image.h"
-+#include "tuxonice_block_io.h"
-+#include "tuxonice_ui.h"
-+#include "tuxonice_alloc.h"
-+#include "tuxonice_io.h"
++void toi_put_extent_chain(struct hibernate_extent_chain *chain);
++int toi_add_to_extent_chain(struct hibernate_extent_chain *chain,
++ unsigned long start, unsigned long end);
+
-+#define MEMORY_ONLY 1
-+#define THROTTLE_WAIT 2
++struct hibernate_extent_saved_state {
++ int extent_num;
++ struct hibernate_extent *extent_ptr;
++ unsigned long offset;
++};
+
-+/* #define MEASURE_MUTEX_CONTENTION */
-+#ifndef MEASURE_MUTEX_CONTENTION
-+#define my_mutex_lock(index, the_lock) mutex_lock(the_lock)
-+#define my_mutex_unlock(index, the_lock) mutex_unlock(the_lock)
-+#else
-+unsigned long mutex_times[2][2][NR_CPUS];
-+#define my_mutex_lock(index, the_lock) do { \
-+ int have_mutex; \
-+ have_mutex = mutex_trylock(the_lock); \
-+ if (!have_mutex) { \
-+ mutex_lock(the_lock); \
-+ mutex_times[index][0][smp_processor_id()]++; \
-+ } else { \
-+ mutex_times[index][1][smp_processor_id()]++; \
-+ }
++struct toi_bdev_info {
++ struct toi_bdev_info *next;
++ struct hibernate_extent_chain blocks;
++ struct block_device *bdev;
++ struct toi_module_ops *allocator;
++ int allocator_index;
++ struct hibernate_extent_chain allocations;
+
-+#define my_mutex_unlock(index, the_lock) \
-+ mutex_unlock(the_lock); \
-+} while (0)
-+#endif
++ /* Saved in header */
++ char uuid[17];
++ dev_t dev_t;
++ int prio;
++ int bmap_shift;
++ int blocks_per_page;
++ struct hibernate_extent_saved_state saved_state[4];
++};
+
-+static int target_outstanding_io = 1024;
-+static int max_outstanding_writes, max_outstanding_reads;
++struct toi_extent_iterate_state {
++ struct toi_bdev_info *current_chain;
++ int num_chains;
++ int saved_chain_number[4];
++ struct toi_bdev_info *saved_chain_ptr[4];
++};
+
-+static struct page *bio_queue_head, *bio_queue_tail;
-+static atomic_t toi_bio_queue_size;
-+static DEFINE_SPINLOCK(bio_queue_lock);
++/*
++ * Our exported interface so the swapwriter and filewriter don't
++ * need these functions duplicated.
++ */
++struct toi_bio_ops {
++ int (*bdev_page_io) (int rw, struct block_device *bdev, long pos,
++ struct page *page);
++ int (*register_storage)(struct toi_bdev_info *new);
++ void (*free_storage)(void);
++};
+
-+static int free_mem_throttle, throughput_throttle;
-+static int more_readahead = 1;
-+static struct page *readahead_list_head, *readahead_list_tail;
++struct toi_allocator_ops {
++ unsigned long (*toi_swap_storage_available) (void);
++};
+
-+static struct page *waiting_on;
++extern struct toi_bio_ops toi_bio_ops;
+
-+static atomic_t toi_io_in_progress, toi_io_done;
-+static DECLARE_WAIT_QUEUE_HEAD(num_in_progress_wait);
++extern char *toi_writer_buffer;
++extern int toi_writer_buffer_posn;
++
++struct toi_bio_allocator_ops {
++ int (*register_storage) (void);
++ unsigned long (*storage_available)(void);
++ int (*allocate_storage) (struct toi_bdev_info *, unsigned long);
++ int (*bmap) (struct toi_bdev_info *);
++ void (*free_storage) (struct toi_bdev_info *);
++};
+diff --git a/kernel/power/tuxonice_bio_chains.c b/kernel/power/tuxonice_bio_chains.c
+new file mode 100644
+index 0000000..daddd65
+--- /dev/null
++++ b/kernel/power/tuxonice_bio_chains.c
+@@ -0,0 +1,961 @@
++/*
++ * kernel/power/tuxonice_bio_devinfo.c
++ *
++ * Copyright (C) 2009 Nigel Cunningham (nigel at tuxonice net)
++ *
++ * Distributed under GPLv2.
++ *
++ */
+
-+static int extra_page_forward;
++#include <linux/mm_types.h>
++#include "tuxonice_bio.h"
++#include "tuxonice_bio_internal.h"
++#include "tuxonice_alloc.h"
++#include "tuxonice_ui.h"
++#include "tuxonice.h"
++#include "tuxonice_io.h"
+
-+static int current_stream;
-+/* 0 = Header, 1 = Pageset1, 2 = Pageset2, 3 = End of PS1 */
-+struct hibernate_extent_iterate_saved_state toi_writer_posn_save[4];
-+EXPORT_SYMBOL_GPL(toi_writer_posn_save);
++static struct toi_bdev_info *prio_chain_head;
++static int num_chains;
+
+/* Pointer to current entry being loaded/saved. */
+struct toi_extent_iterate_state toi_writer_posn;
-+EXPORT_SYMBOL_GPL(toi_writer_posn);
+
-+/* Not static, so that the allocators can setup and complete
-+ * writing the header */
-+char *toi_writer_buffer;
-+EXPORT_SYMBOL_GPL(toi_writer_buffer);
++#define metadata_size (sizeof(struct toi_bdev_info) - \
++ offsetof(struct toi_bdev_info, uuid))
+
-+int toi_writer_buffer_posn;
-+EXPORT_SYMBOL_GPL(toi_writer_buffer_posn);
++/*
++ * After section 0 (header) comes 2 => next_section[0] = 2
++ */
++static int next_section[3] = { 2, 3, 1 };
++
++/**
++ * dump_block_chains - print the contents of the bdev info array.
++ **/
++void dump_block_chains(void)
++{
++ int i = 0;
++ int j;
++ struct toi_bdev_info *cur_chain = prio_chain_head;
+
-+static struct toi_bdev_info *toi_devinfo;
++ while (cur_chain) {
++ struct hibernate_extent *this = cur_chain->blocks.first;
+
-+static DEFINE_MUTEX(toi_bio_mutex);
-+static DEFINE_MUTEX(toi_bio_readahead_mutex);
++ printk(KERN_DEBUG "Chain %d (prio %d):", i, cur_chain->prio);
+
-+static struct task_struct *toi_queue_flusher;
-+static int toi_bio_queue_flush_pages(int dedicated_thread);
++ while (this) {
++ printk(KERN_CONT " [%lu-%lu]%s", this->start,
++ this->end, this->next ? "," : "");
++ this = this->next;
++ }
+
-+#define TOTAL_OUTSTANDING_IO (atomic_read(&toi_io_in_progress) + \
-+ atomic_read(&toi_bio_queue_size))
++ printk("\n");
++ cur_chain = cur_chain->next;
++ }
++
++ printk(KERN_DEBUG "Saved states:\n");
++ for (i = 0; i < 4; i++) {
++ printk(KERN_DEBUG "Slot %d: Chain %d.\n",
++ i, toi_writer_posn.saved_chain_number[i]);
++
++ cur_chain = prio_chain_head;
++ j = 0;
++ while (cur_chain) {
++ printk(KERN_DEBUG " Chain %d: Extent %d. Offset %lu.\n",
++ j, cur_chain->saved_state[i].extent_num,
++ cur_chain->saved_state[i].offset);
++ cur_chain = cur_chain->next;
++ j++;
++ }
++ printk(KERN_CONT "\n");
++ }
++}
+
+/**
-+ * set_free_mem_throttle - set the point where we pause to avoid oom.
+ *
-+ * Initially, this value is zero, but when we first fail to allocate memory,
-+ * we set it (plus a buffer) and thereafter throttle i/o once that limit is
-+ * reached.
+ **/
-+static void set_free_mem_throttle(void)
++static void toi_extent_chain_next(void)
+{
-+ int new_throttle = nr_unallocated_buffer_pages() + 256;
++ struct toi_bdev_info *this = toi_writer_posn.current_chain;
+
-+ if (new_throttle > free_mem_throttle)
-+ free_mem_throttle = new_throttle;
-+}
++ if (!this->blocks.current_extent)
++ return;
+
-+#define NUM_REASONS 7
-+static atomic_t reasons[NUM_REASONS];
-+static char *reason_name[NUM_REASONS] = {
-+ "readahead not ready",
-+ "bio allocation",
-+ "synchronous I/O",
-+ "toi_bio_get_new_page",
-+ "memory low",
-+ "readahead buffer allocation",
-+ "throughput_throttle",
-+};
++ if (this->blocks.current_offset == this->blocks.current_extent->end) {
++ if (this->blocks.current_extent->next) {
++ this->blocks.current_extent =
++ this->blocks.current_extent->next;
++ this->blocks.current_offset =
++ this->blocks.current_extent->start;
++ } else {
++ this->blocks.current_extent = NULL;
++ this->blocks.current_offset = 0;
++ }
++ } else
++ this->blocks.current_offset++;
++}
+
+/**
-+ * do_bio_wait - wait for some TuxOnIce I/O to complete
-+ * @reason: The array index of the reason we're waiting.
-+ *
-+ * Wait for a particular page of I/O if we're after a particular page.
-+ * If we're not after a particular page, wait instead for all in flight
-+ * I/O to be completed or for us to have enough free memory to be able
-+ * to submit more I/O.
+ *
-+ * If we wait, we also update our statistics regarding why we waited.
-+ **/
-+static void do_bio_wait(int reason)
++ */
++
++static struct toi_bdev_info *__find_next_chain_same_prio(void)
+{
-+ struct page *was_waiting_on = waiting_on;
++ struct toi_bdev_info *start_chain = toi_writer_posn.current_chain;
++ struct toi_bdev_info *this = start_chain;
++ int orig_prio = this->prio;
+
-+ /* On SMP, waiting_on can be reset, so we make a copy */
-+ if (was_waiting_on) {
-+ if (PageLocked(was_waiting_on)) {
-+ wait_on_page_bit(was_waiting_on, PG_locked);
-+ atomic_inc(&reasons[reason]);
-+ }
-+ } else {
-+ atomic_inc(&reasons[reason]);
++ do {
++ this = this->next;
+
-+ wait_event(num_in_progress_wait,
-+ !atomic_read(&toi_io_in_progress) ||
-+ nr_unallocated_buffer_pages() > free_mem_throttle);
-+ }
++ if (!this)
++ this = prio_chain_head;
++
++ /* Back on original chain? Use it again. */
++ if (this == start_chain)
++ return start_chain;
++
++ } while (!this->blocks.current_extent || this->prio != orig_prio);
++
++ return this;
+}
+
-+/**
-+ * throttle_if_needed - wait for I/O completion if throttle points are reached
-+ * @flags: What to check and how to act.
-+ *
-+ * Check whether we need to wait for some I/O to complete. We always check
-+ * whether we have enough memory available, but may also (depending upon
-+ * @reason) check if the throughput throttle limit has been reached.
-+ **/
-+static int throttle_if_needed(int flags)
++static void find_next_chain(void)
+{
-+ int free_pages = nr_unallocated_buffer_pages();
++ struct toi_bdev_info *this;
+
-+ /* Getting low on memory and I/O is in progress? */
-+ while (unlikely(free_pages < free_mem_throttle) &&
-+ atomic_read(&toi_io_in_progress)) {
-+ if (!(flags & THROTTLE_WAIT))
-+ return -ENOMEM;
-+ do_bio_wait(4);
-+ free_pages = nr_unallocated_buffer_pages();
-+ }
++ this = __find_next_chain_same_prio();
+
-+ while (!(flags & MEMORY_ONLY) && throughput_throttle &&
-+ TOTAL_OUTSTANDING_IO >= throughput_throttle) {
-+ int result = toi_bio_queue_flush_pages(0);
-+ if (result)
-+ return result;
-+ atomic_inc(&reasons[6]);
-+ wait_event(num_in_progress_wait,
-+ !atomic_read(&toi_io_in_progress) ||
-+ TOTAL_OUTSTANDING_IO < throughput_throttle);
-+ }
++ /*
++ * If we didn't get another chain of the same priority that we
++ * can use, look for the next priority.
++ */
++ while (this && !this->blocks.current_extent)
++ this = this->next;
+
-+ return 0;
++ toi_writer_posn.current_chain = this;
+}
+
+/**
-+ * update_throughput_throttle - update the raw throughput throttle
-+ * @jif_index: The number of times this function has been called.
-+ *
-+ * This function is called twice per second by the core, and used to limit the
-+ * amount of I/O we submit at once, spreading out our waiting through the
-+ * whole job and letting userui get an opportunity to do its work.
++ * toi_extent_state_next - go to the next extent
++ * @blocks: The number of values to progress.
++ * @stripe_mode: Whether to spread usage across all chains.
+ *
-+ * We don't start limiting I/O until 1/2s has gone so that we get a
-+ * decent sample for our initial limit, and keep updating it because
-+ * throughput may vary (on rotating media, eg) with our block number.
++ * Given a state, progress to the next valid entry. We may begin in an
++ * invalid state, as we do when invoked after extent_state_goto_start below.
+ *
-+ * We throttle to 1/10s worth of I/O.
++ * When using compression and expected_compression > 0, we let the image size
++ * be larger than storage, so we can validly run out of data to return.
+ **/
-+static void update_throughput_throttle(int jif_index)
++static unsigned long toi_extent_state_next(int blocks, int current_stream)
+{
-+ int done = atomic_read(&toi_io_done);
-+ throughput_throttle = done / jif_index / 5;
++ int i;
++
++ if (!toi_writer_posn.current_chain)
++ return -ENODATA;
++
++ /* Assume chains always have lengths that are multiples of @blocks */
++ for (i = 0; i < blocks; i++)
++ toi_extent_chain_next();
++
++ /* The header stream is not striped */
++ if (current_stream ||
++ !toi_writer_posn.current_chain->blocks.current_extent)
++ find_next_chain();
++
++ return toi_writer_posn.current_chain ? 0 : -ENODATA;
++}
++
++static void toi_insert_chain_in_prio_list(struct toi_bdev_info *this)
++{
++ struct toi_bdev_info **prev_ptr;
++ struct toi_bdev_info *cur;
++
++ /* Loop through the existing chain, finding where to insert it */
++ prev_ptr = &prio_chain_head;
++ cur = prio_chain_head;
++
++ while (cur && cur->prio >= this->prio) {
++ prev_ptr = &cur->next;
++ cur = cur->next;
++ }
++
++ this->next = *prev_ptr;
++ *prev_ptr = this;
++
++ this = prio_chain_head;
++ while (this)
++ this = this->next;
++ num_chains++;
+}
+
+/**
-+ * toi_finish_all_io - wait for all outstanding i/o to complete
-+ *
-+ * Flush any queued but unsubmitted I/O and wait for it all to complete.
++ * toi_extent_state_goto_start - reinitialize an extent chain iterator
++ * @state: Iterator to reinitialize
+ **/
-+static int toi_finish_all_io(void)
++void toi_extent_state_goto_start(void)
+{
-+ int result = toi_bio_queue_flush_pages(0);
-+ wait_event(num_in_progress_wait, !TOTAL_OUTSTANDING_IO);
-+ return result;
++ struct toi_bdev_info *this = prio_chain_head;
++
++ while (this) {
++ toi_message(TOI_IO, TOI_VERBOSE, 0,
++ "Setting current extent to %p.", this->blocks.first);
++ this->blocks.current_extent = this->blocks.first;
++ if (this->blocks.current_extent) {
++ toi_message(TOI_IO, TOI_VERBOSE, 0,
++ "Setting current offset to %lu.",
++ this->blocks.current_extent->start);
++ this->blocks.current_offset =
++ this->blocks.current_extent->start;
++ }
++
++ this = this->next;
++ }
++
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Setting current chain to %p.",
++ prio_chain_head);
++ toi_writer_posn.current_chain = prio_chain_head;
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Leaving extent state goto start.");
+}
+
+/**
-+ * toi_end_bio - bio completion function.
-+ * @bio: bio that has completed.
-+ * @err: Error value. Yes, like end_swap_bio_read, we ignore it.
++ * toi_extent_state_save - save state of the iterator
++ * @state: Current state of the chain
++ * @saved_state: Iterator to populate
+ *
-+ * Function called by the block driver from interrupt context when I/O is
-+ * completed. If we were writing the page, we want to free it and will have
-+ * set bio->bi_private to the parameter we should use in telling the page
-+ * allocation accounting code what the page was allocated for. If we're
-+ * reading the page, it will be in the singly linked list made from
-+ * page->private pointers.
++ * Given a state and a struct hibernate_extent_state_store, save the current
++ * position in a format that can be used with relocated chains (at
++ * resume time).
+ **/
-+static void toi_end_bio(struct bio *bio, int err)
++void toi_extent_state_save(int slot)
+{
-+ struct page *page = bio->bi_io_vec[0].bv_page;
++ struct toi_bdev_info *cur_chain = prio_chain_head;
++ struct hibernate_extent *extent;
++ struct hibernate_extent_saved_state *chain_state;
++ int i = 0;
+
-+ BUG_ON(!test_bit(BIO_UPTODATE, &bio->bi_flags));
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "toi_extent_state_save, slot %d.",
++ slot);
+
-+ unlock_page(page);
-+ bio_put(bio);
++ if (!toi_writer_posn.current_chain) {
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "No current chain => "
++ "chain_num = -1.");
++ toi_writer_posn.saved_chain_number[slot] = -1;
++ return;
++ }
+
-+ if (waiting_on == page)
-+ waiting_on = NULL;
++ while (cur_chain) {
++ i++;
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Saving chain %d (%p) "
++ "state, slot %d.", i, cur_chain, slot);
+
-+ put_page(page);
++ chain_state = &cur_chain->saved_state[slot];
+
-+ if (bio->bi_private)
-+ toi__free_page((int) ((unsigned long) bio->bi_private) , page);
++ chain_state->offset = cur_chain->blocks.current_offset;
+
-+ bio_put(bio);
++ if (toi_writer_posn.current_chain == cur_chain) {
++ toi_writer_posn.saved_chain_number[slot] = i;
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "This is the chain "
++ "we were on => chain_num is %d.", i);
++ }
+
-+ atomic_dec(&toi_io_in_progress);
-+ atomic_inc(&toi_io_done);
++ if (!cur_chain->blocks.current_extent) {
++ chain_state->extent_num = 0;
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "No current extent "
++ "for this chain => extent_num %d is 0.",
++ i);
++ cur_chain = cur_chain->next;
++ continue;
++ }
+
-+ wake_up(&num_in_progress_wait);
++ extent = cur_chain->blocks.first;
++ chain_state->extent_num = 1;
++
++ while (extent != cur_chain->blocks.current_extent) {
++ chain_state->extent_num++;
++ extent = extent->next;
++ }
++
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "extent num %d is %d.", i,
++ chain_state->extent_num);
++
++ cur_chain = cur_chain->next;
++ }
++ toi_message(TOI_IO, TOI_VERBOSE, 0,
++ "Completed saving extent state slot %d.", slot);
+}
+
+/**
-+ * submit - submit BIO request
-+ * @writing: READ or WRITE.
-+ * @dev: The block device we're using.
-+ * @first_block: The first sector we're using.
-+ * @page: The page being used for I/O.
-+ * @free_group: If writing, the group that was used in allocating the page
-+ * and which will be used in freeing the page from the completion
-+ * routine.
-+ *
-+ * Based on Patrick Mochell's pmdisk code from long ago: "Straight from the
-+ * textbook - allocate and initialize the bio. If we're writing, make sure
-+ * the page is marked as dirty. Then submit it and carry on."
-+ *
-+ * If we're just testing the speed of our own code, we fake having done all
-+ * the hard work and all toi_end_bio immediately.
++ * toi_extent_state_restore - restore the position saved by extent_state_save
++ * @state: State to populate
++ * @saved_state: Iterator saved to restore
+ **/
-+static int submit(int writing, struct block_device *dev, sector_t first_block,
-+ struct page *page, int free_group)
++void toi_extent_state_restore(int slot)
+{
-+ struct bio *bio = NULL;
-+ int cur_outstanding_io, result;
++ int i = 0;
++ struct toi_bdev_info *cur_chain = prio_chain_head;
++ struct hibernate_extent_saved_state *chain_state;
+
-+ /*
-+ * Shouldn't throttle if reading - can deadlock in the single
-+ * threaded case as pages are only freed when we use the
-+ * readahead.
-+ */
-+ if (writing) {
-+ result = throttle_if_needed(MEMORY_ONLY | THROTTLE_WAIT);
-+ if (result)
-+ return result;
-+ }
++ toi_message(TOI_IO, TOI_VERBOSE, 0,
++ "toi_extent_state_restore - slot %d.", slot);
+
-+ while (!bio) {
-+ bio = bio_alloc(TOI_ATOMIC_GFP, 1);
-+ if (!bio) {
-+ set_free_mem_throttle();
-+ do_bio_wait(1);
-+ }
++ if (toi_writer_posn.saved_chain_number[slot] == -1) {
++ toi_writer_posn.current_chain = NULL;
++ return;
+ }
+
-+ bio->bi_bdev = dev;
-+ bio->bi_sector = first_block;
-+ bio->bi_private = (void *) ((unsigned long) free_group);
-+ bio->bi_end_io = toi_end_bio;
++ while (cur_chain) {
++ int posn;
++ int j;
++ i++;
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Restoring chain %d (%p) "
++ "state, slot %d.", i, cur_chain, slot);
+
-+ if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
-+ printk(KERN_DEBUG "ERROR: adding page to bio at %lld\n",
-+ (unsigned long long) first_block);
-+ bio_put(bio);
-+ return -EFAULT;
-+ }
++ chain_state = &cur_chain->saved_state[slot];
+
-+ bio_get(bio);
++ posn = chain_state->extent_num;
+
-+ cur_outstanding_io = atomic_add_return(1, &toi_io_in_progress);
-+ if (writing) {
-+ if (cur_outstanding_io > max_outstanding_writes)
-+ max_outstanding_writes = cur_outstanding_io;
-+ } else {
-+ if (cur_outstanding_io > max_outstanding_reads)
-+ max_outstanding_reads = cur_outstanding_io;
-+ }
++ cur_chain->blocks.current_extent = cur_chain->blocks.first;
++ cur_chain->blocks.current_offset = chain_state->offset;
+
++ if (i == toi_writer_posn.saved_chain_number[slot]) {
++ toi_writer_posn.current_chain = cur_chain;
++ toi_message(TOI_IO, TOI_VERBOSE, 0,
++ "Found current chain.");
++ }
+
-+ if (unlikely(test_action_state(TOI_TEST_FILTER_SPEED))) {
-+ /* Fake having done the hard work */
-+ set_bit(BIO_UPTODATE, &bio->bi_flags);
-+ toi_end_bio(bio, 0);
-+ } else
-+ submit_bio(writing | (1 << BIO_RW_SYNCIO) |
-+ (1 << BIO_RW_UNPLUG), bio);
++ for (j = 0; j < 4; j++)
++ if (i == toi_writer_posn.saved_chain_number[j]) {
++ toi_writer_posn.saved_chain_ptr[j] = cur_chain;
++ toi_message(TOI_IO, TOI_VERBOSE, 0,
++ "Found saved chain ptr %d (%p) (offset"
++ " %d).", j, cur_chain,
++ cur_chain->saved_state[j].offset);
++ }
+
-+ return 0;
++ if (posn) {
++ while (--posn)
++ cur_chain->blocks.current_extent =
++ cur_chain->blocks.current_extent->next;
++ } else
++ cur_chain->blocks.current_extent = NULL;
++
++ cur_chain = cur_chain->next;
++ }
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Done.");
++ if (test_action_state(TOI_LOGALL))
++ dump_block_chains();
+}
+
-+/**
-+ * toi_do_io: Prepare to do some i/o on a page and submit or batch it.
-+ *
-+ * @writing: Whether reading or writing.
-+ * @bdev: The block device which we're using.
-+ * @block0: The first sector we're reading or writing.
-+ * @page: The page on which I/O is being done.
-+ * @readahead_index: If doing readahead, the index (reset this flag when done).
-+ * @syncio: Whether the i/o is being done synchronously.
-+ *
-+ * Prepare and start a read or write operation.
++/*
++ * Storage needed
+ *
-+ * Note that we always work with our own page. If writing, we might be given a
-+ * compression buffer that will immediately be used to start compressing the
-+ * next page. For reading, we do readahead and therefore don't know the final
-+ * address where the data needs to go.
-+ **/
-+static int toi_do_io(int writing, struct block_device *bdev, long block0,
-+ struct page *page, int is_readahead, int syncio, int free_group)
++ * Returns amount of space in the image header required
++ * for the chain data. This ignores the links between
++ * pages, which we factor in when allocating the space.
++ */
++int toi_bio_devinfo_storage_needed(void)
+{
-+ page->private = 0;
-+
-+ /* Do here so we don't race against toi_bio_get_next_page_read */
-+ lock_page(page);
-+
-+ if (is_readahead) {
-+ if (readahead_list_head)
-+ readahead_list_tail->private = (unsigned long) page;
-+ else
-+ readahead_list_head = page;
-+
-+ readahead_list_tail = page;
-+ }
-+
-+ /* Done before submitting to avoid races. */
-+ if (syncio)
-+ waiting_on = page;
++ int result = sizeof(num_chains);
++ struct toi_bdev_info *chain = prio_chain_head;
+
-+ /* Submit the page */
-+ get_page(page);
++ while (chain) {
++ result += metadata_size;
+
-+ if (submit(writing, bdev, block0, page, free_group))
-+ return -EFAULT;
++ /* Chain size */
++ result += sizeof(int);
+
-+ if (syncio)
-+ do_bio_wait(2);
++ /* Extents */
++ result += (2 * sizeof(unsigned long) *
++ chain->blocks.num_extents);
+
-+ return 0;
-+}
++ chain = chain->next;
++ }
+
-+/**
-+ * toi_bdev_page_io - simpler interface to do directly i/o on a single page
-+ * @writing: Whether reading or writing.
-+ * @bdev: Block device on which we're operating.
-+ * @pos: Sector at which page to read or write starts.
-+ * @page: Page to be read/written.
-+ *
-+ * A simple interface to submit a page of I/O and wait for its completion.
-+ * The caller must free the page used.
-+ **/
-+static int toi_bdev_page_io(int writing, struct block_device *bdev,
-+ long pos, struct page *page)
-+{
-+ return toi_do_io(writing, bdev, pos, page, 0, 1, 0);
++ result += 4 * sizeof(int);
++ return result;
+}
+
+/**
-+ * toi_bio_memory_needed - report the amount of memory needed for block i/o
-+ *
-+ * We want to have at least enough memory so as to have target_outstanding_io
-+ * or more transactions on the fly at once. If we can do more, fine.
++ * toi_serialise_extent_chain - write a chain in the image
++ * @chain: Chain to write.
+ **/
-+static int toi_bio_memory_needed(void)
++static int toi_serialise_extent_chain(struct toi_bdev_info *chain)
+{
-+ return target_outstanding_io * (PAGE_SIZE + sizeof(struct request) +
-+ sizeof(struct bio));
-+}
++ struct hibernate_extent *this;
++ int ret;
++ int i = 1;
+
-+/**
-+ * toi_bio_print_debug_stats - put out debugging info in the buffer provided
-+ * @buffer: A buffer of size @size into which text should be placed.
-+ * @size: The size of @buffer.
-+ *
-+ * Fill a buffer with debugging info. This is used for both our debug_info sysfs
-+ * entry and for recording the same info in dmesg.
-+ **/
-+static int toi_bio_print_debug_stats(char *buffer, int size)
-+{
-+ int len = scnprintf(buffer, size, "- Max outstanding reads %d. Max "
-+ "writes %d.\n", max_outstanding_reads,
-+ max_outstanding_writes);
++ if (test_action_state(TOI_LOGALL))
++ dump_block_chains();
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Serialising chain (dev_t %lx).",
++ chain->dev_t);
++ /* Device info - dev_t, prio, bmap_shift, blocks per page, positions */
++ ret = toiActiveAllocator->rw_header_chunk(WRITE, &toi_blockwriter_ops,
++ (char *) &chain->uuid, metadata_size);
++ if (ret)
++ return ret;
+
-+ len += scnprintf(buffer + len, size - len,
-+ " Memory_needed: %d x (%lu + %u + %u) = %d bytes.\n",
-+ target_outstanding_io,
-+ PAGE_SIZE, (unsigned int) sizeof(struct request),
-+ (unsigned int) sizeof(struct bio), toi_bio_memory_needed());
++ /* Num extents */
++ ret = toiActiveAllocator->rw_header_chunk(WRITE, &toi_blockwriter_ops,
++ (char *) &chain->blocks.num_extents, sizeof(int));
++ if (ret)
++ return ret;
+
-+#ifdef MEASURE_MUTEX_CONTENTION
-+ {
-+ int i;
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "%d extents.",
++ chain->blocks.num_extents);
+
-+ len += scnprintf(buffer + len, size - len,
-+ " Mutex contention while reading:\n Contended Free\n");
++ this = chain->blocks.first;
++ while (this) {
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Extent %d.", i);
++ ret = toiActiveAllocator->rw_header_chunk(WRITE,
++ &toi_blockwriter_ops,
++ (char *) this, 2 * sizeof(this->start));
++ if (ret)
++ return ret;
++ this = this->next;
++ i++;
++ }
+
-+ for_each_online_cpu(i)
-+ len += scnprintf(buffer + len, size - len,
-+ " %9lu %9lu\n",
-+ mutex_times[0][0][i], mutex_times[0][1][i]);
++ return ret;
++}
+
-+ len += scnprintf(buffer + len, size - len,
-+ " Mutex contention while writing:\n Contended Free\n");
++int toi_serialise_extent_chains(void)
++{
++ struct toi_bdev_info *this = prio_chain_head;
++ int result;
+
-+ for_each_online_cpu(i)
-+ len += scnprintf(buffer + len, size - len,
-+ " %9lu %9lu\n",
-+ mutex_times[1][0][i], mutex_times[1][1][i]);
++ /* Write the number of chains */
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Write number of chains (%d)",
++ num_chains);
++ result = toiActiveAllocator->rw_header_chunk(WRITE,
++ &toi_blockwriter_ops, (char *) &num_chains,
++ sizeof(int));
++ if (result)
++ return result;
+
++ /* Then the chains themselves */
++ while (this) {
++ result = toi_serialise_extent_chain(this);
++ if (result)
++ return result;
++ this = this->next;
+ }
-+#endif
+
-+ return len + scnprintf(buffer + len, size - len,
-+ " Free mem throttle point reached %d.\n", free_mem_throttle);
++ /*
++ * Finally, the chain we should be on at the start of each
++ * section.
++ */
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Saved chain numbers.");
++ result = toiActiveAllocator->rw_header_chunk(WRITE,
++ &toi_blockwriter_ops,
++ (char *) &toi_writer_posn.saved_chain_number[0],
++ 4 * sizeof(int));
++
++ return result;
+}
+
-+/**
-+ * toi_set_devinfo - set the bdev info used for i/o
-+ * @info: Pointer to an array of struct toi_bdev_info - the list of
-+ * bdevs and blocks on them in which the image is stored.
-+ *
-+ * Set the list of bdevs and blocks in which the image will be stored.
-+ * Think of them (all together) as one long tape on which the data will be
-+ * stored.
-+ **/
-+static void toi_set_devinfo(struct toi_bdev_info *info)
++int toi_register_storage_chain(struct toi_bdev_info *new)
+{
-+ toi_devinfo = info;
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Inserting chain %p into list.",
++ new);
++ toi_insert_chain_in_prio_list(new);
++ return 0;
+}
+
-+/**
-+ * dump_block_chains - print the contents of the bdev info array.
-+ **/
-+static void dump_block_chains(void)
++static void free_bdev_info(struct toi_bdev_info *chain)
+{
-+ int i;
-+
-+ for (i = 0; i < toi_writer_posn.num_chains; i++) {
-+ struct hibernate_extent *this;
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Free chain %p.", chain);
+
-+ this = (toi_writer_posn.chains + i)->first;
++ toi_message(TOI_IO, TOI_VERBOSE, 0, " - Block extents.");
++ toi_put_extent_chain(&chain->blocks);
+
-+ if (!this)
-+ continue;
++ /*
++ * The allocator may need to do more than just free the chains
++ * (swap_free, for example).
++ */
++ toi_message(TOI_IO, TOI_VERBOSE, 0, " - Allocator extents.");
++ chain->allocator->bio_allocator_ops->free_storage(chain);
+
-+ printk(KERN_DEBUG "Chain %d:", i);
++ /*
++ * Dropping out of reading atomic copy? Need to undo
++ * toi_open_by_devnum.
++ */
++ toi_message(TOI_IO, TOI_VERBOSE, 0, " - Bdev.");
++ if (chain->bdev && !IS_ERR(chain->bdev) &&
++ chain->bdev != resume_block_device &&
++ chain->bdev != header_block_device &&
++ test_toi_state(TOI_TRYING_TO_RESUME))
++ toi_close_bdev(chain->bdev);
+
-+ while (this) {
-+ printk(" [%lu-%lu]%s", this->start,
-+ this->end, this->next ? "," : "");
-+ this = this->next;
-+ }
++ /* Poison */
++ toi_message(TOI_IO, TOI_VERBOSE, 0, " - Struct.");
++ toi_kfree(39, chain, sizeof(*chain));
+
-+ printk("\n");
-+ }
++ if (prio_chain_head == chain)
++ prio_chain_head = NULL;
+
-+ for (i = 0; i < 4; i++)
-+ printk(KERN_DEBUG "Posn %d: Chain %d, extent %d, offset %lu.\n",
-+ i, toi_writer_posn_save[i].chain_num,
-+ toi_writer_posn_save[i].extent_num,
-+ toi_writer_posn_save[i].offset);
++ num_chains--;
+}
+
-+static int total_header_bytes;
-+static int unowned;
-+
-+static int debug_broken_header(void)
++void free_all_bdev_info(void)
+{
-+ printk(KERN_DEBUG "Image header too big for size allocated!\n");
-+ print_toi_header_storage_for_modules();
-+ printk(KERN_DEBUG "Page flags : %d.\n", toi_pageflags_space_needed());
-+ printk(KERN_DEBUG "toi_header : %ld.\n", sizeof(struct toi_header));
-+ printk(KERN_DEBUG "Total unowned : %d.\n", unowned);
-+ printk(KERN_DEBUG "Total used : %d (%ld pages).\n", total_header_bytes,
-+ DIV_ROUND_UP(total_header_bytes, PAGE_SIZE));
-+ printk(KERN_DEBUG "Space needed now : %ld.\n",
-+ get_header_storage_needed());
-+ dump_block_chains();
-+ abort_hibernate(TOI_HEADER_TOO_BIG, "Header reservation too small.");
-+ return -EIO;
++ struct toi_bdev_info *this = prio_chain_head;
++
++ while (this) {
++ struct toi_bdev_info *next = this->next;
++ free_bdev_info(this);
++ this = next;
++ }
++
++ memset((char *) &toi_writer_posn, 0, sizeof(toi_writer_posn));
++ prio_chain_head = NULL;
+}
+
+/**
-+ * go_next_page - skip blocks to the start of the next page
-+ * @writing: Whether we're reading or writing the image.
++ * toi_load_extent_chain - read back a chain saved in the image
++ * @chain: Chain to load
+ *
-+ * Go forward one page, or two if extra_page_forward is set. It only gets
-+ * set at the start of reading the image header, to skip the first page
-+ * of the header, which is read without using the extent chains.
++ * The linked list of extents is reconstructed from the disk. chain will point
++ * to the first entry.
+ **/
-+static int go_next_page(int writing, int section_barrier)
++int toi_load_extent_chain(int index)
+{
-+ int i, chain_num = toi_writer_posn.current_chain,
-+ max = (chain_num == -1) ? 1 : toi_devinfo[chain_num].blocks_per_page,
-+ compare_to = 0, compare_chain, compare_offset;
-+
-+ /* Have we already used the last page of the stream? */
-+ switch (current_stream) {
-+ case 0:
-+ compare_to = 2;
-+ break;
-+ case 1:
-+ compare_to = 3;
-+ break;
-+ case 2:
-+ compare_to = 1;
-+ break;
-+ }
++ struct toi_bdev_info *chain = toi_kzalloc(39,
++ sizeof(struct toi_bdev_info), GFP_ATOMIC);
++ struct hibernate_extent *this, *last = NULL;
++ int i, ret;
+
-+ compare_chain = toi_writer_posn_save[compare_to].chain_num;
-+ compare_offset = toi_writer_posn_save[compare_to].offset;
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Loading extent chain %d.", index);
++ /* Get dev_t, prio, bmap_shift, blocks per page, positions */
++ ret = toiActiveAllocator->rw_header_chunk_noreadahead(READ, NULL,
++ (char *) &chain->uuid, metadata_size);
+
-+ if (section_barrier && chain_num == compare_chain &&
-+ toi_writer_posn.current_offset == compare_offset) {
-+ if (writing) {
-+ if (!current_stream)
-+ return debug_broken_header();
++ if (ret) {
++ printk(KERN_ERR "Failed to read the size of extent chain.\n");
++ toi_kfree(39, chain, sizeof(*chain));
++ return 1;
++ }
++
++ ret = toiActiveAllocator->rw_header_chunk_noreadahead(READ, NULL,
++ (char *) &chain->blocks.num_extents, sizeof(int));
++ if (ret) {
++ printk(KERN_ERR "Failed to read the size of extent chain.\n");
++ toi_kfree(39, chain, sizeof(*chain));
++ return 1;
++ }
++
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "%d extents.",
++ chain->blocks.num_extents);
++
++ for (i = 0; i < chain->blocks.num_extents; i++) {
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Extent %d.", i + 1);
++
++ this = toi_kzalloc(2, sizeof(struct hibernate_extent),
++ TOI_ATOMIC_GFP);
++ if (!this) {
++ printk(KERN_INFO "Failed to allocate a new extent.\n");
++ free_bdev_info(chain);
++ return -ENOMEM;
++ }
++ this->next = NULL;
++ /* Get the next page */
++ ret = toiActiveAllocator->rw_header_chunk_noreadahead(READ,
++ NULL, (char *) this, 2 * sizeof(this->start));
++ if (ret) {
++ printk(KERN_INFO "Failed to read an extent.\n");
++ toi_kfree(2, this, sizeof(struct hibernate_extent));
++ free_bdev_info(chain);
++ return 1;
++ }
++
++ if (last)
++ last->next = this;
++ else {
++ char b1[32], b2[32], b3[32];
++ /*
++ * Open the bdev
++ */
++ toi_message(TOI_IO, TOI_VERBOSE, 0,
++ "Chain dev_t is %s. Resume dev t is %s. Header"
++ " bdev_t is %s.\n",
++ format_dev_t(b1, chain->dev_t),
++ format_dev_t(b2, resume_dev_t),
++ format_dev_t(b3, toi_sig_data->header_dev_t));
++
++ if (chain->dev_t == resume_dev_t)
++ chain->bdev = resume_block_device;
++ else if (chain->dev_t == toi_sig_data->header_dev_t)
++ chain->bdev = header_block_device;
++ else {
++ chain->bdev = toi_open_bdev(chain->uuid,
++ chain->dev_t, 1);
++ if (IS_ERR(chain->bdev)) {
++ free_bdev_info(chain);
++ return -ENODEV;
++ }
++ }
++
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Chain bmap shift "
++ "is %d and blocks per page is %d.",
++ chain->bmap_shift,
++ chain->blocks_per_page);
++
++ chain->blocks.first = this;
++
++ /*
++ * Couldn't do this earlier, but can't do
++ * goto_start now - we may have already used blocks
++ * in the first chain.
++ */
++ chain->blocks.current_extent = this;
++ chain->blocks.current_offset = this->start;
++
++ /*
++ * Can't wait until we've read the whole chain
++ * before we insert it in the list. We might need
++ * this chain to read the next page in the header
++ */
++ toi_insert_chain_in_prio_list(chain);
++ if (!index) {
++ toi_writer_posn.current_chain = prio_chain_head;
++ go_next_page(0, 0);
++ }
++ }
++ last = this;
++ }
++
++ /*
++ * Shouldn't get empty chains, but it's not impossible. Link them in so
++ * they get freed properly later.
++ */
++ if (!chain->blocks.num_extents)
++ toi_insert_chain_in_prio_list(chain);
++
++ if (!chain->blocks.current_extent) {
++ chain->blocks.current_extent = chain->blocks.first;
++ if (chain->blocks.current_extent)
++ chain->blocks.current_offset =
++ chain->blocks.current_extent->start;
++ }
++ return 0;
++}
++
++int toi_load_extent_chains(void)
++{
++ int result;
++ int to_load;
++ int i;
++
++ result = toiActiveAllocator->rw_header_chunk_noreadahead(READ, NULL,
++ (char *) &to_load,
++ sizeof(int));
++ if (result)
++ return result;
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "%d chains to read.", to_load);
++
++ for (i = 0; i < to_load; i++) {
++ toi_message(TOI_IO, TOI_VERBOSE, 0, " >> Loading chain %d/%d.",
++ i, to_load);
++ result = toi_load_extent_chain(i);
++ if (result)
++ return result;
++ }
++
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Save chain numbers.");
++ result = toiActiveAllocator->rw_header_chunk_noreadahead(READ,
++ &toi_blockwriter_ops,
++ (char *) &toi_writer_posn.saved_chain_number[0],
++ 4 * sizeof(int));
++
++ return result;
++}
++
++static int toi_end_of_stream(int writing, int section_barrier)
++{
++ struct toi_bdev_info *cur_chain = toi_writer_posn.current_chain;
++ int compare_to = next_section[current_stream];
++ struct toi_bdev_info *compare_chain =
++ toi_writer_posn.saved_chain_ptr[compare_to];
++ int compare_offset = compare_chain ?
++ compare_chain->saved_state[compare_to].offset : 0;
++
++ if (!section_barrier)
++ return 0;
++
++ if (!cur_chain)
++ return 1;
++
++ if (cur_chain == compare_chain &&
++ cur_chain->blocks.current_offset == compare_offset) {
++ if (writing) {
++ if (!current_stream) {
++ debug_broken_header();
++ return 1;
++ }
+ } else {
+ more_readahead = 0;
-+ return -ENODATA;
++ toi_message(TOI_IO, TOI_VERBOSE, 0,
++ "Reached the end of stream %d "
++ "(not an error).", current_stream);
++ return 1;
+ }
+ }
+
-+ /* Nope. Go foward a page - or maybe two */
-+ for (i = 0; i < max; i++)
-+ toi_extent_state_next(&toi_writer_posn);
++ return 0;
++}
++
++/**
++ * go_next_page - skip blocks to the start of the next page
++ * @writing: Whether we're reading or writing the image.
++ *
++ * Go forward one page.
++ **/
++int go_next_page(int writing, int section_barrier)
++{
++ struct toi_bdev_info *cur_chain = toi_writer_posn.current_chain;
++ int max = cur_chain ? cur_chain->blocks_per_page : 1;
+
-+ if (toi_extent_state_eof(&toi_writer_posn)) {
++ /* Nope. Go foward a page - or maybe two. Don't stripe the header,
++ * so that bad fragmentation doesn't put the extent data containing
++ * the location of the second page out of the first header page.
++ */
++ if (toi_extent_state_next(max, current_stream)) {
+ /* Don't complain if readahead falls off the end */
+ if (writing && section_barrier) {
-+ printk(KERN_DEBUG "Extent state eof. "
-+ "Expected compression ratio too optimistic?\n");
-+ dump_block_chains();
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Extent state eof. "
++ "Expected compression ratio too optimistic?");
++ if (test_action_state(TOI_LOGALL))
++ dump_block_chains();
+ }
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Ran out of extents to "
++ "read/write. (Not necessarily a fatal error.");
+ return -ENODATA;
+ }
+
-+ if (extra_page_forward) {
-+ extra_page_forward = 0;
-+ return go_next_page(writing, section_barrier);
-+ }
-+
+ return 0;
+}
+
-+/**
-+ * set_extra_page_forward - make us skip an extra page on next go_next_page
-+ *
-+ * Used in reading header, to jump to 2nd page after getting 1st page
-+ * direct from image header.
-+ **/
-+static void set_extra_page_forward(void)
++int devices_of_same_priority(struct toi_bdev_info *this)
+{
-+ extra_page_forward = 1;
++ struct toi_bdev_info *check = prio_chain_head;
++ int i = 0;
++
++ while (check) {
++ if (check->prio == this->prio)
++ i++;
++ check = check->next;
++ }
++
++ return i;
+}
+
+/**
+ * Pass the group used in allocating the page as well, as it should
+ * be freed on completion of the bio if we're writing the page.
+ **/
-+static int toi_bio_rw_page(int writing, struct page *page,
++int toi_bio_rw_page(int writing, struct page *page,
+ int is_readahead, int free_group)
+{
-+ struct toi_bdev_info *dev_info;
-+ int result = go_next_page(writing, 1);
++ int result = toi_end_of_stream(writing, 1);
++ struct toi_bdev_info *dev_info = toi_writer_posn.current_chain;
+
-+ if (result)
-+ return result;
++ if (result) {
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Seeking to read/write "
++ "another page when stream has ended.");
++ return -ENODATA;
++ }
+
-+ dev_info = &toi_devinfo[toi_writer_posn.current_chain];
++ toi_message(TOI_IO, TOI_VERBOSE, 0,
++ "%sing device %lx, sector %d << %d.",
++ writing ? "Writ" : "Read",
++ dev_info->bdev, dev_info->blocks.current_offset,
++ dev_info->bmap_shift);
+
-+ return toi_do_io(writing, dev_info->bdev,
-+ toi_writer_posn.current_offset <<
-+ dev_info->bmap_shift,
++ result = toi_do_io(writing, dev_info->bdev,
++ dev_info->blocks.current_offset << dev_info->bmap_shift,
+ page, is_readahead, 0, free_group);
-+}
-+
-+/**
-+ * toi_rw_init - prepare to read or write a stream in the image
-+ * @writing: Whether reading or writing.
-+ * @stream number: Section of the image being processed.
-+ *
-+ * Prepare to read or write a section ('stream') in the image.
-+ **/
-+static int toi_rw_init(int writing, int stream_number)
-+{
-+ if (stream_number)
-+ toi_extent_state_restore(&toi_writer_posn,
-+ &toi_writer_posn_save[stream_number]);
-+ else
-+ toi_extent_state_goto_start(&toi_writer_posn);
-+
-+ atomic_set(&toi_io_done, 0);
-+ toi_writer_buffer = (char *) toi_get_zeroed_page(11, TOI_ATOMIC_GFP);
-+ toi_writer_buffer_posn = writing ? 0 : PAGE_SIZE;
-+
-+ current_stream = stream_number;
+
-+ more_readahead = 1;
++ /* Ignore the result here - will check end of stream if come in again */
++ go_next_page(writing, 1);
+
-+ return toi_writer_buffer ? 0 : -ENOMEM;
++ if (result)
++ printk(KERN_ERR "toi_do_io returned %d.\n", result);
++ return result;
+}
+
-+/**
-+ * toi_read_header_init - prepare to read the image header
-+ *
-+ * Reset readahead indices prior to starting to read a section of the image.
-+ **/
-+static void toi_read_header_init(void)
++dev_t get_header_dev_t(void)
+{
-+ toi_writer_buffer = (char *) toi_get_zeroed_page(11, TOI_ATOMIC_GFP);
-+ more_readahead = 1;
++ return prio_chain_head->dev_t;
+}
+
-+/**
-+ * toi_bio_queue_write - queue a page for writing
-+ * @full_buffer: Pointer to a page to be queued
-+ *
-+ * Add a page to the queue to be submitted. If we're the queue flusher,
-+ * we'll do this once we've dropped toi_bio_mutex, so other threads can
-+ * continue to submit I/O while we're on the slow path doing the actual
-+ * submission.
-+ **/
-+static void toi_bio_queue_write(char **full_buffer)
++struct block_device *get_header_bdev(void)
+{
-+ struct page *page = virt_to_page(*full_buffer);
-+ unsigned long flags;
-+
-+ page->private = 0;
++ return prio_chain_head->bdev;
++}
+
-+ spin_lock_irqsave(&bio_queue_lock, flags);
-+ if (!bio_queue_head)
-+ bio_queue_head = page;
-+ else
-+ bio_queue_tail->private = (unsigned long) page;
++unsigned long get_headerblock(void)
++{
++ return prio_chain_head->blocks.first->start <<
++ prio_chain_head->bmap_shift;
++}
+
-+ bio_queue_tail = page;
-+ atomic_inc(&toi_bio_queue_size);
++int get_main_pool_phys_params(void)
++{
++ struct toi_bdev_info *this = prio_chain_head;
++ int result;
+
-+ spin_unlock_irqrestore(&bio_queue_lock, flags);
-+ wake_up(&toi_io_queue_flusher);
++ while (this) {
++ result = this->allocator->bio_allocator_ops->bmap(this);
++ if (result)
++ return result;
++ this = this->next;
++ }
+
-+ *full_buffer = NULL;
++ return 0;
+}
+
-+/**
-+ * toi_rw_cleanup - Cleanup after i/o.
-+ * @writing: Whether we were reading or writing.
-+ *
-+ * Flush all I/O and clean everything up after reading or writing a
-+ * section of the image.
-+ **/
-+static int toi_rw_cleanup(int writing)
++static int apply_header_reservation(void)
+{
-+ int i, result;
-+
-+ if (writing) {
-+ int result;
-+
-+ if (toi_writer_buffer_posn && !test_result_state(TOI_ABORTED))
-+ toi_bio_queue_write(&toi_writer_buffer);
++ int i;
+
-+ result = toi_bio_queue_flush_pages(0);
++ if (!header_pages_reserved) {
++ toi_message(TOI_IO, TOI_VERBOSE, 0,
++ "No header pages reserved at the moment.");
++ return 0;
++ }
+
-+ if (result)
-+ return result;
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Applying header reservation.");
+
-+ if (current_stream == 2)
-+ toi_extent_state_save(&toi_writer_posn,
-+ &toi_writer_posn_save[1]);
-+ else if (current_stream == 1)
-+ toi_extent_state_save(&toi_writer_posn,
-+ &toi_writer_posn_save[3]);
-+ }
++ /* Apply header space reservation */
++ toi_extent_state_goto_start();
+
-+ result = toi_finish_all_io();
++ for (i = 0; i < header_pages_reserved; i++)
++ if (go_next_page(1, 0))
++ return -ENODATA;
+
-+ while (readahead_list_head) {
-+ void *next = (void *) readahead_list_head->private;
-+ toi__free_page(12, readahead_list_head);
-+ readahead_list_head = next;
-+ }
++ /* The end of header pages will be the start of pageset 2 */
++ toi_extent_state_save(2);
+
-+ readahead_list_tail = NULL;
++ toi_message(TOI_IO, TOI_VERBOSE, 0,
++ "Finished applying header reservation.");
++ return 0;
++}
+
-+ if (!current_stream)
-+ return result;
++static int toi_bio_register_storage(void)
++{
++ int result = 0;
++ struct toi_module_ops *this_module;
+
-+ for (i = 0; i < NUM_REASONS; i++) {
-+ if (!atomic_read(&reasons[i]))
++ list_for_each_entry(this_module, &toi_modules, module_list) {
++ if (!this_module->enabled ||
++ this_module->type != BIO_ALLOCATOR_MODULE)
+ continue;
-+ printk(KERN_DEBUG "Waited for i/o due to %s %d times.\n",
-+ reason_name[i], atomic_read(&reasons[i]));
-+ atomic_set(&reasons[i], 0);
++ toi_message(TOI_IO, TOI_VERBOSE, 0,
++ "Registering storage from %s.",
++ this_module->name);
++ result = this_module->bio_allocator_ops->register_storage();
++ if (result)
++ break;
+ }
+
-+ current_stream = 0;
+ return result;
+}
+
-+/**
-+ * toi_start_one_readahead - start one page of readahead
-+ * @dedicated_thread: Is this a thread dedicated to doing readahead?
-+ *
-+ * Start one new page of readahead. If this is being called by a thread
-+ * whose only just is to submit readahead, don't quit because we failed
-+ * to allocate a page.
-+ **/
-+static int toi_start_one_readahead(int dedicated_thread)
++int toi_bio_allocate_storage(unsigned long request)
+{
-+ char *buffer = NULL;
-+ int oom = 0, result;
++ struct toi_bdev_info *chain = prio_chain_head;
++ unsigned long to_get = request;
++ unsigned long extra_pages, needed;
++ int no_free = 0;
+
-+ result = throttle_if_needed(dedicated_thread ? THROTTLE_WAIT : 0);
-+ if (result)
-+ return result;
++ if (!chain) {
++ int result = toi_bio_register_storage();
++ if (result)
++ return 0;
++ chain = prio_chain_head;
++ }
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "toi_bio_allocate_storage: "
++ "Request is %lu pages.", request);
++ extra_pages = DIV_ROUND_UP(request * (sizeof(unsigned long)
++ + sizeof(int)), PAGE_SIZE);
++ needed = request + extra_pages + header_pages_reserved;
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Adding %lu extra pages and %lu "
++ "for header => %lu.",
++ extra_pages, header_pages_reserved, needed);
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Already allocated %lu pages.",
++ raw_pages_allocd);
+
-+ mutex_lock(&toi_bio_readahead_mutex);
++ to_get = needed > raw_pages_allocd ? needed - raw_pages_allocd : 0;
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Need to get %lu pages.", to_get);
+
-+ while (!buffer) {
-+ buffer = (char *) toi_get_zeroed_page(12,
-+ TOI_ATOMIC_GFP);
-+ if (!buffer) {
-+ if (oom && !dedicated_thread) {
-+ mutex_unlock(&toi_bio_readahead_mutex);
-+ return -ENOMEM;
-+ }
++ if (!to_get)
++ return apply_header_reservation();
+
-+ oom = 1;
-+ set_free_mem_throttle();
-+ do_bio_wait(5);
-+ }
-+ }
++ while (to_get && chain) {
++ int divisor = devices_of_same_priority(chain) - no_free;
++ int i;
++ unsigned long portion = DIV_ROUND_UP(to_get, divisor);
++ unsigned long got = 0;
++ unsigned long got_this_round = 0;
++ struct toi_bdev_info *top = chain;
+
-+ result = toi_bio_rw_page(READ, virt_to_page(buffer), 1, 0);
-+ mutex_unlock(&toi_bio_readahead_mutex);
-+ return result;
-+}
++ toi_message(TOI_IO, TOI_VERBOSE, 0,
++ " Start of loop. To get is %lu. Divisor is %d.",
++ to_get, divisor);
++ no_free = 0;
+
-+/**
-+ * toi_start_new_readahead - start new readahead
-+ * @dedicated_thread: Are we dedicated to this task?
++ /*
++ * We're aiming to spread the allocated storage as evenly
++ * as possible, but we also want to get all the storage we
++ * can off this priority.
++ */
++ for (i = 0; i < divisor; i++) {
++ struct toi_bio_allocator_ops *ops =
++ chain->allocator->bio_allocator_ops;
++ toi_message(TOI_IO, TOI_VERBOSE, 0,
++ " Asking for %lu pages from chain %p.",
++ portion, chain);
++ got = ops->allocate_storage(chain, portion);
++ toi_message(TOI_IO, TOI_VERBOSE, 0,
++ " Got %lu pages from allocator %p.",
++ got, chain);
++ if (!got)
++ no_free++;
++ got_this_round += got;
++ chain = chain->next;
++ }
++ toi_message(TOI_IO, TOI_VERBOSE, 0, " Loop finished. Got a "
++ "total of %lu pages from %d allocators.",
++ got_this_round, divisor - no_free);
++
++ raw_pages_allocd += got_this_round;
++ to_get = needed > raw_pages_allocd ? needed - raw_pages_allocd :
++ 0;
++
++ /*
++ * If we got anything from chains of this priority and we
++ * still have storage to allocate, go over this priority
++ * again.
++ */
++ if (got_this_round && to_get)
++ chain = top;
++ else
++ no_free = 0;
++ }
++
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Finished allocating. Calling "
++ "get_main_pool_phys_params");
++ /* Now let swap allocator bmap the pages */
++ get_main_pool_phys_params();
++
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Done. Reserving header.");
++ return apply_header_reservation();
++}
+diff --git a/kernel/power/tuxonice_bio_core.c b/kernel/power/tuxonice_bio_core.c
+new file mode 100644
+index 0000000..188931a
+--- /dev/null
++++ b/kernel/power/tuxonice_bio_core.c
+@@ -0,0 +1,1791 @@
++/*
++ * kernel/power/tuxonice_bio.c
+ *
-+ * Start readahead of image pages.
++ * Copyright (C) 2004-2008 Nigel Cunningham (nigel at tuxonice net)
+ *
-+ * We can be called as a thread dedicated to this task (may be helpful on
-+ * systems with lots of CPUs), in which case we don't exit until there's no
-+ * more readahead.
++ * Distributed under GPLv2.
+ *
-+ * If this is not called by a dedicated thread, we top up our queue until
-+ * there's no more readahead to submit, we've submitted the number given
-+ * in target_outstanding_io or the number in progress exceeds the target
-+ * outstanding I/O value.
++ * This file contains block io functions for TuxOnIce. These are
++ * used by the swapwriter and it is planned that they will also
++ * be used by the NFSwriter.
+ *
-+ * No mutex needed because this is only ever called by the first cpu.
-+ **/
-+static int toi_start_new_readahead(int dedicated_thread)
-+{
-+ int last_result, num_submitted = 0;
++ */
+
-+ /* Start a new readahead? */
-+ if (!more_readahead)
-+ return 0;
++#include <linux/blkdev.h>
++#include <linux/syscalls.h>
++#include <linux/suspend.h>
++#include <linux/ctype.h>
++#include <linux/uuid.h>
++#include <scsi/scsi_scan.h>
+
-+ do {
-+ last_result = toi_start_one_readahead(dedicated_thread);
++#include "tuxonice.h"
++#include "tuxonice_sysfs.h"
++#include "tuxonice_modules.h"
++#include "tuxonice_prepare_image.h"
++#include "tuxonice_bio.h"
++#include "tuxonice_ui.h"
++#include "tuxonice_alloc.h"
++#include "tuxonice_io.h"
++#include "tuxonice_builtin.h"
++#include "tuxonice_bio_internal.h"
+
-+ if (last_result) {
-+ if (last_result == -ENOMEM || last_result == -ENODATA)
-+ return 0;
++#define MEMORY_ONLY 1
++#define THROTTLE_WAIT 2
+
-+ printk(KERN_DEBUG
-+ "Begin read chunk returned %d.\n",
-+ last_result);
-+ } else
-+ num_submitted++;
++/* #define MEASURE_MUTEX_CONTENTION */
++#ifndef MEASURE_MUTEX_CONTENTION
++#define my_mutex_lock(index, the_lock) mutex_lock(the_lock)
++#define my_mutex_unlock(index, the_lock) mutex_unlock(the_lock)
++#else
++unsigned long mutex_times[2][2][NR_CPUS];
++#define my_mutex_lock(index, the_lock) do { \
++ int have_mutex; \
++ have_mutex = mutex_trylock(the_lock); \
++ if (!have_mutex) { \
++ mutex_lock(the_lock); \
++ mutex_times[index][0][smp_processor_id()]++; \
++ } else { \
++ mutex_times[index][1][smp_processor_id()]++; \
++ }
+
-+ } while (more_readahead && !last_result &&
-+ (dedicated_thread ||
-+ (num_submitted < target_outstanding_io &&
-+ atomic_read(&toi_io_in_progress) < target_outstanding_io)));
++#define my_mutex_unlock(index, the_lock) \
++ mutex_unlock(the_lock); \
++} while (0)
++#endif
+
-+ return last_result;
-+}
++static int page_idx, reset_idx;
++
++static int target_outstanding_io = 1024;
++static int max_outstanding_writes, max_outstanding_reads;
++
++static struct page *bio_queue_head, *bio_queue_tail;
++static atomic_t toi_bio_queue_size;
++static DEFINE_SPINLOCK(bio_queue_lock);
++
++static int free_mem_throttle, throughput_throttle;
++int more_readahead = 1;
++static struct page *readahead_list_head, *readahead_list_tail;
++
++static struct page *waiting_on;
++
++static atomic_t toi_io_in_progress, toi_io_done;
++static DECLARE_WAIT_QUEUE_HEAD(num_in_progress_wait);
++
++int current_stream;
++/* Not static, so that the allocators can setup and complete
++ * writing the header */
++char *toi_writer_buffer;
++int toi_writer_buffer_posn;
++
++static DEFINE_MUTEX(toi_bio_mutex);
++static DEFINE_MUTEX(toi_bio_readahead_mutex);
++
++static struct task_struct *toi_queue_flusher;
++static int toi_bio_queue_flush_pages(int dedicated_thread);
++
++struct toi_module_ops toi_blockwriter_ops;
++
++#define TOTAL_OUTSTANDING_IO (atomic_read(&toi_io_in_progress) + \
++ atomic_read(&toi_bio_queue_size))
++
++unsigned long raw_pages_allocd, header_pages_reserved;
+
+/**
-+ * bio_io_flusher - start the dedicated I/O flushing routine
-+ * @writing: Whether we're writing the image.
++ * set_free_mem_throttle - set the point where we pause to avoid oom.
++ *
++ * Initially, this value is zero, but when we first fail to allocate memory,
++ * we set it (plus a buffer) and thereafter throttle i/o once that limit is
++ * reached.
+ **/
-+static int bio_io_flusher(int writing)
++static void set_free_mem_throttle(void)
+{
++ int new_throttle = nr_unallocated_buffer_pages() + 256;
+
-+ if (writing)
-+ return toi_bio_queue_flush_pages(1);
-+ else
-+ return toi_start_new_readahead(1);
++ if (new_throttle > free_mem_throttle)
++ free_mem_throttle = new_throttle;
+}
+
++#define NUM_REASONS 7
++static atomic_t reasons[NUM_REASONS];
++static char *reason_name[NUM_REASONS] = {
++ "readahead not ready",
++ "bio allocation",
++ "synchronous I/O",
++ "toi_bio_get_new_page",
++ "memory low",
++ "readahead buffer allocation",
++ "throughput_throttle",
++};
++
++/* User Specified Parameters. */
++unsigned long resume_firstblock;
++dev_t resume_dev_t;
++struct block_device *resume_block_device;
++static atomic_t resume_bdev_open_count;
++
++struct block_device *header_block_device;
++
+/**
-+ * toi_bio_get_next_page_read - read a disk page, perhaps with readahead
-+ * @no_readahead: Whether we can use readahead
++ * toi_close_bdev: Close a swap bdev.
+ *
-+ * Read a page from disk, submitting readahead and cleaning up finished i/o
-+ * while we wait for the page we're after.
-+ **/
-+static int toi_bio_get_next_page_read(int no_readahead)
++ * int: The swap entry number to close.
++ */
++void toi_close_bdev(struct block_device *bdev)
+{
-+ unsigned long *virt;
-+ struct page *next;
++ toi_message(TOI_IO, TOI_VERBOSE, 0, ">>> TuxOnIce closing bdev %p.",
++ bdev);
++ blkdev_put(bdev, FMODE_READ | FMODE_NDELAY);
++}
+
-+ /*
-+ * When reading the second page of the header, we have to
-+ * delay submitting the read until after we've gotten the
-+ * extents out of the first page.
-+ */
-+ if (unlikely(no_readahead && toi_start_one_readahead(0))) {
-+ printk(KERN_DEBUG "No readahead and toi_start_one_readahead "
-+ "returned non-zero.\n");
-+ return -EIO;
++/**
++ * toi_open_bdev: Open a bdev at resume time.
++ *
++ * index: The swap index. May be MAX_SWAPFILES for the resume_dev_t
++ * (the user can have resume= pointing at a swap partition/file that isn't
++ * swapon'd when they hibernate. MAX_SWAPFILES+1 for the first page of the
++ * header. It will be from a swap partition that was enabled when we hibernated,
++ * but we don't know it's real index until we read that first page.
++ * dev_t: The device major/minor.
++ * display_errs: Whether to try to do this quietly.
++ *
++ * We stored a dev_t in the image header. Open the matching device without
++ * requiring /dev/<whatever> in most cases and record the details needed
++ * to close it later and avoid duplicating work.
++ */
++struct block_device *toi_open_bdev(char *uuid, dev_t default_device,
++ int display_errs)
++{
++ struct block_device *bdev;
++ dev_t device = default_device;
++ char buf[32];
++
++ if (uuid) {
++ device = blk_lookup_uuid(uuid);
++ if (!device) {
++ device = default_device;
++ printk(KERN_DEBUG "Unable to resolve uuid. Falling back"
++ " to dev_t.\n");
++ } else
++ printk(KERN_DEBUG "Resolved uuid to device %s.\n",
++ format_dev_t(buf, device));
+ }
+
-+ if (unlikely(!readahead_list_head)) {
-+ /*
-+ * If the last page finishes exactly on the page
-+ * boundary, we will be called one extra time and
-+ * have no data to return. In this case, we should
-+ * not BUG(), like we used to!
-+ */
-+ if (!more_readahead)
-+ return -ENODATA;
-+ if (unlikely(toi_start_one_readahead(0))) {
-+ printk(KERN_DEBUG "No readahead and "
-+ "toi_start_one_readahead returned non-zero.\n");
-+ return -EIO;
-+ }
++ if (!device) {
++ printk(KERN_ERR "TuxOnIce attempting to open a "
++ "blank dev_t!\n");
++ dump_stack();
++ return NULL;
+ }
++ bdev = toi_open_by_devnum(device, FMODE_READ | FMODE_NDELAY);
+
-+ if (PageLocked(readahead_list_head)) {
-+ waiting_on = readahead_list_head;
-+ do_bio_wait(0);
++ if (IS_ERR(bdev) || !bdev) {
++ if (display_errs)
++ toi_early_boot_message(1, TOI_CONTINUE_REQ,
++ "Failed to get access to block device "
++ "\"%x\" (error %d).\n Maybe you need "
++ "to run mknod and/or lvmsetup in an "
++ "initrd/ramfs?", device, bdev);
++ return ERR_PTR(-EINVAL);
+ }
++ toi_message(TOI_IO, TOI_VERBOSE, 0,
++ "TuxOnIce got bdev %p for dev_t %x.",
++ bdev, device);
+
-+ virt = page_address(readahead_list_head);
-+ memcpy(toi_writer_buffer, virt, PAGE_SIZE);
++ return bdev;
++}
+
-+ next = (struct page *) readahead_list_head->private;
-+ toi__free_page(12, readahead_list_head);
-+ readahead_list_head = next;
-+ return 0;
++static void toi_bio_reserve_header_space(unsigned long request)
++{
++ header_pages_reserved = request;
+}
+
+/**
-+ * toi_bio_queue_flush_pages - flush the queue of pages queued for writing
-+ * @dedicated_thread: Whether we're a dedicated thread
-+ *
-+ * Flush the queue of pages ready to be written to disk.
-+ *
-+ * If we're a dedicated thread, stay in here until told to leave,
-+ * sleeping in wait_event.
++ * do_bio_wait - wait for some TuxOnIce I/O to complete
++ * @reason: The array index of the reason we're waiting.
+ *
-+ * The first thread is normally the only one to come in here. Another
-+ * thread can enter this routine too, though, via throttle_if_needed.
-+ * Since that's the case, we must be careful to only have one thread
-+ * doing this work at a time. Otherwise we have a race and could save
-+ * pages out of order.
++ * Wait for a particular page of I/O if we're after a particular page.
++ * If we're not after a particular page, wait instead for all in flight
++ * I/O to be completed or for us to have enough free memory to be able
++ * to submit more I/O.
+ *
-+ * If an error occurs, free all remaining pages without submitting them
-+ * for I/O.
++ * If we wait, we also update our statistics regarding why we waited.
+ **/
-+
-+int toi_bio_queue_flush_pages(int dedicated_thread)
++static void do_bio_wait(int reason)
+{
-+ unsigned long flags;
-+ int result = 0;
-+ static int busy;
-+
-+ if (busy)
-+ return 0;
++ struct page *was_waiting_on = waiting_on;
+
-+ busy = 1;
-+
-+top:
-+ spin_lock_irqsave(&bio_queue_lock, flags);
-+ while (bio_queue_head) {
-+ struct page *page = bio_queue_head;
-+ bio_queue_head = (struct page *) page->private;
-+ if (bio_queue_tail == page)
-+ bio_queue_tail = NULL;
-+ atomic_dec(&toi_bio_queue_size);
-+ spin_unlock_irqrestore(&bio_queue_lock, flags);
-+ if (!result)
-+ result = toi_bio_rw_page(WRITE, page, 0, 11);
-+ if (result)
-+ toi__free_page(11 , page);
-+ spin_lock_irqsave(&bio_queue_lock, flags);
-+ }
-+ spin_unlock_irqrestore(&bio_queue_lock, flags);
++ /* On SMP, waiting_on can be reset, so we make a copy */
++ if (was_waiting_on) {
++ if (PageLocked(was_waiting_on)) {
++ wait_on_page_bit(was_waiting_on, PG_locked);
++ atomic_inc(&reasons[reason]);
++ }
++ } else {
++ atomic_inc(&reasons[reason]);
+
-+ if (dedicated_thread) {
-+ wait_event(toi_io_queue_flusher, bio_queue_head ||
-+ toi_bio_queue_flusher_should_finish);
-+ if (likely(!toi_bio_queue_flusher_should_finish))
-+ goto top;
-+ toi_bio_queue_flusher_should_finish = 0;
++ wait_event(num_in_progress_wait,
++ !atomic_read(&toi_io_in_progress) ||
++ nr_unallocated_buffer_pages() > free_mem_throttle);
+ }
-+
-+ busy = 0;
-+ return result;
+}
+
+/**
-+ * toi_bio_get_new_page - get a new page for I/O
-+ * @full_buffer: Pointer to a page to allocate.
++ * throttle_if_needed - wait for I/O completion if throttle points are reached
++ * @flags: What to check and how to act.
++ *
++ * Check whether we need to wait for some I/O to complete. We always check
++ * whether we have enough memory available, but may also (depending upon
++ * @reason) check if the throughput throttle limit has been reached.
+ **/
-+static int toi_bio_get_new_page(char **full_buffer)
++static int throttle_if_needed(int flags)
+{
-+ int result = throttle_if_needed(THROTTLE_WAIT);
-+ if (result)
-+ return result;
++ int free_pages = nr_unallocated_buffer_pages();
+
-+ while (!*full_buffer) {
-+ *full_buffer = (char *) toi_get_zeroed_page(11, TOI_ATOMIC_GFP);
-+ if (!*full_buffer) {
-+ set_free_mem_throttle();
-+ do_bio_wait(3);
-+ }
++ /* Getting low on memory and I/O is in progress? */
++ while (unlikely(free_pages < free_mem_throttle) &&
++ atomic_read(&toi_io_in_progress)) {
++ if (!(flags & THROTTLE_WAIT))
++ return -ENOMEM;
++ do_bio_wait(4);
++ free_pages = nr_unallocated_buffer_pages();
++ }
++
++ while (!(flags & MEMORY_ONLY) && throughput_throttle &&
++ TOTAL_OUTSTANDING_IO >= throughput_throttle) {
++ int result = toi_bio_queue_flush_pages(0);
++ if (result)
++ return result;
++ atomic_inc(&reasons[6]);
++ wait_event(num_in_progress_wait,
++ !atomic_read(&toi_io_in_progress) ||
++ TOTAL_OUTSTANDING_IO < throughput_throttle);
+ }
+
+ return 0;
+}
+
+/**
-+ * toi_rw_buffer - combine smaller buffers into PAGE_SIZE I/O
-+ * @writing: Bool - whether writing (or reading).
-+ * @buffer: The start of the buffer to write or fill.
-+ * @buffer_size: The size of the buffer to write or fill.
-+ * @no_readahead: Don't try to start readhead (when getting extents).
++ * update_throughput_throttle - update the raw throughput throttle
++ * @jif_index: The number of times this function has been called.
++ *
++ * This function is called twice per second by the core, and used to limit the
++ * amount of I/O we submit at once, spreading out our waiting through the
++ * whole job and letting userui get an opportunity to do its work.
++ *
++ * We don't start limiting I/O until 1/2s has gone so that we get a
++ * decent sample for our initial limit, and keep updating it because
++ * throughput may vary (on rotating media, eg) with our block number.
++ *
++ * We throttle to 1/10s worth of I/O.
+ **/
-+static int toi_rw_buffer(int writing, char *buffer, int buffer_size,
-+ int no_readahead)
++static void update_throughput_throttle(int jif_index)
+{
-+ int bytes_left = buffer_size, result = 0;
-+
-+ while (bytes_left) {
-+ char *source_start = buffer + buffer_size - bytes_left;
-+ char *dest_start = toi_writer_buffer + toi_writer_buffer_posn;
-+ int capacity = PAGE_SIZE - toi_writer_buffer_posn;
-+ char *to = writing ? dest_start : source_start;
-+ char *from = writing ? source_start : dest_start;
-+
-+ if (bytes_left <= capacity) {
-+ memcpy(to, from, bytes_left);
-+ toi_writer_buffer_posn += bytes_left;
-+ return 0;
-+ }
-+
-+ /* Complete this page and start a new one */
-+ memcpy(to, from, capacity);
-+ bytes_left -= capacity;
-+
-+ if (!writing) {
-+ /*
-+ * Perform actual I/O:
-+ * read readahead_list_head into toi_writer_buffer
-+ */
-+ int result = toi_bio_get_next_page_read(no_readahead);
-+ if (result)
-+ return result;
-+ } else {
-+ toi_bio_queue_write(&toi_writer_buffer);
-+ result = toi_bio_get_new_page(&toi_writer_buffer);
-+ if (result)
-+ return result;
-+ }
-+
-+ toi_writer_buffer_posn = 0;
-+ toi_cond_pause(0, NULL);
-+ }
-+
-+ return 0;
++ int done = atomic_read(&toi_io_done);
++ throughput_throttle = done / jif_index / 5;
+}
+
+/**
-+ * toi_bio_read_page - read a page of the image
-+ * @pfn: The pfn where the data belongs.
-+ * @buffer_page: The page containing the (possibly compressed) data.
-+ * @buf_size: The number of bytes on @buffer_page used (PAGE_SIZE).
++ * toi_finish_all_io - wait for all outstanding i/o to complete
+ *
-+ * Read a (possibly compressed) page from the image, into buffer_page,
-+ * returning its pfn and the buffer size.
++ * Flush any queued but unsubmitted I/O and wait for it all to complete.
+ **/
-+static int toi_bio_read_page(unsigned long *pfn, struct page *buffer_page,
-+ unsigned int *buf_size)
++static int toi_finish_all_io(void)
+{
-+ int result = 0;
-+ char *buffer_virt = kmap(buffer_page);
-+
-+ /*
-+ * Only call start_new_readahead if we don't have a dedicated thread
-+ * and we're the queue flusher.
-+ */
-+ if (current == toi_queue_flusher && more_readahead) {
-+ int result2 = toi_start_new_readahead(0);
-+ if (result2) {
-+ printk(KERN_DEBUG "Queue flusher and "
-+ "toi_start_one_readahead returned non-zero.\n");
-+ result = -EIO;
-+ goto out;
-+ }
-+ }
-+
-+ my_mutex_lock(0, &toi_bio_mutex);
-+
-+ /*
-+ * Structure in the image:
-+ * [destination pfn|page size|page data]
-+ * buf_size is PAGE_SIZE
-+ */
-+ if (toi_rw_buffer(READ, (char *) pfn, sizeof(unsigned long), 0) ||
-+ toi_rw_buffer(READ, (char *) buf_size, sizeof(int), 0) ||
-+ toi_rw_buffer(READ, buffer_virt, *buf_size, 0)) {
-+ abort_hibernate(TOI_FAILED_IO, "Read of data failed.");
-+ result = 1;
-+ }
-+
-+ my_mutex_unlock(0, &toi_bio_mutex);
-+out:
-+ kunmap(buffer_page);
++ int result = toi_bio_queue_flush_pages(0);
++ wait_event(num_in_progress_wait, !TOTAL_OUTSTANDING_IO);
+ return result;
+}
+
+/**
-+ * toi_bio_write_page - write a page of the image
-+ * @pfn: The pfn where the data belongs.
-+ * @buffer_page: The page containing the (possibly compressed) data.
-+ * @buf_size: The number of bytes on @buffer_page used.
++ * toi_end_bio - bio completion function.
++ * @bio: bio that has completed.
++ * @err: Error value. Yes, like end_swap_bio_read, we ignore it.
+ *
-+ * Write a (possibly compressed) page to the image from the buffer, together
-+ * with it's index and buffer size.
++ * Function called by the block driver from interrupt context when I/O is
++ * completed. If we were writing the page, we want to free it and will have
++ * set bio->bi_private to the parameter we should use in telling the page
++ * allocation accounting code what the page was allocated for. If we're
++ * reading the page, it will be in the singly linked list made from
++ * page->private pointers.
+ **/
-+static int toi_bio_write_page(unsigned long pfn, struct page *buffer_page,
-+ unsigned int buf_size)
++static void toi_end_bio(struct bio *bio, int err)
+{
-+ char *buffer_virt;
-+ int result = 0, result2 = 0;
++ struct page *page = bio->bi_io_vec[0].bv_page;
+
-+ if (unlikely(test_action_state(TOI_TEST_FILTER_SPEED)))
-+ return 0;
++ BUG_ON(!test_bit(BIO_UPTODATE, &bio->bi_flags));
+
-+ my_mutex_lock(1, &toi_bio_mutex);
++ unlock_page(page);
++ bio_put(bio);
+
-+ if (test_result_state(TOI_ABORTED)) {
-+ my_mutex_unlock(1, &toi_bio_mutex);
-+ return -EIO;
-+ }
++ if (waiting_on == page)
++ waiting_on = NULL;
+
-+ buffer_virt = kmap(buffer_page);
++ put_page(page);
+
-+ /*
-+ * Structure in the image:
-+ * [destination pfn|page size|page data]
-+ * buf_size is PAGE_SIZE
-+ */
-+ if (toi_rw_buffer(WRITE, (char *) &pfn, sizeof(unsigned long), 0) ||
-+ toi_rw_buffer(WRITE, (char *) &buf_size, sizeof(int), 0) ||
-+ toi_rw_buffer(WRITE, buffer_virt, buf_size, 0)) {
-+ printk(KERN_DEBUG "toi_rw_buffer returned non-zero to "
-+ "toi_bio_write_page.\n");
-+ result = -EIO;
-+ }
++ if (bio->bi_private)
++ toi__free_page((int) ((unsigned long) bio->bi_private) , page);
+
-+ kunmap(buffer_page);
-+ my_mutex_unlock(1, &toi_bio_mutex);
++ bio_put(bio);
+
-+ if (current == toi_queue_flusher)
-+ result2 = toi_bio_queue_flush_pages(0);
++ atomic_dec(&toi_io_in_progress);
++ atomic_inc(&toi_io_done);
+
-+ return result ? result : result2;
++ wake_up(&num_in_progress_wait);
+}
+
+/**
-+ * _toi_rw_header_chunk - read or write a portion of the image header
-+ * @writing: Whether reading or writing.
-+ * @owner: The module for which we're writing.
-+ * Used for confirming that modules
-+ * don't use more header space than they asked for.
-+ * @buffer: Address of the data to write.
-+ * @buffer_size: Size of the data buffer.
-+ * @no_readahead: Don't try to start readhead (when getting extents).
++ * submit - submit BIO request
++ * @writing: READ or WRITE.
++ * @dev: The block device we're using.
++ * @first_block: The first sector we're using.
++ * @page: The page being used for I/O.
++ * @free_group: If writing, the group that was used in allocating the page
++ * and which will be used in freeing the page from the completion
++ * routine.
+ *
-+ * Perform PAGE_SIZE I/O. Start readahead if needed.
-+ **/
-+static int _toi_rw_header_chunk(int writing, struct toi_module_ops *owner,
-+ char *buffer, int buffer_size, int no_readahead)
++ * Based on Patrick Mochell's pmdisk code from long ago: "Straight from the
++ * textbook - allocate and initialize the bio. If we're writing, make sure
++ * the page is marked as dirty. Then submit it and carry on."
++ *
++ * If we're just testing the speed of our own code, we fake having done all
++ * the hard work and all toi_end_bio immediately.
++ **/
++static int submit(int writing, struct block_device *dev, sector_t first_block,
++ struct page *page, int free_group)
+{
-+ int result = 0;
++ struct bio *bio = NULL;
++ int cur_outstanding_io, result;
+
-+ if (owner) {
-+ owner->header_used += buffer_size;
-+ toi_message(TOI_HEADER, TOI_LOW, 1,
-+ "Header: %s : %d bytes (%d/%d).\n",
-+ owner->name,
-+ buffer_size, owner->header_used,
-+ owner->header_requested);
-+ if (owner->header_used > owner->header_requested) {
-+ printk(KERN_EMERG "TuxOnIce module %s is using more "
-+ "header space (%u) than it requested (%u).\n",
-+ owner->name,
-+ owner->header_used,
-+ owner->header_requested);
-+ return buffer_size;
++ /*
++ * Shouldn't throttle if reading - can deadlock in the single
++ * threaded case as pages are only freed when we use the
++ * readahead.
++ */
++ if (writing) {
++ result = throttle_if_needed(MEMORY_ONLY | THROTTLE_WAIT);
++ if (result)
++ return result;
++ }
++
++ while (!bio) {
++ bio = bio_alloc(TOI_ATOMIC_GFP, 1);
++ if (!bio) {
++ set_free_mem_throttle();
++ do_bio_wait(1);
+ }
-+ } else {
-+ unowned += buffer_size;
-+ toi_message(TOI_HEADER, TOI_LOW, 1,
-+ "Header: (No owner): %d bytes (%d total so far)\n",
-+ buffer_size, unowned);
+ }
+
-+ if (!writing && !no_readahead && more_readahead)
-+ result = toi_start_new_readahead(0);
++ bio->bi_bdev = dev;
++ bio->bi_sector = first_block;
++ bio->bi_private = (void *) ((unsigned long) free_group);
++ bio->bi_end_io = toi_end_bio;
+
-+ if (!result)
-+ result = toi_rw_buffer(writing, buffer, buffer_size,
-+ no_readahead);
++ if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
++ printk(KERN_DEBUG "ERROR: adding page to bio at %lld\n",
++ (unsigned long long) first_block);
++ bio_put(bio);
++ return -EFAULT;
++ }
+
-+ total_header_bytes += buffer_size;
-+ return result;
-+}
++ bio_get(bio);
+
-+static int toi_rw_header_chunk(int writing, struct toi_module_ops *owner,
-+ char *buffer, int size)
-+{
-+ return _toi_rw_header_chunk(writing, owner, buffer, size, 0);
-+}
++ cur_outstanding_io = atomic_add_return(1, &toi_io_in_progress);
++ if (writing) {
++ if (cur_outstanding_io > max_outstanding_writes)
++ max_outstanding_writes = cur_outstanding_io;
++ } else {
++ if (cur_outstanding_io > max_outstanding_reads)
++ max_outstanding_reads = cur_outstanding_io;
++ }
+
-+static int toi_rw_header_chunk_noreadahead(int writing,
-+ struct toi_module_ops *owner, char *buffer, int size)
-+{
-+ return _toi_rw_header_chunk(writing, owner, buffer, size, 1);
++
++ if (unlikely(test_action_state(TOI_TEST_BIO))) {
++ /* Fake having done the hard work */
++ set_bit(BIO_UPTODATE, &bio->bi_flags);
++ toi_end_bio(bio, 0);
++ } else
++ submit_bio(writing | (1 << BIO_RW_SYNCIO) |
++ (1 << BIO_RW_TUXONICE) |
++ (1 << BIO_RW_UNPLUG), bio);
++
++ return 0;
+}
+
+/**
-+ * write_header_chunk_finish - flush any buffered header data
++ * toi_do_io: Prepare to do some i/o on a page and submit or batch it.
++ *
++ * @writing: Whether reading or writing.
++ * @bdev: The block device which we're using.
++ * @block0: The first sector we're reading or writing.
++ * @page: The page on which I/O is being done.
++ * @readahead_index: If doing readahead, the index (reset this flag when done).
++ * @syncio: Whether the i/o is being done synchronously.
++ *
++ * Prepare and start a read or write operation.
++ *
++ * Note that we always work with our own page. If writing, we might be given a
++ * compression buffer that will immediately be used to start compressing the
++ * next page. For reading, we do readahead and therefore don't know the final
++ * address where the data needs to go.
+ **/
-+static int write_header_chunk_finish(void)
++int toi_do_io(int writing, struct block_device *bdev, long block0,
++ struct page *page, int is_readahead, int syncio, int free_group)
+{
-+ int result = 0;
++ page->private = 0;
+
-+ if (toi_writer_buffer_posn)
-+ toi_bio_queue_write(&toi_writer_buffer);
++ /* Do here so we don't race against toi_bio_get_next_page_read */
++ lock_page(page);
+
-+ result = toi_finish_all_io();
++ if (is_readahead) {
++ if (readahead_list_head)
++ readahead_list_tail->private = (unsigned long) page;
++ else
++ readahead_list_head = page;
+
-+ unowned = 0;
-+ total_header_bytes = 0;
-+ return result;
-+}
++ readahead_list_tail = page;
++ }
+
-+/**
-+ * toi_bio_storage_needed - get the amount of storage needed for my fns
-+ **/
-+static int toi_bio_storage_needed(void)
-+{
-+ return sizeof(int);
++ /* Done before submitting to avoid races. */
++ if (syncio)
++ waiting_on = page;
++
++ /* Submit the page */
++ get_page(page);
++
++ if (submit(writing, bdev, block0, page, free_group))
++ return -EFAULT;
++
++ if (syncio)
++ do_bio_wait(2);
++
++ return 0;
+}
+
+/**
-+ * toi_bio_save_config_info - save block I/O config to image header
-+ * @buf: PAGE_SIZE'd buffer into which data should be saved.
++ * toi_bdev_page_io - simpler interface to do directly i/o on a single page
++ * @writing: Whether reading or writing.
++ * @bdev: Block device on which we're operating.
++ * @pos: Sector at which page to read or write starts.
++ * @page: Page to be read/written.
++ *
++ * A simple interface to submit a page of I/O and wait for its completion.
++ * The caller must free the page used.
+ **/
-+static int toi_bio_save_config_info(char *buf)
++static int toi_bdev_page_io(int writing, struct block_device *bdev,
++ long pos, struct page *page)
+{
-+ int *ints = (int *) buf;
-+ ints[0] = target_outstanding_io;
-+ return sizeof(int);
++ return toi_do_io(writing, bdev, pos, page, 0, 1, 0);
+}
+
+/**
-+ * toi_bio_load_config_info - restore block I/O config
-+ * @buf: Data to be reloaded.
-+ * @size: Size of the buffer saved.
++ * toi_bio_memory_needed - report the amount of memory needed for block i/o
++ *
++ * We want to have at least enough memory so as to have target_outstanding_io
++ * or more transactions on the fly at once. If we can do more, fine.
+ **/
-+static void toi_bio_load_config_info(char *buf, int size)
++static int toi_bio_memory_needed(void)
+{
-+ int *ints = (int *) buf;
-+ target_outstanding_io = ints[0];
++ return target_outstanding_io * (PAGE_SIZE + sizeof(struct request) +
++ sizeof(struct bio));
+}
+
+/**
-+ * toi_bio_initialise - initialise bio code at start of some action
-+ * @starting_cycle: Whether starting a hibernation cycle, or just reading or
-+ * writing a sysfs value.
++ * toi_bio_print_debug_stats - put out debugging info in the buffer provided
++ * @buffer: A buffer of size @size into which text should be placed.
++ * @size: The size of @buffer.
++ *
++ * Fill a buffer with debugging info. This is used for both our debug_info sysfs
++ * entry and for recording the same info in dmesg.
+ **/
-+static int toi_bio_initialise(int starting_cycle)
++static int toi_bio_print_debug_stats(char *buffer, int size)
+{
-+ if (starting_cycle) {
-+ max_outstanding_writes = 0;
-+ max_outstanding_reads = 0;
-+ toi_queue_flusher = current;
-+#ifdef MEASURE_MUTEX_CONTENTION
-+ {
-+ int i, j, k;
++ int len = 0;
+
-+ for (i = 0; i < 2; i++)
-+ for (j = 0; j < 2; j++)
-+ for_each_online_cpu(k)
-+ mutex_times[i][j][k] = 0;
-+ }
-+#endif
++ if (toiActiveAllocator != &toi_blockwriter_ops) {
++ len = scnprintf(buffer, size,
++ "- Block I/O inactive.\n");
++ return len;
+ }
+
-+ return 0;
-+}
++ len = scnprintf(buffer, size, "- Block I/O active.\n");
+
-+/**
-+ * toi_bio_cleanup - cleanup after some action
-+ * @finishing_cycle: Whether completing a cycle.
-+ **/
-+static void toi_bio_cleanup(int finishing_cycle)
-+{
-+ if (toi_writer_buffer) {
-+ toi_free_page(11, (unsigned long) toi_writer_buffer);
-+ toi_writer_buffer = NULL;
-+ }
-+}
++ len += scnprintf(buffer + len, size - len,
++ "- Max outstanding reads %d. Max writes %d.\n",
++ max_outstanding_reads, max_outstanding_writes);
+
-+struct toi_bio_ops toi_bio_ops = {
-+ .bdev_page_io = toi_bdev_page_io,
-+ .finish_all_io = toi_finish_all_io,
-+ .update_throughput_throttle = update_throughput_throttle,
-+ .forward_one_page = go_next_page,
-+ .set_extra_page_forward = set_extra_page_forward,
-+ .set_devinfo = toi_set_devinfo,
-+ .read_page = toi_bio_read_page,
-+ .write_page = toi_bio_write_page,
-+ .rw_init = toi_rw_init,
-+ .rw_cleanup = toi_rw_cleanup,
-+ .read_header_init = toi_read_header_init,
-+ .rw_header_chunk = toi_rw_header_chunk,
-+ .rw_header_chunk_noreadahead = toi_rw_header_chunk_noreadahead,
-+ .write_header_chunk_finish = write_header_chunk_finish,
-+ .io_flusher = bio_io_flusher,
-+};
-+EXPORT_SYMBOL_GPL(toi_bio_ops);
++ len += scnprintf(buffer + len, size - len,
++ " Memory_needed: %d x (%lu + %u + %u) = %d bytes.\n",
++ target_outstanding_io,
++ PAGE_SIZE, (unsigned int) sizeof(struct request),
++ (unsigned int) sizeof(struct bio), toi_bio_memory_needed());
+
-+static struct toi_sysfs_data sysfs_params[] = {
-+ SYSFS_INT("target_outstanding_io", SYSFS_RW, &target_outstanding_io,
-+ 0, 16384, 0, NULL),
-+};
++#ifdef MEASURE_MUTEX_CONTENTION
++ {
++ int i;
+
-+static struct toi_module_ops toi_blockwriter_ops = {
-+ .name = "lowlevel i/o",
-+ .type = MISC_HIDDEN_MODULE,
-+ .directory = "block_io",
-+ .module = THIS_MODULE,
-+ .print_debug_info = toi_bio_print_debug_stats,
-+ .memory_needed = toi_bio_memory_needed,
-+ .storage_needed = toi_bio_storage_needed,
-+ .save_config_info = toi_bio_save_config_info,
-+ .load_config_info = toi_bio_load_config_info,
-+ .initialise = toi_bio_initialise,
-+ .cleanup = toi_bio_cleanup,
++ len += scnprintf(buffer + len, size - len,
++ " Mutex contention while reading:\n Contended Free\n");
+
-+ .sysfs_data = sysfs_params,
-+ .num_sysfs_entries = sizeof(sysfs_params) /
-+ sizeof(struct toi_sysfs_data),
-+};
++ for_each_online_cpu(i)
++ len += scnprintf(buffer + len, size - len,
++ " %9lu %9lu\n",
++ mutex_times[0][0][i], mutex_times[0][1][i]);
+
-+/**
-+ * toi_block_io_load - load time routine for block I/O module
-+ *
-+ * Register block i/o ops and sysfs entries.
-+ **/
-+static __init int toi_block_io_load(void)
-+{
-+ return toi_register_module(&toi_blockwriter_ops);
-+}
++ len += scnprintf(buffer + len, size - len,
++ " Mutex contention while writing:\n Contended Free\n");
+
-+#ifdef MODULE
-+static __exit void toi_block_io_unload(void)
-+{
-+ toi_unregister_module(&toi_blockwriter_ops);
-+}
++ for_each_online_cpu(i)
++ len += scnprintf(buffer + len, size - len,
++ " %9lu %9lu\n",
++ mutex_times[1][0][i], mutex_times[1][1][i]);
+
-+module_init(toi_block_io_load);
-+module_exit(toi_block_io_unload);
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Nigel Cunningham");
-+MODULE_DESCRIPTION("TuxOnIce block io functions");
-+#else
-+late_initcall(toi_block_io_load);
++ }
+#endif
-diff --git a/kernel/power/tuxonice_block_io.h b/kernel/power/tuxonice_block_io.h
-new file mode 100644
-index 0000000..b18298c
---- /dev/null
-+++ b/kernel/power/tuxonice_block_io.h
-@@ -0,0 +1,59 @@
-+/*
-+ * kernel/power/tuxonice_block_io.h
-+ *
-+ * Copyright (C) 2004-2008 Nigel Cunningham (nigel at tuxonice net)
-+ * Copyright (C) 2006 Red Hat, inc.
-+ *
-+ * Distributed under GPLv2.
-+ *
-+ * This file contains declarations for functions exported from
-+ * tuxonice_block_io.c, which contains low level io functions.
-+ */
-+
-+#include <linux/buffer_head.h>
-+#include "tuxonice_extent.h"
+
-+struct toi_bdev_info {
-+ struct block_device *bdev;
-+ dev_t dev_t;
-+ int bmap_shift;
-+ int blocks_per_page;
-+ int ignored;
-+};
++ return len + scnprintf(buffer + len, size - len,
++ " Free mem throttle point reached %d.\n", free_mem_throttle);
++}
+
-+/*
-+ * Our exported interface so the swapwriter and filewriter don't
-+ * need these functions duplicated.
-+ */
-+struct toi_bio_ops {
-+ int (*bdev_page_io) (int rw, struct block_device *bdev, long pos,
-+ struct page *page);
-+ void (*check_io_stats) (void);
-+ void (*reset_io_stats) (void);
-+ void (*update_throughput_throttle) (int jif_index);
-+ int (*finish_all_io) (void);
-+ int (*forward_one_page) (int writing, int section_barrier);
-+ void (*set_extra_page_forward) (void);
-+ void (*set_devinfo) (struct toi_bdev_info *info);
-+ int (*read_page) (unsigned long *index, struct page *buffer_page,
-+ unsigned int *buf_size);
-+ int (*write_page) (unsigned long index, struct page *buffer_page,
-+ unsigned int buf_size);
-+ void (*read_header_init) (void);
-+ int (*rw_header_chunk) (int rw, struct toi_module_ops *owner,
-+ char *buffer, int buffer_size);
-+ int (*rw_header_chunk_noreadahead) (int rw,
-+ struct toi_module_ops *owner,
-+ char *buffer, int buffer_size);
-+ int (*write_header_chunk_finish) (void);
-+ int (*rw_init) (int rw, int stream_number);
-+ int (*rw_cleanup) (int rw);
-+ int (*io_flusher) (int rw);
-+};
++static int total_header_bytes;
++static int unowned;
+
-+extern struct toi_bio_ops toi_bio_ops;
++void debug_broken_header(void)
++{
++ printk(KERN_DEBUG "Image header too big for size allocated!\n");
++ print_toi_header_storage_for_modules();
++ printk(KERN_DEBUG "Page flags : %d.\n", toi_pageflags_space_needed());
++ printk(KERN_DEBUG "toi_header : %ld.\n", sizeof(struct toi_header));
++ printk(KERN_DEBUG "Total unowned : %d.\n", unowned);
++ printk(KERN_DEBUG "Total used : %d (%ld pages).\n", total_header_bytes,
++ DIV_ROUND_UP(total_header_bytes, PAGE_SIZE));
++ printk(KERN_DEBUG "Space needed now : %ld.\n",
++ get_header_storage_needed());
++ dump_block_chains();
++ abort_hibernate(TOI_HEADER_TOO_BIG, "Header reservation too small.");
++}
+
-+extern char *toi_writer_buffer;
-+extern int toi_writer_buffer_posn;
-+extern struct hibernate_extent_iterate_saved_state toi_writer_posn_save[4];
-+extern struct toi_extent_iterate_state toi_writer_posn;
-diff --git a/kernel/power/tuxonice_builtin.c b/kernel/power/tuxonice_builtin.c
-new file mode 100644
-index 0000000..2e3be44
---- /dev/null
-+++ b/kernel/power/tuxonice_builtin.c
-@@ -0,0 +1,324 @@
-+/*
-+ * Copyright (C) 2004-2008 Nigel Cunningham (nigel at tuxonice net)
++/**
++ * toi_rw_init - prepare to read or write a stream in the image
++ * @writing: Whether reading or writing.
++ * @stream number: Section of the image being processed.
+ *
-+ * This file is released under the GPLv2.
-+ */
-+#include <linux/resume-trace.h>
-+#include <linux/kernel.h>
-+#include <linux/swap.h>
-+#include <linux/syscalls.h>
-+#include <linux/bio.h>
-+#include <linux/root_dev.h>
-+#include <linux/freezer.h>
-+#include <linux/reboot.h>
-+#include <linux/writeback.h>
-+#include <linux/tty.h>
-+#include <linux/crypto.h>
-+#include <linux/cpu.h>
-+#include <linux/ctype.h>
-+#include "tuxonice_io.h"
-+#include "tuxonice.h"
-+#include "tuxonice_extent.h"
-+#include "tuxonice_netlink.h"
-+#include "tuxonice_prepare_image.h"
-+#include "tuxonice_ui.h"
-+#include "tuxonice_sysfs.h"
-+#include "tuxonice_pagedir.h"
-+#include "tuxonice_modules.h"
-+#include "tuxonice_builtin.h"
-+#include "tuxonice_power_off.h"
++ * Prepare to read or write a section ('stream') in the image.
++ **/
++static int toi_rw_init(int writing, int stream_number)
++{
++ if (stream_number)
++ toi_extent_state_restore(stream_number);
++ else
++ toi_extent_state_goto_start();
+
-+/*
-+ * Highmem related functions (x86 only).
-+ */
++ if (writing) {
++ reset_idx = 0;
++ if (!current_stream)
++ page_idx = 0;
++ } else {
++ reset_idx = 1;
++ }
+
-+#ifdef CONFIG_HIGHMEM
++ atomic_set(&toi_io_done, 0);
++ if (!toi_writer_buffer)
++ toi_writer_buffer = (char *) toi_get_zeroed_page(11,
++ TOI_ATOMIC_GFP);
++ toi_writer_buffer_posn = writing ? 0 : PAGE_SIZE;
++
++ current_stream = stream_number;
++
++ more_readahead = 1;
++
++ return toi_writer_buffer ? 0 : -ENOMEM;
++}
+
+/**
-+ * copyback_high: Restore highmem pages.
++ * toi_bio_queue_write - queue a page for writing
++ * @full_buffer: Pointer to a page to be queued
+ *
-+ * Highmem data and pbe lists are/can be stored in highmem.
-+ * The format is slightly different to the lowmem pbe lists
-+ * used for the assembly code: the last pbe in each page is
-+ * a struct page * instead of struct pbe *, pointing to the
-+ * next page where pbes are stored (or NULL if happens to be
-+ * the end of the list). Since we don't want to generate
-+ * unnecessary deltas against swsusp code, we use a cast
-+ * instead of a union.
++ * Add a page to the queue to be submitted. If we're the queue flusher,
++ * we'll do this once we've dropped toi_bio_mutex, so other threads can
++ * continue to submit I/O while we're on the slow path doing the actual
++ * submission.
+ **/
-+
-+static void copyback_high(void)
++static void toi_bio_queue_write(char **full_buffer)
+{
-+ struct page *pbe_page = (struct page *) restore_highmem_pblist;
-+ struct pbe *this_pbe, *first_pbe;
-+ unsigned long *origpage, *copypage;
-+ int pbe_index = 1;
-+
-+ if (!pbe_page)
-+ return;
++ struct page *page = virt_to_page(*full_buffer);
++ unsigned long flags;
+
-+ this_pbe = (struct pbe *) kmap_atomic(pbe_page, KM_BOUNCE_READ);
-+ first_pbe = this_pbe;
++ *full_buffer = NULL;
++ page->private = 0;
+
-+ while (this_pbe) {
-+ int loop = (PAGE_SIZE / sizeof(unsigned long)) - 1;
++ spin_lock_irqsave(&bio_queue_lock, flags);
++ if (!bio_queue_head)
++ bio_queue_head = page;
++ else
++ bio_queue_tail->private = (unsigned long) page;
+
-+ origpage = kmap_atomic((struct page *) this_pbe->orig_address,
-+ KM_BIO_DST_IRQ);
-+ copypage = kmap_atomic((struct page *) this_pbe->address,
-+ KM_BIO_SRC_IRQ);
++ bio_queue_tail = page;
++ atomic_inc(&toi_bio_queue_size);
+
-+ while (loop >= 0) {
-+ *(origpage + loop) = *(copypage + loop);
-+ loop--;
-+ }
++ spin_unlock_irqrestore(&bio_queue_lock, flags);
++ wake_up(&toi_io_queue_flusher);
++}
+
-+ kunmap_atomic(origpage, KM_BIO_DST_IRQ);
-+ kunmap_atomic(copypage, KM_BIO_SRC_IRQ);
++/**
++ * toi_rw_cleanup - Cleanup after i/o.
++ * @writing: Whether we were reading or writing.
++ *
++ * Flush all I/O and clean everything up after reading or writing a
++ * section of the image.
++ **/
++static int toi_rw_cleanup(int writing)
++{
++ int i, result;
+
-+ if (!this_pbe->next)
-+ break;
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "toi_rw_cleanup.");
++ if (writing) {
++ int result;
+
-+ if (pbe_index < PBES_PER_PAGE) {
-+ this_pbe++;
-+ pbe_index++;
-+ } else {
-+ pbe_page = (struct page *) this_pbe->next;
-+ kunmap_atomic(first_pbe, KM_BOUNCE_READ);
-+ if (!pbe_page)
-+ return;
-+ this_pbe = (struct pbe *) kmap_atomic(pbe_page,
-+ KM_BOUNCE_READ);
-+ first_pbe = this_pbe;
-+ pbe_index = 1;
-+ }
-+ }
-+ kunmap_atomic(first_pbe, KM_BOUNCE_READ);
-+}
++ if (toi_writer_buffer_posn && !test_result_state(TOI_ABORTED))
++ toi_bio_queue_write(&toi_writer_buffer);
+
-+#else /* CONFIG_HIGHMEM */
-+static void copyback_high(void) { }
-+#endif
++ result = toi_bio_queue_flush_pages(0);
+
-+char toi_wait_for_keypress_dev_console(int timeout)
-+{
-+ int fd, this_timeout = 255;
-+ char key = '\0';
-+ struct termios t, t_backup;
++ if (result)
++ return result;
+
-+ /* We should be guaranteed /dev/console exists after populate_rootfs()
-+ * in init/main.c.
-+ */
-+ fd = sys_open("/dev/console", O_RDONLY, 0);
-+ if (fd < 0) {
-+ printk(KERN_INFO "Couldn't open /dev/console.\n");
-+ return key;
++ if (current_stream == 2)
++ toi_extent_state_save(1);
++ else if (current_stream == 1)
++ toi_extent_state_save(3);
+ }
+
-+ if (sys_ioctl(fd, TCGETS, (long)&t) < 0)
-+ goto out_close;
-+
-+ memcpy(&t_backup, &t, sizeof(t));
-+
-+ t.c_lflag &= ~(ISIG|ICANON|ECHO);
-+ t.c_cc[VMIN] = 0;
++ result = toi_finish_all_io();
+
-+new_timeout:
-+ if (timeout > 0) {
-+ this_timeout = timeout < 26 ? timeout : 25;
-+ timeout -= this_timeout;
-+ this_timeout *= 10;
++ while (readahead_list_head) {
++ void *next = (void *) readahead_list_head->private;
++ toi__free_page(12, readahead_list_head);
++ readahead_list_head = next;
+ }
+
-+ t.c_cc[VTIME] = this_timeout;
++ readahead_list_tail = NULL;
+
-+ if (sys_ioctl(fd, TCSETS, (long)&t) < 0)
-+ goto out_restore;
++ if (!current_stream)
++ return result;
+
-+ while (1) {
-+ if (sys_read(fd, &key, 1) <= 0) {
-+ if (timeout)
-+ goto new_timeout;
-+ key = '\0';
-+ break;
-+ }
-+ key = tolower(key);
-+ if (test_toi_state(TOI_SANITY_CHECK_PROMPT)) {
-+ if (key == 'c') {
-+ set_toi_state(TOI_CONTINUE_REQ);
-+ break;
-+ } else if (key == ' ')
-+ break;
-+ } else
-+ break;
++ for (i = 0; i < NUM_REASONS; i++) {
++ if (!atomic_read(&reasons[i]))
++ continue;
++ printk(KERN_DEBUG "Waited for i/o due to %s %d times.\n",
++ reason_name[i], atomic_read(&reasons[i]));
++ atomic_set(&reasons[i], 0);
+ }
+
-+out_restore:
-+ sys_ioctl(fd, TCSETS, (long)&t_backup);
-+out_close:
-+ sys_close(fd);
-+
-+ return key;
++ current_stream = 0;
++ return result;
+}
-+EXPORT_SYMBOL_GPL(toi_wait_for_keypress_dev_console);
-+
-+struct toi_boot_kernel_data toi_bkd __nosavedata
-+ __attribute__((aligned(PAGE_SIZE))) = {
-+ MY_BOOT_KERNEL_DATA_VERSION,
-+ 0,
-+#ifdef CONFIG_TOI_REPLACE_SWSUSP
-+ (1 << TOI_REPLACE_SWSUSP) |
-+#endif
-+ (1 << TOI_NO_FLUSHER_THREAD) |
-+ (1 << TOI_PAGESET2_FULL) | (1 << TOI_LATE_CPU_HOTPLUG),
-+};
-+EXPORT_SYMBOL_GPL(toi_bkd);
+
-+struct block_device *toi_open_by_devnum(dev_t dev, fmode_t mode)
++/**
++ * toi_start_one_readahead - start one page of readahead
++ * @dedicated_thread: Is this a thread dedicated to doing readahead?
++ *
++ * Start one new page of readahead. If this is being called by a thread
++ * whose only just is to submit readahead, don't quit because we failed
++ * to allocate a page.
++ **/
++static int toi_start_one_readahead(int dedicated_thread)
+{
-+ struct block_device *bdev = bdget(dev);
-+ int err = -ENOMEM;
-+ if (bdev)
-+ err = blkdev_get(bdev, mode);
-+ return err ? ERR_PTR(err) : bdev;
-+}
-+EXPORT_SYMBOL_GPL(toi_open_by_devnum);
++ char *buffer = NULL;
++ int oom = 0, result;
+
-+int toi_wait = CONFIG_TOI_DEFAULT_WAIT;
-+EXPORT_SYMBOL_GPL(toi_wait);
++ result = throttle_if_needed(dedicated_thread ? THROTTLE_WAIT : 0);
++ if (result) {
++ printk(KERN_ERR "throttle_if_needed returned %d.\n", result);
++ return result;
++ }
+
-+struct toi_core_fns *toi_core_fns;
-+EXPORT_SYMBOL_GPL(toi_core_fns);
++ mutex_lock(&toi_bio_readahead_mutex);
+
-+unsigned long toi_result;
-+EXPORT_SYMBOL_GPL(toi_result);
++ while (!buffer) {
++ buffer = (char *) toi_get_zeroed_page(12,
++ TOI_ATOMIC_GFP);
++ if (!buffer) {
++ if (oom && !dedicated_thread) {
++ mutex_unlock(&toi_bio_readahead_mutex);
++ printk(KERN_ERR
++ "oom and not dedicated thread.\n");
++ return -ENOMEM;
++ }
+
-+struct pagedir pagedir1 = {1};
-+EXPORT_SYMBOL_GPL(pagedir1);
++ oom = 1;
++ set_free_mem_throttle();
++ do_bio_wait(5);
++ }
++ }
+
-+unsigned long toi_get_nonconflicting_page(void)
-+{
-+ return toi_core_fns->get_nonconflicting_page();
++ result = toi_bio_rw_page(READ, virt_to_page(buffer), 1, 0);
++ if (result == -ENODATA)
++ toi__free_page(12, virt_to_page(buffer));
++ mutex_unlock(&toi_bio_readahead_mutex);
++ if (result)
++ printk(KERN_DEBUG "toi_bio_rw_page returned %d.\n", result);
++ return result;
+}
+
-+int toi_post_context_save(void)
++/**
++ * toi_start_new_readahead - start new readahead
++ * @dedicated_thread: Are we dedicated to this task?
++ *
++ * Start readahead of image pages.
++ *
++ * We can be called as a thread dedicated to this task (may be helpful on
++ * systems with lots of CPUs), in which case we don't exit until there's no
++ * more readahead.
++ *
++ * If this is not called by a dedicated thread, we top up our queue until
++ * there's no more readahead to submit, we've submitted the number given
++ * in target_outstanding_io or the number in progress exceeds the target
++ * outstanding I/O value.
++ *
++ * No mutex needed because this is only ever called by the first cpu.
++ **/
++static int toi_start_new_readahead(int dedicated_thread)
+{
-+ return toi_core_fns->post_context_save();
-+}
++ int last_result, num_submitted = 0;
+
-+int try_tuxonice_hibernate(void)
-+{
-+ if (!toi_core_fns)
-+ return -ENODEV;
++ /* Start a new readahead? */
++ if (!more_readahead)
++ return 0;
+
-+ return toi_core_fns->try_hibernate();
-+}
++ do {
++ last_result = toi_start_one_readahead(dedicated_thread);
+
-+static int num_resume_calls;
-+#ifdef CONFIG_TOI_IGNORE_LATE_INITCALL
-+static int ignore_late_initcall = 1;
-+#else
-+static int ignore_late_initcall;
-+#endif
++ if (last_result) {
++ if (last_result == -ENOMEM || last_result == -ENODATA)
++ return 0;
+
-+int toi_translate_err_default = TOI_CONTINUE_REQ;
-+EXPORT_SYMBOL_GPL(toi_translate_err_default);
++ printk(KERN_DEBUG
++ "Begin read chunk returned %d.\n",
++ last_result);
++ } else
++ num_submitted++;
+
-+void try_tuxonice_resume(void)
-+{
-+ /* Don't let it wrap around eventually */
-+ if (num_resume_calls < 2)
-+ num_resume_calls++;
++ } while (more_readahead && !last_result &&
++ (dedicated_thread ||
++ (num_submitted < target_outstanding_io &&
++ atomic_read(&toi_io_in_progress) < target_outstanding_io)));
+
-+ if (num_resume_calls == 1 && ignore_late_initcall) {
-+ printk(KERN_INFO "TuxOnIce: Ignoring late initcall, as requested.\n");
-+ return;
-+ }
++ return last_result;
++}
+
-+ if (toi_core_fns)
-+ toi_core_fns->try_resume();
++/**
++ * bio_io_flusher - start the dedicated I/O flushing routine
++ * @writing: Whether we're writing the image.
++ **/
++static int bio_io_flusher(int writing)
++{
++
++ if (writing)
++ return toi_bio_queue_flush_pages(1);
+ else
-+ printk(KERN_INFO "TuxOnIce core not loaded yet.\n");
++ return toi_start_new_readahead(1);
+}
+
-+int toi_lowlevel_builtin(void)
++/**
++ * toi_bio_get_next_page_read - read a disk page, perhaps with readahead
++ * @no_readahead: Whether we can use readahead
++ *
++ * Read a page from disk, submitting readahead and cleaning up finished i/o
++ * while we wait for the page we're after.
++ **/
++static int toi_bio_get_next_page_read(int no_readahead)
+{
-+ int error = 0;
++ unsigned long *virt;
++ struct page *next;
+
-+ save_processor_state();
-+ error = swsusp_arch_suspend();
-+ if (error)
-+ printk(KERN_ERR "Error %d hibernating\n", error);
++ /*
++ * When reading the second page of the header, we have to
++ * delay submitting the read until after we've gotten the
++ * extents out of the first page.
++ */
++ if (unlikely(no_readahead && toi_start_one_readahead(0))) {
++ printk(KERN_EMERG "No readahead and toi_start_one_readahead "
++ "returned non-zero.\n");
++ return -EIO;
++ }
+
-+ /* Restore control flow appears here */
-+ if (!toi_in_hibernate) {
-+ copyback_high();
-+ set_toi_state(TOI_NOW_RESUMING);
++ if (unlikely(!readahead_list_head)) {
++ /*
++ * If the last page finishes exactly on the page
++ * boundary, we will be called one extra time and
++ * have no data to return. In this case, we should
++ * not BUG(), like we used to!
++ */
++ if (!more_readahead) {
++ printk(KERN_EMERG "No more readahead.\n");
++ return -ENODATA;
++ }
++ if (unlikely(toi_start_one_readahead(0))) {
++ printk(KERN_EMERG "No readahead and "
++ "toi_start_one_readahead returned non-zero.\n");
++ return -EIO;
++ }
+ }
+
-+ restore_processor_state();
++ if (PageLocked(readahead_list_head)) {
++ waiting_on = readahead_list_head;
++ do_bio_wait(0);
++ }
+
-+ return error;
++ virt = page_address(readahead_list_head);
++ memcpy(toi_writer_buffer, virt, PAGE_SIZE);
++
++ next = (struct page *) readahead_list_head->private;
++ toi__free_page(12, readahead_list_head);
++ readahead_list_head = next;
++ return 0;
+}
-+EXPORT_SYMBOL_GPL(toi_lowlevel_builtin);
+
-+unsigned long toi_compress_bytes_in;
-+EXPORT_SYMBOL_GPL(toi_compress_bytes_in);
++/**
++ * toi_bio_queue_flush_pages - flush the queue of pages queued for writing
++ * @dedicated_thread: Whether we're a dedicated thread
++ *
++ * Flush the queue of pages ready to be written to disk.
++ *
++ * If we're a dedicated thread, stay in here until told to leave,
++ * sleeping in wait_event.
++ *
++ * The first thread is normally the only one to come in here. Another
++ * thread can enter this routine too, though, via throttle_if_needed.
++ * Since that's the case, we must be careful to only have one thread
++ * doing this work at a time. Otherwise we have a race and could save
++ * pages out of order.
++ *
++ * If an error occurs, free all remaining pages without submitting them
++ * for I/O.
++ **/
+
-+unsigned long toi_compress_bytes_out;
-+EXPORT_SYMBOL_GPL(toi_compress_bytes_out);
++int toi_bio_queue_flush_pages(int dedicated_thread)
++{
++ unsigned long flags;
++ int result = 0;
++ static DEFINE_MUTEX(busy);
+
-+unsigned long toi_state = ((1 << TOI_BOOT_TIME) |
-+ (1 << TOI_IGNORE_LOGLEVEL) |
-+ (1 << TOI_IO_STOPPED));
-+EXPORT_SYMBOL_GPL(toi_state);
++ if (!mutex_trylock(&busy))
++ return 0;
+
-+/* The number of hibernates we have started (some may have been cancelled) */
-+unsigned int nr_hibernates;
-+EXPORT_SYMBOL_GPL(nr_hibernates);
-+
-+int toi_running;
-+EXPORT_SYMBOL_GPL(toi_running);
++top:
++ spin_lock_irqsave(&bio_queue_lock, flags);
++ while (bio_queue_head) {
++ struct page *page = bio_queue_head;
++ bio_queue_head = (struct page *) page->private;
++ if (bio_queue_tail == page)
++ bio_queue_tail = NULL;
++ atomic_dec(&toi_bio_queue_size);
++ spin_unlock_irqrestore(&bio_queue_lock, flags);
++ result = toi_bio_rw_page(WRITE, page, 0, 11);
++ /*
++ * If writing the page failed, don't drop out.
++ * Flush the rest of the queue too.
++ */
++ if (result)
++ toi__free_page(11 , page);
++ spin_lock_irqsave(&bio_queue_lock, flags);
++ }
++ spin_unlock_irqrestore(&bio_queue_lock, flags);
+
-+__nosavedata int toi_in_hibernate;
-+EXPORT_SYMBOL_GPL(toi_in_hibernate);
++ if (dedicated_thread) {
++ wait_event(toi_io_queue_flusher, bio_queue_head ||
++ toi_bio_queue_flusher_should_finish);
++ if (likely(!toi_bio_queue_flusher_should_finish))
++ goto top;
++ toi_bio_queue_flusher_should_finish = 0;
++ }
+
-+__nosavedata struct pbe *restore_highmem_pblist;
-+EXPORT_SYMBOL_GPL(restore_highmem_pblist);
++ mutex_unlock(&busy);
++ return result;
++}
+
-+static int __init toi_wait_setup(char *str)
++/**
++ * toi_bio_get_new_page - get a new page for I/O
++ * @full_buffer: Pointer to a page to allocate.
++ **/
++static int toi_bio_get_new_page(char **full_buffer)
+{
-+ int value;
++ int result = throttle_if_needed(THROTTLE_WAIT);
++ if (result)
++ return result;
+
-+ if (sscanf(str, "=%d", &value)) {
-+ if (value < -1 || value > 255)
-+ printk(KERN_INFO "TuxOnIce_wait outside range -1 to "
-+ "255.\n");
-+ else
-+ toi_wait = value;
++ while (!*full_buffer) {
++ *full_buffer = (char *) toi_get_zeroed_page(11, TOI_ATOMIC_GFP);
++ if (!*full_buffer) {
++ set_free_mem_throttle();
++ do_bio_wait(3);
++ }
+ }
+
-+ return 1;
++ return 0;
+}
+
-+__setup("toi_wait", toi_wait_setup);
-+
-+static int __init toi_translate_retry_setup(char *str)
++/**
++ * toi_rw_buffer - combine smaller buffers into PAGE_SIZE I/O
++ * @writing: Bool - whether writing (or reading).
++ * @buffer: The start of the buffer to write or fill.
++ * @buffer_size: The size of the buffer to write or fill.
++ * @no_readahead: Don't try to start readhead (when getting extents).
++ **/
++static int toi_rw_buffer(int writing, char *buffer, int buffer_size,
++ int no_readahead)
+{
-+ toi_translate_err_default = 0;
-+ return 1;
-+}
++ int bytes_left = buffer_size, result = 0;
+
-+__setup("toi_translate_retry", toi_translate_retry_setup);
++ while (bytes_left) {
++ char *source_start = buffer + buffer_size - bytes_left;
++ char *dest_start = toi_writer_buffer + toi_writer_buffer_posn;
++ int capacity = PAGE_SIZE - toi_writer_buffer_posn;
++ char *to = writing ? dest_start : source_start;
++ char *from = writing ? source_start : dest_start;
+
-+static int __init toi_ignore_late_initcall_setup(char *str)
-+{
-+ int value;
++ if (bytes_left <= capacity) {
++ memcpy(to, from, bytes_left);
++ toi_writer_buffer_posn += bytes_left;
++ return 0;
++ }
+
-+ if (sscanf(str, "=%d", &value))
-+ ignore_late_initcall = value;
++ /* Complete this page and start a new one */
++ memcpy(to, from, capacity);
++ bytes_left -= capacity;
+
-+ return 1;
++ if (!writing) {
++ /*
++ * Perform actual I/O:
++ * read readahead_list_head into toi_writer_buffer
++ */
++ int result = toi_bio_get_next_page_read(no_readahead);
++ if (result) {
++ printk("toi_bio_get_next_page_read "
++ "returned %d.\n", result);
++ return result;
++ }
++ } else {
++ toi_bio_queue_write(&toi_writer_buffer);
++ result = toi_bio_get_new_page(&toi_writer_buffer);
++ if (result) {
++ printk(KERN_ERR "toi_bio_get_new_page returned "
++ "%d.\n", result);
++ return result;
++ }
++ }
++
++ toi_writer_buffer_posn = 0;
++ toi_cond_pause(0, NULL);
++ }
++
++ return 0;
+}
+
-+__setup("toi_initramfs_resume_only", toi_ignore_late_initcall_setup);
-diff --git a/kernel/power/tuxonice_builtin.h b/kernel/power/tuxonice_builtin.h
-new file mode 100644
-index 0000000..82d926f
---- /dev/null
-+++ b/kernel/power/tuxonice_builtin.h
-@@ -0,0 +1,28 @@
-+/*
-+ * Copyright (C) 2004-2008 Nigel Cunningham (nigel at tuxonice net)
++/**
++ * toi_bio_read_page - read a page of the image
++ * @pfn: The pfn where the data belongs.
++ * @buffer_page: The page containing the (possibly compressed) data.
++ * @buf_size: The number of bytes on @buffer_page used (PAGE_SIZE).
+ *
-+ * This file is released under the GPLv2.
-+ */
-+#include <asm/setup.h>
++ * Read a (possibly compressed) page from the image, into buffer_page,
++ * returning its pfn and the buffer size.
++ **/
++static int toi_bio_read_page(unsigned long *pfn, struct page *buffer_page,
++ unsigned int *buf_size)
++{
++ int result = 0;
++ int this_idx;
++ char *buffer_virt = kmap(buffer_page);
+
-+extern struct toi_core_fns *toi_core_fns;
-+extern unsigned long toi_compress_bytes_in, toi_compress_bytes_out;
-+extern unsigned int nr_hibernates;
-+extern int toi_in_hibernate;
++ /*
++ * Only call start_new_readahead if we don't have a dedicated thread
++ * and we're the queue flusher.
++ */
++ if (current == toi_queue_flusher && more_readahead) {
++ int result2 = toi_start_new_readahead(0);
++ if (result2) {
++ printk(KERN_DEBUG "Queue flusher and "
++ "toi_start_one_readahead returned non-zero.\n");
++ result = -EIO;
++ goto out;
++ }
++ }
+
-+extern __nosavedata struct pbe *restore_highmem_pblist;
++ my_mutex_lock(0, &toi_bio_mutex);
+
-+int toi_lowlevel_builtin(void);
++ /*
++ * Structure in the image:
++ * [destination pfn|page size|page data]
++ * buf_size is PAGE_SIZE
++ */
++ if (toi_rw_buffer(READ, (char *) &this_idx, sizeof(int), 0) ||
++ toi_rw_buffer(READ, (char *) pfn, sizeof(unsigned long), 0) ||
++ toi_rw_buffer(READ, (char *) buf_size, sizeof(int), 0) ||
++ toi_rw_buffer(READ, buffer_virt, *buf_size, 0)) {
++ abort_hibernate(TOI_FAILED_IO, "Read of data failed.");
++ result = 1;
++ }
+
-+#ifdef CONFIG_HIGHMEM
-+extern __nosavedata struct zone_data *toi_nosave_zone_list;
-+extern __nosavedata unsigned long toi_nosave_max_pfn;
-+#endif
++ if (reset_idx) {
++ page_idx = this_idx;
++ reset_idx = 0;
++ } else {
++ page_idx++;
++ if (page_idx != this_idx)
++ printk(KERN_ERR "Got page index %d, expected %d.\n",
++ this_idx, page_idx);
++ }
+
-+extern unsigned long toi_get_nonconflicting_page(void);
-+extern int toi_post_context_save(void);
++ my_mutex_unlock(0, &toi_bio_mutex);
++out:
++ kunmap(buffer_page);
++ return result;
++}
+
-+extern char toi_wait_for_keypress_dev_console(int timeout);
-+extern struct block_device *toi_open_by_devnum(dev_t dev, fmode_t mode);
-+extern int toi_wait;
-+extern int toi_translate_err_default;
-diff --git a/kernel/power/tuxonice_checksum.c b/kernel/power/tuxonice_checksum.c
-new file mode 100644
-index 0000000..b0adc17
---- /dev/null
-+++ b/kernel/power/tuxonice_checksum.c
-@@ -0,0 +1,375 @@
-+/*
-+ * kernel/power/tuxonice_checksum.c
-+ *
-+ * Copyright (C) 2006-2008 Nigel Cunningham (nigel at tuxonice net)
-+ * Copyright (C) 2006 Red Hat, inc.
-+ *
-+ * This file is released under the GPLv2.
++/**
++ * toi_bio_write_page - write a page of the image
++ * @pfn: The pfn where the data belongs.
++ * @buffer_page: The page containing the (possibly compressed) data.
++ * @buf_size: The number of bytes on @buffer_page used.
+ *
-+ * This file contains data checksum routines for TuxOnIce,
-+ * using cryptoapi. They are used to locate any modifications
-+ * made to pageset 2 while we're saving it.
-+ */
++ * Write a (possibly compressed) page to the image from the buffer, together
++ * with it's index and buffer size.
++ **/
++static int toi_bio_write_page(unsigned long pfn, struct page *buffer_page,
++ unsigned int buf_size)
++{
++ char *buffer_virt;
++ int result = 0, result2 = 0;
+
-+#include <linux/suspend.h>
-+#include <linux/highmem.h>
-+#include <linux/vmalloc.h>
-+#include <linux/crypto.h>
-+#include <linux/scatterlist.h>
++ if (unlikely(test_action_state(TOI_TEST_FILTER_SPEED)))
++ return 0;
+
-+#include "tuxonice.h"
-+#include "tuxonice_modules.h"
-+#include "tuxonice_sysfs.h"
-+#include "tuxonice_io.h"
-+#include "tuxonice_pageflags.h"
-+#include "tuxonice_checksum.h"
-+#include "tuxonice_pagedir.h"
-+#include "tuxonice_alloc.h"
++ my_mutex_lock(1, &toi_bio_mutex);
+
-+static struct toi_module_ops toi_checksum_ops;
++ if (test_result_state(TOI_ABORTED)) {
++ my_mutex_unlock(1, &toi_bio_mutex);
++ return -EIO;
++ }
+
-+/* Constant at the mo, but I might allow tuning later */
-+static char toi_checksum_name[32] = "md4";
-+/* Bytes per checksum */
-+#define CHECKSUM_SIZE (16)
++ buffer_virt = kmap(buffer_page);
++ page_idx++;
+
-+#define CHECKSUMS_PER_PAGE ((PAGE_SIZE - sizeof(void *)) / CHECKSUM_SIZE)
++ /*
++ * Structure in the image:
++ * [destination pfn|page size|page data]
++ * buf_size is PAGE_SIZE
++ */
++ if (toi_rw_buffer(WRITE, (char *) &page_idx, sizeof(int), 0) ||
++ toi_rw_buffer(WRITE, (char *) &pfn, sizeof(unsigned long), 0) ||
++ toi_rw_buffer(WRITE, (char *) &buf_size, sizeof(int), 0) ||
++ toi_rw_buffer(WRITE, buffer_virt, buf_size, 0)) {
++ printk(KERN_DEBUG "toi_rw_buffer returned non-zero to "
++ "toi_bio_write_page.\n");
++ result = -EIO;
++ }
+
-+struct cpu_context {
-+ struct crypto_hash *transform;
-+ struct hash_desc desc;
-+ struct scatterlist sg[2];
-+ char *buf;
-+};
-+
-+static DEFINE_PER_CPU(struct cpu_context, contexts);
-+static int pages_allocated;
-+static unsigned long page_list;
-+
-+static int toi_num_resaved;
++ kunmap(buffer_page);
++ my_mutex_unlock(1, &toi_bio_mutex);
+
-+static unsigned long this_checksum, next_page;
-+static int checksum_index;
++ if (current == toi_queue_flusher)
++ result2 = toi_bio_queue_flush_pages(0);
+
-+static inline int checksum_pages_needed(void)
-+{
-+ return DIV_ROUND_UP(pagedir2.size, CHECKSUMS_PER_PAGE);
++ return result ? result : result2;
+}
+
-+/* ---- Local buffer management ---- */
-+
-+/*
-+ * toi_checksum_cleanup
++/**
++ * _toi_rw_header_chunk - read or write a portion of the image header
++ * @writing: Whether reading or writing.
++ * @owner: The module for which we're writing.
++ * Used for confirming that modules
++ * don't use more header space than they asked for.
++ * @buffer: Address of the data to write.
++ * @buffer_size: Size of the data buffer.
++ * @no_readahead: Don't try to start readhead (when getting extents).
+ *
-+ * Frees memory allocated for our labours.
-+ */
-+static void toi_checksum_cleanup(int ending_cycle)
++ * Perform PAGE_SIZE I/O. Start readahead if needed.
++ **/
++static int _toi_rw_header_chunk(int writing, struct toi_module_ops *owner,
++ char *buffer, int buffer_size, int no_readahead)
+{
-+ int cpu;
-+
-+ if (ending_cycle) {
-+ for_each_online_cpu(cpu) {
-+ struct cpu_context *this = &per_cpu(contexts, cpu);
-+ if (this->transform) {
-+ crypto_free_hash(this->transform);
-+ this->transform = NULL;
-+ this->desc.tfm = NULL;
-+ }
++ int result = 0;
+
-+ if (this->buf) {
-+ toi_free_page(27, (unsigned long) this->buf);
-+ this->buf = NULL;
-+ }
++ if (owner) {
++ owner->header_used += buffer_size;
++ toi_message(TOI_HEADER, TOI_LOW, 1,
++ "Header: %s : %d bytes (%d/%d) from offset %d.",
++ owner->name,
++ buffer_size, owner->header_used,
++ owner->header_requested,
++ toi_writer_buffer_posn);
++ if (owner->header_used > owner->header_requested && writing) {
++ printk(KERN_EMERG "TuxOnIce module %s is using more "
++ "header space (%u) than it requested (%u).\n",
++ owner->name,
++ owner->header_used,
++ owner->header_requested);
++ return buffer_size;
+ }
++ } else {
++ unowned += buffer_size;
++ toi_message(TOI_HEADER, TOI_LOW, 1,
++ "Header: (No owner): %d bytes (%d total so far) from "
++ "offset %d.", buffer_size, unowned,
++ toi_writer_buffer_posn);
+ }
-+}
-+
-+/*
-+ * toi_crypto_initialise
-+ *
-+ * Prepare to do some work by allocating buffers and transforms.
-+ * Returns: Int: Zero. Even if we can't set up checksum, we still
-+ * seek to hibernate.
-+ */
-+static int toi_checksum_initialise(int starting_cycle)
-+{
-+ int cpu;
-+
-+ if (!(starting_cycle & SYSFS_HIBERNATE) || !toi_checksum_ops.enabled)
-+ return 0;
+
-+ if (!*toi_checksum_name) {
-+ printk(KERN_INFO "TuxOnIce: No checksum algorithm name set.\n");
-+ return 1;
++ if (!writing && !no_readahead && more_readahead) {
++ result = toi_start_new_readahead(0);
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Start new readahead "
++ "returned %d.", result);
+ }
+
-+ for_each_online_cpu(cpu) {
-+ struct cpu_context *this = &per_cpu(contexts, cpu);
-+ struct page *page;
-+
-+ this->transform = crypto_alloc_hash(toi_checksum_name, 0, 0);
-+ if (IS_ERR(this->transform)) {
-+ printk(KERN_INFO "TuxOnIce: Failed to initialise the "
-+ "%s checksum algorithm: %ld.\n",
-+ toi_checksum_name, (long) this->transform);
-+ this->transform = NULL;
-+ return 1;
-+ }
-+
-+ this->desc.tfm = this->transform;
-+ this->desc.flags = 0;
-+
-+ page = toi_alloc_page(27, GFP_KERNEL);
-+ if (!page)
-+ return 1;
-+ this->buf = page_address(page);
-+ sg_init_one(&this->sg[0], this->buf, PAGE_SIZE);
++ if (!result) {
++ result = toi_rw_buffer(writing, buffer, buffer_size,
++ no_readahead);
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "rw_buffer returned "
++ "%d.", result);
+ }
-+ return 0;
-+}
+
-+/*
-+ * toi_checksum_print_debug_stats
-+ * @buffer: Pointer to a buffer into which the debug info will be printed.
-+ * @size: Size of the buffer.
-+ *
-+ * Print information to be recorded for debugging purposes into a buffer.
-+ * Returns: Number of characters written to the buffer.
-+ */
++ total_header_bytes += buffer_size;
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "_toi_rw_header_chunk returning "
++ "%d.", result);
++ return result;
++}
+
-+static int toi_checksum_print_debug_stats(char *buffer, int size)
++static int toi_rw_header_chunk(int writing, struct toi_module_ops *owner,
++ char *buffer, int size)
+{
-+ int len;
-+
-+ if (!toi_checksum_ops.enabled)
-+ return scnprintf(buffer, size,
-+ "- Checksumming disabled.\n");
-+
-+ len = scnprintf(buffer, size, "- Checksum method is '%s'.\n",
-+ toi_checksum_name);
-+ len += scnprintf(buffer + len, size - len,
-+ " %d pages resaved in atomic copy.\n", toi_num_resaved);
-+ return len;
++ return _toi_rw_header_chunk(writing, owner, buffer, size, 1);
+}
+
-+static int toi_checksum_memory_needed(void)
++static int toi_rw_header_chunk_noreadahead(int writing,
++ struct toi_module_ops *owner, char *buffer, int size)
+{
-+ return toi_checksum_ops.enabled ?
-+ checksum_pages_needed() << PAGE_SHIFT : 0;
++ return _toi_rw_header_chunk(writing, owner, buffer, size, 1);
+}
+
-+static int toi_checksum_storage_needed(void)
++/**
++ * toi_bio_storage_needed - get the amount of storage needed for my fns
++ **/
++static int toi_bio_storage_needed(void)
+{
-+ if (toi_checksum_ops.enabled)
-+ return strlen(toi_checksum_name) + sizeof(int) + 1;
-+ else
-+ return 0;
++ return sizeof(int) + PAGE_SIZE + toi_bio_devinfo_storage_needed();
+}
+
-+/*
-+ * toi_checksum_save_config_info
-+ * @buffer: Pointer to a buffer of size PAGE_SIZE.
-+ *
-+ * Save informaton needed when reloading the image at resume time.
-+ * Returns: Number of bytes used for saving our data.
-+ */
-+static int toi_checksum_save_config_info(char *buffer)
++/**
++ * toi_bio_save_config_info - save block I/O config to image header
++ * @buf: PAGE_SIZE'd buffer into which data should be saved.
++ **/
++static int toi_bio_save_config_info(char *buf)
+{
-+ int namelen = strlen(toi_checksum_name) + 1;
-+ int total_len;
-+
-+ *((unsigned int *) buffer) = namelen;
-+ strncpy(buffer + sizeof(unsigned int), toi_checksum_name, namelen);
-+ total_len = sizeof(unsigned int) + namelen;
-+ return total_len;
++ int *ints = (int *) buf;
++ ints[0] = target_outstanding_io;
++ return sizeof(int);
+}
+
-+/* toi_checksum_load_config_info
-+ * @buffer: Pointer to the start of the data.
-+ * @size: Number of bytes that were saved.
-+ *
-+ * Description: Reload information needed for dechecksuming the image at
-+ * resume time.
-+ */
-+static void toi_checksum_load_config_info(char *buffer, int size)
++/**
++ * toi_bio_load_config_info - restore block I/O config
++ * @buf: Data to be reloaded.
++ * @size: Size of the buffer saved.
++ **/
++static void toi_bio_load_config_info(char *buf, int size)
+{
-+ int namelen;
-+
-+ namelen = *((unsigned int *) (buffer));
-+ strncpy(toi_checksum_name, buffer + sizeof(unsigned int),
-+ namelen);
-+ return;
++ int *ints = (int *) buf;
++ target_outstanding_io = ints[0];
+}
+
-+/*
-+ * Free Checksum Memory
-+ */
-+
-+void free_checksum_pages(void)
++static void close_resume_dev_t(int force)
+{
-+ while (pages_allocated) {
-+ unsigned long next = *((unsigned long *) page_list);
-+ ClearPageNosave(virt_to_page(page_list));
-+ toi_free_page(15, (unsigned long) page_list);
-+ page_list = next;
-+ pages_allocated--;
++ if ((force || atomic_dec_and_test(&resume_bdev_open_count)) &&
++ resume_block_device) {
++ toi_close_bdev(resume_block_device);
++ resume_block_device = NULL;
+ }
+}
+
-+/*
-+ * Allocate Checksum Memory
-+ */
-+
-+int allocate_checksum_pages(void)
++static int open_resume_dev_t(int force, int quiet)
+{
-+ int pages_needed = checksum_pages_needed();
++ if (force)
++ close_resume_dev_t(1);
++ else
++ atomic_inc(&resume_bdev_open_count);
+
-+ if (!toi_checksum_ops.enabled)
++ if (resume_block_device)
+ return 0;
+
-+ while (pages_allocated < pages_needed) {
-+ unsigned long *new_page =
-+ (unsigned long *) toi_get_zeroed_page(15, TOI_ATOMIC_GFP);
-+ if (!new_page) {
-+ printk(KERN_ERR "Unable to allocate checksum pages.\n");
-+ return -ENOMEM;
-+ }
-+ SetPageNosave(virt_to_page(new_page));
-+ (*new_page) = page_list;
-+ page_list = (unsigned long) new_page;
-+ pages_allocated++;
++ resume_block_device = toi_open_bdev(NULL, resume_dev_t, 0);
++ if (IS_ERR(resume_block_device)) {
++ if (!quiet)
++ toi_early_boot_message(1, TOI_CONTINUE_REQ,
++ "Failed to open device %x, where"
++ " the header should be found.",
++ resume_dev_t);
++ return 1;
+ }
+
-+ next_page = (unsigned long) page_list;
-+ checksum_index = 0;
-+
+ return 0;
+}
+
-+char *tuxonice_get_next_checksum(void)
++/**
++ * toi_bio_initialise - initialise bio code at start of some action
++ * @starting_cycle: Whether starting a hibernation cycle, or just reading or
++ * writing a sysfs value.
++ **/
++static int toi_bio_initialise(int starting_cycle)
+{
-+ if (!toi_checksum_ops.enabled)
-+ return NULL;
++ int result;
+
-+ if (checksum_index % CHECKSUMS_PER_PAGE)
-+ this_checksum += CHECKSUM_SIZE;
-+ else {
-+ this_checksum = next_page + sizeof(void *);
-+ next_page = *((unsigned long *) next_page);
-+ }
++ if (!starting_cycle || !resume_dev_t)
++ return 0;
+
-+ checksum_index++;
-+ return (char *) this_checksum;
++ max_outstanding_writes = 0;
++ max_outstanding_reads = 0;
++ current_stream = 0;
++ toi_queue_flusher = current;
++#ifdef MEASURE_MUTEX_CONTENTION
++ {
++ int i, j, k;
++
++ for (i = 0; i < 2; i++)
++ for (j = 0; j < 2; j++)
++ for_each_online_cpu(k)
++ mutex_times[i][j][k] = 0;
++ }
++#endif
++ result = open_resume_dev_t(0, 1);
++
++ if (result)
++ return result;
++
++ return get_signature_page();
+}
+
-+int tuxonice_calc_checksum(struct page *page, char *checksum_locn)
++static unsigned long raw_to_real(unsigned long raw)
+{
-+ char *pa;
-+ int result, cpu = smp_processor_id();
-+ struct cpu_context *ctx = &per_cpu(contexts, cpu);
++ unsigned long result;
+
-+ if (!toi_checksum_ops.enabled)
-+ return 0;
++ result = raw - (raw * (sizeof(unsigned long) + sizeof(int)) +
++ (PAGE_SIZE + sizeof(unsigned long) + sizeof(int) + 1)) /
++ (PAGE_SIZE + sizeof(unsigned long) + sizeof(int));
+
-+ pa = kmap(page);
-+ memcpy(ctx->buf, pa, PAGE_SIZE);
-+ kunmap(page);
-+ result = crypto_hash_digest(&ctx->desc, ctx->sg, PAGE_SIZE,
-+ checksum_locn);
-+ return result;
++ return result < 0 ? 0 : result;
++}
++
++static unsigned long toi_bio_storage_available(void)
++{
++ unsigned long sum = 0;
++ struct toi_module_ops *this_module;
++
++ list_for_each_entry(this_module, &toi_modules, module_list) {
++ if (!this_module->enabled ||
++ this_module->type != BIO_ALLOCATOR_MODULE)
++ continue;
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Seeking storage "
++ "available from %s.", this_module->name);
++ sum += this_module->bio_allocator_ops->storage_available();
++ }
++
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Total storage available is %lu "
++ "pages.", sum);
++ return raw_to_real(sum - header_pages_reserved);
++
++}
++
++static unsigned long toi_bio_storage_allocated(void)
++{
++ return raw_pages_allocd > header_pages_reserved ?
++ raw_to_real(raw_pages_allocd - header_pages_reserved) : 0;
+}
++
+/*
-+ * Calculate checksums
++ * If we have read part of the image, we might have filled memory with
++ * data that should be zeroed out.
+ */
-+
-+void check_checksums(void)
++static void toi_bio_noresume_reset(void)
+{
-+ int pfn, index = 0, cpu = smp_processor_id();
-+ char current_checksum[CHECKSUM_SIZE];
-+ struct cpu_context *ctx = &per_cpu(contexts, cpu);
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "toi_bio_noresume_reset.");
++ toi_rw_cleanup(READ);
++ free_all_bdev_info();
++}
+
-+ if (!toi_checksum_ops.enabled)
++/**
++ * toi_bio_cleanup - cleanup after some action
++ * @finishing_cycle: Whether completing a cycle.
++ **/
++static void toi_bio_cleanup(int finishing_cycle)
++{
++ if (!finishing_cycle)
+ return;
+
-+ next_page = (unsigned long) page_list;
++ if (toi_writer_buffer) {
++ toi_free_page(11, (unsigned long) toi_writer_buffer);
++ toi_writer_buffer = NULL;
++ }
+
-+ toi_num_resaved = 0;
-+ this_checksum = 0;
++ forget_signature_page();
+
-+ memory_bm_position_reset(pageset2_map);
-+ for (pfn = memory_bm_next_pfn(pageset2_map); pfn != BM_END_OF_MAP;
-+ pfn = memory_bm_next_pfn(pageset2_map)) {
-+ int ret;
-+ char *pa;
-+ struct page *page = pfn_to_page(pfn);
++ if (header_block_device && toi_sig_data &&
++ toi_sig_data->header_dev_t != resume_dev_t)
++ toi_close_bdev(header_block_device);
+
-+ if (index % CHECKSUMS_PER_PAGE) {
-+ this_checksum += CHECKSUM_SIZE;
-+ } else {
-+ this_checksum = next_page + sizeof(void *);
-+ next_page = *((unsigned long *) next_page);
-+ }
++ header_block_device = NULL;
++}
+
-+ /* Done when IRQs disabled so must be atomic */
-+ pa = kmap_atomic(page, KM_USER1);
-+ memcpy(ctx->buf, pa, PAGE_SIZE);
-+ kunmap_atomic(pa, KM_USER1);
-+ ret = crypto_hash_digest(&ctx->desc, ctx->sg, PAGE_SIZE,
-+ current_checksum);
++static int toi_bio_write_header_init(void)
++{
++ int result;
+
-+ if (ret) {
-+ printk(KERN_INFO "Digest failed. Returned %d.\n", ret);
-+ return;
-+ }
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "toi_bio_write_header_init");
++ toi_rw_init(WRITE, 0);
++ toi_writer_buffer_posn = 0;
+
-+ if (memcmp(current_checksum, (char *) this_checksum,
-+ CHECKSUM_SIZE)) {
-+ SetPageResave(pfn_to_page(pfn));
-+ toi_num_resaved++;
-+ if (test_action_state(TOI_ABORT_ON_RESAVE_NEEDED))
-+ set_abort_result(TOI_RESAVE_NEEDED);
-+ }
++ /* Info needed to bootstrap goes at the start of the header.
++ * First we save the positions and devinfo, including the number
++ * of header pages. Then we save the structs containing data needed
++ * for reading the header pages back.
++ * Note that even if header pages take more than one page, when we
++ * read back the info, we will have restored the location of the
++ * next header page by the time we go to use it.
++ */
+
-+ index++;
-+ }
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "serialise extent chains.");
++ result = toi_serialise_extent_chains();
++
++ if (result)
++ return result;
++
++ /*
++ * Signature page hasn't been modified at this point. Write it in
++ * the header so we can restore it later.
++ */
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "serialise signature page.");
++ return toi_rw_header_chunk_noreadahead(WRITE, &toi_blockwriter_ops,
++ (char *) toi_cur_sig_page,
++ PAGE_SIZE);
+}
+
-+static struct toi_sysfs_data sysfs_params[] = {
-+ SYSFS_INT("enabled", SYSFS_RW, &toi_checksum_ops.enabled, 0, 1, 0,
-+ NULL),
-+ SYSFS_BIT("abort_if_resave_needed", SYSFS_RW, &toi_bkd.toi_action,
-+ TOI_ABORT_ON_RESAVE_NEEDED, 0)
-+};
++static int toi_bio_write_header_cleanup(void)
++{
++ int result = 0;
++
++ if (toi_writer_buffer_posn)
++ toi_bio_queue_write(&toi_writer_buffer);
++
++ result = toi_finish_all_io();
++
++ unowned = 0;
++ total_header_bytes = 0;
++
++ /* Set signature to save we have an image */
++ if (!result)
++ result = toi_bio_mark_have_image();
++
++ return result;
++}
+
+/*
-+ * Ops structure.
++ * toi_bio_read_header_init()
++ *
++ * Description:
++ * 1. Attempt to read the device specified with resume=.
++ * 2. Check the contents of the swap header for our signature.
++ * 3. Warn, ignore, reset and/or continue as appropriate.
++ * 4. If continuing, read the toi_swap configuration section
++ * of the header and set up block device info so we can read
++ * the rest of the header & image.
++ *
++ * Returns:
++ * May not return if user choose to reboot at a warning.
++ * -EINVAL if cannot resume at this time. Booting should continue
++ * normally.
+ */
-+static struct toi_module_ops toi_checksum_ops = {
-+ .type = MISC_MODULE,
-+ .name = "checksumming",
-+ .directory = "checksum",
-+ .module = THIS_MODULE,
-+ .initialise = toi_checksum_initialise,
-+ .cleanup = toi_checksum_cleanup,
-+ .print_debug_info = toi_checksum_print_debug_stats,
-+ .save_config_info = toi_checksum_save_config_info,
-+ .load_config_info = toi_checksum_load_config_info,
-+ .memory_needed = toi_checksum_memory_needed,
-+ .storage_needed = toi_checksum_storage_needed,
-+
-+ .sysfs_data = sysfs_params,
-+ .num_sysfs_entries = sizeof(sysfs_params) /
-+ sizeof(struct toi_sysfs_data),
-+};
+
-+/* ---- Registration ---- */
-+int toi_checksum_init(void)
++static int toi_bio_read_header_init(void)
+{
-+ int result = toi_register_module(&toi_checksum_ops);
-+ return result;
++ int result = 0;
++ char buf[32];
++
++ toi_writer_buffer_posn = 0;
++
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "toi_bio_read_header_init");
++
++ if (!toi_sig_data) {
++ printk(KERN_INFO "toi_bio_read_header_init called when we "
++ "haven't verified there is an image!\n");
++ return -EINVAL;
++ }
++
++ /*
++ * If the header is not on the resume_swap_dev_t, get the resume device
++ * first.
++ */
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Header dev_t is %lx.",
++ toi_sig_data->header_dev_t);
++ if (toi_sig_data->have_uuid) {
++ dev_t device;
++ device = blk_lookup_uuid(toi_sig_data->header_uuid);
++ if (device) {
++ printk("Using dev_t %s, returned by blk_lookup_uuid.\n",
++ format_dev_t(buf, device));
++ toi_sig_data->header_dev_t = device;
++ }
++ }
++ if (toi_sig_data->header_dev_t != resume_dev_t) {
++ header_block_device = toi_open_bdev(NULL,
++ toi_sig_data->header_dev_t, 1);
++
++ if (IS_ERR(header_block_device))
++ return PTR_ERR(header_block_device);
++ } else
++ header_block_device = resume_block_device;
++
++ if (!toi_writer_buffer)
++ toi_writer_buffer = (char *) toi_get_zeroed_page(11,
++ TOI_ATOMIC_GFP);
++ more_readahead = 1;
++
++ /*
++ * Read toi_swap configuration.
++ * Headerblock size taken into account already.
++ */
++ result = toi_bio_ops.bdev_page_io(READ, header_block_device,
++ toi_sig_data->first_header_block,
++ virt_to_page((unsigned long) toi_writer_buffer));
++ if (result)
++ return result;
++
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "load extent chains.");
++ result = toi_load_extent_chains();
++
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "load original signature page.");
++ toi_orig_sig_page = (char *) toi_get_zeroed_page(38, TOI_ATOMIC_GFP);
++ if (!toi_orig_sig_page) {
++ printk(KERN_ERR "Failed to allocate memory for the current"
++ " image signature.\n");
++ return -ENOMEM;
++ }
++
++ return toi_rw_header_chunk_noreadahead(READ, &toi_blockwriter_ops,
++ (char *) toi_orig_sig_page,
++ PAGE_SIZE);
+}
+
-+void toi_checksum_exit(void)
++static int toi_bio_read_header_cleanup(void)
+{
-+ toi_unregister_module(&toi_checksum_ops);
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "toi_bio_read_header_cleanup.");
++ return toi_rw_cleanup(READ);
+}
-diff --git a/kernel/power/tuxonice_checksum.h b/kernel/power/tuxonice_checksum.h
-new file mode 100644
-index 0000000..84a9174
---- /dev/null
-+++ b/kernel/power/tuxonice_checksum.h
-@@ -0,0 +1,32 @@
++
++/* Works only for digits and letters, but small and fast */
++#define TOLOWER(x) ((x) | 0x20)
++
+/*
-+ * kernel/power/tuxonice_checksum.h
-+ *
-+ * Copyright (C) 2006-2008 Nigel Cunningham (nigel at tuxonice net)
-+ * Copyright (C) 2006 Red Hat, inc.
-+ *
-+ * This file is released under the GPLv2.
-+ *
-+ * This file contains data checksum routines for TuxOnIce,
-+ * using cryptoapi. They are used to locate any modifications
-+ * made to pageset 2 while we're saving it.
++ * UUID must be 32 chars long. It may have dashes, but nothing
++ * else.
+ */
++char *uuid_from_commandline(char *commandline)
++{
++ int low = 0;
++ char *result = NULL, *output, *ptr;
+
-+#if defined(CONFIG_TOI_CHECKSUM)
-+extern int toi_checksum_init(void);
-+extern void toi_checksum_exit(void);
-+void check_checksums(void);
-+int allocate_checksum_pages(void);
-+void free_checksum_pages(void);
-+char *tuxonice_get_next_checksum(void);
-+int tuxonice_calc_checksum(struct page *page, char *checksum_locn);
-+#else
-+static inline int toi_checksum_init(void) { return 0; }
-+static inline void toi_checksum_exit(void) { }
-+static inline void check_checksums(void) { };
-+static inline int allocate_checksum_pages(void) { return 0; };
-+static inline void free_checksum_pages(void) { };
-+static inline char *tuxonice_get_next_checksum(void) { return NULL; };
-+static inline int tuxonice_calc_checksum(struct page *page, char *checksum_locn)
-+ { return 0; }
-+#endif
++ if (strncmp(commandline, "UUID=", 5))
++ return NULL;
+
-diff --git a/kernel/power/tuxonice_cluster.c b/kernel/power/tuxonice_cluster.c
-new file mode 100644
-index 0000000..671006d
---- /dev/null
-+++ b/kernel/power/tuxonice_cluster.c
-@@ -0,0 +1,1069 @@
-+/*
-+ * kernel/power/tuxonice_cluster.c
-+ *
-+ * Copyright (C) 2006-2008 Nigel Cunningham (nigel at tuxonice net)
-+ *
-+ * This file is released under the GPLv2.
-+ *
-+ * This file contains routines for cluster hibernation support.
-+ *
-+ * Based on ip autoconfiguration code in net/ipv4/ipconfig.c.
-+ *
-+ * How does it work?
-+ *
-+ * There is no 'master' node that tells everyone else what to do. All nodes
-+ * send messages to the broadcast address/port, maintain a list of peers
-+ * and figure out when to progress to the next step in hibernating or resuming.
-+ * This makes us more fault tolerant when it comes to nodes coming and going
-+ * (which may be more of an issue if we're hibernating when power supplies
-+ * are being unreliable).
-+ *
-+ * At boot time, we start a ktuxonice thread that handles communication with
-+ * other nodes. This node maintains a state machine that controls our progress
-+ * through hibernating and resuming, keeping us in step with other nodes. Nodes
-+ * are identified by their hw address.
-+ *
-+ * On startup, the node sends CLUSTER_PING on the configured interface's
-+ * broadcast address, port $toi_cluster_port (see below) and begins to listen
-+ * for other broadcast messages. CLUSTER_PING messages are repeated at
-+ * intervals of 5 minutes, with a random offset to spread traffic out.
-+ *
-+ * A hibernation cycle is initiated from any node via
-+ *
-+ * echo > /sys/power/tuxonice/do_hibernate
-+ *
-+ * and (possibily) the hibernate script. At each step of the process, the node
-+ * completes its work, and waits for all other nodes to signal completion of
-+ * their work (or timeout) before progressing to the next step.
-+ *
-+ * Request/state Action before reply Possible reply Next state
-+ * HIBERNATE capable, pre-script HIBERNATE|ACK NODE_PREP
-+ * HIBERNATE|NACK INIT_0
-+ *
-+ * PREP prepare_image PREP|ACK IMAGE_WRITE
-+ * PREP|NACK INIT_0
-+ * ABORT RUNNING
-+ *
-+ * IO write image IO|ACK power off
-+ * ABORT POST_RESUME
-+ *
-+ * (Boot time) check for image IMAGE|ACK RESUME_PREP
-+ * (Note 1)
-+ * IMAGE|NACK (Note 2)
-+ *
-+ * PREP prepare read image PREP|ACK IMAGE_READ
-+ * PREP|NACK (As NACK_IMAGE)
-+ *
-+ * IO read image IO|ACK POST_RESUME
++ result = kzalloc(17, GFP_KERNEL);
++ if (!result) {
++ printk("Failed to kzalloc UUID text memory.\n");
++ return NULL;
++ }
++
++ ptr = commandline + 5;
++ output = result;
++
++ while (*ptr && (output - result) < 16) {
++ if (isxdigit(*ptr)) {
++ int value = isdigit(*ptr) ? *ptr - '0' :
++ TOLOWER(*ptr) - 'a' + 10;
++ if (low) {
++ *output += value;
++ output++;
++ } else {
++ *output = value << 4;
++ }
++ low = !low;
++ } else if (*ptr != '-')
++ break;
++ ptr++;
++ }
++
++ if ((output - result) < 16 || *ptr) {
++ printk(KERN_DEBUG "Found resume=UUID=, but the value looks "
++ "invalid.\n");
++ kfree(result);
++ result = NULL;
++ }
++
++ return result;
++}
++
++/**
++ * try_to_open_resume_device: Try to parse and open resume=
+ *
-+ * POST_RESUME thaw, post-script RUNNING
++ * Any "swap:" has been stripped away and we just have the path to deal with.
++ * We attempt to do name_to_dev_t, open and stat the file. Having opened the
++ * file, get the struct block_device * to match.
++ */
++static int try_to_open_resume_device(char *commandline, int quiet)
++{
++ struct kstat stat;
++ int error = 0;
++ char *uuid = uuid_from_commandline(commandline);
++
++ resume_dev_t = MKDEV(0, 0);
++
++ if (uuid) {
++ resume_dev_t = blk_lookup_uuid(uuid);
++ kfree(uuid);
++ }
++
++ if (!resume_dev_t)
++ resume_dev_t = name_to_dev_t(commandline);
++
++ if (!resume_dev_t) {
++ wait_for_device_probe();
++ scsi_complete_async_scans();
++ resume_dev_t = name_to_dev_t(commandline);
++ }
++
++ if (!resume_dev_t) {
++ struct file *file = filp_open(commandline,
++ O_RDONLY|O_LARGEFILE, 0);
++
++ if (!IS_ERR(file) && file) {
++ vfs_getattr(file->f_vfsmnt, file->f_dentry, &stat);
++ filp_close(file, NULL);
++ } else
++ error = vfs_stat(commandline, &stat);
++ if (!error)
++ resume_dev_t = stat.rdev;
++ }
++
++ if (!resume_dev_t) {
++ if (quiet)
++ return 1;
++
++ if (test_toi_state(TOI_TRYING_TO_RESUME))
++ toi_early_boot_message(1, toi_translate_err_default,
++ "Failed to translate \"%s\" into a device id.\n",
++ commandline);
++ else
++ printk("TuxOnIce: Can't translate \"%s\" into a device "
++ "id yet.\n", commandline);
++ return 1;
++ }
++
++ return open_resume_dev_t(1, quiet);
++}
++
++/*
++ * Parse Image Location
+ *
-+ * INIT_0 init 0
++ * Attempt to parse a resume= parameter.
++ * Swap Writer accepts:
++ * resume=[swap:|file:]DEVNAME[:FIRSTBLOCK][@BLOCKSIZE]
+ *
-+ * Other messages:
++ * Where:
++ * DEVNAME is convertable to a dev_t by name_to_dev_t
++ * FIRSTBLOCK is the location of the first block in the swap file
++ * (specifying for a swap partition is nonsensical but not prohibited).
++ * Data is validated by attempting to read a swap header from the
++ * location given. Failure will result in toi_swap refusing to
++ * save an image, and a reboot with correct parameters will be
++ * necessary.
++ */
++static int toi_bio_parse_sig_location(char *commandline,
++ int only_allocator, int quiet)
++{
++ char *thischar, *devstart, *colon = NULL;
++ int signature_found, result = -EINVAL, temp_result = 0;
++
++ if (strncmp(commandline, "swap:", 5) &&
++ strncmp(commandline, "file:", 5)) {
++ /*
++ * Failing swap:, we'll take a simple
++ * resume=/dev/hda2, but fall through to
++ * other allocators if /dev/ or UUID= isn't matched.
++ */
++ if (strncmp(commandline, "/dev/", 5) &&
++ strncmp(commandline, "UUID=", 5))
++ return 1;
++ } else
++ commandline += 5;
++
++ devstart = commandline;
++ thischar = commandline;
++ while ((*thischar != ':') && (*thischar != '@') &&
++ ((thischar - commandline) < 250) && (*thischar))
++ thischar++;
++
++ if (*thischar == ':') {
++ colon = thischar;
++ *colon = 0;
++ thischar++;
++ }
++
++ while ((thischar - commandline) < 250 && *thischar)
++ thischar++;
++
++ if (colon) {
++ unsigned long block;
++ temp_result = strict_strtoul(colon + 1, 0, &block);
++ if (!temp_result)
++ resume_firstblock = (int) block;
++ } else
++ resume_firstblock = 0;
++
++ clear_toi_state(TOI_CAN_HIBERNATE);
++ clear_toi_state(TOI_CAN_RESUME);
++
++ if (!temp_result)
++ temp_result = try_to_open_resume_device(devstart, quiet);
++
++ if (colon)
++ *colon = ':';
++
++ if (temp_result)
++ return -EINVAL;
++
++ signature_found = toi_bio_image_exists(quiet);
++
++ if (signature_found != -1) {
++ result = 0;
++ /*
++ * TODO: If only file storage, CAN_HIBERNATE should only be
++ * set if file allocator's target is valid.
++ */
++ set_toi_state(TOI_CAN_HIBERNATE);
++ set_toi_state(TOI_CAN_RESUME);
++ } else
++ if (!quiet)
++ printk(KERN_ERR "TuxOnIce: Block I/O: No "
++ "signature found at %s.\n", devstart);
++
++ close_resume_dev_t(0);
++ return result;
++}
++
++static void toi_bio_release_storage(void)
++{
++ header_pages_reserved = 0;
++ raw_pages_allocd = 0;
++
++ free_all_bdev_info();
++}
++
++/* toi_swap_remove_image
+ *
-+ * - PING: Request for all other live nodes to send a PONG. Used at startup to
-+ * announce presence, when a node is suspected dead and periodically, in case
-+ * segments of the network are [un]plugged.
++ */
++static int toi_bio_remove_image(void)
++{
++ int result;
++
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "toi_bio_remove_image.");
++
++ result = toi_bio_restore_original_signature();
++
++ /*
++ * We don't do a sanity check here: we want to restore the swap
++ * whatever version of kernel made the hibernate image.
++ *
++ * We need to write swap, but swap may not be enabled so
++ * we write the device directly
++ *
++ * If we don't have an current_signature_page, we didn't
++ * read an image header, so don't change anything.
++ */
++
++ toi_bio_release_storage();
++
++ return result;
++}
++
++struct toi_bio_ops toi_bio_ops = {
++ .bdev_page_io = toi_bdev_page_io,
++ .register_storage = toi_register_storage_chain,
++ .free_storage = toi_bio_release_storage,
++};
++EXPORT_SYMBOL_GPL(toi_bio_ops);
++
++static struct toi_sysfs_data sysfs_params[] = {
++ SYSFS_INT("target_outstanding_io", SYSFS_RW, &target_outstanding_io,
++ 0, 16384, 0, NULL),
++};
++
++struct toi_module_ops toi_blockwriter_ops = {
++ .type = WRITER_MODULE,
++ .name = "block i/o",
++ .directory = "block_io",
++ .module = THIS_MODULE,
++ .memory_needed = toi_bio_memory_needed,
++ .print_debug_info = toi_bio_print_debug_stats,
++ .storage_needed = toi_bio_storage_needed,
++ .save_config_info = toi_bio_save_config_info,
++ .load_config_info = toi_bio_load_config_info,
++ .initialise = toi_bio_initialise,
++ .cleanup = toi_bio_cleanup,
++
++ .rw_init = toi_rw_init,
++ .rw_cleanup = toi_rw_cleanup,
++ .read_page = toi_bio_read_page,
++ .write_page = toi_bio_write_page,
++ .rw_header_chunk = toi_rw_header_chunk,
++ .rw_header_chunk_noreadahead = toi_rw_header_chunk_noreadahead,
++ .io_flusher = bio_io_flusher,
++ .update_throughput_throttle = update_throughput_throttle,
++ .finish_all_io = toi_finish_all_io,
++
++ .noresume_reset = toi_bio_noresume_reset,
++ .storage_available = toi_bio_storage_available,
++ .storage_allocated = toi_bio_storage_allocated,
++ .reserve_header_space = toi_bio_reserve_header_space,
++ .allocate_storage = toi_bio_allocate_storage,
++ .image_exists = toi_bio_image_exists,
++ .mark_resume_attempted = toi_bio_mark_resume_attempted,
++ .write_header_init = toi_bio_write_header_init,
++ .write_header_cleanup = toi_bio_write_header_cleanup,
++ .read_header_init = toi_bio_read_header_init,
++ .read_header_cleanup = toi_bio_read_header_cleanup,
++ .remove_image = toi_bio_remove_image,
++ .parse_sig_location = toi_bio_parse_sig_location,
++
++ .sysfs_data = sysfs_params,
++ .num_sysfs_entries = sizeof(sysfs_params) /
++ sizeof(struct toi_sysfs_data),
++};
++
++/**
++ * toi_block_io_load - load time routine for block I/O module
+ *
-+ * - PONG: Response to a PING.
++ * Register block i/o ops and sysfs entries.
++ **/
++static __init int toi_block_io_load(void)
++{
++ return toi_register_module(&toi_blockwriter_ops);
++}
++
++#ifdef MODULE
++static __exit void toi_block_io_unload(void)
++{
++ toi_unregister_module(&toi_blockwriter_ops);
++}
++
++module_init(toi_block_io_load);
++module_exit(toi_block_io_unload);
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Nigel Cunningham");
++MODULE_DESCRIPTION("TuxOnIce block io functions");
++#else
++late_initcall(toi_block_io_load);
++#endif
+diff --git a/kernel/power/tuxonice_bio_internal.h b/kernel/power/tuxonice_bio_internal.h
+new file mode 100644
+index 0000000..a141faa
+--- /dev/null
++++ b/kernel/power/tuxonice_bio_internal.h
+@@ -0,0 +1,64 @@
++/* Extent chains */
++void toi_extent_state_goto_start(void);
++void toi_extent_state_save(int slot);
++int go_next_page(int writing, int section_barrier);
++void toi_extent_state_restore(int slot);
++void free_all_bdev_info(void);
++int devices_of_same_priority(struct toi_bdev_info *this);
++int toi_register_storage_chain(struct toi_bdev_info *new);
++int toi_serialise_extent_chains(void);
++int toi_load_extent_chains(void);
++int toi_bio_rw_page(int writing, struct page *page, int is_readahead,
++ int free_group);
++int toi_bio_restore_original_signature(void);
++int toi_bio_devinfo_storage_needed(void);
++unsigned long get_headerblock(void);
++dev_t get_header_dev_t(void);
++struct block_device *get_header_bdev(void);
++int toi_bio_allocate_storage(unsigned long request);
++
++/* Signature functions */
++#define HaveImage "HaveImage"
++#define NoImage "TuxOnIce"
++#define sig_size (sizeof(HaveImage))
++
++struct sig_data {
++ char sig[sig_size];
++ int have_image;
++ int resumed_before;
++
++ char have_uuid;
++ char header_uuid[17];
++ dev_t header_dev_t;
++ unsigned long first_header_block;
++};
++
++void forget_signature_page(void);
++int toi_check_for_signature(void);
++int toi_bio_image_exists(int quiet);
++int get_signature_page(void);
++int toi_bio_mark_resume_attempted(int);
++extern char *toi_cur_sig_page;
++extern char *toi_orig_sig_page;
++int toi_bio_mark_have_image(void);
++extern struct sig_data *toi_sig_data;
++extern dev_t resume_dev_t;
++extern struct block_device *resume_block_device;
++extern struct block_device *header_block_device;
++extern unsigned long resume_firstblock;
++
++struct block_device *open_bdev(dev_t device, int display_errs);
++extern int current_stream;
++extern int more_readahead;
++int toi_do_io(int writing, struct block_device *bdev, long block0,
++ struct page *page, int is_readahead, int syncio, int free_group);
++int get_main_pool_phys_params(void);
++
++void toi_close_bdev(struct block_device *bdev);
++struct block_device *toi_open_bdev(char *uuid, dev_t default_device,
++ int display_errs);
++
++extern struct toi_module_ops toi_blockwriter_ops;
++void dump_block_chains(void);
++void debug_broken_header(void);
++extern unsigned long raw_pages_allocd, header_pages_reserved;
+diff --git a/kernel/power/tuxonice_bio_signature.c b/kernel/power/tuxonice_bio_signature.c
+new file mode 100644
+index 0000000..7954027
+--- /dev/null
++++ b/kernel/power/tuxonice_bio_signature.c
+@@ -0,0 +1,281 @@
++/*
++ * kernel/power/tuxonice_bio_signature.c
+ *
-+ * - ABORT: Request to cancel writing an image.
++ * Copyright (C) 2004-2008 Nigel Cunningham (nigel at tuxonice net)
+ *
-+ * - BYE: Notification that this node is shutting down.
++ * Distributed under GPLv2.
+ *
-+ * Note 1: Repeated at 3s intervals until we continue to boot/resume, so that
-+ * nodes which are slower to start up can get state synchronised. If a node
-+ * starting up sees other nodes sending RESUME_PREP or IMAGE_READ, it may send
-+ * ACK_IMAGE and they will wait for it to catch up. If it sees ACK_READ, it
-+ * must invalidate its image (if any) and boot normally.
++ */
++
++#include <linux/uuid.h>
++
++#include "tuxonice.h"
++#include "tuxonice_sysfs.h"
++#include "tuxonice_modules.h"
++#include "tuxonice_prepare_image.h"
++#include "tuxonice_bio.h"
++#include "tuxonice_ui.h"
++#include "tuxonice_alloc.h"
++#include "tuxonice_io.h"
++#include "tuxonice_builtin.h"
++#include "tuxonice_bio_internal.h"
++
++struct sig_data *toi_sig_data;
++
++/* Struct of swap header pages */
++
++union diskpage {
++ union swap_header swh; /* swh.magic is the only member used */
++ struct sig_data sig_data;
++};
++
++union p_diskpage {
++ union diskpage *pointer;
++ char *ptr;
++ unsigned long address;
++};
++
++char *toi_cur_sig_page;
++char *toi_orig_sig_page;
++int have_image;
++
++int get_signature_page(void)
++{
++ if (!toi_cur_sig_page) {
++ toi_message(TOI_IO, TOI_VERBOSE, 0,
++ "Allocating current signature page.");
++ toi_cur_sig_page = (char *) toi_get_zeroed_page(38,
++ TOI_ATOMIC_GFP);
++ if (!toi_cur_sig_page) {
++ printk(KERN_ERR "Failed to allocate memory for the "
++ "current image signature.\n");
++ return -ENOMEM;
++ }
++
++ toi_sig_data = (struct sig_data *) toi_cur_sig_page;
++ }
++
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Reading signature from dev %lx,"
++ " sector %d.",
++ resume_block_device->bd_dev, resume_firstblock);
++
++ return toi_bio_ops.bdev_page_io(READ, resume_block_device,
++ resume_firstblock, virt_to_page(toi_cur_sig_page));
++}
++
++void forget_signature_page(void)
++{
++ if (toi_cur_sig_page) {
++ toi_sig_data = NULL;
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Freeing toi_cur_sig_page"
++ " (%p).", toi_cur_sig_page);
++ toi_free_page(38, (unsigned long) toi_cur_sig_page);
++ toi_cur_sig_page = NULL;
++ }
++
++ if (toi_orig_sig_page) {
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Freeing toi_orig_sig_page"
++ " (%p).", toi_orig_sig_page);
++ toi_free_page(38, (unsigned long) toi_orig_sig_page);
++ toi_orig_sig_page = NULL;
++ }
++}
++
++int toi_bio_mark_resume_attempted(int flag)
++{
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Make resume attempted = %d.",
++ flag);
++ toi_sig_data->resumed_before = flag;
++ return toi_bio_ops.bdev_page_io(WRITE, resume_block_device,
++ resume_firstblock, virt_to_page(toi_cur_sig_page));
++}
++
++int toi_bio_mark_have_image(void)
++{
++ int result;
++ char buf[32];
++
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Recording that an image exists.");
++ memcpy(toi_sig_data->sig, tuxonice_signature,
++ sizeof(tuxonice_signature));
++ toi_sig_data->have_image = 1;
++ toi_sig_data->resumed_before = 0;
++ toi_sig_data->header_dev_t = get_header_dev_t();
++ toi_sig_data->have_uuid = 0;
++
++ result = uuid_from_block_dev(get_header_bdev(),
++ toi_sig_data->header_uuid);
++ if (!result) {
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Got uuid for dev_t %s.",
++ format_dev_t(buf, get_header_dev_t()));
++ toi_sig_data->have_uuid = 1;
++ } else
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Could not get uuid for "
++ "dev_t %s.",
++ format_dev_t(buf, get_header_dev_t()));
++
++ toi_sig_data->first_header_block = get_headerblock();
++ have_image = 1;
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "header dev_t is %x. First block "
++ "is %d.", toi_sig_data->header_dev_t,
++ toi_sig_data->first_header_block);
++
++ return toi_bio_ops.bdev_page_io(WRITE, resume_block_device,
++ resume_firstblock, virt_to_page(toi_cur_sig_page));
++}
++
++/*
++ * toi_bio_restore_original_signature - restore the original signature
+ *
-+ * Note 2: May occur when one node lost power or powered off while others
-+ * hibernated. This node waits for others to complete resuming (ACK_READ)
-+ * before completing its boot, so that it appears as a fail node restarting.
++ * At boot time (aborting pre atomic-restore), toi_orig_sig_page gets used.
++ * It will have the original signature page contents, stored in the image
++ * header. Post atomic-restore, we use :toi_cur_sig_page, which will contain
++ * the contents that were loaded when we started the cycle.
++ */
++int toi_bio_restore_original_signature(void)
++{
++ char *use = toi_orig_sig_page ? toi_orig_sig_page : toi_cur_sig_page;
++
++ if (!use) {
++ printk("toi_bio_restore_original_signature: No signature "
++ "page loaded.\n");
++ return 0;
++ }
++
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Recording that no image exists.");
++ have_image = 0;
++ toi_sig_data->have_image = 0;
++ return toi_bio_ops.bdev_page_io(WRITE, resume_block_device,
++ resume_firstblock, virt_to_page(use));
++}
++
++/*
++ * check_for_signature - See whether we have an image.
+ *
-+ * If any node has an image, then it also has a list of nodes that hibernated
-+ * in synchronisation with it. The node will wait for other nodes to appear
-+ * or timeout before beginning its restoration.
++ * Returns 0 if no image, 1 if there is one, -1 if indeterminate.
++ */
++int toi_check_for_signature(void)
++{
++ union p_diskpage swap_header_page;
++ int type;
++ const char *normal_sigs[] = {"SWAP-SPACE", "SWAPSPACE2" };
++ const char *swsusp_sigs[] = {"S1SUSP", "S2SUSP", "S1SUSPEND" };
++ char *swap_header;
++
++ if (!toi_cur_sig_page) {
++ int result = get_signature_page();
++
++ if (result)
++ return result;
++ }
++
++ /*
++ * Start by looking for the binary header.
++ */
++ if (!memcmp(tuxonice_signature, toi_cur_sig_page,
++ sizeof(tuxonice_signature))) {
++ have_image = toi_sig_data->have_image;
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Have binary signature. "
++ "Have image is %d.", have_image);
++ if (have_image)
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "header dev_t is "
++ "%x. First block is %d.",
++ toi_sig_data->header_dev_t,
++ toi_sig_data->first_header_block);
++ return toi_sig_data->have_image;
++ }
++
++ /*
++ * Failing that, try old file allocator headers.
++ */
++
++ if (!memcmp(HaveImage, toi_cur_sig_page, strlen(HaveImage))) {
++ have_image = 1;
++ return 1;
++ }
++
++ have_image = 0;
++
++ if (!memcmp(NoImage, toi_cur_sig_page, strlen(NoImage)))
++ return 0;
++
++ /*
++ * Nope? How about swap?
++ */
++ swap_header_page = (union p_diskpage) toi_cur_sig_page;
++ swap_header = swap_header_page.pointer->swh.magic.magic;
++
++ /* Normal swapspace? */
++ for (type = 0; type < 2; type++)
++ if (!memcmp(normal_sigs[type], swap_header,
++ strlen(normal_sigs[type])))
++ return 0;
++
++ /* Swsusp or uswsusp? */
++ for (type = 0; type < 3; type++)
++ if (!memcmp(swsusp_sigs[type], swap_header,
++ strlen(swsusp_sigs[type])))
++ return 2;
++
++ return -1;
++}
++
++/*
++ * Image_exists
+ *
-+ * If a node has no image, it needs to wait, in case other nodes which do have
-+ * an image are going to resume, but are taking longer to announce their
-+ * presence. For this reason, the user can specify a timeout value and a number
-+ * of nodes detected before we just continue. (We might want to assume in a
-+ * cluster of, say, 15 nodes, if 8 others have booted without finding an image,
-+ * the remaining nodes will too. This might help in situations where some nodes
-+ * are much slower to boot, or more subject to hardware failures or such like).
++ * Returns -1 if don't know, otherwise 0 (no) or 1 (yes).
+ */
++int toi_bio_image_exists(int quiet)
++{
++ int result;
++ char *orig_sig_page = toi_cur_sig_page;
++ char *msg = NULL;
+
-+#include <linux/suspend.h>
-+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+#include <linux/if.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/ip.h>
-+#include <linux/udp.h>
-+#include <linux/in.h>
-+#include <linux/if_arp.h>
-+#include <linux/kthread.h>
-+#include <linux/wait.h>
-+#include <linux/netdevice.h>
-+#include <net/ip.h>
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "toi_bio_image_exists.");
++
++ if (!resume_dev_t) {
++ if (!quiet)
++ printk(KERN_INFO "Not even trying to read header "
++ "because resume_dev_t is not set.\n");
++ return -1;
++ }
++
++ if (!resume_block_device) {
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Opening resume_dev_t %lx.",
++ resume_dev_t);
++ resume_block_device = toi_open_bdev(NULL, resume_dev_t, 1);
++ if (IS_ERR(resume_block_device)) {
++ if (!quiet)
++ printk(KERN_INFO "Failed to open resume dev_t"
++ " (%x).\n", resume_dev_t);
++ return -1;
++ }
++ }
++
++ result = toi_check_for_signature();
++
++ clear_toi_state(TOI_RESUMED_BEFORE);
++ if (toi_sig_data->resumed_before)
++ set_toi_state(TOI_RESUMED_BEFORE);
++
++ if (quiet || result == -ENOMEM)
++ goto out;
++
++ if (result == -1)
++ msg = "TuxOnIce: Unable to find a signature."
++ " Could you have moved a swap file?\n";
++ else if (!result)
++ msg = "TuxOnIce: No image found.\n";
++ else if (result == 1)
++ msg = "TuxOnIce: Image found.\n";
++ else if (result == 2)
++ msg = "TuxOnIce: uswsusp or swsusp image found.\n";
+
++ printk(KERN_INFO "%s", msg);
++
++out:
++ if (!orig_sig_page)
++ forget_signature_page();
++
++ return result;
++}
+diff --git a/kernel/power/tuxonice_builtin.c b/kernel/power/tuxonice_builtin.c
+new file mode 100644
+index 0000000..b75663d
+--- /dev/null
++++ b/kernel/power/tuxonice_builtin.c
+@@ -0,0 +1,349 @@
++/*
++ * Copyright (C) 2004-2008 Nigel Cunningham (nigel at tuxonice net)
++ *
++ * This file is released under the GPLv2.
++ */
++#include <linux/resume-trace.h>
++#include <linux/kernel.h>
++#include <linux/swap.h>
++#include <linux/syscalls.h>
++#include <linux/bio.h>
++#include <linux/root_dev.h>
++#include <linux/freezer.h>
++#include <linux/reboot.h>
++#include <linux/writeback.h>
++#include <linux/tty.h>
++#include <linux/crypto.h>
++#include <linux/cpu.h>
++#include <linux/ctype.h>
++#include "tuxonice_io.h"
+#include "tuxonice.h"
-+#include "tuxonice_modules.h"
++#include "tuxonice_extent.h"
++#include "tuxonice_netlink.h"
++#include "tuxonice_prepare_image.h"
++#include "tuxonice_ui.h"
+#include "tuxonice_sysfs.h"
-+#include "tuxonice_alloc.h"
-+#include "tuxonice_io.h"
-+
-+#if 1
-+#define PRINTK(a, b...) do { printk(a, ##b); } while (0)
-+#else
-+#define PRINTK(a, b...) do { } while (0)
-+#endif
++#include "tuxonice_pagedir.h"
++#include "tuxonice_modules.h"
++#include "tuxonice_builtin.h"
++#include "tuxonice_power_off.h"
+
-+static int loopback_mode;
-+static int num_local_nodes = 1;
-+#define MAX_LOCAL_NODES 8
-+#define SADDR (loopback_mode ? b->sid : h->saddr)
++/*
++ * Highmem related functions (x86 only).
++ */
+
-+#define MYNAME "TuxOnIce Clustering"
++#ifdef CONFIG_HIGHMEM
+
-+enum cluster_message {
-+ MSG_ACK = 1,
-+ MSG_NACK = 2,
-+ MSG_PING = 4,
-+ MSG_ABORT = 8,
-+ MSG_BYE = 16,
-+ MSG_HIBERNATE = 32,
-+ MSG_IMAGE = 64,
-+ MSG_IO = 128,
-+ MSG_RUNNING = 256
-+};
++/**
++ * copyback_high: Restore highmem pages.
++ *
++ * Highmem data and pbe lists are/can be stored in highmem.
++ * The format is slightly different to the lowmem pbe lists
++ * used for the assembly code: the last pbe in each page is
++ * a struct page * instead of struct pbe *, pointing to the
++ * next page where pbes are stored (or NULL if happens to be
++ * the end of the list). Since we don't want to generate
++ * unnecessary deltas against swsusp code, we use a cast
++ * instead of a union.
++ **/
+
-+static char *str_message(int message)
++static void copyback_high(void)
+{
-+ switch (message) {
-+ case 4:
-+ return "Ping";
-+ case 8:
-+ return "Abort";
-+ case 9:
-+ return "Abort acked";
-+ case 10:
-+ return "Abort nacked";
-+ case 16:
-+ return "Bye";
-+ case 17:
-+ return "Bye acked";
-+ case 18:
-+ return "Bye nacked";
-+ case 32:
-+ return "Hibernate request";
-+ case 33:
-+ return "Hibernate ack";
-+ case 34:
-+ return "Hibernate nack";
-+ case 64:
-+ return "Image exists?";
-+ case 65:
-+ return "Image does exist";
-+ case 66:
-+ return "No image here";
-+ case 128:
-+ return "I/O";
-+ case 129:
-+ return "I/O okay";
-+ case 130:
-+ return "I/O failed";
-+ case 256:
-+ return "Running";
-+ default:
-+ printk(KERN_ERR "Unrecognised message %d.\n", message);
-+ return "Unrecognised message (see dmesg)";
++ struct page *pbe_page = (struct page *) restore_highmem_pblist;
++ struct pbe *this_pbe, *first_pbe;
++ unsigned long *origpage, *copypage;
++ int pbe_index = 1;
++
++ if (!pbe_page)
++ return;
++
++ this_pbe = (struct pbe *) kmap_atomic(pbe_page, KM_BOUNCE_READ);
++ first_pbe = this_pbe;
++
++ while (this_pbe) {
++ int loop = (PAGE_SIZE / sizeof(unsigned long)) - 1;
++
++ origpage = kmap_atomic((struct page *) this_pbe->orig_address,
++ KM_BIO_DST_IRQ);
++ copypage = kmap_atomic((struct page *) this_pbe->address,
++ KM_BIO_SRC_IRQ);
++
++ while (loop >= 0) {
++ *(origpage + loop) = *(copypage + loop);
++ loop--;
++ }
++
++ kunmap_atomic(origpage, KM_BIO_DST_IRQ);
++ kunmap_atomic(copypage, KM_BIO_SRC_IRQ);
++
++ if (!this_pbe->next)
++ break;
++
++ if (pbe_index < PBES_PER_PAGE) {
++ this_pbe++;
++ pbe_index++;
++ } else {
++ pbe_page = (struct page *) this_pbe->next;
++ kunmap_atomic(first_pbe, KM_BOUNCE_READ);
++ if (!pbe_page)
++ return;
++ this_pbe = (struct pbe *) kmap_atomic(pbe_page,
++ KM_BOUNCE_READ);
++ first_pbe = this_pbe;
++ pbe_index = 1;
++ }
+ }
++ kunmap_atomic(first_pbe, KM_BOUNCE_READ);
+}
+
-+#define MSG_ACK_MASK (MSG_ACK | MSG_NACK)
-+#define MSG_STATE_MASK (~MSG_ACK_MASK)
++#else /* CONFIG_HIGHMEM */
++static void copyback_high(void) { }
++#endif
+
-+struct node_info {
-+ struct list_head member_list;
-+ wait_queue_head_t member_events;
-+ spinlock_t member_list_lock;
-+ spinlock_t receive_lock;
-+ int peer_count, ignored_peer_count;
-+ struct toi_sysfs_data sysfs_data;
-+ enum cluster_message current_message;
-+};
++char toi_wait_for_keypress_dev_console(int timeout)
++{
++ int fd, this_timeout = 255;
++ char key = '\0';
++ struct termios t, t_backup;
++
++ /* We should be guaranteed /dev/console exists after populate_rootfs()
++ * in init/main.c.
++ */
++ fd = sys_open("/dev/console", O_RDONLY, 0);
++ if (fd < 0) {
++ printk(KERN_INFO "Couldn't open /dev/console.\n");
++ return key;
++ }
++
++ if (sys_ioctl(fd, TCGETS, (long)&t) < 0)
++ goto out_close;
++
++ memcpy(&t_backup, &t, sizeof(t));
++
++ t.c_lflag &= ~(ISIG|ICANON|ECHO);
++ t.c_cc[VMIN] = 0;
++
++new_timeout:
++ if (timeout > 0) {
++ this_timeout = timeout < 26 ? timeout : 25;
++ timeout -= this_timeout;
++ this_timeout *= 10;
++ }
++
++ t.c_cc[VTIME] = this_timeout;
++
++ if (sys_ioctl(fd, TCSETS, (long)&t) < 0)
++ goto out_restore;
++
++ while (1) {
++ if (sys_read(fd, &key, 1) <= 0) {
++ if (timeout)
++ goto new_timeout;
++ key = '\0';
++ break;
++ }
++ key = tolower(key);
++ if (test_toi_state(TOI_SANITY_CHECK_PROMPT)) {
++ if (key == 'c') {
++ set_toi_state(TOI_CONTINUE_REQ);
++ break;
++ } else if (key == ' ')
++ break;
++ } else
++ break;
++ }
+
-+struct node_info node_array[MAX_LOCAL_NODES];
++out_restore:
++ sys_ioctl(fd, TCSETS, (long)&t_backup);
++out_close:
++ sys_close(fd);
+
-+struct cluster_member {
-+ __be32 addr;
-+ enum cluster_message message;
-+ struct list_head list;
-+ int ignore;
++ return key;
++}
++EXPORT_SYMBOL_GPL(toi_wait_for_keypress_dev_console);
++
++struct toi_boot_kernel_data toi_bkd __nosavedata
++ __attribute__((aligned(PAGE_SIZE))) = {
++ MY_BOOT_KERNEL_DATA_VERSION,
++ 0,
++#ifdef CONFIG_TOI_REPLACE_SWSUSP
++ (1 << TOI_REPLACE_SWSUSP) |
++#endif
++ (1 << TOI_NO_FLUSHER_THREAD) |
++ (1 << TOI_PAGESET2_FULL) | (1 << TOI_LATE_CPU_HOTPLUG),
+};
++EXPORT_SYMBOL_GPL(toi_bkd);
+
-+#define toi_cluster_port_send 3501
-+#define toi_cluster_port_recv 3502
++struct block_device *toi_open_by_devnum(dev_t dev, fmode_t mode)
++{
++ struct block_device *bdev = bdget(dev);
++ int err = -ENOMEM;
++ if (bdev)
++ err = blkdev_get(bdev, mode);
++ return err ? ERR_PTR(err) : bdev;
++}
++EXPORT_SYMBOL_GPL(toi_open_by_devnum);
+
-+static struct net_device *net_dev;
-+static struct toi_module_ops toi_cluster_ops;
++int toi_wait = CONFIG_TOI_DEFAULT_WAIT;
++EXPORT_SYMBOL_GPL(toi_wait);
+
-+static int toi_recv(struct sk_buff *skb, struct net_device *dev,
-+ struct packet_type *pt, struct net_device *orig_dev);
++struct toi_core_fns *toi_core_fns;
++EXPORT_SYMBOL_GPL(toi_core_fns);
+
-+static struct packet_type toi_cluster_packet_type = {
-+ .type = __constant_htons(ETH_P_IP),
-+ .func = toi_recv,
-+};
++unsigned long toi_result;
++EXPORT_SYMBOL_GPL(toi_result);
+
-+struct toi_pkt { /* BOOTP packet format */
-+ struct iphdr iph; /* IP header */
-+ struct udphdr udph; /* UDP header */
-+ u8 htype; /* HW address type */
-+ u8 hlen; /* HW address length */
-+ __be32 xid; /* Transaction ID */
-+ __be16 secs; /* Seconds since we started */
-+ __be16 flags; /* Just what it says */
-+ u8 hw_addr[16]; /* Sender's HW address */
-+ u16 message; /* Message */
-+ unsigned long sid; /* Source ID for loopback testing */
-+};
++struct pagedir pagedir1 = {1};
++EXPORT_SYMBOL_GPL(pagedir1);
+
-+static char toi_cluster_iface[IFNAMSIZ] = CONFIG_TOI_DEFAULT_CLUSTER_INTERFACE;
++unsigned long toi_get_nonconflicting_page(void)
++{
++ return toi_core_fns->get_nonconflicting_page();
++}
+
-+static int added_pack;
++int toi_post_context_save(void)
++{
++ return toi_core_fns->post_context_save();
++}
+
-+static int others_have_image;
++int try_tuxonice_hibernate(void)
++{
++ if (!toi_core_fns)
++ return -ENODEV;
+
-+/* Key used to allow multiple clusters on the same lan */
-+static char toi_cluster_key[32] = CONFIG_TOI_DEFAULT_CLUSTER_KEY;
-+static char pre_hibernate_script[255] =
-+ CONFIG_TOI_DEFAULT_CLUSTER_PRE_HIBERNATE;
-+static char post_hibernate_script[255] =
-+ CONFIG_TOI_DEFAULT_CLUSTER_POST_HIBERNATE;
++ return toi_core_fns->try_hibernate();
++}
+
-+/* List of cluster members */
-+static unsigned long continue_delay = 5 * HZ;
-+static unsigned long cluster_message_timeout = 3 * HZ;
++static int num_resume_calls;
++#ifdef CONFIG_TOI_IGNORE_LATE_INITCALL
++static int ignore_late_initcall = 1;
++#else
++static int ignore_late_initcall;
++#endif
+
-+/* === Membership list === */
++int toi_translate_err_default = TOI_CONTINUE_REQ;
++EXPORT_SYMBOL_GPL(toi_translate_err_default);
+
-+static void print_member_info(int index)
++void try_tuxonice_resume(void)
+{
-+ struct cluster_member *this;
++ /* Don't let it wrap around eventually */
++ if (num_resume_calls < 2)
++ num_resume_calls++;
+
-+ printk(KERN_INFO "==> Dumping node %d.\n", index);
++ if (num_resume_calls == 1 && ignore_late_initcall) {
++ printk(KERN_INFO "TuxOnIce: Ignoring late initcall, as requested.\n");
++ return;
++ }
+
-+ list_for_each_entry(this, &node_array[index].member_list, list)
-+ printk(KERN_INFO "%d.%d.%d.%d last message %s. %s\n",
-+ NIPQUAD(this->addr),
-+ str_message(this->message),
-+ this->ignore ? "(Ignored)" : "");
-+ printk(KERN_INFO "== Done ==\n");
++ if (toi_core_fns)
++ toi_core_fns->try_resume();
++ else
++ printk(KERN_INFO "TuxOnIce core not loaded yet.\n");
+}
+
-+static struct cluster_member *__find_member(int index, __be32 addr)
++int toi_lowlevel_builtin(void)
+{
-+ struct cluster_member *this;
++ int error = 0;
+
-+ list_for_each_entry(this, &node_array[index].member_list, list) {
-+ if (this->addr != addr)
-+ continue;
++ save_processor_state();
++ error = swsusp_arch_suspend();
++ if (error)
++ printk(KERN_ERR "Error %d hibernating\n", error);
+
-+ return this;
++ /* Restore control flow appears here */
++ if (!toi_in_hibernate) {
++ copyback_high();
++ set_toi_state(TOI_NOW_RESUMING);
+ }
+
-+ return NULL;
++ restore_processor_state();
++
++ return error;
+}
++EXPORT_SYMBOL_GPL(toi_lowlevel_builtin);
+
-+static void set_ignore(int index, __be32 addr, struct cluster_member *this)
-+{
-+ if (this->ignore) {
-+ PRINTK("Node %d already ignoring %d.%d.%d.%d.\n",
-+ index, NIPQUAD(addr));
-+ return;
-+ }
++unsigned long toi_compress_bytes_in;
++EXPORT_SYMBOL_GPL(toi_compress_bytes_in);
+
-+ PRINTK("Node %d sees node %d.%d.%d.%d now being ignored.\n",
-+ index, NIPQUAD(addr));
-+ this->ignore = 1;
-+ node_array[index].ignored_peer_count++;
-+}
++unsigned long toi_compress_bytes_out;
++EXPORT_SYMBOL_GPL(toi_compress_bytes_out);
+
-+static int __add_update_member(int index, __be32 addr, int message)
-+{
-+ struct cluster_member *this;
++unsigned long toi_state = ((1 << TOI_BOOT_TIME) |
++ (1 << TOI_IGNORE_LOGLEVEL) |
++ (1 << TOI_IO_STOPPED));
++EXPORT_SYMBOL_GPL(toi_state);
+
-+ this = __find_member(index, addr);
-+ if (this) {
-+ if (this->message != message) {
-+ this->message = message;
-+ if ((message & MSG_NACK) &&
-+ (message & (MSG_HIBERNATE | MSG_IMAGE | MSG_IO)))
-+ set_ignore(index, addr, this);
-+ PRINTK("Node %d sees node %d.%d.%d.%d now sending "
-+ "%s.\n", index, NIPQUAD(addr),
-+ str_message(message));
-+ wake_up(&node_array[index].member_events);
-+ }
-+ return 0;
-+ }
++/* The number of hibernates we have started (some may have been cancelled) */
++unsigned int nr_hibernates;
++EXPORT_SYMBOL_GPL(nr_hibernates);
+
-+ this = (struct cluster_member *) toi_kzalloc(36,
-+ sizeof(struct cluster_member), GFP_KERNEL);
++int toi_running;
++EXPORT_SYMBOL_GPL(toi_running);
+
-+ if (!this)
-+ return -1;
++__nosavedata int toi_in_hibernate;
++EXPORT_SYMBOL_GPL(toi_in_hibernate);
+
-+ this->addr = addr;
-+ this->message = message;
-+ this->ignore = 0;
-+ INIT_LIST_HEAD(&this->list);
++__nosavedata struct pbe *restore_highmem_pblist;
++EXPORT_SYMBOL_GPL(restore_highmem_pblist);
+
-+ node_array[index].peer_count++;
++static int __init toi_wait_setup(char *str)
++{
++ int value;
+
-+ PRINTK("Node %d sees node %d.%d.%d.%d sending %s.\n", index,
-+ NIPQUAD(addr), str_message(message));
++ if (sscanf(str, "=%d", &value)) {
++ if (value < -1 || value > 255)
++ printk(KERN_INFO "TuxOnIce_wait outside range -1 to "
++ "255.\n");
++ else
++ toi_wait = value;
++ }
+
-+ if ((message & MSG_NACK) &&
-+ (message & (MSG_HIBERNATE | MSG_IMAGE | MSG_IO)))
-+ set_ignore(index, addr, this);
-+ list_add_tail(&this->list, &node_array[index].member_list);
+ return 1;
+}
+
-+static int add_update_member(int index, __be32 addr, int message)
-+{
-+ int result;
-+ unsigned long flags;
-+ spin_lock_irqsave(&node_array[index].member_list_lock, flags);
-+ result = __add_update_member(index, addr, message);
-+ spin_unlock_irqrestore(&node_array[index].member_list_lock, flags);
++__setup("toi_wait", toi_wait_setup);
+
-+ print_member_info(index);
++static int __init toi_translate_retry_setup(char *str)
++{
++ toi_translate_err_default = 0;
++ return 1;
++}
+
-+ wake_up(&node_array[index].member_events);
++__setup("toi_translate_retry", toi_translate_retry_setup);
+
-+ return result;
++static int __init toi_debug_setup(char *str)
++{
++ toi_bkd.toi_action |= (1 << TOI_LOGALL) | (1 << TOI_PAUSE);
++ toi_bkd.toi_debug_state = 255;
++ toi_bkd.toi_default_console_level = 7;
++ return 1;
+}
+
-+static void del_member(int index, __be32 addr)
++__setup("toi_debug_setup", toi_debug_setup);
++
++static int __init toi_ignore_late_initcall_setup(char *str)
+{
-+ struct cluster_member *this;
-+ unsigned long flags;
++ int value;
+
-+ spin_lock_irqsave(&node_array[index].member_list_lock, flags);
-+ this = __find_member(index, addr);
++ if (sscanf(str, "=%d", &value))
++ ignore_late_initcall = value;
+
-+ if (this) {
-+ list_del_init(&this->list);
-+ toi_kfree(36, this, sizeof(*this));
-+ node_array[index].peer_count--;
-+ }
++ return 1;
++}
++
++__setup("toi_initramfs_resume_only", toi_ignore_late_initcall_setup);
+
-+ spin_unlock_irqrestore(&node_array[index].member_list_lock, flags);
-+}
++int toi_force_no_multithreaded;
++EXPORT_SYMBOL_GPL(toi_force_no_multithreaded);
+
-+/* === Message transmission === */
++static int __init toi_force_no_multithreaded_setup(char *str)
++{
++ int value;
+
-+static void toi_send_if(int message, unsigned long my_id);
++ if (sscanf(str, "=%d", &value))
++ toi_force_no_multithreaded = value;
++
++ return 1;
++}
+
++__setup("toi_no_multithreaded", toi_force_no_multithreaded_setup);
+diff --git a/kernel/power/tuxonice_builtin.h b/kernel/power/tuxonice_builtin.h
+new file mode 100644
+index 0000000..9972bb4
+--- /dev/null
++++ b/kernel/power/tuxonice_builtin.h
+@@ -0,0 +1,29 @@
+/*
-+ * Process received TOI packet.
++ * Copyright (C) 2004-2008 Nigel Cunningham (nigel at tuxonice net)
++ *
++ * This file is released under the GPLv2.
+ */
-+static int toi_recv(struct sk_buff *skb, struct net_device *dev,
-+ struct packet_type *pt, struct net_device *orig_dev)
-+{
-+ struct toi_pkt *b;
-+ struct iphdr *h;
-+ int len, result, index;
-+ unsigned long addr, message, ack;
++#include <asm/setup.h>
+
-+ /* Perform verifications before taking the lock. */
-+ if (skb->pkt_type == PACKET_OTHERHOST)
-+ goto drop;
++extern struct toi_core_fns *toi_core_fns;
++extern unsigned long toi_compress_bytes_in, toi_compress_bytes_out;
++extern unsigned int nr_hibernates;
++extern int toi_in_hibernate;
+
-+ if (dev != net_dev)
-+ goto drop;
++extern __nosavedata struct pbe *restore_highmem_pblist;
+
-+ skb = skb_share_check(skb, GFP_ATOMIC);
-+ if (!skb)
-+ return NET_RX_DROP;
++int toi_lowlevel_builtin(void);
+
-+ if (!pskb_may_pull(skb,
-+ sizeof(struct iphdr) +
-+ sizeof(struct udphdr)))
-+ goto drop;
++#ifdef CONFIG_HIGHMEM
++extern __nosavedata struct zone_data *toi_nosave_zone_list;
++extern __nosavedata unsigned long toi_nosave_max_pfn;
++#endif
+
-+ b = (struct toi_pkt *)skb_network_header(skb);
-+ h = &b->iph;
++extern unsigned long toi_get_nonconflicting_page(void);
++extern int toi_post_context_save(void);
+
-+ if (h->ihl != 5 || h->version != 4 || h->protocol != IPPROTO_UDP)
-+ goto drop;
++extern char toi_wait_for_keypress_dev_console(int timeout);
++extern struct block_device *toi_open_by_devnum(dev_t dev, fmode_t mode);
++extern int toi_wait;
++extern int toi_translate_err_default;
++extern int toi_force_no_multithreaded;
+diff --git a/kernel/power/tuxonice_checksum.c b/kernel/power/tuxonice_checksum.c
+new file mode 100644
+index 0000000..b8c2c00
+--- /dev/null
++++ b/kernel/power/tuxonice_checksum.c
+@@ -0,0 +1,378 @@
++/*
++ * kernel/power/tuxonice_checksum.c
++ *
++ * Copyright (C) 2006-2008 Nigel Cunningham (nigel at tuxonice net)
++ * Copyright (C) 2006 Red Hat, inc.
++ *
++ * This file is released under the GPLv2.
++ *
++ * This file contains data checksum routines for TuxOnIce,
++ * using cryptoapi. They are used to locate any modifications
++ * made to pageset 2 while we're saving it.
++ */
+
-+ /* Fragments are not supported */
-+ if (h->frag_off & htons(IP_OFFSET | IP_MF)) {
-+ if (net_ratelimit())
-+ printk(KERN_ERR "TuxOnIce: Ignoring fragmented "
-+ "cluster message.\n");
-+ goto drop;
-+ }
++#include <linux/suspend.h>
++#include <linux/highmem.h>
++#include <linux/vmalloc.h>
++#include <linux/crypto.h>
++#include <linux/scatterlist.h>
+
-+ if (skb->len < ntohs(h->tot_len))
-+ goto drop;
++#include "tuxonice.h"
++#include "tuxonice_modules.h"
++#include "tuxonice_sysfs.h"
++#include "tuxonice_io.h"
++#include "tuxonice_pageflags.h"
++#include "tuxonice_checksum.h"
++#include "tuxonice_pagedir.h"
++#include "tuxonice_alloc.h"
+
-+ if (ip_fast_csum((char *) h, h->ihl))
-+ goto drop;
++static struct toi_module_ops toi_checksum_ops;
+
-+ if (b->udph.source != htons(toi_cluster_port_send) ||
-+ b->udph.dest != htons(toi_cluster_port_recv))
-+ goto drop;
++/* Constant at the mo, but I might allow tuning later */
++static char toi_checksum_name[32] = "md4";
++/* Bytes per checksum */
++#define CHECKSUM_SIZE (16)
+
-+ if (ntohs(h->tot_len) < ntohs(b->udph.len) + sizeof(struct iphdr))
-+ goto drop;
++#define CHECKSUMS_PER_PAGE ((PAGE_SIZE - sizeof(void *)) / CHECKSUM_SIZE)
+
-+ len = ntohs(b->udph.len) - sizeof(struct udphdr);
++struct cpu_context {
++ struct crypto_hash *transform;
++ struct hash_desc desc;
++ struct scatterlist sg[2];
++ char *buf;
++};
+
-+ /* Ok the front looks good, make sure we can get at the rest. */
-+ if (!pskb_may_pull(skb, skb->len))
-+ goto drop;
++static DEFINE_PER_CPU(struct cpu_context, contexts);
++static int pages_allocated;
++static unsigned long page_list;
+
-+ b = (struct toi_pkt *)skb_network_header(skb);
-+ h = &b->iph;
++static int toi_num_resaved;
+
-+ addr = SADDR;
-+ PRINTK(">>> Message %s received from " NIPQUAD_FMT ".\n",
-+ str_message(b->message), NIPQUAD(addr));
++static unsigned long this_checksum, next_page;
++static int checksum_index;
+
-+ message = b->message & MSG_STATE_MASK;
-+ ack = b->message & MSG_ACK_MASK;
++static inline int checksum_pages_needed(void)
++{
++ return DIV_ROUND_UP(pagedir2.size, CHECKSUMS_PER_PAGE);
++}
+
-+ for (index = 0; index < num_local_nodes; index++) {
-+ int new_message = node_array[index].current_message,
-+ old_message = new_message;
++/* ---- Local buffer management ---- */
+
-+ if (index == SADDR || !old_message) {
-+ PRINTK("Ignoring node %d (offline or self).\n", index);
-+ continue;
-+ }
++/*
++ * toi_checksum_cleanup
++ *
++ * Frees memory allocated for our labours.
++ */
++static void toi_checksum_cleanup(int ending_cycle)
++{
++ int cpu;
+
-+ /* One message at a time, please. */
-+ spin_lock(&node_array[index].receive_lock);
++ if (ending_cycle) {
++ for_each_online_cpu(cpu) {
++ struct cpu_context *this = &per_cpu(contexts, cpu);
++ if (this->transform) {
++ crypto_free_hash(this->transform);
++ this->transform = NULL;
++ this->desc.tfm = NULL;
++ }
+
-+ result = add_update_member(index, SADDR, b->message);
-+ if (result == -1) {
-+ printk(KERN_INFO "Failed to add new cluster member "
-+ NIPQUAD_FMT ".\n",
-+ NIPQUAD(addr));
-+ goto drop_unlock;
++ if (this->buf) {
++ toi_free_page(27, (unsigned long) this->buf);
++ this->buf = NULL;
++ }
+ }
++ }
++}
+
-+ switch (b->message & MSG_STATE_MASK) {
-+ case MSG_PING:
-+ break;
-+ case MSG_ABORT:
-+ break;
-+ case MSG_BYE:
-+ break;
-+ case MSG_HIBERNATE:
-+ /* Can I hibernate? */
-+ new_message = MSG_HIBERNATE |
-+ ((index & 1) ? MSG_NACK : MSG_ACK);
-+ break;
-+ case MSG_IMAGE:
-+ /* Can I resume? */
-+ new_message = MSG_IMAGE |
-+ ((index & 1) ? MSG_NACK : MSG_ACK);
-+ if (new_message != old_message)
-+ printk(KERN_ERR "Setting whether I can resume "
-+ "to %d.\n", new_message);
-+ break;
-+ case MSG_IO:
-+ new_message = MSG_IO | MSG_ACK;
-+ break;
-+ case MSG_RUNNING:
-+ break;
-+ default:
-+ if (net_ratelimit())
-+ printk(KERN_ERR "Unrecognised TuxOnIce cluster"
-+ " message %d from " NIPQUAD_FMT ".\n",
-+ b->message, NIPQUAD(addr));
-+ };
++/*
++ * toi_crypto_initialise
++ *
++ * Prepare to do some work by allocating buffers and transforms.
++ * Returns: Int: Zero. Even if we can't set up checksum, we still
++ * seek to hibernate.
++ */
++static int toi_checksum_initialise(int starting_cycle)
++{
++ int cpu;
+
-+ if (old_message != new_message) {
-+ node_array[index].current_message = new_message;
-+ printk(KERN_INFO ">>> Sending new message for node "
-+ "%d.\n", index);
-+ toi_send_if(new_message, index);
-+ } else if (!ack) {
-+ printk(KERN_INFO ">>> Resending message for node %d.\n",
-+ index);
-+ toi_send_if(new_message, index);
++ if (!(starting_cycle & SYSFS_HIBERNATE) || !toi_checksum_ops.enabled)
++ return 0;
++
++ if (!*toi_checksum_name) {
++ printk(KERN_INFO "TuxOnIce: No checksum algorithm name set.\n");
++ return 1;
++ }
++
++ for_each_online_cpu(cpu) {
++ struct cpu_context *this = &per_cpu(contexts, cpu);
++ struct page *page;
++
++ this->transform = crypto_alloc_hash(toi_checksum_name, 0, 0);
++ if (IS_ERR(this->transform)) {
++ printk(KERN_INFO "TuxOnIce: Failed to initialise the "
++ "%s checksum algorithm: %ld.\n",
++ toi_checksum_name, (long) this->transform);
++ this->transform = NULL;
++ return 1;
+ }
-+drop_unlock:
-+ spin_unlock(&node_array[index].receive_lock);
-+ };
+
-+drop:
-+ /* Throw the packet out. */
-+ kfree_skb(skb);
++ this->desc.tfm = this->transform;
++ this->desc.flags = 0;
+
++ page = toi_alloc_page(27, GFP_KERNEL);
++ if (!page)
++ return 1;
++ this->buf = page_address(page);
++ sg_init_one(&this->sg[0], this->buf, PAGE_SIZE);
++ }
+ return 0;
+}
+
+/*
-+ * Send cluster message to single interface.
++ * toi_checksum_print_debug_stats
++ * @buffer: Pointer to a buffer into which the debug info will be printed.
++ * @size: Size of the buffer.
++ *
++ * Print information to be recorded for debugging purposes into a buffer.
++ * Returns: Number of characters written to the buffer.
+ */
-+static void toi_send_if(int message, unsigned long my_id)
-+{
-+ struct sk_buff *skb;
-+ struct toi_pkt *b;
-+ int hh_len = LL_RESERVED_SPACE(net_dev);
-+ struct iphdr *h;
-+
-+ /* Allocate packet */
-+ skb = alloc_skb(sizeof(struct toi_pkt) + hh_len + 15, GFP_KERNEL);
-+ if (!skb)
-+ return;
-+ skb_reserve(skb, hh_len);
-+ b = (struct toi_pkt *) skb_put(skb, sizeof(struct toi_pkt));
-+ memset(b, 0, sizeof(struct toi_pkt));
+
-+ /* Construct IP header */
-+ skb_reset_network_header(skb);
-+ h = ip_hdr(skb);
-+ h->version = 4;
-+ h->ihl = 5;
-+ h->tot_len = htons(sizeof(struct toi_pkt));
-+ h->frag_off = htons(IP_DF);
-+ h->ttl = 64;
-+ h->protocol = IPPROTO_UDP;
-+ h->daddr = htonl(INADDR_BROADCAST);
-+ h->check = ip_fast_csum((unsigned char *) h, h->ihl);
++static int toi_checksum_print_debug_stats(char *buffer, int size)
++{
++ int len;
+
-+ /* Construct UDP header */
-+ b->udph.source = htons(toi_cluster_port_send);
-+ b->udph.dest = htons(toi_cluster_port_recv);
-+ b->udph.len = htons(sizeof(struct toi_pkt) - sizeof(struct iphdr));
-+ /* UDP checksum not calculated -- explicitly allowed in BOOTP RFC */
++ if (!toi_checksum_ops.enabled)
++ return scnprintf(buffer, size,
++ "- Checksumming disabled.\n");
+
-+ /* Construct message */
-+ b->message = message;
-+ b->sid = my_id;
-+ b->htype = net_dev->type; /* can cause undefined behavior */
-+ b->hlen = net_dev->addr_len;
-+ memcpy(b->hw_addr, net_dev->dev_addr, net_dev->addr_len);
-+ b->secs = htons(3); /* 3 seconds */
++ len = scnprintf(buffer, size, "- Checksum method is '%s'.\n",
++ toi_checksum_name);
++ len += scnprintf(buffer + len, size - len,
++ " %d pages resaved in atomic copy.\n", toi_num_resaved);
++ return len;
++}
+
-+ /* Chain packet down the line... */
-+ skb->dev = net_dev;
-+ skb->protocol = htons(ETH_P_IP);
-+ if ((dev_hard_header(skb, net_dev, ntohs(skb->protocol),
-+ net_dev->broadcast, net_dev->dev_addr, skb->len) < 0) ||
-+ dev_queue_xmit(skb) < 0)
-+ printk(KERN_INFO "E");
++static int toi_checksum_memory_needed(void)
++{
++ return toi_checksum_ops.enabled ?
++ checksum_pages_needed() << PAGE_SHIFT : 0;
+}
+
-+/* ========================================= */
++static int toi_checksum_storage_needed(void)
++{
++ if (toi_checksum_ops.enabled)
++ return strlen(toi_checksum_name) + sizeof(int) + 1;
++ else
++ return 0;
++}
+
-+/* kTOICluster */
++/*
++ * toi_checksum_save_config_info
++ * @buffer: Pointer to a buffer of size PAGE_SIZE.
++ *
++ * Save informaton needed when reloading the image at resume time.
++ * Returns: Number of bytes used for saving our data.
++ */
++static int toi_checksum_save_config_info(char *buffer)
++{
++ int namelen = strlen(toi_checksum_name) + 1;
++ int total_len;
+
-+static atomic_t num_cluster_threads;
-+static DECLARE_WAIT_QUEUE_HEAD(clusterd_events);
++ *((unsigned int *) buffer) = namelen;
++ strncpy(buffer + sizeof(unsigned int), toi_checksum_name, namelen);
++ total_len = sizeof(unsigned int) + namelen;
++ return total_len;
++}
+
-+static int kTOICluster(void *data)
++/* toi_checksum_load_config_info
++ * @buffer: Pointer to the start of the data.
++ * @size: Number of bytes that were saved.
++ *
++ * Description: Reload information needed for dechecksuming the image at
++ * resume time.
++ */
++static void toi_checksum_load_config_info(char *buffer, int size)
+{
-+ unsigned long my_id;
-+
-+ my_id = atomic_add_return(1, &num_cluster_threads) - 1;
-+ node_array[my_id].current_message = (unsigned long) data;
++ int namelen;
+
-+ PRINTK("kTOICluster daemon %lu starting.\n", my_id);
++ namelen = *((unsigned int *) (buffer));
++ strncpy(toi_checksum_name, buffer + sizeof(unsigned int),
++ namelen);
++ return;
++}
+
-+ current->flags |= PF_NOFREEZE;
++/*
++ * Free Checksum Memory
++ */
+
-+ while (node_array[my_id].current_message) {
-+ toi_send_if(node_array[my_id].current_message, my_id);
-+ sleep_on_timeout(&clusterd_events,
-+ cluster_message_timeout);
-+ PRINTK("Link state %lu is %d.\n", my_id,
-+ node_array[my_id].current_message);
++void free_checksum_pages(void)
++{
++ while (pages_allocated) {
++ unsigned long next = *((unsigned long *) page_list);
++ ClearPageNosave(virt_to_page(page_list));
++ toi_free_page(15, (unsigned long) page_list);
++ page_list = next;
++ pages_allocated--;
+ }
-+
-+ toi_send_if(MSG_BYE, my_id);
-+ atomic_dec(&num_cluster_threads);
-+ wake_up(&clusterd_events);
-+
-+ PRINTK("kTOICluster daemon %lu exiting.\n", my_id);
-+ __set_current_state(TASK_RUNNING);
-+ return 0;
+}
+
-+static void kill_clusterd(void)
++/*
++ * Allocate Checksum Memory
++ */
++
++int allocate_checksum_pages(void)
+{
-+ int i;
++ int pages_needed = checksum_pages_needed();
+
-+ for (i = 0; i < num_local_nodes; i++) {
-+ if (node_array[i].current_message) {
-+ PRINTK("Seeking to kill clusterd %d.\n", i);
-+ node_array[i].current_message = 0;
++ if (!toi_checksum_ops.enabled)
++ return 0;
++
++ while (pages_allocated < pages_needed) {
++ unsigned long *new_page =
++ (unsigned long *) toi_get_zeroed_page(15, TOI_ATOMIC_GFP);
++ if (!new_page) {
++ printk(KERN_ERR "Unable to allocate checksum pages.\n");
++ return -ENOMEM;
+ }
++ SetPageNosave(virt_to_page(new_page));
++ (*new_page) = page_list;
++ page_list = (unsigned long) new_page;
++ pages_allocated++;
+ }
-+ wait_event(clusterd_events,
-+ !atomic_read(&num_cluster_threads));
-+ PRINTK("All cluster daemons have exited.\n");
-+}
-+
-+static int peers_not_in_message(int index, int message, int precise)
-+{
-+ struct cluster_member *this;
-+ unsigned long flags;
-+ int result = 0;
+
-+ spin_lock_irqsave(&node_array[index].member_list_lock, flags);
-+ list_for_each_entry(this, &node_array[index].member_list, list) {
-+ if (this->ignore)
-+ continue;
++ next_page = (unsigned long) page_list;
++ checksum_index = 0;
+
-+ PRINTK("Peer %d.%d.%d.%d sending %s. "
-+ "Seeking %s.\n",
-+ NIPQUAD(this->addr),
-+ str_message(this->message), str_message(message));
-+ if ((precise ? this->message :
-+ this->message & MSG_STATE_MASK) !=
-+ message)
-+ result++;
-+ }
-+ spin_unlock_irqrestore(&node_array[index].member_list_lock, flags);
-+ PRINTK("%d peers in sought message.\n", result);
-+ return result;
++ return 0;
+}
+
-+static void reset_ignored(int index)
++char *tuxonice_get_next_checksum(void)
+{
-+ struct cluster_member *this;
-+ unsigned long flags;
++ if (!toi_checksum_ops.enabled)
++ return NULL;
+
-+ spin_lock_irqsave(&node_array[index].member_list_lock, flags);
-+ list_for_each_entry(this, &node_array[index].member_list, list)
-+ this->ignore = 0;
-+ node_array[index].ignored_peer_count = 0;
-+ spin_unlock_irqrestore(&node_array[index].member_list_lock, flags);
-+}
++ if (checksum_index % CHECKSUMS_PER_PAGE)
++ this_checksum += CHECKSUM_SIZE;
++ else {
++ this_checksum = next_page + sizeof(void *);
++ next_page = *((unsigned long *) next_page);
++ }
+
-+static int peers_in_message(int index, int message, int precise)
-+{
-+ return node_array[index].peer_count -
-+ node_array[index].ignored_peer_count -
-+ peers_not_in_message(index, message, precise);
++ checksum_index++;
++ return (char *) this_checksum;
+}
+
-+static int time_to_continue(int index, unsigned long start, int message)
++int tuxonice_calc_checksum(struct page *page, char *checksum_locn)
+{
-+ int first = peers_not_in_message(index, message, 0);
-+ int second = peers_in_message(index, message, 1);
-+
-+ PRINTK("First part returns %d, second returns %d.\n", first, second);
-+
-+ if (!first && !second) {
-+ PRINTK("All peers answered message %d.\n",
-+ message);
-+ return 1;
-+ }
++ char *pa;
++ int result, cpu = smp_processor_id();
++ struct cpu_context *ctx = &per_cpu(contexts, cpu);
+
-+ if (time_after(jiffies, start + continue_delay)) {
-+ PRINTK("Timeout reached.\n");
-+ return 1;
-+ }
++ if (!toi_checksum_ops.enabled)
++ return 0;
+
-+ PRINTK("Not time to continue yet (%lu < %lu).\n", jiffies,
-+ start + continue_delay);
-+ return 0;
++ pa = kmap(page);
++ memcpy(ctx->buf, pa, PAGE_SIZE);
++ kunmap(page);
++ result = crypto_hash_digest(&ctx->desc, ctx->sg, PAGE_SIZE,
++ checksum_locn);
++ if (result)
++ printk(KERN_ERR "TuxOnIce checksumming: crypto_hash_digest "
++ "returned %d.\n", result);
++ return result;
+}
++/*
++ * Calculate checksums
++ */
+
-+void toi_initiate_cluster_hibernate(void)
++void check_checksums(void)
+{
-+ int result;
-+ unsigned long start;
++ int pfn, index = 0, cpu = smp_processor_id();
++ char current_checksum[CHECKSUM_SIZE];
++ struct cpu_context *ctx = &per_cpu(contexts, cpu);
+
-+ result = do_toi_step(STEP_HIBERNATE_PREPARE_IMAGE);
-+ if (result)
++ if (!toi_checksum_ops.enabled)
+ return;
+
-+ toi_send_if(MSG_HIBERNATE, 0);
++ next_page = (unsigned long) page_list;
+
-+ start = jiffies;
-+ wait_event(node_array[0].member_events,
-+ time_to_continue(0, start, MSG_HIBERNATE));
++ toi_num_resaved = 0;
++ this_checksum = 0;
+
-+ if (test_action_state(TOI_FREEZER_TEST)) {
-+ toi_send_if(MSG_ABORT, 0);
++ memory_bm_position_reset(pageset2_map);
++ for (pfn = memory_bm_next_pfn(pageset2_map); pfn != BM_END_OF_MAP;
++ pfn = memory_bm_next_pfn(pageset2_map)) {
++ int ret;
++ char *pa;
++ struct page *page = pfn_to_page(pfn);
+
-+ start = jiffies;
-+ wait_event(node_array[0].member_events,
-+ time_to_continue(0, start, MSG_RUNNING));
++ if (index % CHECKSUMS_PER_PAGE) {
++ this_checksum += CHECKSUM_SIZE;
++ } else {
++ this_checksum = next_page + sizeof(void *);
++ next_page = *((unsigned long *) next_page);
++ }
+
-+ do_toi_step(STEP_QUIET_CLEANUP);
-+ return;
-+ }
++ /* Done when IRQs disabled so must be atomic */
++ pa = kmap_atomic(page, KM_USER1);
++ memcpy(ctx->buf, pa, PAGE_SIZE);
++ kunmap_atomic(pa, KM_USER1);
++ ret = crypto_hash_digest(&ctx->desc, ctx->sg, PAGE_SIZE,
++ current_checksum);
+
-+ toi_send_if(MSG_IO, 0);
++ if (ret) {
++ printk(KERN_INFO "Digest failed. Returned %d.\n", ret);
++ return;
++ }
+
-+ result = do_toi_step(STEP_HIBERNATE_SAVE_IMAGE);
-+ if (result)
-+ return;
++ if (memcmp(current_checksum, (char *) this_checksum,
++ CHECKSUM_SIZE)) {
++ SetPageResave(pfn_to_page(pfn));
++ toi_num_resaved++;
++ if (test_action_state(TOI_ABORT_ON_RESAVE_NEEDED))
++ set_abort_result(TOI_RESAVE_NEEDED);
++ }
+
-+ /* This code runs at resume time too! */
-+ if (toi_in_hibernate)
-+ result = do_toi_step(STEP_HIBERNATE_POWERDOWN);
++ index++;
++ }
+}
-+EXPORT_SYMBOL_GPL(toi_initiate_cluster_hibernate);
+
-+/* toi_cluster_print_debug_stats
-+ *
-+ * Description: Print information to be recorded for debugging purposes into a
-+ * buffer.
-+ * Arguments: buffer: Pointer to a buffer into which the debug info will be
-+ * printed.
-+ * size: Size of the buffer.
-+ * Returns: Number of characters written to the buffer.
++static struct toi_sysfs_data sysfs_params[] = {
++ SYSFS_INT("enabled", SYSFS_RW, &toi_checksum_ops.enabled, 0, 1, 0,
++ NULL),
++ SYSFS_BIT("abort_if_resave_needed", SYSFS_RW, &toi_bkd.toi_action,
++ TOI_ABORT_ON_RESAVE_NEEDED, 0)
++};
++
++/*
++ * Ops structure.
+ */
-+static int toi_cluster_print_debug_stats(char *buffer, int size)
-+{
-+ int len;
++static struct toi_module_ops toi_checksum_ops = {
++ .type = MISC_MODULE,
++ .name = "checksumming",
++ .directory = "checksum",
++ .module = THIS_MODULE,
++ .initialise = toi_checksum_initialise,
++ .cleanup = toi_checksum_cleanup,
++ .print_debug_info = toi_checksum_print_debug_stats,
++ .save_config_info = toi_checksum_save_config_info,
++ .load_config_info = toi_checksum_load_config_info,
++ .memory_needed = toi_checksum_memory_needed,
++ .storage_needed = toi_checksum_storage_needed,
+
-+ if (strlen(toi_cluster_iface))
-+ len = scnprintf(buffer, size,
-+ "- Cluster interface is '%s'.\n",
-+ toi_cluster_iface);
-+ else
-+ len = scnprintf(buffer, size,
-+ "- Cluster support is disabled.\n");
-+ return len;
-+}
++ .sysfs_data = sysfs_params,
++ .num_sysfs_entries = sizeof(sysfs_params) /
++ sizeof(struct toi_sysfs_data),
++};
+
-+/* cluster_memory_needed
-+ *
-+ * Description: Tell the caller how much memory we need to operate during
-+ * hibernate/resume.
-+ * Returns: Unsigned long. Maximum number of bytes of memory required for
-+ * operation.
-+ */
-+static int toi_cluster_memory_needed(void)
++/* ---- Registration ---- */
++int toi_checksum_init(void)
+{
-+ return 0;
++ int result = toi_register_module(&toi_checksum_ops);
++ return result;
+}
+
-+static int toi_cluster_storage_needed(void)
++void toi_checksum_exit(void)
+{
-+ return 1 + strlen(toi_cluster_iface);
++ toi_unregister_module(&toi_checksum_ops);
+}
-+
-+/* toi_cluster_save_config_info
+diff --git a/kernel/power/tuxonice_checksum.h b/kernel/power/tuxonice_checksum.h
+new file mode 100644
+index 0000000..84a9174
+--- /dev/null
++++ b/kernel/power/tuxonice_checksum.h
+@@ -0,0 +1,32 @@
++/*
++ * kernel/power/tuxonice_checksum.h
+ *
-+ * Description: Save informaton needed when reloading the image at resume time.
-+ * Arguments: Buffer: Pointer to a buffer of size PAGE_SIZE.
-+ * Returns: Number of bytes used for saving our data.
++ * Copyright (C) 2006-2008 Nigel Cunningham (nigel at tuxonice net)
++ * Copyright (C) 2006 Red Hat, inc.
++ *
++ * This file is released under the GPLv2.
++ *
++ * This file contains data checksum routines for TuxOnIce,
++ * using cryptoapi. They are used to locate any modifications
++ * made to pageset 2 while we're saving it.
+ */
-+static int toi_cluster_save_config_info(char *buffer)
-+{
-+ strcpy(buffer, toi_cluster_iface);
-+ return strlen(toi_cluster_iface + 1);
-+}
+
-+/* toi_cluster_load_config_info
++#if defined(CONFIG_TOI_CHECKSUM)
++extern int toi_checksum_init(void);
++extern void toi_checksum_exit(void);
++void check_checksums(void);
++int allocate_checksum_pages(void);
++void free_checksum_pages(void);
++char *tuxonice_get_next_checksum(void);
++int tuxonice_calc_checksum(struct page *page, char *checksum_locn);
++#else
++static inline int toi_checksum_init(void) { return 0; }
++static inline void toi_checksum_exit(void) { }
++static inline void check_checksums(void) { };
++static inline int allocate_checksum_pages(void) { return 0; };
++static inline void free_checksum_pages(void) { };
++static inline char *tuxonice_get_next_checksum(void) { return NULL; };
++static inline int tuxonice_calc_checksum(struct page *page, char *checksum_locn)
++ { return 0; }
++#endif
++
+diff --git a/kernel/power/tuxonice_cluster.c b/kernel/power/tuxonice_cluster.c
+new file mode 100644
+index 0000000..671006d
+--- /dev/null
++++ b/kernel/power/tuxonice_cluster.c
+@@ -0,0 +1,1069 @@
++/*
++ * kernel/power/tuxonice_cluster.c
++ *
++ * Copyright (C) 2006-2008 Nigel Cunningham (nigel at tuxonice net)
++ *
++ * This file is released under the GPLv2.
++ *
++ * This file contains routines for cluster hibernation support.
++ *
++ * Based on ip autoconfiguration code in net/ipv4/ipconfig.c.
++ *
++ * How does it work?
++ *
++ * There is no 'master' node that tells everyone else what to do. All nodes
++ * send messages to the broadcast address/port, maintain a list of peers
++ * and figure out when to progress to the next step in hibernating or resuming.
++ * This makes us more fault tolerant when it comes to nodes coming and going
++ * (which may be more of an issue if we're hibernating when power supplies
++ * are being unreliable).
++ *
++ * At boot time, we start a ktuxonice thread that handles communication with
++ * other nodes. This node maintains a state machine that controls our progress
++ * through hibernating and resuming, keeping us in step with other nodes. Nodes
++ * are identified by their hw address.
++ *
++ * On startup, the node sends CLUSTER_PING on the configured interface's
++ * broadcast address, port $toi_cluster_port (see below) and begins to listen
++ * for other broadcast messages. CLUSTER_PING messages are repeated at
++ * intervals of 5 minutes, with a random offset to spread traffic out.
++ *
++ * A hibernation cycle is initiated from any node via
++ *
++ * echo > /sys/power/tuxonice/do_hibernate
++ *
++ * and (possibily) the hibernate script. At each step of the process, the node
++ * completes its work, and waits for all other nodes to signal completion of
++ * their work (or timeout) before progressing to the next step.
++ *
++ * Request/state Action before reply Possible reply Next state
++ * HIBERNATE capable, pre-script HIBERNATE|ACK NODE_PREP
++ * HIBERNATE|NACK INIT_0
++ *
++ * PREP prepare_image PREP|ACK IMAGE_WRITE
++ * PREP|NACK INIT_0
++ * ABORT RUNNING
++ *
++ * IO write image IO|ACK power off
++ * ABORT POST_RESUME
++ *
++ * (Boot time) check for image IMAGE|ACK RESUME_PREP
++ * (Note 1)
++ * IMAGE|NACK (Note 2)
++ *
++ * PREP prepare read image PREP|ACK IMAGE_READ
++ * PREP|NACK (As NACK_IMAGE)
++ *
++ * IO read image IO|ACK POST_RESUME
++ *
++ * POST_RESUME thaw, post-script RUNNING
++ *
++ * INIT_0 init 0
++ *
++ * Other messages:
++ *
++ * - PING: Request for all other live nodes to send a PONG. Used at startup to
++ * announce presence, when a node is suspected dead and periodically, in case
++ * segments of the network are [un]plugged.
++ *
++ * - PONG: Response to a PING.
++ *
++ * - ABORT: Request to cancel writing an image.
++ *
++ * - BYE: Notification that this node is shutting down.
++ *
++ * Note 1: Repeated at 3s intervals until we continue to boot/resume, so that
++ * nodes which are slower to start up can get state synchronised. If a node
++ * starting up sees other nodes sending RESUME_PREP or IMAGE_READ, it may send
++ * ACK_IMAGE and they will wait for it to catch up. If it sees ACK_READ, it
++ * must invalidate its image (if any) and boot normally.
++ *
++ * Note 2: May occur when one node lost power or powered off while others
++ * hibernated. This node waits for others to complete resuming (ACK_READ)
++ * before completing its boot, so that it appears as a fail node restarting.
+ *
-+ * Description: Reload information needed for declustering the image at
-+ * resume time.
-+ * Arguments: Buffer: Pointer to the start of the data.
-+ * Size: Number of bytes that were saved.
++ * If any node has an image, then it also has a list of nodes that hibernated
++ * in synchronisation with it. The node will wait for other nodes to appear
++ * or timeout before beginning its restoration.
++ *
++ * If a node has no image, it needs to wait, in case other nodes which do have
++ * an image are going to resume, but are taking longer to announce their
++ * presence. For this reason, the user can specify a timeout value and a number
++ * of nodes detected before we just continue. (We might want to assume in a
++ * cluster of, say, 15 nodes, if 8 others have booted without finding an image,
++ * the remaining nodes will too. This might help in situations where some nodes
++ * are much slower to boot, or more subject to hardware failures or such like).
+ */
-+static void toi_cluster_load_config_info(char *buffer, int size)
-+{
-+ strncpy(toi_cluster_iface, buffer, size);
-+ return;
-+}
-+
-+static void cluster_startup(void)
-+{
-+ int have_image = do_check_can_resume(), i;
-+ unsigned long start = jiffies, initial_message;
-+ struct task_struct *p;
-+
-+ initial_message = MSG_IMAGE;
-+
-+ have_image = 1;
-+
-+ for (i = 0; i < num_local_nodes; i++) {
-+ PRINTK("Starting ktoiclusterd %d.\n", i);
-+ p = kthread_create(kTOICluster, (void *) initial_message,
-+ "ktoiclusterd/%d", i);
-+ if (IS_ERR(p)) {
-+ printk(KERN_ERR "Failed to start ktoiclusterd.\n");
-+ return;
-+ }
-+
-+ wake_up_process(p);
-+ }
+
-+ /* Wait for delay or someone else sending first message */
-+ wait_event(node_array[0].member_events, time_to_continue(0, start,
-+ MSG_IMAGE));
++#include <linux/suspend.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/if.h>
++#include <linux/rtnetlink.h>
++#include <linux/ip.h>
++#include <linux/udp.h>
++#include <linux/in.h>
++#include <linux/if_arp.h>
++#include <linux/kthread.h>
++#include <linux/wait.h>
++#include <linux/netdevice.h>
++#include <net/ip.h>
+
-+ others_have_image = peers_in_message(0, MSG_IMAGE | MSG_ACK, 1);
++#include "tuxonice.h"
++#include "tuxonice_modules.h"
++#include "tuxonice_sysfs.h"
++#include "tuxonice_alloc.h"
++#include "tuxonice_io.h"
+
-+ printk(KERN_INFO "Continuing. I %shave an image. Peers with image:"
-+ " %d.\n", have_image ? "" : "don't ", others_have_image);
++#if 1
++#define PRINTK(a, b...) do { printk(a, ##b); } while (0)
++#else
++#define PRINTK(a, b...) do { } while (0)
++#endif
+
-+ if (have_image) {
-+ int result;
++static int loopback_mode;
++static int num_local_nodes = 1;
++#define MAX_LOCAL_NODES 8
++#define SADDR (loopback_mode ? b->sid : h->saddr)
+
-+ /* Start to resume */
-+ printk(KERN_INFO " === Starting to resume === \n");
-+ node_array[0].current_message = MSG_IO;
-+ toi_send_if(MSG_IO, 0);
++#define MYNAME "TuxOnIce Clustering"
+
-+ /* result = do_toi_step(STEP_RESUME_LOAD_PS1); */
-+ result = 0;
++enum cluster_message {
++ MSG_ACK = 1,
++ MSG_NACK = 2,
++ MSG_PING = 4,
++ MSG_ABORT = 8,
++ MSG_BYE = 16,
++ MSG_HIBERNATE = 32,
++ MSG_IMAGE = 64,
++ MSG_IO = 128,
++ MSG_RUNNING = 256
++};
+
-+ if (!result) {
-+ /*
-+ * Atomic restore - we'll come back in the hibernation
-+ * path.
-+ */
++static char *str_message(int message)
++{
++ switch (message) {
++ case 4:
++ return "Ping";
++ case 8:
++ return "Abort";
++ case 9:
++ return "Abort acked";
++ case 10:
++ return "Abort nacked";
++ case 16:
++ return "Bye";
++ case 17:
++ return "Bye acked";
++ case 18:
++ return "Bye nacked";
++ case 32:
++ return "Hibernate request";
++ case 33:
++ return "Hibernate ack";
++ case 34:
++ return "Hibernate nack";
++ case 64:
++ return "Image exists?";
++ case 65:
++ return "Image does exist";
++ case 66:
++ return "No image here";
++ case 128:
++ return "I/O";
++ case 129:
++ return "I/O okay";
++ case 130:
++ return "I/O failed";
++ case 256:
++ return "Running";
++ default:
++ printk(KERN_ERR "Unrecognised message %d.\n", message);
++ return "Unrecognised message (see dmesg)";
++ }
++}
+
-+ /* result = do_toi_step(STEP_RESUME_DO_RESTORE); */
-+ result = 0;
++#define MSG_ACK_MASK (MSG_ACK | MSG_NACK)
++#define MSG_STATE_MASK (~MSG_ACK_MASK)
+
-+ /* do_toi_step(STEP_QUIET_CLEANUP); */
-+ }
++struct node_info {
++ struct list_head member_list;
++ wait_queue_head_t member_events;
++ spinlock_t member_list_lock;
++ spinlock_t receive_lock;
++ int peer_count, ignored_peer_count;
++ struct toi_sysfs_data sysfs_data;
++ enum cluster_message current_message;
++};
+
-+ node_array[0].current_message |= MSG_NACK;
++struct node_info node_array[MAX_LOCAL_NODES];
+
-+ /* For debugging - disable for real life? */
-+ wait_event(node_array[0].member_events,
-+ time_to_continue(0, start, MSG_IO));
-+ }
++struct cluster_member {
++ __be32 addr;
++ enum cluster_message message;
++ struct list_head list;
++ int ignore;
++};
+
-+ if (others_have_image) {
-+ /* Wait for them to resume */
-+ printk(KERN_INFO "Waiting for other nodes to resume.\n");
-+ start = jiffies;
-+ wait_event(node_array[0].member_events,
-+ time_to_continue(0, start, MSG_RUNNING));
-+ if (peers_not_in_message(0, MSG_RUNNING, 0))
-+ printk(KERN_INFO "Timed out while waiting for other "
-+ "nodes to resume.\n");
-+ }
++#define toi_cluster_port_send 3501
++#define toi_cluster_port_recv 3502
+
-+ /* Find out whether an image exists here. Send ACK_IMAGE or NACK_IMAGE
-+ * as appropriate.
-+ *
-+ * If we don't have an image:
-+ * - Wait until someone else says they have one, or conditions are met
-+ * for continuing to boot (n machines or t seconds).
-+ * - If anyone has an image, wait for them to resume before continuing
-+ * to boot.
-+ *
-+ * If we have an image:
-+ * - Wait until conditions are met before continuing to resume (n
-+ * machines or t seconds). Send RESUME_PREP and freeze processes.
-+ * NACK_PREP if freezing fails (shouldn't) and follow logic for
-+ * us having no image above. On success, wait for [N]ACK_PREP from
-+ * other machines. Read image (including atomic restore) until done.
-+ * Wait for ACK_READ from others (should never fail). Thaw processes
-+ * and do post-resume. (The section after the atomic restore is done
-+ * via the code for hibernating).
-+ */
++static struct net_device *net_dev;
++static struct toi_module_ops toi_cluster_ops;
+
-+ node_array[0].current_message = MSG_RUNNING;
-+}
++static int toi_recv(struct sk_buff *skb, struct net_device *dev,
++ struct packet_type *pt, struct net_device *orig_dev);
+
-+/* toi_cluster_open_iface
-+ *
-+ * Description: Prepare to use an interface.
-+ */
++static struct packet_type toi_cluster_packet_type = {
++ .type = __constant_htons(ETH_P_IP),
++ .func = toi_recv,
++};
+
-+static int toi_cluster_open_iface(void)
-+{
-+ struct net_device *dev;
++struct toi_pkt { /* BOOTP packet format */
++ struct iphdr iph; /* IP header */
++ struct udphdr udph; /* UDP header */
++ u8 htype; /* HW address type */
++ u8 hlen; /* HW address length */
++ __be32 xid; /* Transaction ID */
++ __be16 secs; /* Seconds since we started */
++ __be16 flags; /* Just what it says */
++ u8 hw_addr[16]; /* Sender's HW address */
++ u16 message; /* Message */
++ unsigned long sid; /* Source ID for loopback testing */
++};
+
-+ rtnl_lock();
++static char toi_cluster_iface[IFNAMSIZ] = CONFIG_TOI_DEFAULT_CLUSTER_INTERFACE;
+
-+ for_each_netdev(&init_net, dev) {
-+ if (/* dev == &init_net.loopback_dev || */
-+ strcmp(dev->name, toi_cluster_iface))
-+ continue;
++static int added_pack;
+
-+ net_dev = dev;
-+ break;
-+ }
++static int others_have_image;
+
-+ rtnl_unlock();
++/* Key used to allow multiple clusters on the same lan */
++static char toi_cluster_key[32] = CONFIG_TOI_DEFAULT_CLUSTER_KEY;
++static char pre_hibernate_script[255] =
++ CONFIG_TOI_DEFAULT_CLUSTER_PRE_HIBERNATE;
++static char post_hibernate_script[255] =
++ CONFIG_TOI_DEFAULT_CLUSTER_POST_HIBERNATE;
+
-+ if (!net_dev) {
-+ printk(KERN_ERR MYNAME ": Device %s not found.\n",
-+ toi_cluster_iface);
-+ return -ENODEV;
-+ }
++/* List of cluster members */
++static unsigned long continue_delay = 5 * HZ;
++static unsigned long cluster_message_timeout = 3 * HZ;
+
-+ dev_add_pack(&toi_cluster_packet_type);
-+ added_pack = 1;
++/* === Membership list === */
+
-+ loopback_mode = (net_dev == init_net.loopback_dev);
-+ num_local_nodes = loopback_mode ? 8 : 1;
++static void print_member_info(int index)
++{
++ struct cluster_member *this;
+
-+ PRINTK("Loopback mode is %s. Number of local nodes is %d.\n",
-+ loopback_mode ? "on" : "off", num_local_nodes);
++ printk(KERN_INFO "==> Dumping node %d.\n", index);
+
-+ cluster_startup();
-+ return 0;
++ list_for_each_entry(this, &node_array[index].member_list, list)
++ printk(KERN_INFO "%d.%d.%d.%d last message %s. %s\n",
++ NIPQUAD(this->addr),
++ str_message(this->message),
++ this->ignore ? "(Ignored)" : "");
++ printk(KERN_INFO "== Done ==\n");
+}
+
-+/* toi_cluster_close_iface
-+ *
-+ * Description: Stop using an interface.
-+ */
-+
-+static int toi_cluster_close_iface(void)
++static struct cluster_member *__find_member(int index, __be32 addr)
+{
-+ kill_clusterd();
-+ if (added_pack) {
-+ dev_remove_pack(&toi_cluster_packet_type);
-+ added_pack = 0;
++ struct cluster_member *this;
++
++ list_for_each_entry(this, &node_array[index].member_list, list) {
++ if (this->addr != addr)
++ continue;
++
++ return this;
+ }
-+ return 0;
++
++ return NULL;
+}
+
-+static void write_side_effect(void)
++static void set_ignore(int index, __be32 addr, struct cluster_member *this)
+{
-+ if (toi_cluster_ops.enabled) {
-+ toi_cluster_open_iface();
-+ set_toi_state(TOI_CLUSTER_MODE);
-+ } else {
-+ toi_cluster_close_iface();
-+ clear_toi_state(TOI_CLUSTER_MODE);
++ if (this->ignore) {
++ PRINTK("Node %d already ignoring %d.%d.%d.%d.\n",
++ index, NIPQUAD(addr));
++ return;
+ }
-+}
+
-+static void node_write_side_effect(void)
-+{
++ PRINTK("Node %d sees node %d.%d.%d.%d now being ignored.\n",
++ index, NIPQUAD(addr));
++ this->ignore = 1;
++ node_array[index].ignored_peer_count++;
+}
+
-+/*
-+ * data for our sysfs entries.
-+ */
-+static struct toi_sysfs_data sysfs_params[] = {
-+ SYSFS_STRING("interface", SYSFS_RW, toi_cluster_iface, IFNAMSIZ, 0,
-+ NULL),
-+ SYSFS_INT("enabled", SYSFS_RW, &toi_cluster_ops.enabled, 0, 1, 0,
-+ write_side_effect),
-+ SYSFS_STRING("cluster_name", SYSFS_RW, toi_cluster_key, 32, 0, NULL),
-+ SYSFS_STRING("pre-hibernate-script", SYSFS_RW, pre_hibernate_script,
-+ 256, 0, NULL),
-+ SYSFS_STRING("post-hibernate-script", SYSFS_RW, post_hibernate_script,
-+ 256, 0, STRING),
-+ SYSFS_UL("continue_delay", SYSFS_RW, &continue_delay, HZ / 2, 60 * HZ,
-+ 0)
-+};
++static int __add_update_member(int index, __be32 addr, int message)
++{
++ struct cluster_member *this;
+
-+/*
-+ * Ops structure.
-+ */
++ this = __find_member(index, addr);
++ if (this) {
++ if (this->message != message) {
++ this->message = message;
++ if ((message & MSG_NACK) &&
++ (message & (MSG_HIBERNATE | MSG_IMAGE | MSG_IO)))
++ set_ignore(index, addr, this);
++ PRINTK("Node %d sees node %d.%d.%d.%d now sending "
++ "%s.\n", index, NIPQUAD(addr),
++ str_message(message));
++ wake_up(&node_array[index].member_events);
++ }
++ return 0;
++ }
+
-+static struct toi_module_ops toi_cluster_ops = {
-+ .type = FILTER_MODULE,
-+ .name = "Cluster",
-+ .directory = "cluster",
-+ .module = THIS_MODULE,
-+ .memory_needed = toi_cluster_memory_needed,
-+ .print_debug_info = toi_cluster_print_debug_stats,
-+ .save_config_info = toi_cluster_save_config_info,
-+ .load_config_info = toi_cluster_load_config_info,
-+ .storage_needed = toi_cluster_storage_needed,
++ this = (struct cluster_member *) toi_kzalloc(36,
++ sizeof(struct cluster_member), GFP_KERNEL);
+
-+ .sysfs_data = sysfs_params,
-+ .num_sysfs_entries = sizeof(sysfs_params) /
-+ sizeof(struct toi_sysfs_data),
-+};
++ if (!this)
++ return -1;
+
-+/* ---- Registration ---- */
++ this->addr = addr;
++ this->message = message;
++ this->ignore = 0;
++ INIT_LIST_HEAD(&this->list);
+
-+#ifdef MODULE
-+#define INIT static __init
-+#define EXIT static __exit
-+#else
-+#define INIT
-+#define EXIT
-+#endif
++ node_array[index].peer_count++;
+
-+INIT int toi_cluster_init(void)
-+{
-+ int temp = toi_register_module(&toi_cluster_ops), i;
-+ struct kobject *kobj = toi_cluster_ops.dir_kobj;
++ PRINTK("Node %d sees node %d.%d.%d.%d sending %s.\n", index,
++ NIPQUAD(addr), str_message(message));
+
-+ for (i = 0; i < MAX_LOCAL_NODES; i++) {
-+ node_array[i].current_message = 0;
-+ INIT_LIST_HEAD(&node_array[i].member_list);
-+ init_waitqueue_head(&node_array[i].member_events);
-+ spin_lock_init(&node_array[i].member_list_lock);
-+ spin_lock_init(&node_array[i].receive_lock);
++ if ((message & MSG_NACK) &&
++ (message & (MSG_HIBERNATE | MSG_IMAGE | MSG_IO)))
++ set_ignore(index, addr, this);
++ list_add_tail(&this->list, &node_array[index].member_list);
++ return 1;
++}
+
-+ /* Set up sysfs entry */
-+ node_array[i].sysfs_data.attr.name = toi_kzalloc(8,
-+ sizeof(node_array[i].sysfs_data.attr.name),
-+ GFP_KERNEL);
-+ sprintf((char *) node_array[i].sysfs_data.attr.name, "node_%d",
-+ i);
-+ node_array[i].sysfs_data.attr.mode = SYSFS_RW;
-+ node_array[i].sysfs_data.type = TOI_SYSFS_DATA_INTEGER;
-+ node_array[i].sysfs_data.flags = 0;
-+ node_array[i].sysfs_data.data.integer.variable =
-+ (int *) &node_array[i].current_message;
-+ node_array[i].sysfs_data.data.integer.minimum = 0;
-+ node_array[i].sysfs_data.data.integer.maximum = INT_MAX;
-+ node_array[i].sysfs_data.write_side_effect =
-+ node_write_side_effect;
-+ toi_register_sysfs_file(kobj, &node_array[i].sysfs_data);
-+ }
++static int add_update_member(int index, __be32 addr, int message)
++{
++ int result;
++ unsigned long flags;
++ spin_lock_irqsave(&node_array[index].member_list_lock, flags);
++ result = __add_update_member(index, addr, message);
++ spin_unlock_irqrestore(&node_array[index].member_list_lock, flags);
+
-+ toi_cluster_ops.enabled = (strlen(toi_cluster_iface) > 0);
++ print_member_info(index);
+
-+ if (toi_cluster_ops.enabled)
-+ toi_cluster_open_iface();
++ wake_up(&node_array[index].member_events);
+
-+ return temp;
++ return result;
+}
+
-+EXIT void toi_cluster_exit(void)
++static void del_member(int index, __be32 addr)
+{
-+ int i;
-+ toi_cluster_close_iface();
++ struct cluster_member *this;
++ unsigned long flags;
+
-+ for (i = 0; i < MAX_LOCAL_NODES; i++)
-+ toi_unregister_sysfs_file(toi_cluster_ops.dir_kobj,
-+ &node_array[i].sysfs_data);
-+ toi_unregister_module(&toi_cluster_ops);
-+}
++ spin_lock_irqsave(&node_array[index].member_list_lock, flags);
++ this = __find_member(index, addr);
+
-+static int __init toi_cluster_iface_setup(char *iface)
-+{
-+ toi_cluster_ops.enabled = (*iface &&
-+ strcmp(iface, "off"));
++ if (this) {
++ list_del_init(&this->list);
++ toi_kfree(36, this, sizeof(*this));
++ node_array[index].peer_count--;
++ }
+
-+ if (toi_cluster_ops.enabled)
-+ strncpy(toi_cluster_iface, iface, strlen(iface));
++ spin_unlock_irqrestore(&node_array[index].member_list_lock, flags);
+}
+
-+__setup("toi_cluster=", toi_cluster_iface_setup);
-+
-+#ifdef MODULE
-+MODULE_LICENSE("GPL");
-+module_init(toi_cluster_init);
-+module_exit(toi_cluster_exit);
-+MODULE_AUTHOR("Nigel Cunningham");
-+MODULE_DESCRIPTION("Cluster Support for TuxOnIce");
-+#endif
-diff --git a/kernel/power/tuxonice_cluster.h b/kernel/power/tuxonice_cluster.h
-new file mode 100644
-index 0000000..b0f8918
---- /dev/null
-+++ b/kernel/power/tuxonice_cluster.h
-@@ -0,0 +1,19 @@
-+/*
-+ * kernel/power/tuxonice_cluster.h
-+ *
-+ * Copyright (C) 2006-2008 Nigel Cunningham (nigel at tuxonice net)
-+ * Copyright (C) 2006 Red Hat, inc.
-+ *
-+ * This file is released under the GPLv2.
-+ */
++/* === Message transmission === */
+
-+#ifdef CONFIG_TOI_CLUSTER
-+extern int toi_cluster_init(void);
-+extern void toi_cluster_exit(void);
-+extern void toi_initiate_cluster_hibernate(void);
-+#else
-+static inline int toi_cluster_init(void) { return 0; }
-+static inline void toi_cluster_exit(void) { }
-+static inline void toi_initiate_cluster_hibernate(void) { }
-+#endif
++static void toi_send_if(int message, unsigned long my_id);
+
-diff --git a/kernel/power/tuxonice_compress.c b/kernel/power/tuxonice_compress.c
-new file mode 100644
-index 0000000..1c7aaf3
---- /dev/null
-+++ b/kernel/power/tuxonice_compress.c
-@@ -0,0 +1,445 @@
+/*
-+ * kernel/power/compression.c
-+ *
-+ * Copyright (C) 2003-2008 Nigel Cunningham (nigel at tuxonice net)
-+ *
-+ * This file is released under the GPLv2.
-+ *
-+ * This file contains data compression routines for TuxOnIce,
-+ * using cryptoapi.
++ * Process received TOI packet.
+ */
++static int toi_recv(struct sk_buff *skb, struct net_device *dev,
++ struct packet_type *pt, struct net_device *orig_dev)
++{
++ struct toi_pkt *b;
++ struct iphdr *h;
++ int len, result, index;
++ unsigned long addr, message, ack;
+
-+#include <linux/suspend.h>
-+#include <linux/highmem.h>
-+#include <linux/vmalloc.h>
-+#include <linux/crypto.h>
-+
-+#include "tuxonice_builtin.h"
-+#include "tuxonice.h"
-+#include "tuxonice_modules.h"
-+#include "tuxonice_sysfs.h"
-+#include "tuxonice_io.h"
-+#include "tuxonice_ui.h"
-+#include "tuxonice_alloc.h"
++ /* Perform verifications before taking the lock. */
++ if (skb->pkt_type == PACKET_OTHERHOST)
++ goto drop;
+
-+static int toi_expected_compression;
++ if (dev != net_dev)
++ goto drop;
+
-+static struct toi_module_ops toi_compression_ops;
-+static struct toi_module_ops *next_driver;
++ skb = skb_share_check(skb, GFP_ATOMIC);
++ if (!skb)
++ return NET_RX_DROP;
+
-+static char toi_compressor_name[32] = "lzo";
++ if (!pskb_may_pull(skb,
++ sizeof(struct iphdr) +
++ sizeof(struct udphdr)))
++ goto drop;
+
-+static DEFINE_MUTEX(stats_lock);
++ b = (struct toi_pkt *)skb_network_header(skb);
++ h = &b->iph;
+
-+struct cpu_context {
-+ u8 *page_buffer;
-+ struct crypto_comp *transform;
-+ unsigned int len;
-+ char *buffer_start;
-+ char *output_buffer;
-+};
++ if (h->ihl != 5 || h->version != 4 || h->protocol != IPPROTO_UDP)
++ goto drop;
+
-+static DEFINE_PER_CPU(struct cpu_context, contexts);
++ /* Fragments are not supported */
++ if (h->frag_off & htons(IP_OFFSET | IP_MF)) {
++ if (net_ratelimit())
++ printk(KERN_ERR "TuxOnIce: Ignoring fragmented "
++ "cluster message.\n");
++ goto drop;
++ }
+
-+static int toi_compress_prepare_result;
++ if (skb->len < ntohs(h->tot_len))
++ goto drop;
+
-+/*
-+ * toi_compress_cleanup
-+ *
-+ * Frees memory allocated for our labours.
-+ */
-+static void toi_compress_cleanup(int toi_or_resume)
-+{
-+ int cpu;
++ if (ip_fast_csum((char *) h, h->ihl))
++ goto drop;
+
-+ if (!toi_or_resume)
-+ return;
++ if (b->udph.source != htons(toi_cluster_port_send) ||
++ b->udph.dest != htons(toi_cluster_port_recv))
++ goto drop;
+
-+ for_each_online_cpu(cpu) {
-+ struct cpu_context *this = &per_cpu(contexts, cpu);
-+ if (this->transform) {
-+ crypto_free_comp(this->transform);
-+ this->transform = NULL;
-+ }
++ if (ntohs(h->tot_len) < ntohs(b->udph.len) + sizeof(struct iphdr))
++ goto drop;
+
-+ if (this->page_buffer)
-+ toi_free_page(16, (unsigned long) this->page_buffer);
++ len = ntohs(b->udph.len) - sizeof(struct udphdr);
+
-+ this->page_buffer = NULL;
++ /* Ok the front looks good, make sure we can get at the rest. */
++ if (!pskb_may_pull(skb, skb->len))
++ goto drop;
+
-+ if (this->output_buffer)
-+ vfree(this->output_buffer);
++ b = (struct toi_pkt *)skb_network_header(skb);
++ h = &b->iph;
+
-+ this->output_buffer = NULL;
-+ }
-+}
++ addr = SADDR;
++ PRINTK(">>> Message %s received from " NIPQUAD_FMT ".\n",
++ str_message(b->message), NIPQUAD(addr));
+
-+/*
-+ * toi_crypto_prepare
-+ *
-+ * Prepare to do some work by allocating buffers and transforms.
-+ */
-+static int toi_compress_crypto_prepare(void)
-+{
-+ int cpu;
++ message = b->message & MSG_STATE_MASK;
++ ack = b->message & MSG_ACK_MASK;
+
-+ if (!*toi_compressor_name) {
-+ printk(KERN_INFO "TuxOnIce: Compression enabled but no "
-+ "compressor name set.\n");
-+ return 1;
-+ }
++ for (index = 0; index < num_local_nodes; index++) {
++ int new_message = node_array[index].current_message,
++ old_message = new_message;
+
-+ for_each_online_cpu(cpu) {
-+ struct cpu_context *this = &per_cpu(contexts, cpu);
-+ this->transform = crypto_alloc_comp(toi_compressor_name, 0, 0);
-+ if (IS_ERR(this->transform)) {
-+ printk(KERN_INFO "TuxOnIce: Failed to initialise the "
-+ "%s compression transform.\n",
-+ toi_compressor_name);
-+ this->transform = NULL;
-+ return 1;
++ if (index == SADDR || !old_message) {
++ PRINTK("Ignoring node %d (offline or self).\n", index);
++ continue;
+ }
+
-+ this->page_buffer =
-+ (char *) toi_get_zeroed_page(16, TOI_ATOMIC_GFP);
++ /* One message at a time, please. */
++ spin_lock(&node_array[index].receive_lock);
+
-+ if (!this->page_buffer) {
-+ printk(KERN_ERR
-+ "Failed to allocate a page buffer for TuxOnIce "
-+ "compression driver.\n");
-+ return -ENOMEM;
++ result = add_update_member(index, SADDR, b->message);
++ if (result == -1) {
++ printk(KERN_INFO "Failed to add new cluster member "
++ NIPQUAD_FMT ".\n",
++ NIPQUAD(addr));
++ goto drop_unlock;
+ }
+
-+ this->output_buffer =
-+ (char *) vmalloc_32(2 * PAGE_SIZE);
++ switch (b->message & MSG_STATE_MASK) {
++ case MSG_PING:
++ break;
++ case MSG_ABORT:
++ break;
++ case MSG_BYE:
++ break;
++ case MSG_HIBERNATE:
++ /* Can I hibernate? */
++ new_message = MSG_HIBERNATE |
++ ((index & 1) ? MSG_NACK : MSG_ACK);
++ break;
++ case MSG_IMAGE:
++ /* Can I resume? */
++ new_message = MSG_IMAGE |
++ ((index & 1) ? MSG_NACK : MSG_ACK);
++ if (new_message != old_message)
++ printk(KERN_ERR "Setting whether I can resume "
++ "to %d.\n", new_message);
++ break;
++ case MSG_IO:
++ new_message = MSG_IO | MSG_ACK;
++ break;
++ case MSG_RUNNING:
++ break;
++ default:
++ if (net_ratelimit())
++ printk(KERN_ERR "Unrecognised TuxOnIce cluster"
++ " message %d from " NIPQUAD_FMT ".\n",
++ b->message, NIPQUAD(addr));
++ };
+
-+ if (!this->output_buffer) {
-+ printk(KERN_ERR
-+ "Failed to allocate a output buffer for TuxOnIce "
-+ "compression driver.\n");
-+ return -ENOMEM;
++ if (old_message != new_message) {
++ node_array[index].current_message = new_message;
++ printk(KERN_INFO ">>> Sending new message for node "
++ "%d.\n", index);
++ toi_send_if(new_message, index);
++ } else if (!ack) {
++ printk(KERN_INFO ">>> Resending message for node %d.\n",
++ index);
++ toi_send_if(new_message, index);
+ }
++drop_unlock:
++ spin_unlock(&node_array[index].receive_lock);
++ };
+
-+ }
++drop:
++ /* Throw the packet out. */
++ kfree_skb(skb);
+
+ return 0;
+}
+
+/*
-+ * toi_compress_init
++ * Send cluster message to single interface.
+ */
++static void toi_send_if(int message, unsigned long my_id)
++{
++ struct sk_buff *skb;
++ struct toi_pkt *b;
++ int hh_len = LL_RESERVED_SPACE(net_dev);
++ struct iphdr *h;
+
-+static int toi_compress_init(int toi_or_resume)
++ /* Allocate packet */
++ skb = alloc_skb(sizeof(struct toi_pkt) + hh_len + 15, GFP_KERNEL);
++ if (!skb)
++ return;
++ skb_reserve(skb, hh_len);
++ b = (struct toi_pkt *) skb_put(skb, sizeof(struct toi_pkt));
++ memset(b, 0, sizeof(struct toi_pkt));
++
++ /* Construct IP header */
++ skb_reset_network_header(skb);
++ h = ip_hdr(skb);
++ h->version = 4;
++ h->ihl = 5;
++ h->tot_len = htons(sizeof(struct toi_pkt));
++ h->frag_off = htons(IP_DF);
++ h->ttl = 64;
++ h->protocol = IPPROTO_UDP;
++ h->daddr = htonl(INADDR_BROADCAST);
++ h->check = ip_fast_csum((unsigned char *) h, h->ihl);
++
++ /* Construct UDP header */
++ b->udph.source = htons(toi_cluster_port_send);
++ b->udph.dest = htons(toi_cluster_port_recv);
++ b->udph.len = htons(sizeof(struct toi_pkt) - sizeof(struct iphdr));
++ /* UDP checksum not calculated -- explicitly allowed in BOOTP RFC */
++
++ /* Construct message */
++ b->message = message;
++ b->sid = my_id;
++ b->htype = net_dev->type; /* can cause undefined behavior */
++ b->hlen = net_dev->addr_len;
++ memcpy(b->hw_addr, net_dev->dev_addr, net_dev->addr_len);
++ b->secs = htons(3); /* 3 seconds */
++
++ /* Chain packet down the line... */
++ skb->dev = net_dev;
++ skb->protocol = htons(ETH_P_IP);
++ if ((dev_hard_header(skb, net_dev, ntohs(skb->protocol),
++ net_dev->broadcast, net_dev->dev_addr, skb->len) < 0) ||
++ dev_queue_xmit(skb) < 0)
++ printk(KERN_INFO "E");
++}
++
++/* ========================================= */
++
++/* kTOICluster */
++
++static atomic_t num_cluster_threads;
++static DECLARE_WAIT_QUEUE_HEAD(clusterd_events);
++
++static int kTOICluster(void *data)
+{
-+ if (!toi_or_resume)
-+ return 0;
++ unsigned long my_id;
++
++ my_id = atomic_add_return(1, &num_cluster_threads) - 1;
++ node_array[my_id].current_message = (unsigned long) data;
+
-+ toi_compress_bytes_in = 0;
-+ toi_compress_bytes_out = 0;
++ PRINTK("kTOICluster daemon %lu starting.\n", my_id);
+
-+ next_driver = toi_get_next_filter(&toi_compression_ops);
++ current->flags |= PF_NOFREEZE;
+
-+ if (!next_driver)
-+ return -ECHILD;
++ while (node_array[my_id].current_message) {
++ toi_send_if(node_array[my_id].current_message, my_id);
++ sleep_on_timeout(&clusterd_events,
++ cluster_message_timeout);
++ PRINTK("Link state %lu is %d.\n", my_id,
++ node_array[my_id].current_message);
++ }
+
-+ toi_compress_prepare_result = toi_compress_crypto_prepare();
++ toi_send_if(MSG_BYE, my_id);
++ atomic_dec(&num_cluster_threads);
++ wake_up(&clusterd_events);
+
++ PRINTK("kTOICluster daemon %lu exiting.\n", my_id);
++ __set_current_state(TASK_RUNNING);
+ return 0;
+}
+
-+/*
-+ * toi_compress_rw_init()
-+ */
-+
-+static int toi_compress_rw_init(int rw, int stream_number)
++static void kill_clusterd(void)
+{
-+ if (toi_compress_prepare_result) {
-+ printk(KERN_ERR "Failed to initialise compression "
-+ "algorithm.\n");
-+ if (rw == READ) {
-+ printk(KERN_INFO "Unable to read the image.\n");
-+ return -ENODEV;
-+ } else {
-+ printk(KERN_INFO "Continuing without "
-+ "compressing the image.\n");
-+ toi_compression_ops.enabled = 0;
++ int i;
++
++ for (i = 0; i < num_local_nodes; i++) {
++ if (node_array[i].current_message) {
++ PRINTK("Seeking to kill clusterd %d.\n", i);
++ node_array[i].current_message = 0;
+ }
+ }
++ wait_event(clusterd_events,
++ !atomic_read(&num_cluster_threads));
++ PRINTK("All cluster daemons have exited.\n");
++}
+
-+ return 0;
++static int peers_not_in_message(int index, int message, int precise)
++{
++ struct cluster_member *this;
++ unsigned long flags;
++ int result = 0;
++
++ spin_lock_irqsave(&node_array[index].member_list_lock, flags);
++ list_for_each_entry(this, &node_array[index].member_list, list) {
++ if (this->ignore)
++ continue;
++
++ PRINTK("Peer %d.%d.%d.%d sending %s. "
++ "Seeking %s.\n",
++ NIPQUAD(this->addr),
++ str_message(this->message), str_message(message));
++ if ((precise ? this->message :
++ this->message & MSG_STATE_MASK) !=
++ message)
++ result++;
++ }
++ spin_unlock_irqrestore(&node_array[index].member_list_lock, flags);
++ PRINTK("%d peers in sought message.\n", result);
++ return result;
+}
+
-+/*
-+ * toi_compress_write_page()
-+ *
-+ * Compress a page of data, buffering output and passing on filled
-+ * pages to the next module in the pipeline.
-+ *
-+ * Buffer_page: Pointer to a buffer of size PAGE_SIZE, containing
-+ * data to be compressed.
-+ *
-+ * Returns: 0 on success. Otherwise the error is that returned by later
-+ * modules, -ECHILD if we have a broken pipeline or -EIO if
-+ * zlib errs.
-+ */
-+static int toi_compress_write_page(unsigned long index,
-+ struct page *buffer_page, unsigned int buf_size)
++static void reset_ignored(int index)
+{
-+ int ret, cpu = smp_processor_id();
-+ struct cpu_context *ctx = &per_cpu(contexts, cpu);
++ struct cluster_member *this;
++ unsigned long flags;
+
-+ if (!ctx->transform)
-+ return next_driver->write_page(index, buffer_page, buf_size);
++ spin_lock_irqsave(&node_array[index].member_list_lock, flags);
++ list_for_each_entry(this, &node_array[index].member_list, list)
++ this->ignore = 0;
++ node_array[index].ignored_peer_count = 0;
++ spin_unlock_irqrestore(&node_array[index].member_list_lock, flags);
++}
+
-+ ctx->buffer_start = kmap(buffer_page);
++static int peers_in_message(int index, int message, int precise)
++{
++ return node_array[index].peer_count -
++ node_array[index].ignored_peer_count -
++ peers_not_in_message(index, message, precise);
++}
+
-+ ctx->len = buf_size;
++static int time_to_continue(int index, unsigned long start, int message)
++{
++ int first = peers_not_in_message(index, message, 0);
++ int second = peers_in_message(index, message, 1);
+
-+ ret = crypto_comp_compress(ctx->transform,
-+ ctx->buffer_start, buf_size,
-+ ctx->output_buffer, &ctx->len);
++ PRINTK("First part returns %d, second returns %d.\n", first, second);
+
-+ kunmap(buffer_page);
++ if (!first && !second) {
++ PRINTK("All peers answered message %d.\n",
++ message);
++ return 1;
++ }
+
-+ mutex_lock(&stats_lock);
-+ toi_compress_bytes_in += buf_size;
-+ toi_compress_bytes_out += ctx->len;
-+ mutex_unlock(&stats_lock);
++ if (time_after(jiffies, start + continue_delay)) {
++ PRINTK("Timeout reached.\n");
++ return 1;
++ }
+
-+ if (!ret && ctx->len < buf_size) { /* some compression */
-+ memcpy(ctx->page_buffer, ctx->output_buffer, ctx->len);
-+ return next_driver->write_page(index,
-+ virt_to_page(ctx->page_buffer),
-+ ctx->len);
-+ } else
-+ return next_driver->write_page(index, buffer_page, buf_size);
++ PRINTK("Not time to continue yet (%lu < %lu).\n", jiffies,
++ start + continue_delay);
++ return 0;
+}
+
-+/*
-+ * toi_compress_read_page()
-+ * @buffer_page: struct page *. Pointer to a buffer of size PAGE_SIZE.
-+ *
-+ * Retrieve data from later modules and decompress it until the input buffer
-+ * is filled.
-+ * Zero if successful. Error condition from me or from downstream on failure.
-+ */
-+static int toi_compress_read_page(unsigned long *index,
-+ struct page *buffer_page, unsigned int *buf_size)
++void toi_initiate_cluster_hibernate(void)
+{
-+ int ret, cpu = smp_processor_id();
-+ unsigned int len;
-+ unsigned int outlen = PAGE_SIZE;
-+ char *buffer_start;
-+ struct cpu_context *ctx = &per_cpu(contexts, cpu);
++ int result;
++ unsigned long start;
+
-+ if (!ctx->transform)
-+ return next_driver->read_page(index, buffer_page, buf_size);
++ result = do_toi_step(STEP_HIBERNATE_PREPARE_IMAGE);
++ if (result)
++ return;
+
-+ /*
-+ * All our reads must be synchronous - we can't decompress
-+ * data that hasn't been read yet.
-+ */
++ toi_send_if(MSG_HIBERNATE, 0);
+
-+ ret = next_driver->read_page(index, buffer_page, &len);
++ start = jiffies;
++ wait_event(node_array[0].member_events,
++ time_to_continue(0, start, MSG_HIBERNATE));
+
-+ /* Error or uncompressed data */
-+ if (ret || len == PAGE_SIZE)
-+ return ret;
++ if (test_action_state(TOI_FREEZER_TEST)) {
++ toi_send_if(MSG_ABORT, 0);
+
-+ buffer_start = kmap(buffer_page);
-+ memcpy(ctx->page_buffer, buffer_start, len);
-+ ret = crypto_comp_decompress(
-+ ctx->transform,
-+ ctx->page_buffer,
-+ len, buffer_start, &outlen);
-+ if (ret)
-+ abort_hibernate(TOI_FAILED_IO,
-+ "Compress_read returned %d.\n", ret);
-+ else if (outlen != PAGE_SIZE) {
-+ abort_hibernate(TOI_FAILED_IO,
-+ "Decompression yielded %d bytes instead of %ld.\n",
-+ outlen, PAGE_SIZE);
-+ printk(KERN_ERR "Decompression yielded %d bytes instead of "
-+ "%ld.\n", outlen, PAGE_SIZE);
-+ ret = -EIO;
-+ *buf_size = outlen;
++ start = jiffies;
++ wait_event(node_array[0].member_events,
++ time_to_continue(0, start, MSG_RUNNING));
++
++ do_toi_step(STEP_QUIET_CLEANUP);
++ return;
+ }
-+ kunmap(buffer_page);
-+ return ret;
++
++ toi_send_if(MSG_IO, 0);
++
++ result = do_toi_step(STEP_HIBERNATE_SAVE_IMAGE);
++ if (result)
++ return;
++
++ /* This code runs at resume time too! */
++ if (toi_in_hibernate)
++ result = do_toi_step(STEP_HIBERNATE_POWERDOWN);
+}
++EXPORT_SYMBOL_GPL(toi_initiate_cluster_hibernate);
+
-+/*
-+ * toi_compress_print_debug_stats
-+ * @buffer: Pointer to a buffer into which the debug info will be printed.
-+ * @size: Size of the buffer.
++/* toi_cluster_print_debug_stats
+ *
-+ * Print information to be recorded for debugging purposes into a buffer.
-+ * Returns: Number of characters written to the buffer.
++ * Description: Print information to be recorded for debugging purposes into a
++ * buffer.
++ * Arguments: buffer: Pointer to a buffer into which the debug info will be
++ * printed.
++ * size: Size of the buffer.
++ * Returns: Number of characters written to the buffer.
+ */
-+
-+static int toi_compress_print_debug_stats(char *buffer, int size)
++static int toi_cluster_print_debug_stats(char *buffer, int size)
+{
-+ unsigned long pages_in = toi_compress_bytes_in >> PAGE_SHIFT,
-+ pages_out = toi_compress_bytes_out >> PAGE_SHIFT;
+ int len;
+
-+ /* Output the compression ratio achieved. */
-+ if (*toi_compressor_name)
-+ len = scnprintf(buffer, size, "- Compressor is '%s'.\n",
-+ toi_compressor_name);
++ if (strlen(toi_cluster_iface))
++ len = scnprintf(buffer, size,
++ "- Cluster interface is '%s'.\n",
++ toi_cluster_iface);
+ else
-+ len = scnprintf(buffer, size, "- Compressor is not set.\n");
-+
-+ if (pages_in)
-+ len += scnprintf(buffer+len, size - len, " Compressed "
-+ "%lu bytes into %lu (%ld percent compression).\n",
-+ toi_compress_bytes_in,
-+ toi_compress_bytes_out,
-+ (pages_in - pages_out) * 100 / pages_in);
++ len = scnprintf(buffer, size,
++ "- Cluster support is disabled.\n");
+ return len;
+}
+
-+/*
-+ * toi_compress_compression_memory_needed
-+ *
-+ * Tell the caller how much memory we need to operate during hibernate/resume.
-+ * Returns: Unsigned long. Maximum number of bytes of memory required for
-+ * operation.
++/* cluster_memory_needed
++ *
++ * Description: Tell the caller how much memory we need to operate during
++ * hibernate/resume.
++ * Returns: Unsigned long. Maximum number of bytes of memory required for
++ * operation.
+ */
-+static int toi_compress_memory_needed(void)
++static int toi_cluster_memory_needed(void)
+{
-+ return 2 * PAGE_SIZE;
++ return 0;
+}
+
-+static int toi_compress_storage_needed(void)
++static int toi_cluster_storage_needed(void)
+{
-+ return 4 * sizeof(unsigned long) + strlen(toi_compressor_name) + 1;
++ return 1 + strlen(toi_cluster_iface);
+}
+
-+/*
-+ * toi_compress_save_config_info
-+ * @buffer: Pointer to a buffer of size PAGE_SIZE.
++/* toi_cluster_save_config_info
+ *
-+ * Save informaton needed when reloading the image at resume time.
-+ * Returns: Number of bytes used for saving our data.
++ * Description: Save informaton needed when reloading the image at resume time.
++ * Arguments: Buffer: Pointer to a buffer of size PAGE_SIZE.
++ * Returns: Number of bytes used for saving our data.
+ */
-+static int toi_compress_save_config_info(char *buffer)
++static int toi_cluster_save_config_info(char *buffer)
+{
-+ int namelen = strlen(toi_compressor_name) + 1;
-+ int total_len;
-+
-+ *((unsigned long *) buffer) = toi_compress_bytes_in;
-+ *((unsigned long *) (buffer + 1 * sizeof(unsigned long))) =
-+ toi_compress_bytes_out;
-+ *((unsigned long *) (buffer + 2 * sizeof(unsigned long))) =
-+ toi_expected_compression;
-+ *((unsigned long *) (buffer + 3 * sizeof(unsigned long))) = namelen;
-+ strncpy(buffer + 4 * sizeof(unsigned long), toi_compressor_name,
-+ namelen);
-+ total_len = 4 * sizeof(unsigned long) + namelen;
-+ return total_len;
++ strcpy(buffer, toi_cluster_iface);
++ return strlen(toi_cluster_iface + 1);
+}
+
-+/* toi_compress_load_config_info
-+ * @buffer: Pointer to the start of the data.
-+ * @size: Number of bytes that were saved.
++/* toi_cluster_load_config_info
+ *
-+ * Description: Reload information needed for decompressing the image at
-+ * resume time.
++ * Description: Reload information needed for declustering the image at
++ * resume time.
++ * Arguments: Buffer: Pointer to the start of the data.
++ * Size: Number of bytes that were saved.
+ */
-+static void toi_compress_load_config_info(char *buffer, int size)
++static void toi_cluster_load_config_info(char *buffer, int size)
+{
-+ int namelen;
-+
-+ toi_compress_bytes_in = *((unsigned long *) buffer);
-+ toi_compress_bytes_out = *((unsigned long *) (buffer + 1 *
-+ sizeof(unsigned long)));
-+ toi_expected_compression = *((unsigned long *) (buffer + 2 *
-+ sizeof(unsigned long)));
-+ namelen = *((unsigned long *) (buffer + 3 * sizeof(unsigned long)));
-+ if (strncmp(toi_compressor_name, buffer + 4 * sizeof(unsigned long),
-+ namelen)) {
-+ toi_compress_cleanup(1);
-+ strncpy(toi_compressor_name, buffer + 4 * sizeof(unsigned long),
-+ namelen);
-+ toi_compress_crypto_prepare();
-+ }
++ strncpy(toi_cluster_iface, buffer, size);
+ return;
+}
+
-+/*
-+ * toi_expected_compression_ratio
-+ *
-+ * Description: Returns the expected ratio between data passed into this module
-+ * and the amount of data output when writing.
-+ * Returns: 100 if the module is disabled. Otherwise the value set by the
-+ * user via our sysfs entry.
-+ */
-+
-+static int toi_compress_expected_ratio(void)
++static void cluster_startup(void)
+{
-+ if (!toi_compression_ops.enabled)
-+ return 100;
-+ else
-+ return 100 - toi_expected_compression;
-+}
++ int have_image = do_check_can_resume(), i;
++ unsigned long start = jiffies, initial_message;
++ struct task_struct *p;
+
-+/*
-+ * data for our sysfs entries.
-+ */
-+static struct toi_sysfs_data sysfs_params[] = {
-+ SYSFS_INT("expected_compression", SYSFS_RW, &toi_expected_compression,
-+ 0, 99, 0, NULL),
-+ SYSFS_INT("enabled", SYSFS_RW, &toi_compression_ops.enabled, 0, 1, 0,
-+ NULL),
-+ SYSFS_STRING("algorithm", SYSFS_RW, toi_compressor_name, 31, 0, NULL),
-+};
++ initial_message = MSG_IMAGE;
+
-+/*
-+ * Ops structure.
-+ */
-+static struct toi_module_ops toi_compression_ops = {
-+ .type = FILTER_MODULE,
-+ .name = "compression",
-+ .directory = "compression",
-+ .module = THIS_MODULE,
-+ .initialise = toi_compress_init,
-+ .cleanup = toi_compress_cleanup,
-+ .memory_needed = toi_compress_memory_needed,
-+ .print_debug_info = toi_compress_print_debug_stats,
-+ .save_config_info = toi_compress_save_config_info,
-+ .load_config_info = toi_compress_load_config_info,
-+ .storage_needed = toi_compress_storage_needed,
-+ .expected_compression = toi_compress_expected_ratio,
++ have_image = 1;
+
-+ .rw_init = toi_compress_rw_init,
++ for (i = 0; i < num_local_nodes; i++) {
++ PRINTK("Starting ktoiclusterd %d.\n", i);
++ p = kthread_create(kTOICluster, (void *) initial_message,
++ "ktoiclusterd/%d", i);
++ if (IS_ERR(p)) {
++ printk(KERN_ERR "Failed to start ktoiclusterd.\n");
++ return;
++ }
+
-+ .write_page = toi_compress_write_page,
-+ .read_page = toi_compress_read_page,
++ wake_up_process(p);
++ }
+
-+ .sysfs_data = sysfs_params,
-+ .num_sysfs_entries = sizeof(sysfs_params) /
-+ sizeof(struct toi_sysfs_data),
-+};
++ /* Wait for delay or someone else sending first message */
++ wait_event(node_array[0].member_events, time_to_continue(0, start,
++ MSG_IMAGE));
+
-+/* ---- Registration ---- */
++ others_have_image = peers_in_message(0, MSG_IMAGE | MSG_ACK, 1);
+
-+static __init int toi_compress_load(void)
-+{
-+ return toi_register_module(&toi_compression_ops);
-+}
++ printk(KERN_INFO "Continuing. I %shave an image. Peers with image:"
++ " %d.\n", have_image ? "" : "don't ", others_have_image);
+
-+#ifdef MODULE
-+static __exit void toi_compress_unload(void)
-+{
-+ toi_unregister_module(&toi_compression_ops);
-+}
++ if (have_image) {
++ int result;
+
-+module_init(toi_compress_load);
-+module_exit(toi_compress_unload);
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Nigel Cunningham");
-+MODULE_DESCRIPTION("Compression Support for TuxOnIce");
-+#else
-+late_initcall(toi_compress_load);
-+#endif
-diff --git a/kernel/power/tuxonice_extent.c b/kernel/power/tuxonice_extent.c
-new file mode 100644
-index 0000000..6a5a2a9
---- /dev/null
-+++ b/kernel/power/tuxonice_extent.c
-@@ -0,0 +1,314 @@
-+/*
-+ * kernel/power/tuxonice_extent.c
-+ *
-+ * Copyright (C) 2003-2008 Nigel Cunningham (nigel at tuxonice net)
-+ *
-+ * Distributed under GPLv2.
-+ *
-+ * These functions encapsulate the manipulation of storage metadata.
-+ */
++ /* Start to resume */
++ printk(KERN_INFO " === Starting to resume === \n");
++ node_array[0].current_message = MSG_IO;
++ toi_send_if(MSG_IO, 0);
+
-+#include <linux/suspend.h>
-+#include "tuxonice_modules.h"
-+#include "tuxonice_extent.h"
-+#include "tuxonice_alloc.h"
-+#include "tuxonice_ui.h"
-+#include "tuxonice.h"
++ /* result = do_toi_step(STEP_RESUME_LOAD_PS1); */
++ result = 0;
+
-+/**
-+ * toi_get_extent - return a free extent
-+ *
-+ * May fail, returning NULL instead.
-+ **/
-+static struct hibernate_extent *toi_get_extent(void)
-+{
-+ return (struct hibernate_extent *) toi_kzalloc(2,
-+ sizeof(struct hibernate_extent), TOI_ATOMIC_GFP);
-+}
++ if (!result) {
++ /*
++ * Atomic restore - we'll come back in the hibernation
++ * path.
++ */
+
-+/**
-+ * toi_put_extent_chain - free a whole chain of extents
-+ * @chain: Chain to free.
-+ **/
-+void toi_put_extent_chain(struct hibernate_extent_chain *chain)
-+{
-+ struct hibernate_extent *this;
++ /* result = do_toi_step(STEP_RESUME_DO_RESTORE); */
++ result = 0;
+
-+ this = chain->first;
++ /* do_toi_step(STEP_QUIET_CLEANUP); */
++ }
+
-+ while (this) {
-+ struct hibernate_extent *next = this->next;
-+ toi_kfree(2, this, sizeof(*this));
-+ chain->num_extents--;
-+ this = next;
++ node_array[0].current_message |= MSG_NACK;
++
++ /* For debugging - disable for real life? */
++ wait_event(node_array[0].member_events,
++ time_to_continue(0, start, MSG_IO));
+ }
+
-+ chain->first = NULL;
-+ chain->last_touched = NULL;
-+ chain->size = 0;
-+}
-+EXPORT_SYMBOL_GPL(toi_put_extent_chain);
++ if (others_have_image) {
++ /* Wait for them to resume */
++ printk(KERN_INFO "Waiting for other nodes to resume.\n");
++ start = jiffies;
++ wait_event(node_array[0].member_events,
++ time_to_continue(0, start, MSG_RUNNING));
++ if (peers_not_in_message(0, MSG_RUNNING, 0))
++ printk(KERN_INFO "Timed out while waiting for other "
++ "nodes to resume.\n");
++ }
+
-+/**
-+ * toi_add_to_extent_chain - add an extent to an existing chain
-+ * @chain: Chain to which the extend should be added
-+ * @start: Start of the extent (first physical block)
-+ * @end: End of the extent (last physical block)
-+ *
-+ * The chain information is updated if the insertion is successful.
-+ **/
-+int toi_add_to_extent_chain(struct hibernate_extent_chain *chain,
-+ unsigned long start, unsigned long end)
-+{
-+ struct hibernate_extent *new_ext = NULL, *cur_ext = NULL;
++ /* Find out whether an image exists here. Send ACK_IMAGE or NACK_IMAGE
++ * as appropriate.
++ *
++ * If we don't have an image:
++ * - Wait until someone else says they have one, or conditions are met
++ * for continuing to boot (n machines or t seconds).
++ * - If anyone has an image, wait for them to resume before continuing
++ * to boot.
++ *
++ * If we have an image:
++ * - Wait until conditions are met before continuing to resume (n
++ * machines or t seconds). Send RESUME_PREP and freeze processes.
++ * NACK_PREP if freezing fails (shouldn't) and follow logic for
++ * us having no image above. On success, wait for [N]ACK_PREP from
++ * other machines. Read image (including atomic restore) until done.
++ * Wait for ACK_READ from others (should never fail). Thaw processes
++ * and do post-resume. (The section after the atomic restore is done
++ * via the code for hibernating).
++ */
+
-+ /* Find the right place in the chain */
-+ if (chain->last_touched && chain->last_touched->start < start)
-+ cur_ext = chain->last_touched;
-+ else if (chain->first && chain->first->start < start)
-+ cur_ext = chain->first;
++ node_array[0].current_message = MSG_RUNNING;
++}
+
-+ if (cur_ext) {
-+ while (cur_ext->next && cur_ext->next->start < start)
-+ cur_ext = cur_ext->next;
++/* toi_cluster_open_iface
++ *
++ * Description: Prepare to use an interface.
++ */
+
-+ if (cur_ext->end == (start - 1)) {
-+ struct hibernate_extent *next_ext = cur_ext->next;
-+ cur_ext->end = end;
++static int toi_cluster_open_iface(void)
++{
++ struct net_device *dev;
+
-+ /* Merge with the following one? */
-+ if (next_ext && cur_ext->end + 1 == next_ext->start) {
-+ cur_ext->end = next_ext->end;
-+ cur_ext->next = next_ext->next;
-+ toi_kfree(2, next_ext, sizeof(*next_ext));
-+ chain->num_extents--;
-+ }
++ rtnl_lock();
+
-+ chain->last_touched = cur_ext;
-+ chain->size += (end - start + 1);
++ for_each_netdev(&init_net, dev) {
++ if (/* dev == &init_net.loopback_dev || */
++ strcmp(dev->name, toi_cluster_iface))
++ continue;
+
-+ return 0;
-+ }
++ net_dev = dev;
++ break;
+ }
+
-+ new_ext = toi_get_extent();
-+ if (!new_ext) {
-+ printk(KERN_INFO "Error unable to append a new extent to the "
-+ "chain.\n");
-+ return -ENOMEM;
++ rtnl_unlock();
++
++ if (!net_dev) {
++ printk(KERN_ERR MYNAME ": Device %s not found.\n",
++ toi_cluster_iface);
++ return -ENODEV;
+ }
+
-+ chain->num_extents++;
-+ chain->size += (end - start + 1);
-+ new_ext->start = start;
-+ new_ext->end = end;
++ dev_add_pack(&toi_cluster_packet_type);
++ added_pack = 1;
+
-+ chain->last_touched = new_ext;
++ loopback_mode = (net_dev == init_net.loopback_dev);
++ num_local_nodes = loopback_mode ? 8 : 1;
+
-+ if (cur_ext) {
-+ new_ext->next = cur_ext->next;
-+ cur_ext->next = new_ext;
-+ } else {
-+ if (chain->first)
-+ new_ext->next = chain->first;
-+ chain->first = new_ext;
-+ }
++ PRINTK("Loopback mode is %s. Number of local nodes is %d.\n",
++ loopback_mode ? "on" : "off", num_local_nodes);
+
++ cluster_startup();
+ return 0;
+}
-+EXPORT_SYMBOL_GPL(toi_add_to_extent_chain);
-+
-+/**
-+ * toi_serialise_extent_chain - write a chain in the image
-+ * @owner: Module writing the chain.
-+ * @chain: Chain to write.
-+ **/
-+int toi_serialise_extent_chain(struct toi_module_ops *owner,
-+ struct hibernate_extent_chain *chain)
-+{
-+ struct hibernate_extent *this;
-+ int ret, i = 0;
-+
-+ ret = toiActiveAllocator->rw_header_chunk(WRITE, owner, (char *) chain,
-+ sizeof(chain->size) + sizeof(chain->num_extents));
-+ if (ret)
-+ return ret;
+
-+ this = chain->first;
-+ while (this) {
-+ ret = toiActiveAllocator->rw_header_chunk(WRITE, owner,
-+ (char *) this, 2 * sizeof(this->start));
-+ if (ret)
-+ return ret;
-+ this = this->next;
-+ i++;
-+ }
++/* toi_cluster_close_iface
++ *
++ * Description: Stop using an interface.
++ */
+
-+ if (i != chain->num_extents) {
-+ printk(KERN_EMERG "Saved %d extents but chain metadata says "
-+ "there should be %d.\n", i, chain->num_extents);
-+ return 1;
++static int toi_cluster_close_iface(void)
++{
++ kill_clusterd();
++ if (added_pack) {
++ dev_remove_pack(&toi_cluster_packet_type);
++ added_pack = 0;
+ }
-+
-+ return ret;
++ return 0;
+}
-+EXPORT_SYMBOL_GPL(toi_serialise_extent_chain);
+
-+/**
-+ * toi_load_extent_chain - read back a chain saved in the image
-+ * @chain: Chain to load
-+ *
-+ * The linked list of extents is reconstructed from the disk. chain will point
-+ * to the first entry.
-+ **/
-+int toi_load_extent_chain(struct hibernate_extent_chain *chain)
++static void write_side_effect(void)
+{
-+ struct hibernate_extent *this, *last = NULL;
-+ int i, ret;
-+
-+ /* Get the next page */
-+ ret = toiActiveAllocator->rw_header_chunk_noreadahead(READ, NULL,
-+ (char *) chain, sizeof(chain->size) +
-+ sizeof(chain->num_extents));
-+ if (ret) {
-+ printk(KERN_ERR "Failed to read the size of extent chain.\n");
-+ return 1;
-+ }
-+
-+ for (i = 0; i < chain->num_extents; i++) {
-+ this = toi_kzalloc(3, sizeof(struct hibernate_extent),
-+ TOI_ATOMIC_GFP);
-+ if (!this) {
-+ printk(KERN_INFO "Failed to allocate a new extent.\n");
-+ return -ENOMEM;
-+ }
-+ this->next = NULL;
-+ /* Get the next page */
-+ ret = toiActiveAllocator->rw_header_chunk_noreadahead(READ,
-+ NULL, (char *) this, 2 * sizeof(this->start));
-+ if (ret) {
-+ printk(KERN_INFO "Failed to read an extent.\n");
-+ return 1;
-+ }
-+ if (last)
-+ last->next = this;
-+ else
-+ chain->first = this;
-+ last = this;
++ if (toi_cluster_ops.enabled) {
++ toi_cluster_open_iface();
++ set_toi_state(TOI_CLUSTER_MODE);
++ } else {
++ toi_cluster_close_iface();
++ clear_toi_state(TOI_CLUSTER_MODE);
+ }
-+ return 0;
+}
-+EXPORT_SYMBOL_GPL(toi_load_extent_chain);
+
-+/**
-+ * toi_extent_state_next - go to the next extent
-+ *
-+ * Given a state, progress to the next valid entry. We may begin in an
-+ * invalid state, as we do when invoked after extent_state_goto_start below.
-+ *
-+ * When using compression and expected_compression > 0, we let the image size
-+ * be larger than storage, so we can validly run out of data to return.
-+ **/
-+unsigned long toi_extent_state_next(struct toi_extent_iterate_state *state)
++static void node_write_side_effect(void)
+{
-+ if (state->current_chain == state->num_chains)
-+ return 0;
-+
-+ if (state->current_extent) {
-+ if (state->current_offset == state->current_extent->end) {
-+ if (state->current_extent->next) {
-+ state->current_extent =
-+ state->current_extent->next;
-+ state->current_offset =
-+ state->current_extent->start;
-+ } else {
-+ state->current_extent = NULL;
-+ state->current_offset = 0;
-+ }
-+ } else
-+ state->current_offset++;
-+ }
++}
+
-+ while (!state->current_extent) {
-+ int chain_num = ++(state->current_chain);
++/*
++ * data for our sysfs entries.
++ */
++static struct toi_sysfs_data sysfs_params[] = {
++ SYSFS_STRING("interface", SYSFS_RW, toi_cluster_iface, IFNAMSIZ, 0,
++ NULL),
++ SYSFS_INT("enabled", SYSFS_RW, &toi_cluster_ops.enabled, 0, 1, 0,
++ write_side_effect),
++ SYSFS_STRING("cluster_name", SYSFS_RW, toi_cluster_key, 32, 0, NULL),
++ SYSFS_STRING("pre-hibernate-script", SYSFS_RW, pre_hibernate_script,
++ 256, 0, NULL),
++ SYSFS_STRING("post-hibernate-script", SYSFS_RW, post_hibernate_script,
++ 256, 0, STRING),
++ SYSFS_UL("continue_delay", SYSFS_RW, &continue_delay, HZ / 2, 60 * HZ,
++ 0)
++};
+
-+ if (chain_num == state->num_chains)
-+ return 0;
++/*
++ * Ops structure.
++ */
+
-+ state->current_extent = (state->chains + chain_num)->first;
++static struct toi_module_ops toi_cluster_ops = {
++ .type = FILTER_MODULE,
++ .name = "Cluster",
++ .directory = "cluster",
++ .module = THIS_MODULE,
++ .memory_needed = toi_cluster_memory_needed,
++ .print_debug_info = toi_cluster_print_debug_stats,
++ .save_config_info = toi_cluster_save_config_info,
++ .load_config_info = toi_cluster_load_config_info,
++ .storage_needed = toi_cluster_storage_needed,
+
-+ if (!state->current_extent)
-+ continue;
++ .sysfs_data = sysfs_params,
++ .num_sysfs_entries = sizeof(sysfs_params) /
++ sizeof(struct toi_sysfs_data),
++};
+
-+ state->current_offset = state->current_extent->start;
-+ }
++/* ---- Registration ---- */
+
-+ return state->current_offset;
-+}
-+EXPORT_SYMBOL_GPL(toi_extent_state_next);
++#ifdef MODULE
++#define INIT static __init
++#define EXIT static __exit
++#else
++#define INIT
++#define EXIT
++#endif
+
-+/**
-+ * toi_extent_state_goto_start - reinitialize an extent chain iterator
-+ * @state: Iterator to reinitialize
-+ **/
-+void toi_extent_state_goto_start(struct toi_extent_iterate_state *state)
++INIT int toi_cluster_init(void)
+{
-+ state->current_chain = -1;
-+ state->current_extent = NULL;
-+ state->current_offset = 0;
-+}
-+EXPORT_SYMBOL_GPL(toi_extent_state_goto_start);
++ int temp = toi_register_module(&toi_cluster_ops), i;
++ struct kobject *kobj = toi_cluster_ops.dir_kobj;
+
-+/**
-+ * toi_extent_state_save - save state of the iterator
-+ * @state: Current state of the chain
-+ * @saved_state: Iterator to populate
-+ *
-+ * Given a state and a struct hibernate_extent_state_store, save the current
-+ * position in a format that can be used with relocated chains (at
-+ * resume time).
-+ **/
-+void toi_extent_state_save(struct toi_extent_iterate_state *state,
-+ struct hibernate_extent_iterate_saved_state *saved_state)
-+{
-+ struct hibernate_extent *extent;
++ for (i = 0; i < MAX_LOCAL_NODES; i++) {
++ node_array[i].current_message = 0;
++ INIT_LIST_HEAD(&node_array[i].member_list);
++ init_waitqueue_head(&node_array[i].member_events);
++ spin_lock_init(&node_array[i].member_list_lock);
++ spin_lock_init(&node_array[i].receive_lock);
+
-+ saved_state->chain_num = state->current_chain;
-+ saved_state->extent_num = 0;
-+ saved_state->offset = state->current_offset;
++ /* Set up sysfs entry */
++ node_array[i].sysfs_data.attr.name = toi_kzalloc(8,
++ sizeof(node_array[i].sysfs_data.attr.name),
++ GFP_KERNEL);
++ sprintf((char *) node_array[i].sysfs_data.attr.name, "node_%d",
++ i);
++ node_array[i].sysfs_data.attr.mode = SYSFS_RW;
++ node_array[i].sysfs_data.type = TOI_SYSFS_DATA_INTEGER;
++ node_array[i].sysfs_data.flags = 0;
++ node_array[i].sysfs_data.data.integer.variable =
++ (int *) &node_array[i].current_message;
++ node_array[i].sysfs_data.data.integer.minimum = 0;
++ node_array[i].sysfs_data.data.integer.maximum = INT_MAX;
++ node_array[i].sysfs_data.write_side_effect =
++ node_write_side_effect;
++ toi_register_sysfs_file(kobj, &node_array[i].sysfs_data);
++ }
+
-+ if (saved_state->chain_num == -1)
-+ return;
++ toi_cluster_ops.enabled = (strlen(toi_cluster_iface) > 0);
+
-+ extent = (state->chains + state->current_chain)->first;
++ if (toi_cluster_ops.enabled)
++ toi_cluster_open_iface();
+
-+ while (extent != state->current_extent) {
-+ saved_state->extent_num++;
-+ extent = extent->next;
-+ }
++ return temp;
+}
-+EXPORT_SYMBOL_GPL(toi_extent_state_save);
+
-+/**
-+ * toi_extent_state_restore - restore the position saved by extent_state_save
-+ * @state: State to populate
-+ * @saved_state: Iterator saved to restore
-+ **/
-+void toi_extent_state_restore(struct toi_extent_iterate_state *state,
-+ struct hibernate_extent_iterate_saved_state *saved_state)
++EXIT void toi_cluster_exit(void)
+{
-+ int posn = saved_state->extent_num;
++ int i;
++ toi_cluster_close_iface();
+
-+ if (saved_state->chain_num == -1) {
-+ toi_extent_state_goto_start(state);
-+ return;
-+ }
++ for (i = 0; i < MAX_LOCAL_NODES; i++)
++ toi_unregister_sysfs_file(toi_cluster_ops.dir_kobj,
++ &node_array[i].sysfs_data);
++ toi_unregister_module(&toi_cluster_ops);
++}
+
-+ state->current_chain = saved_state->chain_num;
-+ state->current_extent = (state->chains + state->current_chain)->first;
-+ state->current_offset = saved_state->offset;
++static int __init toi_cluster_iface_setup(char *iface)
++{
++ toi_cluster_ops.enabled = (*iface &&
++ strcmp(iface, "off"));
+
-+ while (posn--)
-+ state->current_extent = state->current_extent->next;
++ if (toi_cluster_ops.enabled)
++ strncpy(toi_cluster_iface, iface, strlen(iface));
+}
-+EXPORT_SYMBOL_GPL(toi_extent_state_restore);
-diff --git a/kernel/power/tuxonice_extent.h b/kernel/power/tuxonice_extent.h
++
++__setup("toi_cluster=", toi_cluster_iface_setup);
++
++#ifdef MODULE
++MODULE_LICENSE("GPL");
++module_init(toi_cluster_init);
++module_exit(toi_cluster_exit);
++MODULE_AUTHOR("Nigel Cunningham");
++MODULE_DESCRIPTION("Cluster Support for TuxOnIce");
++#endif
+diff --git a/kernel/power/tuxonice_cluster.h b/kernel/power/tuxonice_cluster.h
new file mode 100644
-index 0000000..f3530a3
+index 0000000..b0f8918
--- /dev/null
-+++ b/kernel/power/tuxonice_extent.h
-@@ -0,0 +1,72 @@
++++ b/kernel/power/tuxonice_cluster.h
+@@ -0,0 +1,19 @@
+/*
-+ * kernel/power/tuxonice_extent.h
++ * kernel/power/tuxonice_cluster.h
+ *
-+ * Copyright (C) 2003-2008 Nigel Cunningham (nigel at tuxonice net)
++ * Copyright (C) 2006-2008 Nigel Cunningham (nigel at tuxonice net)
++ * Copyright (C) 2006 Red Hat, inc.
+ *
+ * This file is released under the GPLv2.
-+ *
-+ * It contains declarations related to extents. Extents are
-+ * TuxOnIce's method of storing some of the metadata for the image.
-+ * See tuxonice_extent.c for more info.
-+ *
+ */
+
-+#include "tuxonice_modules.h"
-+
-+#ifndef EXTENT_H
-+#define EXTENT_H
-+
-+struct hibernate_extent {
-+ unsigned long start, end;
-+ struct hibernate_extent *next;
-+};
-+
-+struct hibernate_extent_chain {
-+ unsigned long size; /* size of the chain ie sum (max-min+1) */
-+ int num_extents;
-+ struct hibernate_extent *first, *last_touched;
-+};
-+
-+struct toi_extent_iterate_state {
-+ struct hibernate_extent_chain *chains;
-+ int num_chains;
-+ int current_chain;
-+ struct hibernate_extent *current_extent;
-+ unsigned long current_offset;
-+};
-+
-+struct hibernate_extent_iterate_saved_state {
-+ int chain_num;
-+ int extent_num;
-+ unsigned long offset;
-+};
-+
-+#define toi_extent_state_eof(state) \
-+ ((state)->num_chains == (state)->current_chain)
-+
-+/* Simplify iterating through all the values in an extent chain */
-+#define toi_extent_for_each(extent_chain, extentpointer, value) \
-+if ((extent_chain)->first) \
-+ for ((extentpointer) = (extent_chain)->first, (value) = \
-+ (extentpointer)->start; \
-+ ((extentpointer) && ((extentpointer)->next || (value) <= \
-+ (extentpointer)->end)); \
-+ (((value) == (extentpointer)->end) ? \
-+ ((extentpointer) = (extentpointer)->next, (value) = \
-+ ((extentpointer) ? (extentpointer)->start : 0)) : \
-+ (value)++))
-+
-+void toi_put_extent_chain(struct hibernate_extent_chain *chain);
-+int toi_add_to_extent_chain(struct hibernate_extent_chain *chain,
-+ unsigned long start, unsigned long end);
-+int toi_serialise_extent_chain(struct toi_module_ops *owner,
-+ struct hibernate_extent_chain *chain);
-+int toi_load_extent_chain(struct hibernate_extent_chain *chain);
-+
-+void toi_extent_state_save(struct toi_extent_iterate_state *state,
-+ struct hibernate_extent_iterate_saved_state *saved_state);
-+void toi_extent_state_restore(struct toi_extent_iterate_state *state,
-+ struct hibernate_extent_iterate_saved_state *saved_state);
-+void toi_extent_state_goto_start(struct toi_extent_iterate_state *state);
-+unsigned long toi_extent_state_next(struct toi_extent_iterate_state *state);
++#ifdef CONFIG_TOI_CLUSTER
++extern int toi_cluster_init(void);
++extern void toi_cluster_exit(void);
++extern void toi_initiate_cluster_hibernate(void);
++#else
++static inline int toi_cluster_init(void) { return 0; }
++static inline void toi_cluster_exit(void) { }
++static inline void toi_initiate_cluster_hibernate(void) { }
+#endif
-diff --git a/kernel/power/tuxonice_file.c b/kernel/power/tuxonice_file.c
++
+diff --git a/kernel/power/tuxonice_compress.c b/kernel/power/tuxonice_compress.c
new file mode 100644
-index 0000000..fe903bd
+index 0000000..1c7aaf3
--- /dev/null
-+++ b/kernel/power/tuxonice_file.c
-@@ -0,0 +1,1254 @@
++++ b/kernel/power/tuxonice_compress.c
+@@ -0,0 +1,445 @@
+/*
-+ * kernel/power/tuxonice_file.c
-+ *
-+ * Copyright (C) 2005-2008 Nigel Cunningham (nigel at tuxonice net)
-+ *
-+ * Distributed under GPLv2.
-+ *
-+ * This file encapsulates functions for usage of a simple file as a
-+ * backing store. It is based upon the swapallocator, and shares the
-+ * same basic working. Here, though, we have nothing to do with
-+ * swapspace, and only one device to worry about.
-+ *
-+ * The user can just
-+ *
-+ * echo TuxOnIce > /path/to/my_file
-+ *
-+ * dd if=/dev/zero bs=1M count=<file_size_desired> >> /path/to/my_file
-+ *
-+ * and
-+ *
-+ * echo /path/to/my_file > /sys/power/tuxonice/file/target
++ * kernel/power/compression.c
+ *
-+ * then put what they find in /sys/power/tuxonice/resume
-+ * as their resume= parameter in lilo.conf (and rerun lilo if using it).
++ * Copyright (C) 2003-2008 Nigel Cunningham (nigel at tuxonice net)
+ *
-+ * Having done this, they're ready to hibernate and resume.
++ * This file is released under the GPLv2.
+ *
-+ * TODO:
-+ * - File resizing.
++ * This file contains data compression routines for TuxOnIce,
++ * using cryptoapi.
+ */
+
+#include <linux/suspend.h>
-+#include <linux/blkdev.h>
-+#include <linux/file.h>
-+#include <linux/stat.h>
-+#include <linux/mount.h>
-+#include <linux/statfs.h>
-+#include <linux/syscalls.h>
-+#include <linux/namei.h>
-+#include <linux/fs.h>
-+#include <linux/root_dev.h>
-+#include <scsi/scsi_scan.h>
++#include <linux/highmem.h>
++#include <linux/vmalloc.h>
++#include <linux/crypto.h>
+
++#include "tuxonice_builtin.h"
+#include "tuxonice.h"
-+#include "tuxonice_sysfs.h"
+#include "tuxonice_modules.h"
-+#include "tuxonice_ui.h"
-+#include "tuxonice_extent.h"
++#include "tuxonice_sysfs.h"
+#include "tuxonice_io.h"
-+#include "tuxonice_storage.h"
-+#include "tuxonice_block_io.h"
++#include "tuxonice_ui.h"
+#include "tuxonice_alloc.h"
-+#include "tuxonice_builtin.h"
-+
-+static struct toi_module_ops toi_fileops;
-+
-+/* Details of our target. */
-+
-+static char toi_file_target[256];
-+static struct inode *target_inode;
-+static struct file *target_file;
-+static struct block_device *toi_file_target_bdev;
-+static dev_t resume_file_dev_t;
-+static int used_devt;
-+static int setting_toi_file_target;
-+static sector_t target_firstblock, target_header_start;
-+static int target_storage_available;
-+static int target_claim;
-+
-+/* Old signatures */
-+static char HaveImage[] = "HaveImage\n";
-+static char NoImage[] = "TuxOnIce\n";
-+#define sig_size (sizeof(HaveImage) + 1)
-+
-+struct toi_file_header {
-+ char sig[sig_size];
-+ int resumed_before;
-+ unsigned long first_header_block;
-+ int have_image;
-+};
-+
-+/* Header Page Information */
-+static unsigned long header_pages_reserved;
-+
-+/* Main Storage Pages */
-+static unsigned long main_pages_allocated, main_pages_requested;
-+
-+#define target_is_normal_file() (S_ISREG(target_inode->i_mode))
-+
-+static struct toi_bdev_info devinfo;
-+
-+/* Extent chain for blocks */
-+static struct hibernate_extent_chain block_chain;
-+
-+/* Signature operations */
-+enum {
-+ GET_IMAGE_EXISTS,
-+ INVALIDATE,
-+ MARK_RESUME_ATTEMPTED,
-+ UNMARK_RESUME_ATTEMPTED,
-+};
-+
-+/**
-+ * set_devinfo - populate device information
-+ * @bdev: Block device on which the file is.
-+ * @target_blkbits: Number of bits in the page block size of the target
-+ * file inode.
-+ *
-+ * Populate the devinfo structure about the target device.
-+ *
-+ * Background: a sector represents a fixed amount of data (generally 512 bytes).
-+ * The hard drive sector size and the filesystem block size may be different.
-+ * If fs_blksize mesures the filesystem block size and hd_blksize the hard drive
-+ * sector size:
-+ *
-+ * sector << (fs_blksize - hd_blksize) converts hd sector into fs block
-+ * fs_block >> (fs_blksize - hd_blksize) converts fs block into hd sector number
-+ *
-+ * Here target_blkbits == fs_blksize and hd_blksize == 9, hence:
-+ *
-+ * (fs_blksize - hd_blksize) == devinfo.bmap_shift
-+ *
-+ * The memory page size is defined by PAGE_SHIFT. devinfo.blocks_per_page is the
-+ * number of filesystem blocks per memory page.
-+ *
-+ * Note that blocks are stored after >>. They are used after being <<.
-+ * We always only use PAGE_SIZE aligned blocks.
-+ *
-+ * Side effects:
-+ * devinfo.bdev, devinfo.bmap_shift and devinfo.blocks_per_page are set.
-+ */
-+static void set_devinfo(struct block_device *bdev, int target_blkbits)
-+{
-+ devinfo.bdev = bdev;
-+ if (!target_blkbits) {
-+ devinfo.bmap_shift = 0;
-+ devinfo.blocks_per_page = 0;
-+ } else {
-+ /* We are assuming a hard disk with 512 (2^9) bytes/sector */
-+ devinfo.bmap_shift = target_blkbits - 9;
-+ devinfo.blocks_per_page = (1 << (PAGE_SHIFT - target_blkbits));
-+ }
-+}
-+
-+static unsigned long raw_to_real(unsigned long raw)
-+{
-+ unsigned long result;
-+
-+ result = raw - (raw * (sizeof(unsigned long) + sizeof(int)) +
-+ (PAGE_SIZE + sizeof(unsigned long) + sizeof(int) + 1)) /
-+ (PAGE_SIZE + sizeof(unsigned long) + sizeof(int));
-+
-+ return result < 0 ? 0 : result;
-+}
-+
-+static unsigned long toi_file_storage_available(void)
-+{
-+ int result = 0;
-+ struct block_device *bdev = toi_file_target_bdev;
-+
-+ if (!target_inode)
-+ return 0;
-+
-+ switch (target_inode->i_mode & S_IFMT) {
-+ case S_IFSOCK:
-+ case S_IFCHR:
-+ case S_IFIFO: /* Socket, Char, Fifo */
-+ return -1;
-+ case S_IFREG: /* Regular file: current size - holes + free
-+ space on part */
-+ result = target_storage_available;
-+ break;
-+ case S_IFBLK: /* Block device */
-+ if (!bdev->bd_disk) {
-+ printk(KERN_INFO "bdev->bd_disk null.\n");
-+ return 0;
-+ }
-+
-+ result = (bdev->bd_part ?
-+ bdev->bd_part->nr_sects :
-+ get_capacity(bdev->bd_disk)) >> (PAGE_SHIFT - 9);
-+ }
-+
-+ return raw_to_real(result);
-+}
-+
-+static int has_contiguous_blocks(int page_num)
-+{
-+ int j;
-+ sector_t last = 0;
+
-+ for (j = 0; j < devinfo.blocks_per_page; j++) {
-+ sector_t this = bmap(target_inode,
-+ page_num * devinfo.blocks_per_page + j);
-+
-+ if (!this || (last && (last + 1) != this))
-+ break;
++static int toi_expected_compression;
+
-+ last = this;
-+ }
++static struct toi_module_ops toi_compression_ops;
++static struct toi_module_ops *next_driver;
+
-+ return j == devinfo.blocks_per_page;
-+}
++static char toi_compressor_name[32] = "lzo";
+
-+static int size_ignoring_ignored_pages(void)
-+{
-+ int mappable = 0, i;
++static DEFINE_MUTEX(stats_lock);
+
-+ if (!target_is_normal_file())
-+ return toi_file_storage_available();
++struct cpu_context {
++ u8 *page_buffer;
++ struct crypto_comp *transform;
++ unsigned int len;
++ char *buffer_start;
++ char *output_buffer;
++};
+
-+ for (i = 0; i < (target_inode->i_size >> PAGE_SHIFT) ; i++)
-+ if (has_contiguous_blocks(i))
-+ mappable++;
++static DEFINE_PER_CPU(struct cpu_context, contexts);
+
-+ return mappable;
-+}
++static int toi_compress_prepare_result;
+
-+/**
-+ * __populate_block_list - add an extent to the chain
-+ * @min: Start of the extent (first physical block = sector)
-+ * @max: End of the extent (last physical block = sector)
++/*
++ * toi_compress_cleanup
+ *
-+ * If TOI_TEST_BIO is set, print a debug message, outputting the min and max
-+ * fs block numbers.
-+ **/
-+static int __populate_block_list(int min, int max)
++ * Frees memory allocated for our labours.
++ */
++static void toi_compress_cleanup(int toi_or_resume)
+{
-+ if (test_action_state(TOI_TEST_BIO))
-+ printk(KERN_INFO "Adding extent %d-%d.\n",
-+ min << devinfo.bmap_shift,
-+ ((max + 1) << devinfo.bmap_shift) - 1);
++ int cpu;
+
-+ return toi_add_to_extent_chain(&block_chain, min, max);
-+}
++ if (!toi_or_resume)
++ return;
+
-+static int apply_header_reservation(void)
-+{
-+ int i;
++ for_each_online_cpu(cpu) {
++ struct cpu_context *this = &per_cpu(contexts, cpu);
++ if (this->transform) {
++ crypto_free_comp(this->transform);
++ this->transform = NULL;
++ }
+
-+ /* Apply header space reservation */
-+ toi_extent_state_goto_start(&toi_writer_posn);
++ if (this->page_buffer)
++ toi_free_page(16, (unsigned long) this->page_buffer);
+
-+ for (i = 0; i < header_pages_reserved; i++)
-+ if (toi_bio_ops.forward_one_page(1, 0))
-+ return -ENOSPC;
++ this->page_buffer = NULL;
+
-+ /* The end of header pages will be the start of pageset 2 */
-+ toi_extent_state_save(&toi_writer_posn, &toi_writer_posn_save[2]);
++ if (this->output_buffer)
++ vfree(this->output_buffer);
+
-+ return 0;
++ this->output_buffer = NULL;
++ }
+}
+
-+static int populate_block_list(void)
++/*
++ * toi_crypto_prepare
++ *
++ * Prepare to do some work by allocating buffers and transforms.
++ */
++static int toi_compress_crypto_prepare(void)
+{
-+ int i, extent_min = -1, extent_max = -1, got_header = 0, result = 0;
-+
-+ if (block_chain.first)
-+ toi_put_extent_chain(&block_chain);
++ int cpu;
+
-+ if (!target_is_normal_file()) {
-+ result = (target_storage_available > 0) ?
-+ __populate_block_list(devinfo.blocks_per_page,
-+ (target_storage_available + 1) *
-+ devinfo.blocks_per_page - 1) : 0;
-+ if (result)
-+ return result;
-+ goto out;
++ if (!*toi_compressor_name) {
++ printk(KERN_INFO "TuxOnIce: Compression enabled but no "
++ "compressor name set.\n");
++ return 1;
+ }
+
-+ for (i = 0; i < (target_inode->i_size >> PAGE_SHIFT); i++) {
-+ sector_t new_sector;
-+
-+ if (!has_contiguous_blocks(i))
-+ continue;
++ for_each_online_cpu(cpu) {
++ struct cpu_context *this = &per_cpu(contexts, cpu);
++ this->transform = crypto_alloc_comp(toi_compressor_name, 0, 0);
++ if (IS_ERR(this->transform)) {
++ printk(KERN_INFO "TuxOnIce: Failed to initialise the "
++ "%s compression transform.\n",
++ toi_compressor_name);
++ this->transform = NULL;
++ return 1;
++ }
+
-+ new_sector = bmap(target_inode, (i * devinfo.blocks_per_page));
++ this->page_buffer =
++ (char *) toi_get_zeroed_page(16, TOI_ATOMIC_GFP);
+
-+ /*
-+ * Ignore the first block in the file.
-+ * It gets the header.
-+ */
-+ if (new_sector == target_firstblock >> devinfo.bmap_shift) {
-+ got_header = 1;
-+ continue;
++ if (!this->page_buffer) {
++ printk(KERN_ERR
++ "Failed to allocate a page buffer for TuxOnIce "
++ "compression driver.\n");
++ return -ENOMEM;
+ }
+
-+ /*
-+ * I'd love to be able to fill in holes and resize
-+ * files, but not yet...
-+ */
-+
-+ if (new_sector == extent_max + 1)
-+ extent_max += devinfo.blocks_per_page;
-+ else {
-+ if (extent_min > -1) {
-+ result = __populate_block_list(extent_min,
-+ extent_max);
-+ if (result)
-+ return result;
-+ }
++ this->output_buffer =
++ (char *) vmalloc_32(2 * PAGE_SIZE);
+
-+ extent_min = new_sector;
-+ extent_max = extent_min +
-+ devinfo.blocks_per_page - 1;
++ if (!this->output_buffer) {
++ printk(KERN_ERR
++ "Failed to allocate a output buffer for TuxOnIce "
++ "compression driver.\n");
++ return -ENOMEM;
+ }
-+ }
+
-+ if (extent_min > -1) {
-+ result = __populate_block_list(extent_min, extent_max);
-+ if (result)
-+ return result;
+ }
+
-+out:
-+ return apply_header_reservation();
++ return 0;
+}
+
-+static void toi_file_cleanup(int finishing_cycle)
++/*
++ * toi_compress_init
++ */
++
++static int toi_compress_init(int toi_or_resume)
+{
-+ if (toi_file_target_bdev) {
-+ if (target_claim) {
-+ bd_release(toi_file_target_bdev);
-+ target_claim = 0;
-+ }
++ if (!toi_or_resume)
++ return 0;
+
-+ if (used_devt) {
-+ blkdev_put(toi_file_target_bdev,
-+ FMODE_READ | FMODE_NDELAY);
-+ used_devt = 0;
-+ }
-+ toi_file_target_bdev = NULL;
-+ target_inode = NULL;
-+ set_devinfo(NULL, 0);
-+ target_storage_available = 0;
-+ }
++ toi_compress_bytes_in = 0;
++ toi_compress_bytes_out = 0;
+
-+ if (target_file && !IS_ERR(target_file))
-+ filp_close(target_file, NULL);
++ next_driver = toi_get_next_filter(&toi_compression_ops);
+
-+ target_file = NULL;
++ if (!next_driver)
++ return -ECHILD;
++
++ toi_compress_prepare_result = toi_compress_crypto_prepare();
++
++ return 0;
+}
+
-+/**
-+ * reopen_resume_devt - reset the devinfo struct
-+ *
-+ * Having opened resume= once, we remember the major and
-+ * minor nodes and use them to reopen the bdev for checking
-+ * whether an image exists (possibly when starting a resume).
-+ **/
-+static void reopen_resume_devt(void)
++/*
++ * toi_compress_rw_init()
++ */
++
++static int toi_compress_rw_init(int rw, int stream_number)
+{
-+ toi_file_target_bdev = toi_open_by_devnum(resume_file_dev_t,
-+ FMODE_READ | FMODE_NDELAY);
-+ if (IS_ERR(toi_file_target_bdev)) {
-+ printk(KERN_INFO "Got a dev_num (%lx) but failed to open it.\n",
-+ (unsigned long) resume_file_dev_t);
-+ return;
++ if (toi_compress_prepare_result) {
++ printk(KERN_ERR "Failed to initialise compression "
++ "algorithm.\n");
++ if (rw == READ) {
++ printk(KERN_INFO "Unable to read the image.\n");
++ return -ENODEV;
++ } else {
++ printk(KERN_INFO "Continuing without "
++ "compressing the image.\n");
++ toi_compression_ops.enabled = 0;
++ }
+ }
-+ target_inode = toi_file_target_bdev->bd_inode;
-+ set_devinfo(toi_file_target_bdev, target_inode->i_blkbits);
++
++ return 0;
+}
+
-+static void toi_file_get_target_info(char *target, int get_size,
-+ int resume_param)
++/*
++ * toi_compress_write_page()
++ *
++ * Compress a page of data, buffering output and passing on filled
++ * pages to the next module in the pipeline.
++ *
++ * Buffer_page: Pointer to a buffer of size PAGE_SIZE, containing
++ * data to be compressed.
++ *
++ * Returns: 0 on success. Otherwise the error is that returned by later
++ * modules, -ECHILD if we have a broken pipeline or -EIO if
++ * zlib errs.
++ */
++static int toi_compress_write_page(unsigned long index,
++ struct page *buffer_page, unsigned int buf_size)
+{
-+ if (target_file)
-+ toi_file_cleanup(0);
++ int ret, cpu = smp_processor_id();
++ struct cpu_context *ctx = &per_cpu(contexts, cpu);
+
-+ if (!target || !strlen(target))
-+ return;
++ if (!ctx->transform)
++ return next_driver->write_page(index, buffer_page, buf_size);
+
-+ target_file = filp_open(target, O_RDONLY|O_LARGEFILE, 0);
++ ctx->buffer_start = kmap(buffer_page);
+
-+ if (IS_ERR(target_file) || !target_file) {
-+ wait_for_device_probe();
-+ scsi_complete_async_scans();
-+ target_file = filp_open(target, O_RDONLY|O_LARGEFILE, 0);
-+ }
++ ctx->len = buf_size;
+
-+ if (IS_ERR(target_file) || !target_file) {
-+ target_file = NULL;
++ ret = crypto_comp_compress(ctx->transform,
++ ctx->buffer_start, buf_size,
++ ctx->output_buffer, &ctx->len);
+
-+ if (!resume_param) {
-+ printk(KERN_INFO "Open file %s returned %p.\n",
-+ target, target_file);
-+ return;
-+ }
++ kunmap(buffer_page);
+
-+ resume_file_dev_t = name_to_dev_t(target);
-+ if (!resume_file_dev_t) {
-+ struct kstat stat;
-+ int error = vfs_stat(target, &stat);
-+ printk(KERN_INFO "Open file %s returned %p and "
-+ "name_to_devt failed.\n", target,
-+ target_file);
-+ if (error)
-+ printk(KERN_INFO "Stating the file also failed."
-+ " Nothing more we can do.\n");
-+ else
-+ resume_file_dev_t = stat.rdev;
-+ return;
-+ }
++ mutex_lock(&stats_lock);
++ toi_compress_bytes_in += buf_size;
++ toi_compress_bytes_out += ctx->len;
++ mutex_unlock(&stats_lock);
+
-+ toi_file_target_bdev = toi_open_by_devnum(resume_file_dev_t,
-+ FMODE_READ | FMODE_NDELAY);
-+ if (IS_ERR(toi_file_target_bdev)) {
-+ printk(KERN_INFO "Got a dev_num (%lx) but failed to "
-+ "open it.\n",
-+ (unsigned long) resume_file_dev_t);
-+ return;
-+ }
-+ used_devt = 1;
-+ target_inode = toi_file_target_bdev->bd_inode;
++ if (!ret && ctx->len < buf_size) { /* some compression */
++ memcpy(ctx->page_buffer, ctx->output_buffer, ctx->len);
++ return next_driver->write_page(index,
++ virt_to_page(ctx->page_buffer),
++ ctx->len);
+ } else
-+ target_inode = target_file->f_mapping->host;
-+
-+ if (S_ISLNK(target_inode->i_mode) || S_ISDIR(target_inode->i_mode) ||
-+ S_ISSOCK(target_inode->i_mode) || S_ISFIFO(target_inode->i_mode)) {
-+ printk(KERN_INFO "File support works with regular files,"
-+ " character files and block devices.\n");
-+ goto cleanup;
-+ }
++ return next_driver->write_page(index, buffer_page, buf_size);
++}
+
-+ if (!used_devt) {
-+ if (S_ISBLK(target_inode->i_mode)) {
-+ toi_file_target_bdev = I_BDEV(target_inode);
-+ if (!bd_claim(toi_file_target_bdev, &toi_fileops))
-+ target_claim = 1;
-+ } else
-+ toi_file_target_bdev = target_inode->i_sb->s_bdev;
-+ resume_file_dev_t = toi_file_target_bdev->bd_dev;
-+ }
++/*
++ * toi_compress_read_page()
++ * @buffer_page: struct page *. Pointer to a buffer of size PAGE_SIZE.
++ *
++ * Retrieve data from later modules and decompress it until the input buffer
++ * is filled.
++ * Zero if successful. Error condition from me or from downstream on failure.
++ */
++static int toi_compress_read_page(unsigned long *index,
++ struct page *buffer_page, unsigned int *buf_size)
++{
++ int ret, cpu = smp_processor_id();
++ unsigned int len;
++ unsigned int outlen = PAGE_SIZE;
++ char *buffer_start;
++ struct cpu_context *ctx = &per_cpu(contexts, cpu);
+
-+ set_devinfo(toi_file_target_bdev, target_inode->i_blkbits);
++ if (!ctx->transform)
++ return next_driver->read_page(index, buffer_page, buf_size);
+
-+ if (get_size)
-+ target_storage_available = size_ignoring_ignored_pages();
++ /*
++ * All our reads must be synchronous - we can't decompress
++ * data that hasn't been read yet.
++ */
+
-+ if (!resume_param)
-+ target_firstblock = bmap(target_inode, 0) << devinfo.bmap_shift;
++ ret = next_driver->read_page(index, buffer_page, &len);
+
-+ return;
-+cleanup:
-+ target_inode = NULL;
-+ if (target_file) {
-+ filp_close(target_file, NULL);
-+ target_file = NULL;
-+ }
-+ set_devinfo(NULL, 0);
-+ target_storage_available = 0;
-+}
++ /* Error or uncompressed data */
++ if (ret || len == PAGE_SIZE)
++ return ret;
+
-+static void toi_file_noresume_reset(void)
-+{
-+ toi_bio_ops.rw_cleanup(READ);
++ buffer_start = kmap(buffer_page);
++ memcpy(ctx->page_buffer, buffer_start, len);
++ ret = crypto_comp_decompress(
++ ctx->transform,
++ ctx->page_buffer,
++ len, buffer_start, &outlen);
++ if (ret)
++ abort_hibernate(TOI_FAILED_IO,
++ "Compress_read returned %d.\n", ret);
++ else if (outlen != PAGE_SIZE) {
++ abort_hibernate(TOI_FAILED_IO,
++ "Decompression yielded %d bytes instead of %ld.\n",
++ outlen, PAGE_SIZE);
++ printk(KERN_ERR "Decompression yielded %d bytes instead of "
++ "%ld.\n", outlen, PAGE_SIZE);
++ ret = -EIO;
++ *buf_size = outlen;
++ }
++ kunmap(buffer_page);
++ return ret;
+}
+
-+/**
-+ * parse_signature - check if the file is suitable for resuming
-+ * @header: Signature of the file
++/*
++ * toi_compress_print_debug_stats
++ * @buffer: Pointer to a buffer into which the debug info will be printed.
++ * @size: Size of the buffer.
+ *
-+ * Given a file header, check the content of the file. Return true if it
-+ * contains a valid hibernate image.
-+ * TOI_RESUMED_BEFORE is set accordingly.
-+ **/
-+static int parse_signature(struct toi_file_header *header)
-+{
-+ int have_image = !memcmp(HaveImage, header->sig, sizeof(HaveImage) - 1);
-+ int no_image_header = !memcmp(NoImage, header->sig,
-+ sizeof(NoImage) - 1);
-+ int binary_sig = !memcmp(tuxonice_signature, header->sig,
-+ sizeof(tuxonice_signature));
-+
-+ if (no_image_header || (binary_sig && !header->have_image))
-+ return 0;
++ * Print information to be recorded for debugging purposes into a buffer.
++ * Returns: Number of characters written to the buffer.
++ */
+
-+ if (!have_image && !binary_sig)
-+ return -1;
++static int toi_compress_print_debug_stats(char *buffer, int size)
++{
++ unsigned long pages_in = toi_compress_bytes_in >> PAGE_SHIFT,
++ pages_out = toi_compress_bytes_out >> PAGE_SHIFT;
++ int len;
+
-+ if (header->resumed_before)
-+ set_toi_state(TOI_RESUMED_BEFORE);
++ /* Output the compression ratio achieved. */
++ if (*toi_compressor_name)
++ len = scnprintf(buffer, size, "- Compressor is '%s'.\n",
++ toi_compressor_name);
+ else
-+ clear_toi_state(TOI_RESUMED_BEFORE);
++ len = scnprintf(buffer, size, "- Compressor is not set.\n");
+
-+ target_header_start = header->first_header_block;
-+ return 1;
++ if (pages_in)
++ len += scnprintf(buffer+len, size - len, " Compressed "
++ "%lu bytes into %lu (%ld percent compression).\n",
++ toi_compress_bytes_in,
++ toi_compress_bytes_out,
++ (pages_in - pages_out) * 100 / pages_in);
++ return len;
+}
+
-+/**
-+ * prepare_signature - populate the signature structure
-+ * @current_header: Signature structure to populate
-+ * @first_header_block: Sector with the header containing the extents
-+ **/
-+static int prepare_signature(struct toi_file_header *current_header,
-+ unsigned long first_header_block)
++/*
++ * toi_compress_compression_memory_needed
++ *
++ * Tell the caller how much memory we need to operate during hibernate/resume.
++ * Returns: Unsigned long. Maximum number of bytes of memory required for
++ * operation.
++ */
++static int toi_compress_memory_needed(void)
+{
-+ memcpy(current_header->sig, tuxonice_signature,
-+ sizeof(tuxonice_signature));
-+ current_header->resumed_before = 0;
-+ current_header->first_header_block = first_header_block;
-+ current_header->have_image = 1;
-+ return 0;
++ return 2 * PAGE_SIZE;
+}
+
-+static unsigned long toi_file_storage_allocated(void)
++static int toi_compress_storage_needed(void)
+{
-+ if (!target_inode)
-+ return 0;
-+
-+ if (target_is_normal_file())
-+ return raw_to_real(target_storage_available);
-+ else
-+ return raw_to_real(main_pages_requested);
++ return 4 * sizeof(unsigned long) + strlen(toi_compressor_name) + 1;
+}
+
-+/**
-+ * toi_file_release_storage - deallocate the block chain
-+ **/
-+static int toi_file_release_storage(void)
++/*
++ * toi_compress_save_config_info
++ * @buffer: Pointer to a buffer of size PAGE_SIZE.
++ *
++ * Save informaton needed when reloading the image at resume time.
++ * Returns: Number of bytes used for saving our data.
++ */
++static int toi_compress_save_config_info(char *buffer)
+{
-+ toi_put_extent_chain(&block_chain);
-+
-+ header_pages_reserved = 0;
-+ main_pages_allocated = 0;
-+ main_pages_requested = 0;
-+ return 0;
-+}
++ int namelen = strlen(toi_compressor_name) + 1;
++ int total_len;
+
-+static void toi_file_reserve_header_space(unsigned long request)
-+{
-+ header_pages_reserved = request;
++ *((unsigned long *) buffer) = toi_compress_bytes_in;
++ *((unsigned long *) (buffer + 1 * sizeof(unsigned long))) =
++ toi_compress_bytes_out;
++ *((unsigned long *) (buffer + 2 * sizeof(unsigned long))) =
++ toi_expected_compression;
++ *((unsigned long *) (buffer + 3 * sizeof(unsigned long))) = namelen;
++ strncpy(buffer + 4 * sizeof(unsigned long), toi_compressor_name,
++ namelen);
++ total_len = 4 * sizeof(unsigned long) + namelen;
++ return total_len;
+}
+
-+static int toi_file_allocate_storage(unsigned long main_space_requested)
++/* toi_compress_load_config_info
++ * @buffer: Pointer to the start of the data.
++ * @size: Number of bytes that were saved.
++ *
++ * Description: Reload information needed for decompressing the image at
++ * resume time.
++ */
++static void toi_compress_load_config_info(char *buffer, int size)
+{
-+ int result = 0;
-+
-+ unsigned long extra_pages = DIV_ROUND_UP(main_space_requested *
-+ (sizeof(unsigned long) + sizeof(int)), PAGE_SIZE),
-+ pages_to_get = main_space_requested + extra_pages +
-+ header_pages_reserved,
-+ blocks_to_get = (pages_to_get > block_chain.size) ?
-+ pages_to_get - block_chain.size : 0;
-+
-+ /* Only release_storage reduces the size */
-+ if (!blocks_to_get)
-+ return apply_header_reservation();
-+
-+ result = populate_block_list();
-+
-+ if (result)
-+ return result;
-+
-+ toi_message(TOI_WRITER, TOI_MEDIUM, 0,
-+ "Finished with block_chain.size == %d.\n",
-+ block_chain.size);
++ int namelen;
+
-+ if (block_chain.size < pages_to_get) {
-+ printk(KERN_INFO "Block chain size (%lu) < header pages (%lu) + "
-+ "extra pages (%lu) + main pages (%lu) (=%lu "
-+ "pages).\n",
-+ block_chain.size, header_pages_reserved,
-+ extra_pages, main_space_requested,
-+ pages_to_get);
-+ result = -ENOSPC;
++ toi_compress_bytes_in = *((unsigned long *) buffer);
++ toi_compress_bytes_out = *((unsigned long *) (buffer + 1 *
++ sizeof(unsigned long)));
++ toi_expected_compression = *((unsigned long *) (buffer + 2 *
++ sizeof(unsigned long)));
++ namelen = *((unsigned long *) (buffer + 3 * sizeof(unsigned long)));
++ if (strncmp(toi_compressor_name, buffer + 4 * sizeof(unsigned long),
++ namelen)) {
++ toi_compress_cleanup(1);
++ strncpy(toi_compressor_name, buffer + 4 * sizeof(unsigned long),
++ namelen);
++ toi_compress_crypto_prepare();
+ }
-+
-+ main_pages_requested = main_space_requested;
-+ main_pages_allocated = main_space_requested + extra_pages;
-+ return result;
++ return;
+}
+
-+/**
-+ * toi_file_write_header_init - save the header on the image
-+ **/
-+static int toi_file_write_header_init(void)
-+{
-+ int result;
++/*
++ * toi_expected_compression_ratio
++ *
++ * Description: Returns the expected ratio between data passed into this module
++ * and the amount of data output when writing.
++ * Returns: 100 if the module is disabled. Otherwise the value set by the
++ * user via our sysfs entry.
++ */
+
-+ toi_bio_ops.rw_init(WRITE, 0);
-+ toi_writer_buffer_posn = 0;
++static int toi_compress_expected_ratio(void)
++{
++ if (!toi_compression_ops.enabled)
++ return 100;
++ else
++ return 100 - toi_expected_compression;
++}
+
-+ /* Info needed to bootstrap goes at the start of the header.
-+ * First we save the basic info needed for reading, including the number
-+ * of header pages. Then we save the structs containing data needed
-+ * for reading the header pages back.
-+ * Note that even if header pages take more than one page, when we
-+ * read back the info, we will have restored the location of the
-+ * next header page by the time we go to use it.
-+ */
++/*
++ * data for our sysfs entries.
++ */
++static struct toi_sysfs_data sysfs_params[] = {
++ SYSFS_INT("expected_compression", SYSFS_RW, &toi_expected_compression,
++ 0, 99, 0, NULL),
++ SYSFS_INT("enabled", SYSFS_RW, &toi_compression_ops.enabled, 0, 1, 0,
++ NULL),
++ SYSFS_STRING("algorithm", SYSFS_RW, toi_compressor_name, 31, 0, NULL),
++};
+
-+ result = toi_bio_ops.rw_header_chunk(WRITE, &toi_fileops,
-+ (char *) &toi_writer_posn_save,
-+ sizeof(toi_writer_posn_save));
++/*
++ * Ops structure.
++ */
++static struct toi_module_ops toi_compression_ops = {
++ .type = FILTER_MODULE,
++ .name = "compression",
++ .directory = "compression",
++ .module = THIS_MODULE,
++ .initialise = toi_compress_init,
++ .cleanup = toi_compress_cleanup,
++ .memory_needed = toi_compress_memory_needed,
++ .print_debug_info = toi_compress_print_debug_stats,
++ .save_config_info = toi_compress_save_config_info,
++ .load_config_info = toi_compress_load_config_info,
++ .storage_needed = toi_compress_storage_needed,
++ .expected_compression = toi_compress_expected_ratio,
+
-+ if (result)
-+ return result;
++ .rw_init = toi_compress_rw_init,
+
-+ result = toi_bio_ops.rw_header_chunk(WRITE, &toi_fileops,
-+ (char *) &devinfo, sizeof(devinfo));
++ .write_page = toi_compress_write_page,
++ .read_page = toi_compress_read_page,
+
-+ if (result)
-+ return result;
++ .sysfs_data = sysfs_params,
++ .num_sysfs_entries = sizeof(sysfs_params) /
++ sizeof(struct toi_sysfs_data),
++};
+
-+ /* Flush the chain */
-+ toi_serialise_extent_chain(&toi_fileops, &block_chain);
++/* ---- Registration ---- */
+
-+ return 0;
++static __init int toi_compress_load(void)
++{
++ return toi_register_module(&toi_compression_ops);
+}
+
-+static int toi_file_write_header_cleanup(void)
++#ifdef MODULE
++static __exit void toi_compress_unload(void)
+{
-+ struct toi_file_header *header;
-+ int result, result2;
-+ unsigned long sig_page = toi_get_zeroed_page(38, TOI_ATOMIC_GFP);
-+
-+ /* Write any unsaved data */
-+ result = toi_bio_ops.write_header_chunk_finish();
-+
-+ if (result)
-+ goto out;
-+
-+ toi_extent_state_goto_start(&toi_writer_posn);
-+ toi_bio_ops.forward_one_page(1, 1);
-+
-+ /* Adjust image header */
-+ result = toi_bio_ops.bdev_page_io(READ, toi_file_target_bdev,
-+ target_firstblock,
-+ virt_to_page(sig_page));
-+ if (result)
-+ goto out;
-+
-+ header = (struct toi_file_header *) sig_page;
-+
-+ prepare_signature(header,
-+ toi_writer_posn.current_offset <<
-+ devinfo.bmap_shift);
-+
-+ result = toi_bio_ops.bdev_page_io(WRITE, toi_file_target_bdev,
-+ target_firstblock,
-+ virt_to_page(sig_page));
-+
-+out:
-+ result2 = toi_bio_ops.finish_all_io();
-+ toi_free_page(38, sig_page);
-+
-+ return result ? result : result2;
++ toi_unregister_module(&toi_compression_ops);
+}
+
-+/* HEADER READING */
++module_init(toi_compress_load);
++module_exit(toi_compress_unload);
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Nigel Cunningham");
++MODULE_DESCRIPTION("Compression Support for TuxOnIce");
++#else
++late_initcall(toi_compress_load);
++#endif
+diff --git a/kernel/power/tuxonice_extent.c b/kernel/power/tuxonice_extent.c
+new file mode 100644
+index 0000000..ff5afa9
+--- /dev/null
++++ b/kernel/power/tuxonice_extent.c
+@@ -0,0 +1,123 @@
++/*
++ * kernel/power/tuxonice_extent.c
++ *
++ * Copyright (C) 2003-2008 Nigel Cunningham (nigel at tuxonice net)
++ *
++ * Distributed under GPLv2.
++ *
++ * These functions encapsulate the manipulation of storage metadata.
++ */
++
++#include <linux/suspend.h>
++#include "tuxonice_modules.h"
++#include "tuxonice_extent.h"
++#include "tuxonice_alloc.h"
++#include "tuxonice_ui.h"
++#include "tuxonice.h"
+
+/**
-+ * toi_file_read_header_init - check content of signature
-+ *
-+ * Entry point of the resume path.
-+ * 1. Attempt to read the device specified with resume=.
-+ * 2. Check the contents of the header for our signature.
-+ * 3. Warn, ignore, reset and/or continue as appropriate.
-+ * 4. If continuing, read the toi_file configuration section
-+ * of the header and set up block device info so we can read
-+ * the rest of the header & image.
++ * toi_get_extent - return a free extent
+ *
-+ * Returns:
-+ * May not return if user choose to reboot at a warning.
-+ * -EINVAL if cannot resume at this time. Booting should continue
-+ * normally.
++ * May fail, returning NULL instead.
+ **/
-+static int toi_file_read_header_init(void)
++static struct hibernate_extent *toi_get_extent(void)
+{
-+ int result;
-+ struct block_device *tmp;
++ return (struct hibernate_extent *) toi_kzalloc(2,
++ sizeof(struct hibernate_extent), TOI_ATOMIC_GFP);
++}
+
-+ /* Allocate toi_writer_buffer */
-+ toi_bio_ops.read_header_init();
++/**
++ * toi_put_extent_chain - free a whole chain of extents
++ * @chain: Chain to free.
++ **/
++void toi_put_extent_chain(struct hibernate_extent_chain *chain)
++{
++ struct hibernate_extent *this;
+
-+ /*
-+ * Read toi_file configuration (header containing metadata).
-+ * target_header_start is the first sector of the header. It has been
-+ * set when checking if the file was suitable for resuming, see
-+ * do_toi_step(STEP_RESUME_CAN_RESUME).
-+ */
-+ result = toi_bio_ops.bdev_page_io(READ, toi_file_target_bdev,
-+ target_header_start,
-+ virt_to_page((unsigned long) toi_writer_buffer));
++ this = chain->first;
+
-+ if (result) {
-+ printk(KERN_ERR "FileAllocator read header init: Failed to "
-+ "initialise reading the first page of data.\n");
-+ toi_bio_ops.rw_cleanup(READ);
-+ return result;
++ while (this) {
++ struct hibernate_extent *next = this->next;
++ toi_kfree(2, this, sizeof(*this));
++ chain->num_extents--;
++ this = next;
+ }
+
-+ /* toi_writer_posn_save[0] contains the header */
-+ memcpy(&toi_writer_posn_save, toi_writer_buffer,
-+ sizeof(toi_writer_posn_save));
-+
-+ /* Save the position in the buffer */
-+ toi_writer_buffer_posn = sizeof(toi_writer_posn_save);
-+
-+ tmp = devinfo.bdev;
-+
-+ /* See tuxonice_block_io.h */
-+ memcpy(&devinfo,
-+ toi_writer_buffer + toi_writer_buffer_posn,
-+ sizeof(devinfo));
-+
-+ devinfo.bdev = tmp;
-+ toi_writer_buffer_posn += sizeof(devinfo);
-+
-+ /* Reinitialize the extent pointer */
-+ toi_extent_state_goto_start(&toi_writer_posn);
-+ /* Jump to the next page */
-+ toi_bio_ops.set_extra_page_forward();
-+
-+ /* Bring back the chain from disk: this will read
-+ * all extents.
-+ */
-+ return toi_load_extent_chain(&block_chain);
-+}
-+
-+static int toi_file_read_header_cleanup(void)
-+{
-+ toi_bio_ops.rw_cleanup(READ);
-+ return 0;
++ chain->first = NULL;
++ chain->last_touched = NULL;
++ chain->current_extent = NULL;
++ chain->size = 0;
+}
++EXPORT_SYMBOL_GPL(toi_put_extent_chain);
+
+/**
-+ * toi_file_signature_op - perform an operation on the file signature
-+ * @op: operation to perform
++ * toi_add_to_extent_chain - add an extent to an existing chain
++ * @chain: Chain to which the extend should be added
++ * @start: Start of the extent (first physical block)
++ * @end: End of the extent (last physical block)
+ *
-+ * op is either GET_IMAGE_EXISTS, INVALIDATE, MARK_RESUME_ATTEMPTED or
-+ * UNMARK_RESUME_ATTEMPTED.
-+ * If the signature is changed, an I/O operation is performed.
-+ * The signature exists iff toi_file_signature_op(GET_IMAGE_EXISTS)>-1.
++ * The chain information is updated if the insertion is successful.
+ **/
-+static int toi_file_signature_op(int op)
++int toi_add_to_extent_chain(struct hibernate_extent_chain *chain,
++ unsigned long start, unsigned long end)
+{
-+ char *cur;
-+ int result = 0, result2, changed = 0;
-+ struct toi_file_header *header;
++ struct hibernate_extent *new_ext = NULL, *cur_ext = NULL;
+
-+ if (!toi_file_target_bdev || IS_ERR(toi_file_target_bdev))
-+ return -1;
++ toi_message(TOI_IO, TOI_VERBOSE, 0,
++ "Adding extent %lu-%lu to chain %p.\n", start, end, chain);
+
-+ cur = (char *) toi_get_zeroed_page(17, TOI_ATOMIC_GFP);
-+ if (!cur) {
-+ printk(KERN_INFO "Unable to allocate a page for reading the "
-+ "image signature.\n");
-+ return -ENOMEM;
-+ }
++ /* Find the right place in the chain */
++ if (chain->last_touched && chain->last_touched->start < start)
++ cur_ext = chain->last_touched;
++ else if (chain->first && chain->first->start < start)
++ cur_ext = chain->first;
+
-+ result = toi_bio_ops.bdev_page_io(READ, toi_file_target_bdev,
-+ target_firstblock,
-+ virt_to_page(cur));
++ if (cur_ext) {
++ while (cur_ext->next && cur_ext->next->start < start)
++ cur_ext = cur_ext->next;
+
-+ if (result)
-+ goto out;
++ if (cur_ext->end == (start - 1)) {
++ struct hibernate_extent *next_ext = cur_ext->next;
++ cur_ext->end = end;
+
-+ header = (struct toi_file_header *) cur;
-+ result = parse_signature(header);
++ /* Merge with the following one? */
++ if (next_ext && cur_ext->end + 1 == next_ext->start) {
++ cur_ext->end = next_ext->end;
++ cur_ext->next = next_ext->next;
++ toi_kfree(2, next_ext, sizeof(*next_ext));
++ chain->num_extents--;
++ }
+
-+ switch (op) {
-+ case INVALIDATE:
-+ if (result == -1)
-+ goto out;
++ chain->last_touched = cur_ext;
++ chain->size += (end - start + 1);
+
-+ memcpy(header->sig, tuxonice_signature,
-+ sizeof(tuxonice_signature));
-+ header->resumed_before = 0;
-+ header->have_image = 0;
-+ result = 1;
-+ changed = 1;
-+ break;
-+ case MARK_RESUME_ATTEMPTED:
-+ if (result == 1) {
-+ header->resumed_before = 1;
-+ changed = 1;
-+ }
-+ break;
-+ case UNMARK_RESUME_ATTEMPTED:
-+ if (result == 1) {
-+ header->resumed_before = 0;
-+ changed = 1;
++ return 0;
+ }
-+ break;
+ }
+
-+ if (changed) {
-+ int io_result = toi_bio_ops.bdev_page_io(WRITE,
-+ toi_file_target_bdev, target_firstblock,
-+ virt_to_page(cur));
-+ if (io_result)
-+ result = io_result;
++ new_ext = toi_get_extent();
++ if (!new_ext) {
++ printk(KERN_INFO "Error unable to append a new extent to the "
++ "chain.\n");
++ return -ENOMEM;
+ }
+
-+out:
-+ result2 = toi_bio_ops.finish_all_io();
-+ toi_free_page(17, (unsigned long) cur);
-+ return result ? result : result2;
-+}
++ chain->num_extents++;
++ chain->size += (end - start + 1);
++ new_ext->start = start;
++ new_ext->end = end;
+
-+/**
-+ * toi_file_print_debug_stats - print debug info
-+ * @buffer: Buffer to data to populate
-+ * @size: Size of the buffer
-+ **/
-+static int toi_file_print_debug_stats(char *buffer, int size)
-+{
-+ int len = 0;
++ chain->last_touched = new_ext;
+
-+ if (toiActiveAllocator != &toi_fileops) {
-+ len = scnprintf(buffer, size,
-+ "- FileAllocator inactive.\n");
-+ return len;
++ if (cur_ext) {
++ new_ext->next = cur_ext->next;
++ cur_ext->next = new_ext;
++ } else {
++ if (chain->first)
++ new_ext->next = chain->first;
++ chain->first = new_ext;
+ }
+
-+ len = scnprintf(buffer, size, "- FileAllocator active.\n");
++ return 0;
++}
++EXPORT_SYMBOL_GPL(toi_add_to_extent_chain);
+diff --git a/kernel/power/tuxonice_extent.h b/kernel/power/tuxonice_extent.h
+new file mode 100644
+index 0000000..99e4734
+--- /dev/null
++++ b/kernel/power/tuxonice_extent.h
+@@ -0,0 +1,44 @@
++/*
++ * kernel/power/tuxonice_extent.h
++ *
++ * Copyright (C) 2003-2008 Nigel Cunningham (nigel at tuxonice net)
++ *
++ * This file is released under the GPLv2.
++ *
++ * It contains declarations related to extents. Extents are
++ * TuxOnIce's method of storing some of the metadata for the image.
++ * See tuxonice_extent.c for more info.
++ *
++ */
++
++#include "tuxonice_modules.h"
+
-+ len += scnprintf(buffer+len, size-len, " Storage available for "
-+ "image: %lu pages.\n",
-+ toi_file_storage_allocated());
++#ifndef EXTENT_H
++#define EXTENT_H
+
-+ return len;
-+}
++struct hibernate_extent {
++ unsigned long start, end;
++ struct hibernate_extent *next;
++};
+
-+/**
-+ * toi_file_storage_needed - storage needed
++struct hibernate_extent_chain {
++ unsigned long size; /* size of the chain ie sum (max-min+1) */
++ int num_extents;
++ struct hibernate_extent *first, *last_touched;
++ struct hibernate_extent *current_extent;
++ unsigned long current_offset;
++};
++
++/* Simplify iterating through all the values in an extent chain */
++#define toi_extent_for_each(extent_chain, extentpointer, value) \
++if ((extent_chain)->first) \
++ for ((extentpointer) = (extent_chain)->first, (value) = \
++ (extentpointer)->start; \
++ ((extentpointer) && ((extentpointer)->next || (value) <= \
++ (extentpointer)->end)); \
++ (((value) == (extentpointer)->end) ? \
++ ((extentpointer) = (extentpointer)->next, (value) = \
++ ((extentpointer) ? (extentpointer)->start : 0)) : \
++ (value)++))
++
++#endif
+diff --git a/kernel/power/tuxonice_file.c b/kernel/power/tuxonice_file.c
+new file mode 100644
+index 0000000..c71be4b
+--- /dev/null
++++ b/kernel/power/tuxonice_file.c
+@@ -0,0 +1,477 @@
++/*
++ * kernel/power/tuxonice_file.c
+ *
-+ * Returns amount of space in the image header required
-+ * for the toi_file's data.
++ * Copyright (C) 2005-2008 Nigel Cunningham (nigel at tuxonice net)
+ *
-+ * We ensure the space is allocated, but actually save the
-+ * data from write_header_init and therefore don't also define a
-+ * save_config_info routine.
-+ **/
-+static int toi_file_storage_needed(void)
-+{
-+ return strlen(toi_file_target) + 1 +
-+ sizeof(toi_writer_posn_save) +
-+ sizeof(devinfo) +
-+ sizeof(block_chain.size) + sizeof(block_chain.num_extents) +
-+ (2 * sizeof(unsigned long) * block_chain.num_extents);
-+}
++ * Distributed under GPLv2.
++ *
++ * This file encapsulates functions for usage of a simple file as a
++ * backing store. It is based upon the swapallocator, and shares the
++ * same basic working. Here, though, we have nothing to do with
++ * swapspace, and only one device to worry about.
++ *
++ * The user can just
++ *
++ * echo TuxOnIce > /path/to/my_file
++ *
++ * dd if=/dev/zero bs=1M count=<file_size_desired> >> /path/to/my_file
++ *
++ * and
++ *
++ * echo /path/to/my_file > /sys/power/tuxonice/file/target
++ *
++ * then put what they find in /sys/power/tuxonice/resume
++ * as their resume= parameter in lilo.conf (and rerun lilo if using it).
++ *
++ * Having done this, they're ready to hibernate and resume.
++ *
++ * TODO:
++ * - File resizing.
++ */
+
-+/**
-+ * toi_file_remove_image - invalidate the image
-+ **/
-+static int toi_file_remove_image(void)
-+{
-+ toi_file_release_storage();
-+ return toi_file_signature_op(INVALIDATE);
-+}
++#include <linux/blkdev.h>
++#include <linux/mount.h>
++#include <linux/fs.h>
++#include <linux/uuid.h>
+
-+/**
-+ * toi_file_image_exists - test if an image exists
-+ *
-+ * Repopulate toi_file_target_bdev if needed.
-+ **/
-+static int toi_file_image_exists(int quiet)
-+{
-+ if (!toi_file_target_bdev)
-+ reopen_resume_devt();
-+ return toi_file_signature_op(GET_IMAGE_EXISTS);
-+}
++#include "tuxonice.h"
++#include "tuxonice_modules.h"
++#include "tuxonice_bio.h"
++#include "tuxonice_alloc.h"
++#include "tuxonice_builtin.h"
++#include "tuxonice_sysfs.h"
++#include "tuxonice_ui.h"
++#include "tuxonice_io.h"
+
-+/**
-+ * toi_file_mark_resume_attempted - mark resume attempted if so
-+ * @mark: attempted flag
-+ *
-+ * Record that we tried to resume from this image. Resuming
-+ * multiple times from the same image may be dangerous
-+ * (possible filesystem corruption).
-+ **/
-+static int toi_file_mark_resume_attempted(int mark)
++#define target_is_normal_file() (S_ISREG(target_inode->i_mode))
++
++static struct toi_module_ops toi_fileops;
++
++static struct file *target_file;
++static struct block_device *toi_file_target_bdev;
++static unsigned long pages_available, pages_allocated;
++static char toi_file_target[256];
++static struct inode *target_inode;
++static int file_target_priority;
++static int used_devt;
++static int target_claim;
++static dev_t toi_file_dev_t;
++static int sig_page_index;
++
++/* For test_toi_file_target */
++static struct toi_bdev_info *file_chain;
++
++static int has_contiguous_blocks(struct toi_bdev_info *dev_info, int page_num)
+{
-+ return toi_file_signature_op(mark ? MARK_RESUME_ATTEMPTED :
-+ UNMARK_RESUME_ATTEMPTED);
-+}
++ int j;
++ sector_t last = 0;
++
++ for (j = 0; j < dev_info->blocks_per_page; j++) {
++ sector_t this = bmap(target_inode,
++ page_num * dev_info->blocks_per_page + j);
++
++ if (!this || (last && (last + 1) != this))
++ break;
+
-+/**
-+ * toi_file_set_resume_param - validate the specified resume file
-+ *
-+ * Given a target filename, populate the resume parameter. This is
-+ * meant to be used by the user to populate the kernel command line.
-+ * By setting /sys/power/tuxonice/file/target, the valid resume
-+ * parameter to use is set and accessible through
-+ * /sys/power/tuxonice/resume.
-+ *
-+ * If the file could be located, we check if it contains a valid
-+ * signature.
-+ **/
-+static void toi_file_set_resume_param(void)
-+{
-+ char *buffer = (char *) toi_get_zeroed_page(18, TOI_ATOMIC_GFP);
-+ char *buffer2 = (char *) toi_get_zeroed_page(19, TOI_ATOMIC_GFP);
-+ unsigned long sector = bmap(target_inode, 0);
-+ int offset = 0;
-+
-+ if (!buffer || !buffer2) {
-+ if (buffer)
-+ toi_free_page(18, (unsigned long) buffer);
-+ if (buffer2)
-+ toi_free_page(19, (unsigned long) buffer2);
-+ printk(KERN_ERR "TuxOnIce: Failed to allocate memory while "
-+ "setting resume= parameter.\n");
-+ return;
++ last = this;
+ }
+
-+ if (toi_file_target_bdev) {
-+ set_devinfo(toi_file_target_bdev, target_inode->i_blkbits);
++ return j == dev_info->blocks_per_page;
++}
+
-+ bdevname(toi_file_target_bdev, buffer2);
-+ offset += snprintf(buffer + offset, PAGE_SIZE - offset,
-+ "/dev/%s", buffer2);
++static unsigned long get_usable_pages(struct toi_bdev_info *dev_info)
++{
++ unsigned long result = 0;
++ struct block_device *bdev = dev_info->bdev;
++ int i;
+
-+ if (sector)
-+ /* The offset is: sector << (inode->i_blkbits - 9) */
-+ offset += snprintf(buffer + offset, PAGE_SIZE - offset,
-+ ":0x%lx", sector << devinfo.bmap_shift);
-+ } else
-+ offset += snprintf(buffer + offset, PAGE_SIZE - offset,
-+ "%s is not a valid target.", toi_file_target);
++ switch (target_inode->i_mode & S_IFMT) {
++ case S_IFSOCK:
++ case S_IFCHR:
++ case S_IFIFO: /* Socket, Char, Fifo */
++ return -1;
++ case S_IFREG: /* Regular file: current size - holes + free
++ space on part */
++ for (i = 0; i < (target_inode->i_size >> PAGE_SHIFT) ; i++) {
++ if (has_contiguous_blocks(dev_info, i))
++ result++;
++ }
++ break;
++ case S_IFBLK: /* Block device */
++ if (!bdev->bd_disk) {
++ toi_message(TOI_IO, TOI_VERBOSE, 0,
++ "bdev->bd_disk null.");
++ return 0;
++ }
+
-+ sprintf(resume_file, "file:%s", buffer);
++ result = (bdev->bd_part ?
++ bdev->bd_part->nr_sects :
++ get_capacity(bdev->bd_disk)) >> (PAGE_SHIFT - 9);
++ }
+
-+ toi_free_page(18, (unsigned long) buffer);
-+ toi_free_page(19, (unsigned long) buffer2);
+
-+ toi_attempt_to_parse_resume_device(1);
++ return result;
+}
+
-+/**
-+ * __test_toi_file_target - is the file target valid for hibernating?
-+ * @target: target file
-+ * @resume_param: whether resume= has been specified
-+ * @quiet: quiet flag
-+ *
-+ * Test whether the file target can be used for hibernating: valid target
-+ * and signature.
-+ * The resume parameter is set if needed.
-+ **/
-+static int __test_toi_file_target(char *target, int resume_param, int quiet)
++static int toi_file_register_storage(void)
+{
-+ toi_file_get_target_info(target, 0, resume_param);
-+ if (toi_file_signature_op(GET_IMAGE_EXISTS) > -1) {
-+ if (!quiet)
-+ printk(KERN_INFO "TuxOnIce: FileAllocator: File "
-+ "signature found.\n");
-+ if (!resume_param)
-+ toi_file_set_resume_param();
++ struct toi_bdev_info *devinfo;
++ int result;
++
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "toi_file_register_storage.");
++ if (!strlen(toi_file_target)) {
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Register file storage: "
++ "No target filename set.");
++ return 0;
++ }
++
++ target_file = filp_open(toi_file_target, O_RDONLY|O_LARGEFILE, 0);
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "filp_open %s returned %p.",
++ toi_file_target, target_file);
++
++ if (IS_ERR(target_file) || !target_file) {
++ target_file = NULL;
++ toi_file_dev_t = name_to_dev_t(toi_file_target);
++ if (!toi_file_dev_t) {
++ struct kstat stat;
++ int error = vfs_stat(toi_file_target, &stat);
++ printk(KERN_INFO "Open file %s returned %p and "
++ "name_to_devt failed.\n",
++ toi_file_target, target_file);
++ if (error) {
++ printk(KERN_INFO "Stating the file also failed."
++ " Nothing more we can do.\n");
++ return 0;
++ } else
++ toi_file_dev_t = stat.rdev;
++ }
+
-+ toi_bio_ops.set_devinfo(&devinfo);
-+ toi_writer_posn.chains = &block_chain;
-+ toi_writer_posn.num_chains = 1;
++ toi_file_target_bdev = toi_open_by_devnum(toi_file_dev_t,
++ FMODE_READ | FMODE_NDELAY);
++ if (IS_ERR(toi_file_target_bdev)) {
++ printk(KERN_INFO "Got a dev_num (%lx) but failed to "
++ "open it.\n",
++ (unsigned long) toi_file_dev_t);
++ toi_file_target_bdev = NULL;
++ return 0;
++ }
++ used_devt = 1;
++ target_inode = toi_file_target_bdev->bd_inode;
++ } else
++ target_inode = target_file->f_mapping->host;
+
-+ if (!resume_param)
-+ set_toi_state(TOI_CAN_HIBERNATE);
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Succeeded in opening the target.");
++ if (S_ISLNK(target_inode->i_mode) || S_ISDIR(target_inode->i_mode) ||
++ S_ISSOCK(target_inode->i_mode) || S_ISFIFO(target_inode->i_mode)) {
++ printk(KERN_INFO "File support works with regular files,"
++ " character files and block devices.\n");
++ /* Cleanup routine will undo the above */
+ return 0;
+ }
+
-+ /*
-+ * Target unaccessible or no signature found
-+ * Most errors have already been reported
-+ */
++ if (!used_devt) {
++ if (S_ISBLK(target_inode->i_mode)) {
++ toi_file_target_bdev = I_BDEV(target_inode);
++ if (!bd_claim(toi_file_target_bdev, &toi_fileops))
++ target_claim = 1;
++ } else
++ toi_file_target_bdev = target_inode->i_sb->s_bdev;
++ toi_file_dev_t = toi_file_target_bdev->bd_dev;
++ }
+
-+ clear_toi_state(TOI_CAN_HIBERNATE);
++ devinfo = toi_kzalloc(39, sizeof(struct toi_bdev_info), GFP_ATOMIC);
++ if (!devinfo) {
++ printk("Failed to allocate a toi_bdev_info struct for the file allocator.\n");
++ return -ENOMEM;
++ }
+
-+ if (quiet)
-+ return 1;
++ devinfo->bdev = toi_file_target_bdev;
++ devinfo->allocator = &toi_fileops;
++ devinfo->allocator_index = 0;
+
-+ if (*target)
-+ printk(KERN_INFO "TuxOnIce: FileAllocator: Sorry. No signature "
-+ "found at %s.\n", target);
-+ else
-+ if (!resume_param)
-+ printk(KERN_INFO "TuxOnIce: FileAllocator: Sorry. "
-+ "Target is not set for hibernating.\n");
++ result = uuid_from_block_dev(toi_file_target_bdev, devinfo->uuid);
++ if (result)
++ printk(KERN_DEBUG "Failed to get uuid for file device (%d).\n",
++ result);
++ devinfo->dev_t = toi_file_dev_t;
++ devinfo->prio = file_target_priority;
++ devinfo->bmap_shift = target_inode->i_blkbits - 9;
++ devinfo->blocks_per_page =
++ (1 << (PAGE_SHIFT - target_inode->i_blkbits));
++ file_chain = devinfo;
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Dev_t is %lx. Prio is %d. Bmap "
++ "shift is %d. Blocks per page %d.",
++ devinfo->dev_t, devinfo->prio, devinfo->bmap_shift,
++ devinfo->blocks_per_page);
++
++ /* Keep one aside for the signature */
++ pages_available = get_usable_pages(devinfo) - 1;
++
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Registering file storage, %lu "
++ "pages.", pages_available);
++
++ toi_bio_ops.register_storage(devinfo);
++ return 0;
++}
+
-+ return 1;
++static unsigned long toi_file_storage_available(void)
++{
++ return pages_available;
+}
+
-+/**
-+ * test_toi_file_target - sysfs callback for /sys/power/tuxonince/file/target
-+ *
-+ * Test wheter the target file is valid for hibernating.
-+ **/
-+static void test_toi_file_target(void)
++static int toi_file_allocate_storage(struct toi_bdev_info *chain,
++ unsigned long request)
+{
-+ setting_toi_file_target = 1;
++ unsigned long available = pages_available - pages_allocated;
++ unsigned long to_add = min(available, request);
+
-+ printk(KERN_INFO "TuxOnIce: Hibernating %sabled.\n",
-+ __test_toi_file_target(toi_file_target, 0, 1) ?
-+ "dis" : "en");
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Pages available is %lu. Allocated "
++ "is %lu. Allocating %lu pages from file.",
++ pages_available, pages_allocated, to_add);
++ pages_allocated += to_add;
+
-+ setting_toi_file_target = 0;
++ return to_add;
+}
+
+/**
-+ * toi_file_parse_sig_location - parse image Location
-+ * @commandline: the resume parameter
-+ * @only_writer: ??
-+ * @quiet: quiet flag
-+ *
-+ * Attempt to parse a resume= parameter.
-+ * File Allocator accepts:
-+ * resume=file:DEVNAME[:FIRSTBLOCK]
++ * __populate_block_list - add an extent to the chain
++ * @min: Start of the extent (first physical block = sector)
++ * @max: End of the extent (last physical block = sector)
+ *
-+ * Where:
-+ * DEVNAME is convertable to a dev_t by name_to_dev_t
-+ * FIRSTBLOCK is the location of the first block in the file.
-+ * BLOCKSIZE is the logical blocksize >= SECTOR_SIZE &
-+ * <= PAGE_SIZE,
-+ * mod SECTOR_SIZE == 0 of the device.
-+ *
-+ * Data is validated by attempting to read a header from the
-+ * location given. Failure will result in toi_file refusing to
-+ * save an image, and a reboot with correct parameters will be
-+ * necessary.
++ * If TOI_TEST_BIO is set, print a debug message, outputting the min and max
++ * fs block numbers.
+ **/
-+static int toi_file_parse_sig_location(char *commandline,
-+ int only_writer, int quiet)
++static int __populate_block_list(struct toi_bdev_info *chain, int min, int max)
+{
-+ char *thischar, *devstart = NULL, *colon = NULL, *at_symbol = NULL;
-+ int result = -EINVAL, target_blocksize = 0;
-+
-+ if (strncmp(commandline, "file:", 5)) {
-+ if (!only_writer)
-+ return 1;
-+ } else
-+ commandline += 5;
++ if (test_action_state(TOI_TEST_BIO))
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Adding extent %d-%d.",
++ min << chain->bmap_shift,
++ ((max + 1) << chain->bmap_shift) - 1);
+
-+ /*
-+ * Don't check signature again if we're beginning a cycle. If we already
-+ * did the initialisation successfully, assume we'll be okay when it
-+ * comes to resuming.
-+ */
-+ if (toi_file_target_bdev)
-+ return 0;
++ return toi_add_to_extent_chain(&chain->blocks, min, max);
++}
+
-+ devstart = commandline;
-+ thischar = commandline;
-+ while ((*thischar != ':') && (*thischar != '@') &&
-+ ((thischar - commandline) < 250) && (*thischar))
-+ thischar++;
++static int get_main_pool_phys_params(struct toi_bdev_info *chain)
++{
++ int i, extent_min = -1, extent_max = -1, result = 0, have_sig_page = 0;
++ unsigned long pages_mapped = 0;
+
-+ if (*thischar == ':') {
-+ colon = thischar;
-+ *colon = 0;
-+ thischar++;
-+ }
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Getting file allocator blocks.");
+
-+ while ((*thischar != '@') && ((thischar - commandline) < 250)
-+ && (*thischar))
-+ thischar++;
++ if (chain->blocks.first)
++ toi_put_extent_chain(&chain->blocks);
+
-+ if (*thischar == '@') {
-+ at_symbol = thischar;
-+ *at_symbol = 0;
++ if (!target_is_normal_file()) {
++ result = (pages_available > 0) ?
++ __populate_block_list(chain, chain->blocks_per_page,
++ (pages_allocated + 1) *
++ chain->blocks_per_page - 1) : 0;
++ return result;
+ }
+
+ /*
-+ * For the toi_file, you can be able to resume, but not hibernate,
-+ * because the resume= is set correctly, but the toi_file_target
-+ * isn't.
-+ *
-+ * We may have come here as a result of setting resume or
-+ * toi_file_target. We only test the toi_file target in the
-+ * former case (it's already done in the later), and we do it before
-+ * setting the block number ourselves. It will overwrite the values
-+ * given on the command line if we don't.
++ * FIXME: We are assuming the first page is contiguous. Is that
++ * assumption always right?
+ */
+
-+ if (!setting_toi_file_target) /* Concurrent write via /sys? */
-+ __test_toi_file_target(toi_file_target, 1, 0);
++ for (i = 0; i < (target_inode->i_size >> PAGE_SHIFT); i++) {
++ sector_t new_sector;
+
-+ if (colon) {
-+ unsigned long block;
-+ result = strict_strtoul(colon + 1, 0, &block);
-+ if (result)
-+ goto out;
-+ target_firstblock = (int) block;
-+ } else
-+ target_firstblock = 0;
++ if (!has_contiguous_blocks(chain, i))
++ continue;
+
-+ if (at_symbol) {
-+ unsigned long block_size;
-+ result = strict_strtoul(at_symbol + 1, 0, &block_size);
-+ if (result)
-+ goto out;
-+ target_blocksize = (int) block_size;
-+ if (target_blocksize & (SECTOR_SIZE - 1)) {
-+ printk(KERN_INFO "FileAllocator: Blocksizes are "
-+ "multiples of %d.\n", SECTOR_SIZE);
-+ result = -EINVAL;
-+ goto out;
++ if (!have_sig_page) {
++ have_sig_page = 1;
++ sig_page_index = i;
++ continue;
+ }
-+ }
+
-+ if (!quiet)
-+ printk(KERN_INFO "TuxOnIce FileAllocator: Testing whether you "
-+ "can resume:\n");
++ pages_mapped++;
+
-+ toi_file_get_target_info(commandline, 0, 1);
++ /* Ignore first page - it has the header */
++ if (pages_mapped == 1)
++ continue;
+
-+ if (!toi_file_target_bdev || IS_ERR(toi_file_target_bdev)) {
-+ toi_file_target_bdev = NULL;
-+ result = -1;
-+ goto out;
-+ }
++ new_sector = bmap(target_inode, (i * chain->blocks_per_page));
+
-+ if (target_blocksize)
-+ set_devinfo(toi_file_target_bdev, ffs(target_blocksize));
++ /*
++ * I'd love to be able to fill in holes and resize
++ * files, but not yet...
++ */
+
-+ result = __test_toi_file_target(commandline, 1, quiet);
++ if (new_sector == extent_max + 1)
++ extent_max += chain->blocks_per_page;
++ else {
++ if (extent_min > -1) {
++ result = __populate_block_list(chain,
++ extent_min, extent_max);
++ if (result)
++ return result;
++ }
+
-+out:
-+ if (result)
-+ clear_toi_state(TOI_CAN_HIBERNATE);
++ extent_min = new_sector;
++ extent_max = extent_min +
++ chain->blocks_per_page - 1;
++ }
+
-+ if (!quiet)
-+ printk(KERN_INFO "Resuming %sabled.\n", result ? "dis" : "en");
++ if (pages_mapped == pages_allocated)
++ break;
++ }
+
-+ if (colon)
-+ *colon = ':';
-+ if (at_symbol)
-+ *at_symbol = '@';
++ if (extent_min > -1) {
++ result = __populate_block_list(chain, extent_min, extent_max);
++ if (result)
++ return result;
++ }
+
-+ return result;
++ return 0;
+}
+
-+/**
-+ * toi_file_save_config_info - populate toi_file_target
-+ * @buffer: Pointer to a buffer of size PAGE_SIZE.
-+ *
-+ * Save the target's name, not for resume time, but for
-+ * all_settings.
-+ * Returns:
-+ * Number of bytes used for saving our data.
-+ **/
-+static int toi_file_save_config_info(char *buffer)
++static void toi_file_free_storage(struct toi_bdev_info *chain)
+{
-+ strcpy(buffer, toi_file_target);
-+ return strlen(toi_file_target) + 1;
++ pages_allocated = 0;
++ file_chain = NULL;
+}
+
+/**
-+ * toi_file_load_config_info - reload target's name
-+ * @buffer: pointer to the start of the data
-+ * @size: number of bytes that were saved
-+ *
-+ * toi_file_target is set to buffer.
++ * toi_file_print_debug_stats - print debug info
++ * @buffer: Buffer to data to populate
++ * @size: Size of the buffer
+ **/
-+static void toi_file_load_config_info(char *buffer, int size)
++static int toi_file_print_debug_stats(char *buffer, int size)
+{
-+ strlcpy(toi_file_target, buffer, size);
++ int len = scnprintf(buffer, size, "- File Allocator active.\n");
++
++ len += scnprintf(buffer+len, size-len, " Storage available for "
++ "image: %lu pages.\n", pages_available);
++
++ return len;
+}
+
-+static int toi_file_initialise(int starting_cycle)
++static void toi_file_cleanup(int finishing_cycle)
+{
-+ if (starting_cycle) {
-+ if (toiActiveAllocator != &toi_fileops)
-+ return 0;
++ if (toi_file_target_bdev) {
++ if (target_claim) {
++ bd_release(toi_file_target_bdev);
++ target_claim = 0;
++ }
+
-+ if (starting_cycle & SYSFS_HIBERNATE && !*toi_file_target) {
-+ printk(KERN_INFO "FileAllocator is the active writer, "
-+ "but no filename has been set.\n");
-+ return 1;
++ if (used_devt) {
++ blkdev_put(toi_file_target_bdev,
++ FMODE_READ | FMODE_NDELAY);
++ used_devt = 0;
+ }
++ toi_file_target_bdev = NULL;
++ target_inode = NULL;
++ }
++
++ if (target_file) {
++ filp_close(target_file, NULL);
++ target_file = NULL;
+ }
+
-+ if (*toi_file_target)
-+ toi_file_get_target_info(toi_file_target, starting_cycle, 0);
++ pages_available = 0;
++}
+
-+ if (starting_cycle && (toi_file_image_exists(1) == -1)) {
-+ printk("%s is does not have a valid signature for "
-+ "hibernating.\n", toi_file_target);
-+ return 1;
++/**
++ * test_toi_file_target - sysfs callback for /sys/power/tuxonince/file/target
++ *
++ * Test wheter the target file is valid for hibernating.
++ **/
++static void test_toi_file_target(void)
++{
++ int result = toi_file_register_storage();
++ sector_t sector;
++ char uuid[17], buf[50];
++
++ if (result)
++ return;
++
++ /* This doesn't mean we're in business. Is any storage available? */
++ if (!pages_available)
++ goto out;
++
++ toi_file_allocate_storage(file_chain, 1);
++ result = get_main_pool_phys_params(file_chain);
++ if (result)
++ goto out;
++
++
++ sector = bmap(target_inode, sig_page_index *
++ file_chain->blocks_per_page) << file_chain->bmap_shift;
++
++ /* Use the uuid, or the dev_t if that fails */
++ if (uuid_from_block_dev(toi_file_target_bdev, uuid)) {
++ bdevname(toi_file_target_bdev, buf);
++ sprintf(resume_file, "/dev/%s:%llu", buf,
++ (unsigned long long) sector);
++ } else {
++ int i;
++ hex_dump_to_buffer(uuid, 16, 32, 1, buf, 50, 0);
++
++ /* Remove the spaces */
++ for (i = 1; i < 16; i++) {
++ buf[2 * i] = buf[3 * i];
++ buf[2 * i + 1] = buf[3 * i + 1];
++ }
++ buf[32] = 0;
++ sprintf(resume_file, "UUID=%s:%llu", buf,
++ (unsigned long long) sector);
+ }
+
-+ return 0;
++ toi_attempt_to_parse_resume_device(0);
++out:
++ toi_file_free_storage(file_chain);
++ toi_bio_ops.free_storage();
+}
+
+static struct toi_sysfs_data sysfs_params[] = {
-+
+ SYSFS_STRING("target", SYSFS_RW, toi_file_target, 256,
+ SYSFS_NEEDS_SM_FOR_WRITE, test_toi_file_target),
-+ SYSFS_INT("enabled", SYSFS_RW, &toi_fileops.enabled, 0, 1, 0,
-+ attempt_to_parse_resume_device2)
++ SYSFS_INT("enabled", SYSFS_RW, &toi_fileops.enabled, 0, 1, 0, NULL),
++ SYSFS_INT("priority", SYSFS_RW, &file_target_priority, -4095,
++ 4096, 0, NULL),
++};
++
++static struct toi_bio_allocator_ops toi_bio_fileops = {
++ .register_storage = toi_file_register_storage,
++ .storage_available = toi_file_storage_available,
++ .allocate_storage = toi_file_allocate_storage,
++ .bmap = get_main_pool_phys_params,
++ .free_storage = toi_file_free_storage,
+};
+
+static struct toi_module_ops toi_fileops = {
-+ .type = WRITER_MODULE,
++ .type = BIO_ALLOCATOR_MODULE,
+ .name = "file storage",
+ .directory = "file",
+ .module = THIS_MODULE,
+ .print_debug_info = toi_file_print_debug_stats,
-+ .save_config_info = toi_file_save_config_info,
-+ .load_config_info = toi_file_load_config_info,
-+ .storage_needed = toi_file_storage_needed,
-+ .initialise = toi_file_initialise,
+ .cleanup = toi_file_cleanup,
-+
-+ .noresume_reset = toi_file_noresume_reset,
-+ .storage_available = toi_file_storage_available,
-+ .storage_allocated = toi_file_storage_allocated,
-+ .reserve_header_space = toi_file_reserve_header_space,
-+ .allocate_storage = toi_file_allocate_storage,
-+ .image_exists = toi_file_image_exists,
-+ .mark_resume_attempted = toi_file_mark_resume_attempted,
-+ .write_header_init = toi_file_write_header_init,
-+ .write_header_cleanup = toi_file_write_header_cleanup,
-+ .read_header_init = toi_file_read_header_init,
-+ .read_header_cleanup = toi_file_read_header_cleanup,
-+ .remove_image = toi_file_remove_image,
-+ .parse_sig_location = toi_file_parse_sig_location,
++ .bio_allocator_ops = &toi_bio_fileops,
+
+ .sysfs_data = sysfs_params,
+ .num_sysfs_entries = sizeof(sysfs_params) /
+/* ---- Registration ---- */
+static __init int toi_file_load(void)
+{
-+ toi_fileops.rw_init = toi_bio_ops.rw_init;
-+ toi_fileops.rw_cleanup = toi_bio_ops.rw_cleanup;
-+ toi_fileops.read_page = toi_bio_ops.read_page;
-+ toi_fileops.write_page = toi_bio_ops.write_page;
-+ toi_fileops.rw_header_chunk = toi_bio_ops.rw_header_chunk;
-+ toi_fileops.rw_header_chunk_noreadahead =
-+ toi_bio_ops.rw_header_chunk_noreadahead;
-+ toi_fileops.io_flusher = toi_bio_ops.io_flusher;
-+ toi_fileops.update_throughput_throttle =
-+ toi_bio_ops.update_throughput_throttle;
-+ toi_fileops.finish_all_io = toi_bio_ops.finish_all_io;
-+
+ return toi_register_module(&toi_fileops);
+}
+
+#endif
diff --git a/kernel/power/tuxonice_highlevel.c b/kernel/power/tuxonice_highlevel.c
new file mode 100644
-index 0000000..29a442c
+index 0000000..8390946
--- /dev/null
+++ b/kernel/power/tuxonice_highlevel.c
-@@ -0,0 +1,1308 @@
+@@ -0,0 +1,1313 @@
+/*
+ * kernel/power/tuxonice_highlevel.c
+ */
+#include <linux/console.h>
+#include <linux/writeback.h>
+#include <linux/uaccess.h> /* for get/set_fs & KERNEL_DS on i386 */
++#include <linux/bio.h>
+
+#include "tuxonice.h"
+#include "tuxonice_modules.h"
+static int block_dump_save;
+
+/* Binary signature if an image is present */
-+char *tuxonice_signature = "\xed\xc3\x02\xe9\x98\x56\xe5\x0c";
++char tuxonice_signature[9] = "\xed\xc3\x02\xe9\x98\x56\xe5\x0c";
+EXPORT_SYMBOL_GPL(tuxonice_signature);
+
+unsigned long boot_kernel_data_buffer;
+ toi_put_modules();
+ if (hibernate_or_resume) {
+ block_dump = block_dump_save;
-+ set_cpus_allowed(current, CPU_MASK_ALL);
++ set_cpus_allowed_ptr(current, cpu_all_mask);
+ toi_alloc_print_debug_stats();
+ atomic_inc(&snapshot_device_available);
+ mutex_unlock(&pm_mutex);
+ if (hibernate_or_resume) {
+ block_dump_save = block_dump;
+ block_dump = 0;
-+ set_cpus_allowed(current,
-+ cpumask_of_cpu(first_cpu(cpu_online_map)));
++ set_cpus_allowed_ptr(current,
++ &cpumask_of_cpu(first_cpu(cpu_online_map)));
+ }
+
+ if (toi_initialise_modules_early(hibernate_or_resume))
+early_init_err:
+ if (hibernate_or_resume) {
+ block_dump_save = block_dump;
-+ set_cpus_allowed(current, CPU_MASK_ALL);
++ set_cpus_allowed_ptr(current, cpu_all_mask);
+ }
++ toi_put_modules();
+prehibernate_err:
+ if (hibernate_or_resume)
+ atomic_inc(&snapshot_device_available);
+ SNPRINTF("- Kernel Version : " UTS_RELEASE "\n");
+ SNPRINTF("- Compiler vers. : %d.%d\n", __GNUC__, __GNUC_MINOR__);
+ SNPRINTF("- Attempt number : %d\n", nr_hibernates);
-+ SNPRINTF("- Parameters : %ld %ld %ld %d %d %ld\n",
++ SNPRINTF("- Parameters : %ld %ld %ld %d %ld %ld\n",
+ toi_result,
+ toi_bkd.toi_action,
+ toi_bkd.toi_debug_state,
+ int i = 0;
+ char *buffer = NULL;
+
++ trap_non_toi_io = 0;
++
+ if (get_debug_info)
+ toi_prepare_status(DONT_CLEAR_BAR, "Cleaning up...");
+
+ !test_result_state(TOI_ABORTED)) {
+ toi_message(TOI_ANY_SECTION, TOI_LOW, 1,
+ "TuxOnIce: Not invalidating the image due "
-+ "to Keep Image being enabled.\n");
++ "to Keep Image being enabled.");
+ set_result_state(TOI_KEPT_IMAGE);
+ } else
+ if (toiActiveAllocator)
+ toi_prepare_status(DONT_CLEAR_BAR, "Starting to save the image..");
+
+ toi_message(TOI_ANY_SECTION, TOI_LOW, 1,
-+ " - Final values: %d and %d.\n",
++ " - Final values: %d and %d.",
+ pagedir1.size, pagedir2.size);
+
+ toi_cond_pause(1, "About to write pagedir2.");
+
+ toi_cond_pause(1, "About to write pageset1.");
+
-+ toi_message(TOI_ANY_SECTION, TOI_LOW, 1, "-- Writing pageset1\n");
++ toi_message(TOI_ANY_SECTION, TOI_LOW, 1, "-- Writing pageset1");
+
+ temp_result = write_pageset(&pagedir1);
+
+ !test_result_state(TOI_ABORTED))
+ return 0;
+
++ trap_non_toi_io = 1;
++
+ return 1;
+}
+
+ **/
+int do_check_can_resume(void)
+{
-+ char *buf = (char *) toi_get_zeroed_page(21, TOI_ATOMIC_GFP);
-+ int result = 0;
++ int result = -1;
+
-+ if (!buf)
-+ return 0;
++ if (toi_activate_storage(0))
++ return -1;
+
-+ /* Only interested in first byte, so throw away return code. */
-+ image_exists_read(buf, PAGE_SIZE);
++ if (!test_toi_state(TOI_RESUME_DEVICE_OK))
++ toi_attempt_to_parse_resume_device(1);
+
-+ if (buf[0] == '1')
-+ result = 1;
++ if (toiActiveAllocator)
++ result = toiActiveAllocator->image_exists(1);
+
-+ toi_free_page(21, (unsigned long) buf);
++ toi_deactivate_storage(0);
+ return result;
+}
+EXPORT_SYMBOL_GPL(do_check_can_resume);
+ int i;
+ for (i = 0; i < arg; i++)
+ if (argv[i] && argv[i] != channel)
-+ toi_kfree(5, argv[i], sizeof (*argv[i]));
++ toi_kfree(5, argv[i], sizeof(*argv[i]));
+ }
+
+ toi_kfree(4, channel, sizeof(*channel));
+ return retval;
+}
+
-+extern int freezer_sync;
-+
+/*
+ * This array contains entries that are automatically registered at
+ * boot. Modules and the console code register their own entries separately.
+ NULL),
+ SYSFS_BIT("ignore_rootfs", SYSFS_RW, &toi_bkd.toi_action,
+ TOI_IGNORE_ROOTFS, 0),
-+ SYSFS_INT("image_size_limit", SYSFS_RW, &image_size_limit, -2,
-+ INT_MAX, 0, NULL),
++ SYSFS_LONG("image_size_limit", SYSFS_RW, &image_size_limit, -2,
++ INT_MAX, 0),
+ SYSFS_UL("last_result", SYSFS_RW, &toi_result, 0, 0, 0),
+ SYSFS_BIT("no_multithreaded_io", SYSFS_RW, &toi_bkd.toi_action,
+ TOI_NO_MULTITHREADED_IO, 0),
+ TOI_NO_PS2_IF_UNNEEDED, 0),
+ SYSFS_BIT("late_cpu_hotplug", SYSFS_RW, &toi_bkd.toi_action,
+ TOI_LATE_CPU_HOTPLUG, 0),
++ SYSFS_STRING("binary_signature", SYSFS_READONLY,
++ tuxonice_signature, 9, 0, NULL),
+#ifdef CONFIG_TOI_KEEP_IMAGE
+ SYSFS_BIT("keep_image", SYSFS_RW , &toi_bkd.toi_action, TOI_KEEP_IMAGE,
+ 0),
+#endif
diff --git a/kernel/power/tuxonice_io.c b/kernel/power/tuxonice_io.c
new file mode 100644
-index 0000000..9fa1067
+index 0000000..0876f2d
--- /dev/null
+++ b/kernel/power/tuxonice_io.c
-@@ -0,0 +1,1534 @@
+@@ -0,0 +1,1537 @@
+/*
+ * kernel/power/tuxonice_io.c
+ *
+#include <linux/kthread.h>
+#include <linux/cpu.h>
+#include <linux/fs_struct.h>
++#include <linux/bio.h>
+#include <asm/tlbflush.h>
+
+#include "tuxonice.h"
+ }
+
+ /*
-+ * See toi_bio_read_page in tuxonice_block_io.c:
++ * See toi_bio_read_page in tuxonice_bio.c:
+ * read the next page in the image.
+ */
+ return first_filter->read_page(write_pfn, buffer, &buf_size);
+}
+
-+/**
-+ *
-+ **/
+static void use_read_page(unsigned long write_pfn, struct page *buffer)
+{
+ struct page *final_page = pfn_to_page(write_pfn),
+ clear_toi_state(TOI_IO_STOPPED);
+ memory_bm_position_reset(io_map);
+
-+ if (!test_action_state(TOI_NO_MULTITHREADED_IO))
++ if (!test_action_state(TOI_NO_MULTITHREADED_IO) &&
++ (write || !toi_force_no_multithreaded))
+ num_other_threads = start_other_threads();
+
+ if (!num_other_threads || !toiActiveAllocator->io_flusher ||
+ "%ld.\n", next);
+ do {
+ cpu_relax();
-+ } while(0);
++ } while (0);
+ }
+ }
+
+{
+ freeze_result = freeze_processes();
+ wake_up(&freeze_wait);
++ trap_non_toi_io = 1;
+}
+
+static DECLARE_WORK(freeze_work, do_freeze);
+
+ /* Check for an image */
+ result = toiActiveAllocator->image_exists(1);
-+ if (!result) {
++ if (result != 1) {
+ result = -ENODATA;
+ noresume_reset_modules();
+ printk(KERN_INFO "TuxOnIce: No image found.\n");
+ memcpy((char *) &pagedir1,
+ (char *) &toi_header->pagedir, sizeof(pagedir1));
+ toi_result = toi_header->param0;
-+ toi_bkd.toi_action = toi_header->param1;
-+ toi_bkd.toi_debug_state = toi_header->param2;
-+ toi_bkd.toi_default_console_level = toi_header->param3;
++ if (!toi_bkd.toi_debug_state) {
++ toi_bkd.toi_action = toi_header->param1;
++ toi_bkd.toi_debug_state = toi_header->param2;
++ toi_bkd.toi_default_console_level = toi_header->param3;
++ }
+ clear_toi_state(TOI_IGNORE_LOGLEVEL);
+ pagedir2.size = toi_header->pageset_2_size;
+ for (i = 0; i < 4; i++)
+ toi_cond_pause(1, "About to read original pageset1 locations.");
+
+ /*
-+ * See _toi_rw_header_chunk in tuxonice_block_io.c:
++ * See _toi_rw_header_chunk in tuxonice_bio.c:
+ * Initialize pageset1_map by reading the map from the image.
+ */
+ if (memory_bm_read(pageset1_map, toiActiveAllocator->rw_header_chunk))
+ goto out_thaw;
+
+ /*
-+ * See toi_rw_cleanup in tuxonice_block_io.c:
++ * See toi_rw_cleanup in tuxonice_bio.c:
+ * Clean up after reading the header.
+ */
+ result = toiActiveAllocator->read_header_cleanup();
+
+out_thaw:
+ wait_event(freeze_wait, freeze_result != FREEZE_IN_PROGRESS);
++ trap_non_toi_io = 0;
+ thaw_processes();
+ usermodehelper_enable();
+out_enable_nonboot_cpus:
+extern int toi_bio_queue_flusher_should_finish;
diff --git a/kernel/power/tuxonice_modules.c b/kernel/power/tuxonice_modules.c
new file mode 100644
-index 0000000..c650f5c
+index 0000000..6599405
--- /dev/null
+++ b/kernel/power/tuxonice_modules.c
-@@ -0,0 +1,494 @@
+@@ -0,0 +1,492 @@
+/*
+ * kernel/power/tuxonice_modules.c
+ *
+
+LIST_HEAD(toi_filters);
+LIST_HEAD(toiAllocators);
++
+LIST_HEAD(toi_modules);
++EXPORT_SYMBOL_GPL(toi_modules);
+
+struct toi_module_ops *toiActiveAllocator;
+EXPORT_SYMBOL_GPL(toiActiveAllocator);
+ break;
+ case MISC_MODULE:
+ case MISC_HIDDEN_MODULE:
++ case BIO_ALLOCATOR_MODULE:
+ break;
+ default:
+ printk(KERN_ERR "Hmmm. Module '%s' has an invalid type."
+ break;
+ case MISC_MODULE:
+ case MISC_HIDDEN_MODULE:
++ case BIO_ALLOCATOR_MODULE:
+ break;
+ default:
+ printk(KERN_ERR "Module '%s' has an invalid type."
+ break;
+ case MISC_MODULE:
+ case MISC_HIDDEN_MODULE:
++ case BIO_ALLOCATOR_MODULE:
+ break;
+ default:
+ printk(KERN_ERR "Module '%s' has an invalid type."
+ if (this_module->early != early)
+ continue;
+ if (this_module->initialise) {
-+ toi_message(TOI_MEMORY, TOI_MEDIUM, 1,
-+ "Initialising module %s.\n",
-+ this_module->name);
+ result = this_module->initialise(starting_cycle);
+ if (result) {
+ toi_cleanup_modules(starting_cycle);
+ list_for_each_entry(this_module, &toi_modules, module_list) {
+ if (!this_module->enabled || !this_module->initialised)
+ continue;
-+ if (this_module->cleanup) {
-+ toi_message(TOI_MEMORY, TOI_MEDIUM, 1,
-+ "Cleaning up module %s.\n",
-+ this_module->name);
++ if (this_module->cleanup)
+ this_module->cleanup(finishing_cycle);
-+ }
+ this_module->initialised = 0;
+ }
+}
+}
diff --git a/kernel/power/tuxonice_modules.h b/kernel/power/tuxonice_modules.h
new file mode 100644
-index 0000000..d81087c
+index 0000000..5023ae9
--- /dev/null
+++ b/kernel/power/tuxonice_modules.h
-@@ -0,0 +1,181 @@
+@@ -0,0 +1,186 @@
+/*
+ * kernel/power/tuxonice_modules.h
+ *
+enum {
+ FILTER_MODULE,
+ WRITER_MODULE,
-+ MISC_MODULE, /* Block writer, eg. */
++ BIO_ALLOCATOR_MODULE,
++ MISC_MODULE,
+ MISC_HIDDEN_MODULE,
+};
+
+
+ unsigned long (*storage_available) (void);
+ void (*reserve_header_space) (unsigned long space_requested);
++ int (*register_storage) (void);
+ int (*allocate_storage) (unsigned long space_requested);
+ unsigned long (*storage_allocated) (void);
+
+ /* Sysfs Data */
+ struct toi_sysfs_data *sysfs_data;
+ int num_sysfs_entries;
++
++ /* Block I/O allocator */
++ struct toi_bio_allocator_ops *bio_allocator_ops;
+};
+
+extern int toi_num_modules, toiNumAllocators;
+#endif
diff --git a/kernel/power/tuxonice_power_off.c b/kernel/power/tuxonice_power_off.c
new file mode 100644
-index 0000000..9cdb489
+index 0000000..63bb90b
--- /dev/null
+++ b/kernel/power/tuxonice_power_off.c
-@@ -0,0 +1,282 @@
+@@ -0,0 +1,285 @@
+/*
+ * kernel/power/tuxonice_power_off.c
+ *
+ panic("Attempt to reload pagedir 2 failed. "
+ "Try rebooting.");
+
++ pm_prepare_console();
++
+ error = pm_notifier_call_chain(PM_SUSPEND_PREPARE);
+ if (!error) {
+ error = suspend_devices_and_enter(PM_SUSPEND_MEM);
+ did_suspend_to_both = 1;
+ }
+ pm_notifier_call_chain(PM_POST_SUSPEND);
++ pm_restore_console();
+
+ /* Success - we're now post-resume-from-ram */
+ if (did_suspend_to_both)
+extern void platform_restore_cleanup(int platform_mode);
diff --git a/kernel/power/tuxonice_prepare_image.c b/kernel/power/tuxonice_prepare_image.c
new file mode 100644
-index 0000000..7f1d76c
+index 0000000..2626c0f
--- /dev/null
+++ b/kernel/power/tuxonice_prepare_image.c
-@@ -0,0 +1,1076 @@
+@@ -0,0 +1,1079 @@
+/*
+ * kernel/power/tuxonice_prepare_image.c
+ *
+#include "tuxonice_modules.h"
+#include "tuxonice_io.h"
+#include "tuxonice_ui.h"
-+#include "tuxonice_extent.h"
+#include "tuxonice_prepare_image.h"
+#include "tuxonice.h"
++#include "tuxonice_extent.h"
+#include "tuxonice_checksum.h"
+#include "tuxonice_sysfs.h"
+#include "tuxonice_alloc.h"
+
+static unsigned long num_nosave, main_storage_allocated, storage_limit,
+ header_storage_needed;
-+unsigned long extra_pd1_pages_allowance = CONFIG_TOI_DEFAULT_EXTRA_PAGES_ALLOWANCE;
-+int image_size_limit;
++unsigned long extra_pd1_pages_allowance =
++ CONFIG_TOI_DEFAULT_EXTRA_PAGES_ALLOWANCE;
++long image_size_limit;
+static int no_ps2_needed;
+
+struct attention_list {
+ int use_soft_limit = use_image_size_limit && image_size_limit > 0;
+ unsigned long current_size = current_image_size(),
+ soft_limit = use_soft_limit ? (image_size_limit << 8) : 0,
++ to_free = use_soft_limit ? (current_size > soft_limit ?
++ current_size - soft_limit : 0) : 0,
+ storage_limit = storage_still_required(),
+ ram_limit = ram_still_required(),
-+ first_max = max(soft_limit, storage_limit);
++ first_max = max(to_free, storage_limit);
+
-+ printk("Use soft limit is %d. Current size is %lu. Soft limit is %lu. Ram limit %lu. First max %lu.\n",
-+ use_soft_limit, current_size, soft_limit, ram_limit, first_max);
+ return max(first_max, ram_limit);
+}
+
+static int image_not_ready(int use_image_size_limit)
+{
+ toi_message(TOI_EAT_MEMORY, TOI_LOW, 1,
-+ "Amount still needed (%ld) > 0:%d,"
-+ " Storage allocd: %ld < %ld: %d.\n",
++ "Amount still needed (%lu) > 0:%u,"
++ " Storage allocd: %lu < %lu: %u.\n",
+ amount_needed(use_image_size_limit),
+ (amount_needed(use_image_size_limit) > 0),
+ main_storage_allocated,
+{
+ char buffer[255];
+ snprintf(buffer, 254,
-+ "Free:%ld(%ld). Sets:%ld(%ld),%ld(%ld). "
-+ "Nosave:%ld-%ld=%ld. Storage:%lu/%lu(%lu=>%lu). "
-+ "Needed:%ld,%ld,%ld(%d,%ld,%ld,%ld) (PS2:%s)\n",
++ "Free:%lu(%lu). Sets:%lu(%lu),%lu(%lu). "
++ "Nosave:%lu-%lu=%lu. Storage:%lu/%lu(%lu=>%lu). "
++ "Needed:%lu,%lu,%lu(%u,%lu,%lu,%ld) (PS2:%s)\n",
+
+ /* Free */
+ real_nr_free_pages(all_zones_mask),
+ any_to_free(1),
+ MIN_FREE_RAM, toi_memory_for_modules(0),
+ extra_pd1_pages_allowance,
-+ ((unsigned long) image_size_limit) << 8,
++ image_size_limit,
+
+ need_pageset2() ? "yes" : "no");
+
+ struct per_cpu_pageset *pset = zone_pcp(zone, cpu);
+ struct per_cpu_pages *pcp = &pset->pcp;
+ struct page *page;
++ int t;
+
-+ list_for_each_entry(page, &pcp->list, lru)
-+ SetPageNosaveFree(page);
++ for (t = 0; t < MIGRATE_PCPTYPES; t++)
++ list_for_each_entry(page, &pcp->lists[t], lru)
++ SetPageNosaveFree(page);
+ }
+
+ spin_unlock_irqrestore(&zone->lock, flags);
+ storage_limit = toiActiveAllocator->storage_available();
+ seek = min(storage_limit, main_storage_needed(0, 0));
+
-+ //toiActiveAllocator->allocate_storage(seek);
-+ result = toiActiveAllocator->allocate_storage(storage_limit);
++ result = toiActiveAllocator->allocate_storage(seek);
+ if (result)
+ printk("Failed to allocate storage (%d).\n", result);
+
+
+ amount_wanted = amount_needed(1);
+
-+ printk("Asked shrink_all_memory for %ld pages, got %ld.\n",
-+ request, request - amount_wanted);
++ printk(KERN_DEBUG "Asked shrink_all_memory for %ld pages,"
++ "got %ld.\n", request,
++ request - amount_wanted);
+
+ toi_cond_pause(0, NULL);
+
+}
diff --git a/kernel/power/tuxonice_prepare_image.h b/kernel/power/tuxonice_prepare_image.h
new file mode 100644
-index 0000000..35ddadf
+index 0000000..fc4ed05
--- /dev/null
+++ b/kernel/power/tuxonice_prepare_image.h
@@ -0,0 +1,36 @@
+extern int toi_prepare_image(void);
+extern void toi_recalculate_image_contents(int storage_available);
+extern unsigned long real_nr_free_pages(unsigned long zone_idx_mask);
-+extern int image_size_limit;
++extern long image_size_limit;
+extern void toi_free_extra_pagedir_memory(void);
+extern unsigned long extra_pd1_pages_allowance;
+extern void free_attention_list(void);
+};
diff --git a/kernel/power/tuxonice_swap.c b/kernel/power/tuxonice_swap.c
new file mode 100644
-index 0000000..10e6280
+index 0000000..30890aa
--- /dev/null
+++ b/kernel/power/tuxonice_swap.c
-@@ -0,0 +1,1351 @@
+@@ -0,0 +1,478 @@
+/*
+ * kernel/power/tuxonice_swap.c
+ *
+#include <linux/swapops.h>
+#include <linux/swap.h>
+#include <linux/syscalls.h>
-+#include <scsi/scsi_scan.h>
++#include <linux/uuid.h>
+
+#include "tuxonice.h"
+#include "tuxonice_sysfs.h"
+#include "tuxonice_io.h"
+#include "tuxonice_ui.h"
+#include "tuxonice_extent.h"
-+#include "tuxonice_block_io.h"
++#include "tuxonice_bio.h"
+#include "tuxonice_alloc.h"
+#include "tuxonice_builtin.h"
+
+static struct toi_module_ops toi_swapops;
+
-+/* --- Struct of pages stored on disk */
-+
-+struct sig_data {
-+ dev_t device;
-+ unsigned long sector;
-+ int resume_attempted;
-+ int orig_sig_type;
-+};
-+
-+union diskpage {
-+ union swap_header swh; /* swh.magic is the only member used */
-+ struct sig_data sig_data;
-+};
-+
-+union p_diskpage {
-+ union diskpage *pointer;
-+ char *ptr;
-+ unsigned long address;
-+};
-+
-+enum {
-+ IMAGE_SIGNATURE,
-+ NO_IMAGE_SIGNATURE,
-+ TRIED_RESUME,
-+ NO_TRIED_RESUME,
-+};
-+
-+/*
-+ * Both of these point to versions of the swap header page. original_sig points
-+ * to the data we read from disk at the start of hibernating or checking whether
-+ * to resume. no_image is the page stored in the image header, showing what the
-+ * swap header page looked like at the start of hibernating.
-+ */
-+static char *current_signature_page;
-+static char no_image_signature_contents[sizeof(struct sig_data)];
-+
-+/* Devices used for swap */
-+static struct toi_bdev_info devinfo[MAX_SWAPFILES];
-+
-+/* Extent chains for swap & blocks */
-+static struct hibernate_extent_chain swapextents;
-+static struct hibernate_extent_chain block_chain[MAX_SWAPFILES];
-+
-+static dev_t header_dev_t;
-+static struct block_device *header_block_device;
-+static unsigned long headerblock;
-+
-+/* For swapfile automatically swapon/off'd. */
-+static char swapfilename[32] = "";
-+static int toi_swapon_status;
-+
-+/* Header Page Information */
-+static unsigned long header_pages_reserved;
-+
-+/* Swap Pages */
-+static unsigned long swap_pages_allocated;
-+
-+/* User Specified Parameters. */
-+
-+static unsigned long resume_firstblock;
-+static dev_t resume_swap_dev_t;
-+static struct block_device *resume_block_device;
-+
-+static struct sysinfo swapinfo;
-+
-+/* Block devices open. */
-+struct bdev_opened {
-+ dev_t device;
-+ struct block_device *bdev;
-+};
-+
-+/*
-+ * Entry MAX_SWAPFILES is the resume block device, which may
-+ * be a swap device not enabled when we hibernate.
-+ * Entry MAX_SWAPFILES + 1 is the header block device, which
-+ * is needed before we find out which slot it occupies.
-+ *
-+ * We use a separate struct to devInfo so that we can track
-+ * the bdevs we open, because if we need to abort resuming
-+ * prior to the atomic restore, they need to be closed, but
-+ * closing them after sucessfully resuming would be wrong.
-+ */
-+static struct bdev_opened *bdevs_opened[MAX_SWAPFILES + 2];
-+
-+/**
-+ * close_bdev: Close a swap bdev.
-+ *
-+ * int: The swap entry number to close.
-+ */
-+static void close_bdev(int i)
-+{
-+ struct bdev_opened *this = bdevs_opened[i];
-+
-+ if (!this)
-+ return;
-+
-+ blkdev_put(this->bdev, FMODE_READ | FMODE_NDELAY);
-+ toi_kfree(8, this, sizeof(*this));
-+ bdevs_opened[i] = NULL;
-+}
-+
-+/**
-+ * close_bdevs: Close all bdevs we opened.
-+ *
-+ * Close all bdevs that we opened and reset the related vars.
-+ */
-+static void close_bdevs(void)
-+{
-+ int i;
-+
-+ for (i = 0; i < MAX_SWAPFILES + 2; i++)
-+ close_bdev(i);
-+
-+ resume_block_device = NULL;
-+ header_block_device = NULL;
-+}
-+
-+/**
-+ * open_bdev: Open a bdev at resume time.
-+ *
-+ * index: The swap index. May be MAX_SWAPFILES for the resume_dev_t
-+ * (the user can have resume= pointing at a swap partition/file that isn't
-+ * swapon'd when they hibernate. MAX_SWAPFILES+1 for the first page of the
-+ * header. It will be from a swap partition that was enabled when we hibernated,
-+ * but we don't know it's real index until we read that first page.
-+ * dev_t: The device major/minor.
-+ * display_errs: Whether to try to do this quietly.
-+ *
-+ * We stored a dev_t in the image header. Open the matching device without
-+ * requiring /dev/<whatever> in most cases and record the details needed
-+ * to close it later and avoid duplicating work.
-+ */
-+static struct block_device *open_bdev(int index, dev_t device, int display_errs)
-+{
-+ struct bdev_opened *this;
-+ struct block_device *bdev;
-+
-+ if (bdevs_opened[index]) {
-+ if (bdevs_opened[index]->device == device)
-+ return bdevs_opened[index]->bdev;
-+
-+ close_bdev(index);
-+ }
-+
-+ bdev = toi_open_by_devnum(device, FMODE_READ | FMODE_NDELAY);
-+
-+ if (IS_ERR(bdev) || !bdev) {
-+ if (display_errs)
-+ toi_early_boot_message(1, TOI_CONTINUE_REQ,
-+ "Failed to get access to block device "
-+ "\"%x\" (error %d).\n Maybe you need "
-+ "to run mknod and/or lvmsetup in an "
-+ "initrd/ramfs?", device, bdev);
-+ return ERR_PTR(-EINVAL);
-+ }
-+
-+ this = toi_kzalloc(8, sizeof(struct bdev_opened), GFP_KERNEL);
-+ if (!this) {
-+ printk(KERN_WARNING "TuxOnIce: Failed to allocate memory for "
-+ "opening a bdev.");
-+ blkdev_put(bdev, FMODE_READ | FMODE_NDELAY);
-+ return ERR_PTR(-ENOMEM);
-+ }
-+
-+ bdevs_opened[index] = this;
-+ this->device = device;
-+ this->bdev = bdev;
-+
-+ return bdev;
-+}
-+
-+/**
-+ * enable_swapfile: Swapon the user specified swapfile prior to hibernating.
-+ *
-+ * Activate the given swapfile if it wasn't already enabled. Remember whether
-+ * we really did swapon it for swapoffing later.
-+ */
-+static void enable_swapfile(void)
-+{
-+ int activateswapresult = -EINVAL;
-+
-+ if (swapfilename[0]) {
-+ /* Attempt to swap on with maximum priority */
-+ activateswapresult = sys_swapon(swapfilename, 0xFFFF);
-+ if (activateswapresult && activateswapresult != -EBUSY)
-+ printk("TuxOnIce: The swapfile/partition specified by "
-+ "/sys/power/tuxonice/swap/swapfile "
-+ "(%s) could not be turned on (error %d). "
-+ "Attempting to continue.\n",
-+ swapfilename, activateswapresult);
-+ if (!activateswapresult)
-+ toi_swapon_status = 1;
-+ }
-+}
-+
-+/**
-+ * disable_swapfile: Swapoff any file swaponed at the start of the cycle.
-+ *
-+ * If we did successfully swapon a file at the start of the cycle, swapoff
-+ * it now (finishing up).
-+ */
-+static void disable_swapfile(void)
-+{
-+ if (!toi_swapon_status)
-+ return;
-+
-+ sys_swapoff(swapfilename);
-+ toi_swapon_status = 0;
-+}
-+
-+/**
-+ * try_to_parse_resume_device: Try to parse resume=
-+ *
-+ * Any "swap:" has been stripped away and we just have the path to deal with.
-+ * We attempt to do name_to_dev_t, open and stat the file. Having opened the
-+ * file, get the struct block_device * to match.
-+ */
-+static int try_to_parse_resume_device(char *commandline, int quiet)
-+{
-+ struct kstat stat;
-+ int error = 0;
-+
-+ resume_swap_dev_t = name_to_dev_t(commandline);
-+ if (!resume_swap_dev_t) {
-+ wait_for_device_probe();
-+ scsi_complete_async_scans();
-+ resume_swap_dev_t = name_to_dev_t(commandline);
-+ }
-+
-+ if (!resume_swap_dev_t) {
-+ struct file *file = filp_open(commandline,
-+ O_RDONLY|O_LARGEFILE, 0);
-+
-+ if (!IS_ERR(file) && file) {
-+ vfs_getattr(file->f_vfsmnt, file->f_dentry, &stat);
-+ filp_close(file, NULL);
-+ } else
-+ error = vfs_stat(commandline, &stat);
-+ if (!error)
-+ resume_swap_dev_t = stat.rdev;
-+ }
-+
-+ if (!resume_swap_dev_t) {
-+ if (quiet)
-+ return 1;
-+
-+ if (test_toi_state(TOI_TRYING_TO_RESUME))
-+ toi_early_boot_message(1, toi_translate_err_default,
-+ "Failed to translate \"%s\" into a device id.\n",
-+ commandline);
-+ else
-+ printk("TuxOnIce: Can't translate \"%s\" into a device "
-+ "id yet.\n", commandline);
-+ return 1;
-+ }
-+
-+ resume_block_device = open_bdev(MAX_SWAPFILES, resume_swap_dev_t, 0);
-+ if (IS_ERR(resume_block_device)) {
-+ if (!quiet)
-+ toi_early_boot_message(1, TOI_CONTINUE_REQ,
-+ "Failed to get access to \"%s\", where"
-+ " the swap header should be found.",
-+ commandline);
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * If we have read part of the image, we might have filled memory with
-+ * data that should be zeroed out.
-+ */
-+static void toi_swap_noresume_reset(void)
-+{
-+ toi_bio_ops.rw_cleanup(READ);
-+ memset((char *) &devinfo, 0, sizeof(devinfo));
-+}
-+
-+static int get_current_signature(void)
-+{
-+ if (!current_signature_page) {
-+ current_signature_page = (char *) toi_get_zeroed_page(38,
-+ TOI_ATOMIC_GFP);
-+ if (!current_signature_page)
-+ return -ENOMEM;
-+ }
-+
-+ return toi_bio_ops.bdev_page_io(READ, resume_block_device,
-+ resume_firstblock, virt_to_page(current_signature_page));
-+}
-+
-+static int parse_signature(void)
-+{
-+ union p_diskpage swap_header_page;
-+ struct sig_data *sig;
-+ int type;
-+ char *swap_header;
-+ const char *sigs[] = {
-+ "SWAP-SPACE", "SWAPSPACE2", "S1SUSP", "S2SUSP", "S1SUSPEND"
-+ };
-+
-+ int result = get_current_signature();
-+ if (result)
-+ return result;
-+
-+ swap_header_page = (union p_diskpage) current_signature_page;
-+ sig = (struct sig_data *) current_signature_page;
-+ swap_header = swap_header_page.pointer->swh.magic.magic;
-+
-+ for (type = 0; type < 5; type++)
-+ if (!memcmp(sigs[type], swap_header, strlen(sigs[type])))
-+ return type;
-+
-+ if (memcmp(tuxonice_signature, swap_header, sizeof(tuxonice_signature)))
-+ return -1;
-+
-+ header_dev_t = sig->device;
-+ clear_toi_state(TOI_RESUMED_BEFORE);
-+ if (sig->resume_attempted)
-+ set_toi_state(TOI_RESUMED_BEFORE);
-+ headerblock = sig->sector;
-+
-+ return 10;
-+}
-+
-+static void forget_signatures(void)
-+{
-+ if (current_signature_page) {
-+ toi_free_page(38, (unsigned long) current_signature_page);
-+ current_signature_page = NULL;
-+ }
-+}
-+
-+/*
-+ * write_modified_signature
-+ *
-+ * Write a (potentially) modified signature page without forgetting the
-+ * original contents.
-+ */
-+static int write_modified_signature(int modification)
-+{
-+ union p_diskpage swap_header_page;
-+ struct swap_info_struct *si;
-+ int result;
-+ char *orig_sig;
-+
-+ /* In case we haven't already */
-+ result = get_current_signature();
-+
-+ if (result)
-+ return result;
-+
-+ swap_header_page.address = toi_get_zeroed_page(38, TOI_ATOMIC_GFP);
-+
-+ if (!swap_header_page.address)
-+ return -ENOMEM;
-+
-+ memcpy(swap_header_page.ptr, current_signature_page, PAGE_SIZE);
-+
-+ switch (modification) {
-+ case IMAGE_SIGNATURE:
-+
-+ memcpy(no_image_signature_contents, swap_header_page.ptr,
-+ sizeof(no_image_signature_contents));
-+
-+ /* Get the details of the header first page. */
-+ toi_extent_state_goto_start(&toi_writer_posn);
-+ toi_bio_ops.forward_one_page(1, 1);
-+
-+ si = get_swap_info_struct(toi_writer_posn.current_chain);
-+
-+ /* Prepare the signature */
-+ swap_header_page.pointer->sig_data.device = si->bdev->bd_dev;
-+ swap_header_page.pointer->sig_data.sector =
-+ toi_writer_posn.current_offset;
-+ swap_header_page.pointer->sig_data.resume_attempted = 0;
-+ swap_header_page.pointer->sig_data.orig_sig_type =
-+ parse_signature();
-+
-+ memcpy(swap_header_page.pointer->swh.magic.magic,
-+ tuxonice_signature, sizeof(tuxonice_signature));
-+
-+ break;
-+ case NO_IMAGE_SIGNATURE:
-+ if (!swap_header_page.pointer->sig_data.orig_sig_type)
-+ orig_sig = "SWAP-SPACE";
-+ else
-+ orig_sig = "SWAPSPACE2";
-+
-+ memcpy(swap_header_page.pointer->swh.magic.magic, orig_sig, 10);
-+ memcpy(swap_header_page.ptr, no_image_signature_contents,
-+ sizeof(no_image_signature_contents));
-+ break;
-+ case TRIED_RESUME:
-+ swap_header_page.pointer->sig_data.resume_attempted = 1;
-+ break;
-+ case NO_TRIED_RESUME:
-+ swap_header_page.pointer->sig_data.resume_attempted = 0;
-+ break;
-+ }
-+
-+ result = toi_bio_ops.bdev_page_io(WRITE, resume_block_device,
-+ resume_firstblock, virt_to_page(swap_header_page.address));
-+
-+ memcpy(current_signature_page, swap_header_page.ptr, PAGE_SIZE);
++/* For swapfile automatically swapon/off'd. */
++static char swapfilename[255] = "";
++static int toi_swapon_status;
+
-+ toi_free_page(38, swap_header_page.address);
++/* Swap Pages */
++static unsigned long swap_allocated;
+
-+ return result;
-+}
++static struct sysinfo swapinfo;
+
-+/*
-+ * apply_header_reservation
++/**
++ * enable_swapfile: Swapon the user specified swapfile prior to hibernating.
++ *
++ * Activate the given swapfile if it wasn't already enabled. Remember whether
++ * we really did swapon it for swapoffing later.
+ */
-+static int apply_header_reservation(void)
++static void enable_swapfile(void)
+{
-+ unsigned long i;
-+
-+ toi_extent_state_goto_start(&toi_writer_posn);
-+
-+ printk("Applying header reservation for %lu pages.\n",
-+ header_pages_reserved);
-+
-+ if (!header_pages_reserved)
-+ return 0;
-+
-+ for (i = 0; i < header_pages_reserved; i++)
-+ if (toi_bio_ops.forward_one_page(1, 0)) {
-+ printk("Failed to advance to page %lu in reserving "
-+ "space for the header.\n", i);
-+ return -ENOSPC;
-+ }
-+
-+ /* The end of header pages will be the start of pageset 2;
-+ * we are now sitting on the first pageset2 page. */
-+ toi_extent_state_save(&toi_writer_posn, &toi_writer_posn_save[2]);
-+ printk("Done.\n");
-+ return 0;
-+}
++ int activateswapresult = -EINVAL;
+
-+static void toi_swap_reserve_header_space(unsigned long request)
-+{
-+ header_pages_reserved = request;
++ if (swapfilename[0]) {
++ /* Attempt to swap on with maximum priority */
++ activateswapresult = sys_swapon(swapfilename, 0xFFFF);
++ if (activateswapresult && activateswapresult != -EBUSY)
++ printk(KERN_ERR "TuxOnIce: The swapfile/partition "
++ "specified by /sys/power/tuxonice/swap/swapfile"
++ " (%s) could not be turned on (error %d). "
++ "Attempting to continue.\n",
++ swapfilename, activateswapresult);
++ if (!activateswapresult)
++ toi_swapon_status = 1;
++ }
+}
+
-+static void free_block_chains(void)
++/**
++ * disable_swapfile: Swapoff any file swaponed at the start of the cycle.
++ *
++ * If we did successfully swapon a file at the start of the cycle, swapoff
++ * it now (finishing up).
++ */
++static void disable_swapfile(void)
+{
-+ int i;
++ if (!toi_swapon_status)
++ return;
+
-+ for (i = 0; i < MAX_SWAPFILES; i++)
-+ if (block_chain[i].first)
-+ toi_put_extent_chain(&block_chain[i]);
++ sys_swapoff(swapfilename);
++ toi_swapon_status = 0;
+}
+
-+static int add_blocks_to_extent_chain(int chain, unsigned long start, unsigned long end)
++static int add_blocks_to_extent_chain(struct toi_bdev_info *chain,
++ unsigned long start, unsigned long end)
+{
+ if (test_action_state(TOI_TEST_BIO))
-+ printk(KERN_INFO "Adding extent chain %d %lu-%lu.\n", chain,
-+ start << devinfo[chain].bmap_shift,
-+ end << devinfo[chain].bmap_shift);
-+
-+ if (toi_add_to_extent_chain(&block_chain[chain], start, end)) {
-+ free_block_chains();
-+ return -ENOMEM;
-+ }
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Adding extent %lu-%lu to "
++ "chain %p.", start << chain->bmap_shift,
++ end << chain->bmap_shift, chain);
+
-+ return 0;
++ return toi_add_to_extent_chain(&chain->blocks, start, end);
+}
+
+
-+static int get_main_pool_phys_params(void)
++static int get_main_pool_phys_params(struct toi_bdev_info *chain)
+{
+ struct hibernate_extent *extentpointer = NULL;
+ unsigned long address, extent_min = 0, extent_max = 0;
-+ int last_chain = -1;
++ int empty = 1;
++
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "get main pool phys params for "
++ "chain %d.", chain->allocator_index);
++
++ if (!chain->allocations.first)
++ return 0;
+
-+ free_block_chains();
++ if (chain->blocks.first)
++ toi_put_extent_chain(&chain->blocks);
+
-+ toi_extent_for_each(&swapextents, extentpointer, address) {
++ toi_extent_for_each(&chain->allocations, extentpointer, address) {
+ swp_entry_t swap_address = (swp_entry_t) { address };
+ pgoff_t offset = swp_offset(swap_address);
+ unsigned swapfilenum = swp_type(swap_address);
+ get_swap_info_struct(swapfilenum);
+ sector_t new_sector = map_swap_page(sis, offset);
+
-+ if (devinfo[swapfilenum].ignored)
++ if (empty) {
++ empty = 0;
++ extent_min = extent_max = new_sector;
+ continue;
++ }
+
-+ if (last_chain >= 0 && new_sector == extent_max + 1 &&
-+ last_chain == swapfilenum) {
++ if (new_sector == extent_max + 1) {
+ extent_max++;
+ continue;
+ }
+
-+ if (last_chain >= 0 && add_blocks_to_extent_chain(last_chain,
-+ extent_min, extent_max)) {
++ if (add_blocks_to_extent_chain(chain, extent_min, extent_max)) {
+ printk(KERN_ERR "Out of memory while making block "
+ "chains.\n");
+ return -ENOMEM;
+
+ extent_min = new_sector;
+ extent_max = new_sector;
-+ last_chain = swapfilenum;
+ }
+
-+ if (last_chain > -1 && add_blocks_to_extent_chain(last_chain,
-+ extent_min, extent_max)) {
++ if (!empty &&
++ add_blocks_to_extent_chain(chain, extent_min, extent_max)) {
+ printk(KERN_ERR "Out of memory while making block chains.\n");
+ return -ENOMEM;
+ }
+
-+ return apply_header_reservation();
-+}
-+
-+static unsigned long raw_to_real(unsigned long raw)
-+{
-+ unsigned long result;
-+
-+ result = raw - (raw * (sizeof(unsigned long) + sizeof(int)) +
-+ (PAGE_SIZE + sizeof(unsigned long) + sizeof(int) + 1)) /
-+ (PAGE_SIZE + sizeof(unsigned long) + sizeof(int));
-+
-+ return result < 0 ? 0 : result;
-+}
-+
-+static unsigned long toi_swap_storage_allocated(void)
-+{
-+ return raw_to_real(swap_pages_allocated - header_pages_reserved);
++ return 0;
+}
+
+/*
+
+ for (i = 0; i < MAX_SWAPFILES; i++) {
+ struct swap_info_struct *si = get_swap_info_struct(i);
-+ if ((si->flags & SWP_USED) && si->swap_map &&
-+ (si->flags & SWP_WRITEOK) &&
++ if ((si->flags & SWP_WRITEOK) &&
+ (strncmp(si->bdev->bd_disk->disk_name, "ram", 3))) {
+ val->totalswap += si->inuse_pages;
+ val->freeswap += si->pages - si->inuse_pages;
+ */
+static unsigned long toi_swap_storage_available(void)
+{
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "In toi_swap_storage_available.");
+ si_swapinfo_no_compcache(&swapinfo);
-+ return raw_to_real(swapinfo.freeswap +
-+ swap_pages_allocated - header_pages_reserved);
++ return swapinfo.freeswap + swap_allocated;
+}
+
+static int toi_swap_initialise(int starting_cycle)
+{
-+ int result = 0;
-+
+ if (!starting_cycle)
+ return 0;
+
+ enable_swapfile();
-+
-+ if (resume_swap_dev_t && !resume_block_device) {
-+ resume_block_device = open_bdev(MAX_SWAPFILES,
-+ resume_swap_dev_t, 1);
-+ if (IS_ERR(resume_block_device))
-+ result = 1;
-+ }
-+
-+ return result;
++ return 0;
+}
+
+static void toi_swap_cleanup(int ending_cycle)
+{
+ if (ending_cycle)
+ disable_swapfile();
++}
+
-+ close_bdevs();
-+
-+ forget_signatures();
-+}
-+
-+static int toi_swap_release_storage(void)
-+{
-+ header_pages_reserved = 0;
-+ swap_pages_allocated = 0;
-+
-+ if (swapextents.first) {
-+ /* Free swap entries */
-+ struct hibernate_extent *extentpointer;
-+ unsigned long extentvalue;
-+ toi_extent_for_each(&swapextents, extentpointer,
-+ extentvalue)
-+ swap_free((swp_entry_t) { extentvalue });
-+
-+ toi_put_extent_chain(&swapextents);
-+
-+ free_block_chains();
-+ }
-+
-+ return 0;
-+}
-+
-+static void free_swap_range(unsigned long min, unsigned long max)
-+{
-+ int j;
-+
-+ for (j = min; j <= max; j++)
-+ swap_free((swp_entry_t) { j });
-+}
-+
-+/*
-+ * Round robin allocation (where swap storage has the same priority).
-+ * could make this very inefficient, so we track extents allocated on
-+ * a per-swapfile basis.
-+ */
-+static int toi_swap_allocate_storage(unsigned long request)
-+{
-+ int i, result = 0, to_add = 0;
-+ unsigned long pages_to_get, extra_pages, gotten = 0, result2, needed;
-+ unsigned long extent_min = 0, extent_max = 0;
-+ unsigned swapfilenum = MAX_SWAPFILES;
-+
-+ extra_pages = DIV_ROUND_UP(request * (sizeof(unsigned long)
-+ + sizeof(int)), PAGE_SIZE);
-+ needed = request + extra_pages + header_pages_reserved;
-+
-+ pages_to_get = needed > swapextents.size ?
-+ needed - swapextents.size : 0;
-+
-+ printk("Swap allocate storage: Request was %lu pages. Extra pages is %lu,"
-+ "swapextents size is %lu. Header pages reserved is %lu.\n", request,
-+ extra_pages, swapextents.size, header_pages_reserved);
-+
-+ if (pages_to_get < 1)
-+ return apply_header_reservation();
-+
-+ for (i = 0; i < MAX_SWAPFILES; i++) {
-+ struct swap_info_struct *si = get_swap_info_struct(i);
-+ devinfo[i].ignored = 1;
-+ if (!(si->flags & SWP_USED) || !si->swap_map ||
-+ !(si->flags & SWP_WRITEOK))
-+ continue;
-+ if (!strncmp(si->bdev->bd_disk->disk_name, "ram", 3)) {
-+ continue;
-+ }
-+ devinfo[i].ignored = 0;
-+ devinfo[i].bdev = si->bdev;
-+ devinfo[i].dev_t = si->bdev->bd_dev;
-+ devinfo[i].bmap_shift = 3;
-+ devinfo[i].blocks_per_page = 1;
-+ if (swapfilenum == MAX_SWAPFILES)
-+ swapfilenum = i;
-+ }
-+
-+ if (swapfilenum == MAX_SWAPFILES)
-+ return apply_header_reservation();
-+
-+ while (gotten < pages_to_get) {
-+ swp_entry_t entry;
-+ unsigned long new_value;
-+
-+ entry = get_swap_page_of_type(swapfilenum);
-+ if (!entry.val) {
-+ if (to_add) {
-+ result = toi_add_to_extent_chain(&swapextents,
-+ extent_min, extent_max);
-+ if (result) {
-+ free_swap_range(extent_min, extent_max);
-+ gotten -= (extent_max - extent_min + 1);
-+ break;
-+ }
-+ }
-+ swapfilenum++;
-+ while (swapfilenum < MAX_SWAPFILES &&
-+ devinfo[swapfilenum].ignored)
-+ swapfilenum++;
-+ if (swapfilenum == MAX_SWAPFILES)
-+ break;
-+ }
-+
-+ new_value = entry.val;
-+ gotten++;
-+
-+ if (!to_add) {
-+ to_add = 1;
-+ extent_min = new_value;
-+ extent_max = new_value;
-+ continue;
-+ }
-+
-+ if (new_value == extent_max + 1) {
-+ extent_max++;
-+ continue;
-+ }
-+
-+ if (toi_add_to_extent_chain(&swapextents, extent_min,
-+ extent_max)) {
-+ printk(KERN_INFO "Failed to allocate extent for "
-+ "%lu-%lu.\n", extent_min, extent_max);
-+ free_swap_range(extent_min, extent_max);
-+ swap_free(entry);
-+ gotten -= (extent_max - extent_min);
-+ /* Don't try to add again below */
-+ to_add = 0;
-+ break;
-+ }
-+
-+ extent_min = new_value;
-+ extent_max = new_value;
-+ }
-+
-+ if (to_add) {
-+ int this_result = toi_add_to_extent_chain(&swapextents,
-+ extent_min, extent_max);
-+
-+ if (this_result) {
-+ result = this_result;
-+
-+ free_swap_range(extent_min, extent_max);
-+ gotten -= (extent_max - extent_min + 1);
-+ }
-+ }
-+
-+ if (gotten < pages_to_get) {
-+ printk("Got fewer pages than required "
-+ "(%lu wanted, %lu gotten).\n",
-+ pages_to_get, gotten);
-+ result = -ENOSPC;
-+ }
-+
-+ swap_pages_allocated += (long) gotten;
-+
-+ result2 = get_main_pool_phys_params();
-+
-+ return result ? result : result2;
-+}
-+
-+static int toi_swap_write_header_init(void)
-+{
-+ int i, result;
-+ struct swap_info_struct *si;
-+
-+ toi_bio_ops.rw_init(WRITE, 0);
-+ toi_writer_buffer_posn = 0;
-+
-+ /* Info needed to bootstrap goes at the start of the header.
-+ * First we save the positions and devinfo, including the number
-+ * of header pages. Then we save the structs containing data needed
-+ * for reading the header pages back.
-+ * Note that even if header pages take more than one page, when we
-+ * read back the info, we will have restored the location of the
-+ * next header page by the time we go to use it.
-+ */
-+
-+ result = toi_bio_ops.rw_header_chunk(WRITE, &toi_swapops,
-+ (char *) &no_image_signature_contents,
-+ sizeof(struct sig_data));
-+
-+ if (result)
-+ return result;
-+
-+ /* Forward one page will be done prior to the read */
-+ for (i = 0; i < MAX_SWAPFILES; i++) {
-+ si = get_swap_info_struct(i);
-+ if (si->flags & SWP_USED && si->swap_map &&
-+ si->flags & SWP_WRITEOK)
-+ devinfo[i].dev_t = si->bdev->bd_dev;
-+ else
-+ devinfo[i].dev_t = (dev_t) 0;
-+ }
-+
-+ result = toi_bio_ops.rw_header_chunk(WRITE, &toi_swapops,
-+ (char *) &toi_writer_posn_save,
-+ sizeof(toi_writer_posn_save));
-+
-+ if (result)
-+ return result;
-+
-+ result = toi_bio_ops.rw_header_chunk(WRITE, &toi_swapops,
-+ (char *) &devinfo, sizeof(devinfo));
-+
-+ if (result)
-+ return result;
-+
-+ for (i = 0; i < MAX_SWAPFILES; i++)
-+ toi_serialise_extent_chain(&toi_swapops, &block_chain[i]);
-+
-+ return 0;
-+}
-+
-+static int toi_swap_write_header_cleanup(void)
-+{
-+ int result = toi_bio_ops.write_header_chunk_finish();
-+
-+ /* Set signature to save we have an image */
-+ if (!result)
-+ result = write_modified_signature(IMAGE_SIGNATURE);
-+
-+ return result;
-+}
-+
-+/* ------------------------- HEADER READING ------------------------- */
-+
-+/*
-+ * read_header_init()
-+ *
-+ * Description:
-+ * 1. Attempt to read the device specified with resume=.
-+ * 2. Check the contents of the swap header for our signature.
-+ * 3. Warn, ignore, reset and/or continue as appropriate.
-+ * 4. If continuing, read the toi_swap configuration section
-+ * of the header and set up block device info so we can read
-+ * the rest of the header & image.
-+ *
-+ * Returns:
-+ * May not return if user choose to reboot at a warning.
-+ * -EINVAL if cannot resume at this time. Booting should continue
-+ * normally.
-+ */
-+
-+static int toi_swap_read_header_init(void)
-+{
-+ int i, result = 0;
-+ toi_writer_buffer_posn = 0;
-+
-+ if (!header_dev_t) {
-+ printk(KERN_INFO "read_header_init called when we haven't "
-+ "verified there is an image!\n");
-+ return -EINVAL;
-+ }
-+
-+ /*
-+ * If the header is not on the resume_swap_dev_t, get the resume device
-+ * first.
-+ */
-+ if (header_dev_t != resume_swap_dev_t) {
-+ header_block_device = open_bdev(MAX_SWAPFILES + 1,
-+ header_dev_t, 1);
-+
-+ if (IS_ERR(header_block_device))
-+ return PTR_ERR(header_block_device);
-+ } else
-+ header_block_device = resume_block_device;
-+
-+ toi_bio_ops.read_header_init();
++static void toi_swap_free_storage(struct toi_bdev_info *chain)
++{
++ /* Free swap entries */
++ struct hibernate_extent *extentpointer;
++ unsigned long extentvalue;
+
-+ /*
-+ * Read toi_swap configuration.
-+ * Headerblock size taken into account already.
-+ */
-+ result = toi_bio_ops.bdev_page_io(READ, header_block_device,
-+ headerblock << 3,
-+ virt_to_page((unsigned long) toi_writer_buffer));
-+ if (result)
-+ return result;
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Freeing storage for chain %p.",
++ chain);
+
-+ memcpy(&no_image_signature_contents, toi_writer_buffer,
-+ sizeof(no_image_signature_contents));
++ swap_allocated -= chain->allocations.size;
++ toi_extent_for_each(&chain->allocations, extentpointer, extentvalue)
++ swap_free((swp_entry_t) { extentvalue });
+
-+ toi_writer_buffer_posn = sizeof(no_image_signature_contents);
++ toi_put_extent_chain(&chain->allocations);
++}
+
-+ memcpy(&toi_writer_posn_save, toi_writer_buffer +
-+ toi_writer_buffer_posn, sizeof(toi_writer_posn_save));
++static void free_swap_range(unsigned long min, unsigned long max)
++{
++ int j;
+
-+ toi_writer_buffer_posn += sizeof(toi_writer_posn_save);
++ for (j = min; j <= max; j++)
++ swap_free((swp_entry_t) { j });
++ swap_allocated -= (max - min + 1);
++}
+
-+ memcpy(&devinfo, toi_writer_buffer + toi_writer_buffer_posn,
-+ sizeof(devinfo));
++/*
++ * Allocation of a single swap type. Swap priorities are handled at the higher
++ * level.
++ */
++static int toi_swap_allocate_storage(struct toi_bdev_info *chain,
++ unsigned long request)
++{
++ int to_add = 0;
++ unsigned long gotten = 0;
++ unsigned long extent_min = 0, extent_max = 0;
+
-+ toi_writer_buffer_posn += sizeof(devinfo);
++ toi_message(TOI_IO, TOI_VERBOSE, 0, " Swap allocate storage: Asked to"
++ " allocate %lu pages from device %d.", request,
++ chain->allocator_index);
+
-+ /* Restore device info */
-+ for (i = 0; i < MAX_SWAPFILES; i++) {
-+ dev_t thisdevice = devinfo[i].dev_t;
-+ struct block_device *bdev_result;
++ while (gotten < request) {
++ swp_entry_t entry;
++ unsigned long new_value;
+
-+ devinfo[i].bdev = NULL;
++ entry = get_swap_page_of_type(chain->allocator_index);
++ if (!entry.val)
++ break;
+
-+ if (!thisdevice || devinfo[i].ignored)
-+ continue;
++ swap_allocated++;
++ new_value = entry.val;
++ gotten++;
+
-+ if (thisdevice == resume_swap_dev_t) {
-+ devinfo[i].bdev = resume_block_device;
++ if (!to_add) {
++ to_add = 1;
++ extent_min = new_value;
++ extent_max = new_value;
+ continue;
+ }
+
-+ if (thisdevice == header_dev_t) {
-+ devinfo[i].bdev = header_block_device;
++ if (new_value == extent_max + 1) {
++ extent_max++;
+ continue;
+ }
+
-+ bdev_result = open_bdev(i, thisdevice, 1);
-+ if (IS_ERR(bdev_result))
-+ return PTR_ERR(bdev_result);
-+ devinfo[i].bdev = bdevs_opened[i]->bdev;
++ if (toi_add_to_extent_chain(&chain->allocations, extent_min,
++ extent_max)) {
++ printk(KERN_INFO "Failed to allocate extent for "
++ "%lu-%lu.\n", extent_min, extent_max);
++ free_swap_range(extent_min, extent_max);
++ swap_free(entry);
++ gotten -= (extent_max - extent_min);
++ /* Don't try to add again below */
++ to_add = 0;
++ break;
++ }
++
++ extent_min = new_value;
++ extent_max = new_value;
+ }
+
-+ toi_extent_state_goto_start(&toi_writer_posn);
-+ toi_bio_ops.set_extra_page_forward();
++ if (to_add) {
++ int this_result = toi_add_to_extent_chain(&chain->allocations,
++ extent_min, extent_max);
+
-+ for (i = 0; i < MAX_SWAPFILES && !result; i++)
-+ result = toi_load_extent_chain(&block_chain[i]);
++ if (this_result) {
++ free_swap_range(extent_min, extent_max);
++ gotten -= (extent_max - extent_min + 1);
++ }
++ }
+
-+ return result;
++ toi_message(TOI_IO, TOI_VERBOSE, 0, " Allocated %lu pages.", gotten);
++ return gotten;
+}
+
-+static int toi_swap_read_header_cleanup(void)
++static int toi_swap_register_storage(void)
+{
-+ toi_bio_ops.rw_cleanup(READ);
++ int i, result;
++
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "toi_swap_register_storage.");
++ for (i = 0; i < MAX_SWAPFILES; i++) {
++ struct swap_info_struct *si = get_swap_info_struct(i);
++ struct toi_bdev_info *devinfo;
++ if (!(si->flags & SWP_WRITEOK) ||
++ !strncmp(si->bdev->bd_disk->disk_name, "ram", 3))
++ continue;
++
++ devinfo = toi_kzalloc(39, sizeof(struct toi_bdev_info),
++ GFP_ATOMIC);
++ if (!devinfo) {
++ printk("Failed to allocate devinfo struct for swap "
++ "device %d.\n", i);
++ return -ENOMEM;
++ }
++
++ devinfo->bdev = si->bdev;
++ devinfo->allocator = &toi_swapops;
++ devinfo->allocator_index = i;
++
++ result = uuid_from_block_dev(si->bdev, devinfo->uuid);
++ if (result)
++ printk("uuid from block dev returned %d.\n", result);
++ devinfo->dev_t = si->bdev->bd_dev;
++ devinfo->prio = si->prio;
++ devinfo->bmap_shift = 3;
++ devinfo->blocks_per_page = 1;
++
++ toi_message(TOI_IO, TOI_VERBOSE, 0, "Registering swap storage:"
++ " Device %d (%lx), prio %d.", i,
++ (unsigned long) devinfo->dev_t, devinfo->prio);
++ toi_bio_ops.register_storage(devinfo);
++ }
++
+ return 0;
+}
+
+ int len = 0;
+ struct sysinfo sysinfo;
+
-+ if (toiActiveAllocator != &toi_swapops) {
-+ len = scnprintf(buffer, size,
-+ "- SwapAllocator inactive.\n");
-+ return len;
-+ }
-+
-+ len = scnprintf(buffer, size, "- SwapAllocator active.\n");
++ len = scnprintf(buffer, size, "- Swap Allocator enabled.\n");
+ if (swapfilename[0])
+ len += scnprintf(buffer+len, size-len,
+ " Attempting to automatically swapon: %s.\n",
+
+ len += scnprintf(buffer+len, size-len,
+ " Swap available for image: %lu pages.\n",
-+ sysinfo.freeswap + toi_swap_storage_allocated());
++ sysinfo.freeswap + swap_allocated);
+
+ return len;
+}
+
-+/*
-+ * Storage needed
-+ *
-+ * Returns amount of space in the swap header required
-+ * for the toi_swap's data. This ignores the links between
-+ * pages, which we factor in when allocating the space.
-+ *
-+ * We ensure the space is allocated, but actually save the
-+ * data from write_header_init and therefore don't also define a
-+ * save_config_info routine.
-+ */
-+static int toi_swap_storage_needed(void)
-+{
-+ int i, result;
-+ result = sizeof(struct sig_data) + sizeof(toi_writer_posn_save) +
-+ sizeof(devinfo);
-+
-+ for (i = 0; i < MAX_SWAPFILES; i++) {
-+ result += sizeof(block_chain[i].size) +
-+ sizeof(block_chain[i].num_extents);
-+ result += (2 * sizeof(unsigned long) *
-+ block_chain[i].num_extents);
-+ }
-+
-+ return result;
-+}
-+
-+/*
-+ * Image_exists
-+ *
-+ * Returns -1 if don't know, otherwise 0 (no) or 1 (yes).
-+ */
-+static int toi_swap_image_exists(int quiet)
-+{
-+ int signature_found;
-+
-+ if (!resume_swap_dev_t) {
-+ if (!quiet)
-+ printk(KERN_INFO "Not even trying to read header "
-+ "because resume_swap_dev_t is not set.\n");
-+ return -1;
-+ }
-+
-+ if (!resume_block_device) {
-+ resume_block_device = open_bdev(MAX_SWAPFILES,
-+ resume_swap_dev_t, 1);
-+ if (IS_ERR(resume_block_device)) {
-+ if (!quiet)
-+ printk(KERN_INFO "Failed to open resume dev_t"
-+ " (%x).\n", resume_swap_dev_t);
-+ return -1;
-+ }
-+ }
-+
-+ signature_found = parse_signature();
-+
-+ switch (signature_found) {
-+ case -ENOMEM:
-+ return -1;
-+ case -1:
-+ if (!quiet)
-+ printk(KERN_ERR "TuxOnIce: Unable to find a signature."
-+ " Could you have moved a swap file?\n");
-+ return -1;
-+ case 0:
-+ case 1:
-+ if (!quiet)
-+ printk(KERN_INFO "TuxOnIce: Normal swapspace found.\n");
-+ return 0;
-+ case 2:
-+ case 3:
-+ case 4:
-+ if (!quiet)
-+ printk(KERN_INFO "TuxOnIce: Detected another "
-+ "implementation's signature.\n");
-+ return 0;
-+ case 10:
-+ if (!quiet)
-+ printk(KERN_INFO "TuxOnIce: Detected TuxOnIce binary "
-+ "signature.\n");
-+ return 1;
-+ }
-+
-+ printk("Unrecognised parse_signature result (%d).\n", signature_found);
-+ return 0;
-+}
-+
-+/* toi_swap_remove_image
-+ *
-+ */
-+static int toi_swap_remove_image(void)
-+{
-+ /*
-+ * If nr_hibernates == 0, we must be booting, so no swap pages
-+ * will be recorded as used yet.
-+ */
-+
-+ if (nr_hibernates)
-+ toi_swap_release_storage();
-+
-+ /*
-+ * We don't do a sanity check here: we want to restore the swap
-+ * whatever version of kernel made the hibernate image.
-+ *
-+ * We need to write swap, but swap may not be enabled so
-+ * we write the device directly
-+ *
-+ * If we don't have an current_signature_page, we didn't
-+ * read an image header, so don't change anything.
-+ */
-+
-+ return toi_swap_image_exists(1) ?
-+ write_modified_signature(NO_IMAGE_SIGNATURE) : 0;
-+}
-+
-+/*
-+ * Mark resume attempted.
-+ *
-+ * Record that we tried to resume from this image. We have already read the
-+ * signature in. We just need to write the modified version.
-+ */
-+static int toi_swap_mark_resume_attempted(int mark)
-+{
-+ if (!resume_swap_dev_t) {
-+ printk(KERN_INFO "Not even trying to record attempt at resuming"
-+ " because resume_swap_dev_t is not set.\n");
-+ return -ENODEV;
-+ }
-+
-+ return write_modified_signature(mark ? TRIED_RESUME : NO_TRIED_RESUME);
-+}
-+
-+/*
-+ * Parse Image Location
-+ *
-+ * Attempt to parse a resume= parameter.
-+ * Swap Writer accepts:
-+ * resume=swap:DEVNAME[:FIRSTBLOCK][@BLOCKSIZE]
-+ *
-+ * Where:
-+ * DEVNAME is convertable to a dev_t by name_to_dev_t
-+ * FIRSTBLOCK is the location of the first block in the swap file
-+ * (specifying for a swap partition is nonsensical but not prohibited).
-+ * Data is validated by attempting to read a swap header from the
-+ * location given. Failure will result in toi_swap refusing to
-+ * save an image, and a reboot with correct parameters will be
-+ * necessary.
-+ */
-+static int toi_swap_parse_sig_location(char *commandline,
-+ int only_allocator, int quiet)
-+{
-+ char *thischar, *devstart, *colon = NULL;
-+ int signature_found, result = -EINVAL, temp_result = 0;
-+
-+ if (strncmp(commandline, "swap:", 5)) {
-+ /*
-+ * Failing swap:, we'll take a simple
-+ * resume=/dev/hda2, but fall through to
-+ * other allocators if /dev/ isn't matched.
-+ */
-+ if (strncmp(commandline, "/dev/", 5))
-+ return 1;
-+ } else
-+ commandline += 5;
-+
-+ devstart = commandline;
-+ thischar = commandline;
-+ while ((*thischar != ':') && (*thischar != '@') &&
-+ ((thischar - commandline) < 250) && (*thischar))
-+ thischar++;
-+
-+ if (*thischar == ':') {
-+ colon = thischar;
-+ *colon = 0;
-+ thischar++;
-+ }
-+
-+ while ((thischar - commandline) < 250 && *thischar)
-+ thischar++;
-+
-+ if (colon) {
-+ unsigned long block;
-+ temp_result = strict_strtoul(colon + 1, 0, &block);
-+ if (!temp_result)
-+ resume_firstblock = (int) block;
-+ } else
-+ resume_firstblock = 0;
-+
-+ clear_toi_state(TOI_CAN_HIBERNATE);
-+ clear_toi_state(TOI_CAN_RESUME);
-+
-+ if (!temp_result)
-+ temp_result = try_to_parse_resume_device(devstart, quiet);
-+
-+ if (colon)
-+ *colon = ':';
-+
-+ if (temp_result)
-+ return -EINVAL;
-+
-+ signature_found = toi_swap_image_exists(quiet);
-+
-+ if (signature_found != -1) {
-+ result = 0;
-+
-+ toi_bio_ops.set_devinfo(devinfo);
-+ toi_writer_posn.chains = &block_chain[0];
-+ toi_writer_posn.num_chains = MAX_SWAPFILES;
-+ set_toi_state(TOI_CAN_HIBERNATE);
-+ set_toi_state(TOI_CAN_RESUME);
-+ } else
-+ if (!quiet)
-+ printk(KERN_ERR "TuxOnIce: SwapAllocator: No swap "
-+ "signature found at %s.\n", devstart);
-+ return result;
-+}
-+
+static int header_locations_read_sysfs(const char *page, int count)
+{
+ int i, printedpartitionsmessage = 0, len = 0, haveswap = 0;
+ for (i = 0; i < MAX_SWAPFILES; i++) {
+ struct swap_info_struct *si = get_swap_info_struct(i);
+
-+ if ((!si->flags & SWP_USED) || si->swap_map ||
-+ !(si->flags & SWP_WRITEOK))
++ if (!(si->flags & SWP_WRITEOK))
+ continue;
+
+ if (S_ISBLK(si->swap_file->f_mapping->host->i_mode)) {
+ attempt_to_parse_resume_device2),
+};
+
++static struct toi_bio_allocator_ops toi_bio_swapops = {
++ .register_storage = toi_swap_register_storage,
++ .storage_available = toi_swap_storage_available,
++ .allocate_storage = toi_swap_allocate_storage,
++ .bmap = get_main_pool_phys_params,
++ .free_storage = toi_swap_free_storage,
++};
++
+static struct toi_module_ops toi_swapops = {
-+ .type = WRITER_MODULE,
++ .type = BIO_ALLOCATOR_MODULE,
+ .name = "swap storage",
+ .directory = "swap",
+ .module = THIS_MODULE,
+ .memory_needed = toi_swap_memory_needed,
+ .print_debug_info = toi_swap_print_debug_stats,
-+ .storage_needed = toi_swap_storage_needed,
+ .initialise = toi_swap_initialise,
+ .cleanup = toi_swap_cleanup,
-+
-+ .noresume_reset = toi_swap_noresume_reset,
-+ .storage_available = toi_swap_storage_available,
-+ .storage_allocated = toi_swap_storage_allocated,
-+ .reserve_header_space = toi_swap_reserve_header_space,
-+ .allocate_storage = toi_swap_allocate_storage,
-+ .image_exists = toi_swap_image_exists,
-+ .mark_resume_attempted = toi_swap_mark_resume_attempted,
-+ .write_header_init = toi_swap_write_header_init,
-+ .write_header_cleanup = toi_swap_write_header_cleanup,
-+ .read_header_init = toi_swap_read_header_init,
-+ .read_header_cleanup = toi_swap_read_header_cleanup,
-+ .remove_image = toi_swap_remove_image,
-+ .parse_sig_location = toi_swap_parse_sig_location,
++ .bio_allocator_ops = &toi_bio_swapops,
+
+ .sysfs_data = sysfs_params,
+ .num_sysfs_entries = sizeof(sysfs_params) /
+/* ---- Registration ---- */
+static __init int toi_swap_load(void)
+{
-+ toi_swapops.rw_init = toi_bio_ops.rw_init;
-+ toi_swapops.rw_cleanup = toi_bio_ops.rw_cleanup;
-+ toi_swapops.read_page = toi_bio_ops.read_page;
-+ toi_swapops.write_page = toi_bio_ops.write_page;
-+ toi_swapops.rw_header_chunk = toi_bio_ops.rw_header_chunk;
-+ toi_swapops.rw_header_chunk_noreadahead =
-+ toi_bio_ops.rw_header_chunk_noreadahead;
-+ toi_swapops.io_flusher = toi_bio_ops.io_flusher;
-+ toi_swapops.update_throughput_throttle =
-+ toi_bio_ops.update_throughput_throttle;
-+ toi_swapops.finish_all_io = toi_bio_ops.finish_all_io;
-+
+ return toi_register_module(&toi_swapops);
+}
+
+extern void toi_remove_ui_ops(struct ui_ops *this_ui);
diff --git a/kernel/power/tuxonice_userui.c b/kernel/power/tuxonice_userui.c
new file mode 100644
-index 0000000..c7b1053
+index 0000000..ad441c5
--- /dev/null
+++ b/kernel/power/tuxonice_userui.c
-@@ -0,0 +1,662 @@
+@@ -0,0 +1,668 @@
+/*
+ * kernel/power/user_ui.c
+ *
+ (1 << TOI_LOGALL) |
+ (1 << TOI_SINGLESTEP) |
+ (1 << TOI_PAUSE_NEAR_PAGESET_END);
++ static unsigned long new_action;
+
-+ toi_bkd.toi_action = (toi_bkd.toi_action & (~toi_action_mask)) |
++ new_action = (toi_bkd.toi_action & (~toi_action_mask)) |
+ (n & toi_action_mask);
+
++ printk(KERN_DEBUG "n is %x. Action flags being changed from %lx "
++ "to %lx.", n, toi_bkd.toi_action, new_action);
++ toi_bkd.toi_action = new_action;
++
+ if (!test_action_state(TOI_PAUSE) &&
+ !test_action_state(TOI_SINGLESTEP))
+ wake_up_interruptible(&userui_wait_for_key);
+ */
+static void request_abort_hibernate(void)
+{
-+ if (test_result_state(TOI_ABORT_REQUESTED))
++ if (test_result_state(TOI_ABORT_REQUESTED) ||
++ !test_action_state(TOI_CAN_CANCEL))
+ return;
+
+ if (test_toi_state(TOI_NOW_RESUMING)) {
static int snapshot_open(struct inode *inode, struct file *filp)
{
diff --git a/kernel/printk.c b/kernel/printk.c
-index b4d97b5..0fda643 100644
+index f38b07f..f0b3459 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -32,6 +32,7 @@
#include <linux/kexec.h>
#include <asm/uaccess.h>
-@@ -60,6 +61,7 @@ int console_printk[4] = {
+@@ -66,6 +67,7 @@ int console_printk[4] = {
MINIMUM_CONSOLE_LOGLEVEL, /* minimum_console_loglevel */
DEFAULT_CONSOLE_LOGLEVEL, /* default_console_loglevel */
};
+EXPORT_SYMBOL_GPL(console_printk);
- /*
- * Low level drivers may need that to know if they can schedule in
-@@ -926,6 +928,7 @@ void suspend_console(void)
+ static int saved_console_loglevel = -1;
+
+@@ -954,6 +956,7 @@ void suspend_console(void)
console_suspended = 1;
up(&console_sem);
}
void resume_console(void)
{
-@@ -935,6 +938,7 @@ void resume_console(void)
+@@ -963,6 +966,7 @@ void resume_console(void)
console_suspended = 0;
release_console_sem();
}
/**
* acquire_console_sem - lock the console system for exclusive use.
diff --git a/mm/bootmem.c b/mm/bootmem.c
-index 701740c..72f84e3 100644
+index 555d5d2..cd66665 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -23,6 +23,7 @@
#ifdef CONFIG_CRASH_DUMP
/*
diff --git a/mm/highmem.c b/mm/highmem.c
-index 25878cc..32a0767 100644
+index 9c1e627..b0facc3 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -57,6 +57,7 @@ unsigned int nr_free_highpages (void)
static int pkmap_count[LAST_PKMAP];
static unsigned int last_pkmap_nr;
diff --git a/mm/memory.c b/mm/memory.c
-index aede2ce..5cc16dc 100644
+index 6ab19dd..377be88 100644
--- a/mm/memory.c
+++ b/mm/memory.c
-@@ -1186,6 +1186,7 @@ no_page_table:
- }
+@@ -1228,6 +1228,7 @@ no_page_table:
+ return ERR_PTR(-EFAULT);
return page;
}
+EXPORT_SYMBOL_GPL(follow_page);
- /* Can we do the FOLL_ANON optimization? */
- static inline int use_zero_page(struct vm_area_struct *vma)
+ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
+ unsigned long start, int nr_pages, unsigned int gup_flags,
diff --git a/mm/mmzone.c b/mm/mmzone.c
index f5b7d17..72a6770 100644
--- a/mm/mmzone.c
static inline int zref_in_nodemask(struct zoneref *zref, nodemask_t *nodes)
{
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
-index 81627eb..880d936 100644
+index 2c5d792..6d5d74f 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
-@@ -105,6 +105,7 @@ unsigned int dirty_expire_interval = 30 * 100; /* centiseconds */
+@@ -99,6 +99,7 @@ unsigned int dirty_expire_interval = 30 * 100; /* centiseconds */
* Flag that makes the machine dump writes/reads and block dirtyings.
*/
int block_dump;
/*
* Flag that puts the machine in "laptop mode". Doubles as a timeout in jiffies:
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
-index a0de15f..9bed1c3 100644
+index 2bc2ac6..f3a9a61 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
-@@ -2046,6 +2046,26 @@ static unsigned int nr_free_zone_pages(int offset)
+@@ -2098,6 +2098,26 @@ static unsigned int nr_free_zone_pages(int offset)
return sum;
}
/*
* Amount of free RAM allocatable within ZONE_DMA and ZONE_NORMAL
*/
-@@ -2056,6 +2076,15 @@ unsigned int nr_free_buffer_pages(void)
+@@ -2108,6 +2128,15 @@ unsigned int nr_free_buffer_pages(void)
EXPORT_SYMBOL_GPL(nr_free_buffer_pages);
/*
*/
unsigned int nr_free_pagecache_pages(void)
diff --git a/mm/shmem.c b/mm/shmem.c
-index d713239..26fafce 100644
+index 356dd99..94481cb 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
-@@ -1557,6 +1557,8 @@ static struct inode *shmem_get_inode(struct super_block *sb, int mode,
+@@ -1561,6 +1561,8 @@ static struct inode *shmem_get_inode(struct super_block *sb, int mode,
memset(info, 0, (char *)inode - (char *)info);
spin_lock_init(&info->lock);
info->flags = flags & VM_NORESERVE;
cache_no_acl(inode);
diff --git a/mm/swap_state.c b/mm/swap_state.c
-index 42cd38e..105973c 100644
+index 6d1daeb..eced4ef 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
-@@ -45,6 +45,7 @@ struct address_space swapper_space = {
+@@ -46,6 +46,7 @@ struct address_space swapper_space = {
.i_mmap_nonlinear = LIST_HEAD_INIT(swapper_space.i_mmap_nonlinear),
.backing_dev_info = &swap_backing_dev_info,
};
#define INC_CACHE_INFO(x) do { swap_cache_info.x++; } while (0)
diff --git a/mm/swapfile.c b/mm/swapfile.c
-index 8ffdc0d..78df628 100644
+index 9c590ee..796bf72 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
-@@ -493,6 +493,7 @@ noswap:
+@@ -495,6 +495,7 @@ noswap:
spin_unlock(&swap_lock);
return (swp_entry_t) {0};
}
/* The only caller of this function is now susupend routine */
swp_entry_t get_swap_page_of_type(int type)
-@@ -627,6 +628,7 @@ void swapcache_free(swp_entry_t entry, struct page *page)
+@@ -517,6 +518,7 @@ swp_entry_t get_swap_page_of_type(int type)
+ spin_unlock(&swap_lock);
+ return (swp_entry_t) {0};
+ }
++EXPORT_SYMBOL_GPL(get_swap_page_of_type);
+
+ static struct swap_info_struct * swap_info_get(swp_entry_t entry)
+ {
+@@ -629,6 +631,7 @@ void swapcache_free(swp_entry_t entry, struct page *page)
}
return;
}
/*
* How many references to page are currently swapped out?
-@@ -1304,6 +1306,7 @@ sector_t map_swap_page(struct swap_info_struct *sis, pgoff_t offset)
+@@ -1305,6 +1308,7 @@ sector_t map_swap_page(struct swap_info_struct *sis, pgoff_t offset)
BUG_ON(se == start_se); /* It *must* be present */
}
}
#ifdef CONFIG_HIBERNATION
/*
-@@ -1647,6 +1650,7 @@ out_dput:
+@@ -1648,6 +1652,7 @@ out_dput:
out:
return err;
}
#ifdef CONFIG_PROC_FS
/* iterator */
-@@ -2045,6 +2049,7 @@ out:
+@@ -2048,6 +2053,7 @@ out:
}
return error;
}
void si_swapinfo(struct sysinfo *val)
{
-@@ -2062,6 +2067,7 @@ void si_swapinfo(struct sysinfo *val)
+@@ -2065,6 +2071,7 @@ void si_swapinfo(struct sysinfo *val)
val->totalswap = total_swap_pages + nr_to_be_unused;
spin_unlock(&swap_lock);
}
/*
* Verify that a swap entry is valid and increment its swap map count.
-@@ -2162,6 +2168,7 @@ get_swap_info_struct(unsigned type)
+@@ -2165,6 +2172,7 @@ get_swap_info_struct(unsigned type)
{
return &swap_info[type];
}
/*
* swap_lock prevents swap_map being freed. Don't grab an extra
diff --git a/mm/vmscan.c b/mm/vmscan.c
-index 94e86dd..b7dec80 100644
+index 777af57..70313d6 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
-@@ -2101,6 +2101,9 @@ void wakeup_kswapd(struct zone *zone, int order)
+@@ -2211,6 +2211,9 @@ void wakeup_kswapd(struct zone *zone, int order)
if (!populated_zone(zone))
return;
pgdat = zone->zone_pgdat;
if (zone_watermark_ok(zone, order, low_wmark_pages(zone), 0, 0))
return;
-@@ -2261,6 +2264,7 @@ out:
+@@ -2403,6 +2406,7 @@ out:
return sc.nr_reclaimed;
}
#endif /* CONFIG_HIBERNATION */
/* It's optimal to keep kswapds on the same CPUs as their memory, but
---- linux-2.6.31/mm/swapfile.c~ 2009-09-13 09:09:36.506565318 +0200
-+++ linux-2.6.31/mm/swapfile.c 2009-09-14 08:14:30.692422596 +0200
-@@ -518,6 +518,7 @@
- spin_unlock(&swap_lock);
- return (swp_entry_t) {0};
- }
-+EXPORT_SYMBOL_GPL(get_swap_page_of_type);
-
- static struct swap_info_struct * swap_info_get(swp_entry_t entry)
- {
-diff -NurpP --minimal linux-2.6.31.6/arch/alpha/Kconfig linux-2.6.31.6-vs2.3.0.36.24/arch/alpha/Kconfig
---- linux-2.6.31.6/arch/alpha/Kconfig 2009-03-24 14:18:07.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/alpha/Kconfig 2009-09-10 16:11:43.000000000 +0200
-@@ -666,6 +666,8 @@ config DUMMY_CONSOLE
+diff -NurpP --minimal linux-2.6.32/arch/alpha/Kconfig linux-2.6.32-vs2.3.0.36.26/arch/alpha/Kconfig
+--- linux-2.6.32/arch/alpha/Kconfig 2009-12-03 20:01:49.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/alpha/Kconfig 2009-12-03 20:04:56.000000000 +0100
+@@ -674,6 +674,8 @@ config DUMMY_CONSOLE
depends on VGA_HOSE
default y
source "security/Kconfig"
source "crypto/Kconfig"
-diff -NurpP --minimal linux-2.6.31.6/arch/alpha/kernel/entry.S linux-2.6.31.6-vs2.3.0.36.24/arch/alpha/kernel/entry.S
---- linux-2.6.31.6/arch/alpha/kernel/entry.S 2009-06-11 17:11:46.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/alpha/kernel/entry.S 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/alpha/kernel/entry.S linux-2.6.32-vs2.3.0.36.26/arch/alpha/kernel/entry.S
+--- linux-2.6.32/arch/alpha/kernel/entry.S 2009-06-11 17:11:46.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/alpha/kernel/entry.S 2009-12-03 20:04:56.000000000 +0100
@@ -874,24 +874,15 @@ sys_getxgid:
.globl sys_getxpid
.ent sys_getxpid
ret
.end sys_getxpid
-diff -NurpP --minimal linux-2.6.31.6/arch/alpha/kernel/osf_sys.c linux-2.6.31.6-vs2.3.0.36.24/arch/alpha/kernel/osf_sys.c
---- linux-2.6.31.6/arch/alpha/kernel/osf_sys.c 2009-09-10 15:25:14.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/alpha/kernel/osf_sys.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/alpha/kernel/osf_sys.c linux-2.6.32-vs2.3.0.36.26/arch/alpha/kernel/osf_sys.c
+--- linux-2.6.32/arch/alpha/kernel/osf_sys.c 2009-09-10 15:25:14.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/alpha/kernel/osf_sys.c 2009-12-03 20:04:56.000000000 +0100
@@ -872,7 +872,7 @@ SYSCALL_DEFINE2(osf_gettimeofday, struct
{
if (tv) {
if (put_tv32(tv, &ktv))
return -EFAULT;
}
-diff -NurpP --minimal linux-2.6.31.6/arch/alpha/kernel/ptrace.c linux-2.6.31.6-vs2.3.0.36.24/arch/alpha/kernel/ptrace.c
---- linux-2.6.31.6/arch/alpha/kernel/ptrace.c 2009-09-10 15:25:14.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/alpha/kernel/ptrace.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/alpha/kernel/ptrace.c linux-2.6.32-vs2.3.0.36.26/arch/alpha/kernel/ptrace.c
+--- linux-2.6.32/arch/alpha/kernel/ptrace.c 2009-09-10 15:25:14.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/alpha/kernel/ptrace.c 2009-12-03 20:04:56.000000000 +0100
@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/security.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
-diff -NurpP --minimal linux-2.6.31.6/arch/alpha/kernel/systbls.S linux-2.6.31.6-vs2.3.0.36.24/arch/alpha/kernel/systbls.S
---- linux-2.6.31.6/arch/alpha/kernel/systbls.S 2009-03-24 14:18:08.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/alpha/kernel/systbls.S 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/alpha/kernel/systbls.S linux-2.6.32-vs2.3.0.36.26/arch/alpha/kernel/systbls.S
+--- linux-2.6.32/arch/alpha/kernel/systbls.S 2009-03-24 14:18:08.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/alpha/kernel/systbls.S 2009-12-03 20:04:56.000000000 +0100
@@ -446,7 +446,7 @@ sys_call_table:
.quad sys_stat64 /* 425 */
.quad sys_lstat64
.quad sys_ni_syscall /* sys_mbind */
.quad sys_ni_syscall /* sys_get_mempolicy */
.quad sys_ni_syscall /* sys_set_mempolicy */
-diff -NurpP --minimal linux-2.6.31.6/arch/alpha/kernel/traps.c linux-2.6.31.6-vs2.3.0.36.24/arch/alpha/kernel/traps.c
---- linux-2.6.31.6/arch/alpha/kernel/traps.c 2009-06-11 17:11:46.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/alpha/kernel/traps.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/alpha/kernel/traps.c linux-2.6.32-vs2.3.0.36.26/arch/alpha/kernel/traps.c
+--- linux-2.6.32/arch/alpha/kernel/traps.c 2009-06-11 17:11:46.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/alpha/kernel/traps.c 2009-12-03 20:04:56.000000000 +0100
@@ -183,7 +183,8 @@ die_if_kernel(char * str, struct pt_regs
#ifdef CONFIG_SMP
printk("CPU %d ", hard_smp_processor_id());
dik_show_regs(regs, r9_15);
add_taint(TAINT_DIE);
dik_show_trace((unsigned long *)(regs+1));
-diff -NurpP --minimal linux-2.6.31.6/arch/alpha/mm/fault.c linux-2.6.31.6-vs2.3.0.36.24/arch/alpha/mm/fault.c
---- linux-2.6.31.6/arch/alpha/mm/fault.c 2009-09-10 15:25:14.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/alpha/mm/fault.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/alpha/mm/fault.c linux-2.6.32-vs2.3.0.36.26/arch/alpha/mm/fault.c
+--- linux-2.6.32/arch/alpha/mm/fault.c 2009-09-10 15:25:14.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/alpha/mm/fault.c 2009-12-03 20:04:56.000000000 +0100
@@ -193,8 +193,8 @@ do_page_fault(unsigned long address, uns
down_read(&mm->mmap_sem);
goto survive;
if (!user_mode(regs))
goto no_context;
do_group_exit(SIGKILL);
-diff -NurpP --minimal linux-2.6.31.6/arch/arm/Kconfig linux-2.6.31.6-vs2.3.0.36.24/arch/arm/Kconfig
---- linux-2.6.31.6/arch/arm/Kconfig 2009-09-10 15:25:14.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/arm/Kconfig 2009-09-10 16:11:43.000000000 +0200
-@@ -1483,6 +1483,8 @@ source "fs/Kconfig"
+diff -NurpP --minimal linux-2.6.32/arch/arm/Kconfig linux-2.6.32-vs2.3.0.36.26/arch/arm/Kconfig
+--- linux-2.6.32/arch/arm/Kconfig 2009-12-03 20:01:49.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/arm/Kconfig 2009-12-03 20:04:56.000000000 +0100
+@@ -1512,6 +1512,8 @@ source "fs/Kconfig"
source "arch/arm/Kconfig.debug"
source "security/Kconfig"
source "crypto/Kconfig"
-diff -NurpP --minimal linux-2.6.31.6/arch/arm/kernel/calls.S linux-2.6.31.6-vs2.3.0.36.24/arch/arm/kernel/calls.S
---- linux-2.6.31.6/arch/arm/kernel/calls.S 2009-09-10 15:25:15.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/arm/kernel/calls.S 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/arm/kernel/calls.S linux-2.6.32-vs2.3.0.36.26/arch/arm/kernel/calls.S
+--- linux-2.6.32/arch/arm/kernel/calls.S 2009-12-03 20:01:50.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/arm/kernel/calls.S 2009-12-03 20:04:56.000000000 +0100
@@ -322,7 +322,7 @@
/* 310 */ CALL(sys_request_key)
CALL(sys_keyctl)
CALL(sys_ioprio_set)
/* 315 */ CALL(sys_ioprio_get)
CALL(sys_inotify_init)
-diff -NurpP --minimal linux-2.6.31.6/arch/arm/kernel/process.c linux-2.6.31.6-vs2.3.0.36.24/arch/arm/kernel/process.c
---- linux-2.6.31.6/arch/arm/kernel/process.c 2009-09-10 15:25:15.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/arm/kernel/process.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/arm/kernel/process.c linux-2.6.32-vs2.3.0.36.26/arch/arm/kernel/process.c
+--- linux-2.6.32/arch/arm/kernel/process.c 2009-12-03 20:01:50.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/arm/kernel/process.c 2009-12-03 20:04:56.000000000 +0100
@@ -269,7 +269,8 @@ void __show_regs(struct pt_regs *regs)
void show_regs(struct pt_regs * regs)
{
__show_regs(regs);
__backtrace();
}
-diff -NurpP --minimal linux-2.6.31.6/arch/arm/kernel/traps.c linux-2.6.31.6-vs2.3.0.36.24/arch/arm/kernel/traps.c
---- linux-2.6.31.6/arch/arm/kernel/traps.c 2009-06-11 17:11:49.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/arm/kernel/traps.c 2009-09-10 16:11:43.000000000 +0200
-@@ -228,8 +228,8 @@ static void __die(const char *str, int e
- str, err, ++die_counter);
+diff -NurpP --minimal linux-2.6.32/arch/arm/kernel/traps.c linux-2.6.32-vs2.3.0.36.26/arch/arm/kernel/traps.c
+--- linux-2.6.32/arch/arm/kernel/traps.c 2009-12-03 20:01:50.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/arm/kernel/traps.c 2009-12-03 20:04:56.000000000 +0100
+@@ -234,8 +234,8 @@ static void __die(const char *str, int e
+ sysfs_printk_last_file();
print_modules();
__show_regs(regs);
-- printk("Process %s (pid: %d, stack limit = 0x%p)\n",
-- tsk->comm, task_pid_nr(tsk), thread + 1);
-+ printk("Process %s (pid: %d:#%u, stack limit = 0x%p)\n",
-+ tsk->comm, task_pid_nr(tsk), tsk->xid, thread + 1);
+- printk(KERN_EMERG "Process %.*s (pid: %d, stack limit = 0x%p)\n",
+- TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), thread + 1);
++ printk(KERN_EMERG "Process %.*s (pid: %d:#%u, stack limit = 0x%p)\n",
++ TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), tsk->xid, thread + 1);
if (!user_mode(regs) || in_interrupt()) {
- dump_mem("Stack: ", regs->ARM_sp,
-diff -NurpP --minimal linux-2.6.31.6/arch/arm/mm/fault.c linux-2.6.31.6-vs2.3.0.36.24/arch/arm/mm/fault.c
---- linux-2.6.31.6/arch/arm/mm/fault.c 2009-09-10 15:25:18.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/arm/mm/fault.c 2009-09-10 16:11:43.000000000 +0200
-@@ -294,7 +294,8 @@ do_page_fault(unsigned long addr, unsign
- * happened to us that made us unable to handle
- * the page fault gracefully.
- */
-- printk("VM: killing process %s\n", tsk->comm);
-+ printk("VM: killing process %s(%d:#%u)\n",
-+ tsk->comm, task_pid_nr(tsk), tsk->xid);
- do_group_exit(SIGKILL);
- return 0;
- }
-diff -NurpP --minimal linux-2.6.31.6/arch/avr32/mm/fault.c linux-2.6.31.6-vs2.3.0.36.24/arch/avr32/mm/fault.c
---- linux-2.6.31.6/arch/avr32/mm/fault.c 2009-09-10 15:25:20.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/avr32/mm/fault.c 2009-09-29 17:32:09.000000000 +0200
+ dump_mem(KERN_EMERG, "Stack: ", regs->ARM_sp,
+diff -NurpP --minimal linux-2.6.32/arch/avr32/mm/fault.c linux-2.6.32-vs2.3.0.36.26/arch/avr32/mm/fault.c
+--- linux-2.6.32/arch/avr32/mm/fault.c 2009-09-10 15:25:20.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/avr32/mm/fault.c 2009-12-03 20:04:56.000000000 +0100
@@ -216,7 +216,8 @@ out_of_memory:
down_read(&mm->mmap_sem);
goto survive;
if (user_mode(regs))
do_group_exit(SIGKILL);
goto no_context;
-diff -NurpP --minimal linux-2.6.31.6/arch/cris/Kconfig linux-2.6.31.6-vs2.3.0.36.24/arch/cris/Kconfig
---- linux-2.6.31.6/arch/cris/Kconfig 2009-06-11 17:11:56.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/cris/Kconfig 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/cris/Kconfig linux-2.6.32-vs2.3.0.36.26/arch/cris/Kconfig
+--- linux-2.6.32/arch/cris/Kconfig 2009-06-11 17:11:56.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/cris/Kconfig 2009-12-03 20:04:56.000000000 +0100
@@ -685,6 +685,8 @@ source "drivers/staging/Kconfig"
source "arch/cris/Kconfig.debug"
source "security/Kconfig"
source "crypto/Kconfig"
-diff -NurpP --minimal linux-2.6.31.6/arch/cris/mm/fault.c linux-2.6.31.6-vs2.3.0.36.24/arch/cris/mm/fault.c
---- linux-2.6.31.6/arch/cris/mm/fault.c 2009-09-10 15:25:21.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/cris/mm/fault.c 2009-09-29 17:25:13.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/cris/mm/fault.c linux-2.6.32-vs2.3.0.36.26/arch/cris/mm/fault.c
+--- linux-2.6.32/arch/cris/mm/fault.c 2009-12-03 20:01:56.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/cris/mm/fault.c 2009-12-03 20:04:56.000000000 +0100
@@ -245,7 +245,8 @@ do_page_fault(unsigned long address, str
out_of_memory:
if (user_mode(regs))
do_exit(SIGKILL);
goto no_context;
-diff -NurpP --minimal linux-2.6.31.6/arch/frv/kernel/kernel_thread.S linux-2.6.31.6-vs2.3.0.36.24/arch/frv/kernel/kernel_thread.S
---- linux-2.6.31.6/arch/frv/kernel/kernel_thread.S 2008-12-25 00:26:37.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/frv/kernel/kernel_thread.S 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/frv/kernel/kernel_thread.S linux-2.6.32-vs2.3.0.36.26/arch/frv/kernel/kernel_thread.S
+--- linux-2.6.32/arch/frv/kernel/kernel_thread.S 2008-12-25 00:26:37.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/frv/kernel/kernel_thread.S 2009-12-03 20:04:56.000000000 +0100
@@ -37,7 +37,7 @@ kernel_thread:
# start by forking the current process, but with shared VM
sethi.p #0xe4e4,gr9 ; second syscall arg [newsp]
setlo #0xe4e4,gr9
setlos.p #0,gr10 ; third syscall arg [parent_tidptr]
-diff -NurpP --minimal linux-2.6.31.6/arch/frv/mm/fault.c linux-2.6.31.6-vs2.3.0.36.24/arch/frv/mm/fault.c
---- linux-2.6.31.6/arch/frv/mm/fault.c 2009-09-10 15:25:22.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/frv/mm/fault.c 2009-09-29 17:25:48.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/frv/mm/fault.c linux-2.6.32-vs2.3.0.36.26/arch/frv/mm/fault.c
+--- linux-2.6.32/arch/frv/mm/fault.c 2009-09-10 15:25:22.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/frv/mm/fault.c 2009-12-03 20:04:56.000000000 +0100
@@ -257,7 +257,8 @@ asmlinkage void do_page_fault(int datamm
*/
out_of_memory:
if (user_mode(__frame))
do_group_exit(SIGKILL);
goto no_context;
-diff -NurpP --minimal linux-2.6.31.6/arch/h8300/Kconfig linux-2.6.31.6-vs2.3.0.36.24/arch/h8300/Kconfig
---- linux-2.6.31.6/arch/h8300/Kconfig 2009-03-24 14:18:24.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/h8300/Kconfig 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/h8300/Kconfig linux-2.6.32-vs2.3.0.36.26/arch/h8300/Kconfig
+--- linux-2.6.32/arch/h8300/Kconfig 2009-03-24 14:18:24.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/h8300/Kconfig 2009-12-03 20:04:56.000000000 +0100
@@ -226,6 +226,8 @@ source "fs/Kconfig"
source "arch/h8300/Kconfig.debug"
source "security/Kconfig"
source "crypto/Kconfig"
-diff -NurpP --minimal linux-2.6.31.6/arch/ia64/ia32/ia32_entry.S linux-2.6.31.6-vs2.3.0.36.24/arch/ia64/ia32/ia32_entry.S
---- linux-2.6.31.6/arch/ia64/ia32/ia32_entry.S 2009-06-11 17:11:57.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/ia64/ia32/ia32_entry.S 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/ia64/ia32/ia32_entry.S linux-2.6.32-vs2.3.0.36.26/arch/ia64/ia32/ia32_entry.S
+--- linux-2.6.32/arch/ia64/ia32/ia32_entry.S 2009-06-11 17:11:57.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/ia64/ia32/ia32_entry.S 2009-12-03 20:04:56.000000000 +0100
@@ -451,7 +451,7 @@ ia32_syscall_table:
data8 sys_tgkill /* 270 */
data8 compat_sys_utimes
data8 sys_ni_syscall
data8 sys_ni_syscall /* 275 */
data8 sys_ni_syscall
-diff -NurpP --minimal linux-2.6.31.6/arch/ia64/Kconfig linux-2.6.31.6-vs2.3.0.36.24/arch/ia64/Kconfig
---- linux-2.6.31.6/arch/ia64/Kconfig 2009-09-10 15:25:22.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/ia64/Kconfig 2009-09-10 16:11:43.000000000 +0200
-@@ -676,6 +676,8 @@ source "fs/Kconfig"
+diff -NurpP --minimal linux-2.6.32/arch/ia64/Kconfig linux-2.6.32-vs2.3.0.36.26/arch/ia64/Kconfig
+--- linux-2.6.32/arch/ia64/Kconfig 2009-12-03 20:01:56.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/ia64/Kconfig 2009-12-03 20:04:56.000000000 +0100
+@@ -685,6 +685,8 @@ source "fs/Kconfig"
source "arch/ia64/Kconfig.debug"
source "security/Kconfig"
source "crypto/Kconfig"
-diff -NurpP --minimal linux-2.6.31.6/arch/ia64/kernel/entry.S linux-2.6.31.6-vs2.3.0.36.24/arch/ia64/kernel/entry.S
---- linux-2.6.31.6/arch/ia64/kernel/entry.S 2009-09-10 15:25:22.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/ia64/kernel/entry.S 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/ia64/kernel/entry.S linux-2.6.32-vs2.3.0.36.26/arch/ia64/kernel/entry.S
+--- linux-2.6.32/arch/ia64/kernel/entry.S 2009-09-10 15:25:22.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/ia64/kernel/entry.S 2009-12-03 20:04:56.000000000 +0100
@@ -1753,7 +1753,7 @@ sys_call_table:
data8 sys_mq_notify
data8 sys_mq_getsetattr
data8 sys_waitid // 1270
data8 sys_add_key
data8 sys_request_key
-diff -NurpP --minimal linux-2.6.31.6/arch/ia64/kernel/perfmon.c linux-2.6.31.6-vs2.3.0.36.24/arch/ia64/kernel/perfmon.c
---- linux-2.6.31.6/arch/ia64/kernel/perfmon.c 2009-09-10 15:25:22.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/ia64/kernel/perfmon.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/ia64/kernel/perfmon.c linux-2.6.32-vs2.3.0.36.26/arch/ia64/kernel/perfmon.c
+--- linux-2.6.32/arch/ia64/kernel/perfmon.c 2009-09-10 15:25:22.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/ia64/kernel/perfmon.c 2009-12-03 20:04:56.000000000 +0100
@@ -41,6 +41,7 @@
#include <linux/rcupdate.h>
#include <linux/completion.h>
vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file,
vma_pages(vma));
up_write(&task->mm->mmap_sem);
-diff -NurpP --minimal linux-2.6.31.6/arch/ia64/kernel/process.c linux-2.6.31.6-vs2.3.0.36.24/arch/ia64/kernel/process.c
---- linux-2.6.31.6/arch/ia64/kernel/process.c 2009-06-11 17:11:57.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/ia64/kernel/process.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/ia64/kernel/process.c linux-2.6.32-vs2.3.0.36.26/arch/ia64/kernel/process.c
+--- linux-2.6.32/arch/ia64/kernel/process.c 2009-12-03 20:01:56.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/ia64/kernel/process.c 2009-12-03 20:04:56.000000000 +0100
@@ -110,8 +110,8 @@ show_regs (struct pt_regs *regs)
unsigned long ip = regs->cr_iip + ia64_psr(regs)->ri;
printk("psr : %016lx ifs : %016lx ip : [<%016lx>] %s (%s)\n",
regs->cr_ipsr, regs->cr_ifs, ip, print_tainted(),
init_utsname()->release);
-diff -NurpP --minimal linux-2.6.31.6/arch/ia64/kernel/ptrace.c linux-2.6.31.6-vs2.3.0.36.24/arch/ia64/kernel/ptrace.c
---- linux-2.6.31.6/arch/ia64/kernel/ptrace.c 2009-09-10 15:25:22.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/ia64/kernel/ptrace.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/ia64/kernel/ptrace.c linux-2.6.32-vs2.3.0.36.26/arch/ia64/kernel/ptrace.c
+--- linux-2.6.32/arch/ia64/kernel/ptrace.c 2009-09-10 15:25:22.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/ia64/kernel/ptrace.c 2009-12-03 20:04:56.000000000 +0100
@@ -22,6 +22,7 @@
#include <linux/regset.h>
#include <linux/elf.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
-diff -NurpP --minimal linux-2.6.31.6/arch/ia64/kernel/traps.c linux-2.6.31.6-vs2.3.0.36.24/arch/ia64/kernel/traps.c
---- linux-2.6.31.6/arch/ia64/kernel/traps.c 2008-12-25 00:26:37.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/ia64/kernel/traps.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/ia64/kernel/traps.c linux-2.6.32-vs2.3.0.36.26/arch/ia64/kernel/traps.c
+--- linux-2.6.32/arch/ia64/kernel/traps.c 2008-12-25 00:26:37.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/ia64/kernel/traps.c 2009-12-03 20:04:56.000000000 +0100
@@ -60,8 +60,9 @@ die (const char *str, struct pt_regs *re
put_cpu();
}
}
}
-diff -NurpP --minimal linux-2.6.31.6/arch/ia64/mm/fault.c linux-2.6.31.6-vs2.3.0.36.24/arch/ia64/mm/fault.c
---- linux-2.6.31.6/arch/ia64/mm/fault.c 2009-09-10 15:25:23.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/ia64/mm/fault.c 2009-09-29 17:26:21.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/ia64/mm/fault.c linux-2.6.32-vs2.3.0.36.26/arch/ia64/mm/fault.c
+--- linux-2.6.32/arch/ia64/mm/fault.c 2009-09-10 15:25:23.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/ia64/mm/fault.c 2009-12-03 20:04:56.000000000 +0100
@@ -10,6 +10,7 @@
#include <linux/interrupt.h>
#include <linux/kprobes.h>
if (user_mode(regs))
do_group_exit(SIGKILL);
goto no_context;
-diff -NurpP --minimal linux-2.6.31.6/arch/m32r/kernel/traps.c linux-2.6.31.6-vs2.3.0.36.24/arch/m32r/kernel/traps.c
---- linux-2.6.31.6/arch/m32r/kernel/traps.c 2008-12-25 00:26:37.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/m32r/kernel/traps.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/m32r/kernel/traps.c linux-2.6.32-vs2.3.0.36.26/arch/m32r/kernel/traps.c
+--- linux-2.6.32/arch/m32r/kernel/traps.c 2009-12-03 20:01:57.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/m32r/kernel/traps.c 2009-12-03 20:04:56.000000000 +0100
@@ -196,8 +196,9 @@ static void show_registers(struct pt_reg
} else {
printk("SPI: %08lx\n", sp);
/*
* When in-kernel, we also print out the stack and code at the
-diff -NurpP --minimal linux-2.6.31.6/arch/m32r/mm/fault.c linux-2.6.31.6-vs2.3.0.36.24/arch/m32r/mm/fault.c
---- linux-2.6.31.6/arch/m32r/mm/fault.c 2009-09-10 15:25:23.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/m32r/mm/fault.c 2009-09-29 17:26:48.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/m32r/mm/fault.c linux-2.6.32-vs2.3.0.36.26/arch/m32r/mm/fault.c
+--- linux-2.6.32/arch/m32r/mm/fault.c 2009-09-10 15:25:23.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/m32r/mm/fault.c 2009-12-03 20:04:56.000000000 +0100
@@ -276,7 +276,8 @@ out_of_memory:
down_read(&mm->mmap_sem);
goto survive;
if (error_code & ACE_USERMODE)
do_group_exit(SIGKILL);
goto no_context;
-diff -NurpP --minimal linux-2.6.31.6/arch/m68k/Kconfig linux-2.6.31.6-vs2.3.0.36.24/arch/m68k/Kconfig
---- linux-2.6.31.6/arch/m68k/Kconfig 2009-11-12 12:10:08.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/m68k/Kconfig 2009-11-12 12:26:38.000000000 +0100
-@@ -616,6 +616,8 @@ source "fs/Kconfig"
+diff -NurpP --minimal linux-2.6.32/arch/m68k/Kconfig linux-2.6.32-vs2.3.0.36.26/arch/m68k/Kconfig
+--- linux-2.6.32/arch/m68k/Kconfig 2009-12-03 20:01:57.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/m68k/Kconfig 2009-12-03 20:04:56.000000000 +0100
+@@ -622,6 +622,8 @@ source "fs/Kconfig"
source "arch/m68k/Kconfig.debug"
source "security/Kconfig"
source "crypto/Kconfig"
-diff -NurpP --minimal linux-2.6.31.6/arch/m68k/kernel/ptrace.c linux-2.6.31.6-vs2.3.0.36.24/arch/m68k/kernel/ptrace.c
---- linux-2.6.31.6/arch/m68k/kernel/ptrace.c 2008-12-25 00:26:37.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/m68k/kernel/ptrace.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/m68k/kernel/ptrace.c linux-2.6.32-vs2.3.0.36.26/arch/m68k/kernel/ptrace.c
+--- linux-2.6.32/arch/m68k/kernel/ptrace.c 2008-12-25 00:26:37.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/m68k/kernel/ptrace.c 2009-12-03 20:04:56.000000000 +0100
@@ -18,6 +18,7 @@
#include <linux/ptrace.h>
#include <linux/user.h>
return ret;
out_eio:
-diff -NurpP --minimal linux-2.6.31.6/arch/m68k/kernel/traps.c linux-2.6.31.6-vs2.3.0.36.24/arch/m68k/kernel/traps.c
---- linux-2.6.31.6/arch/m68k/kernel/traps.c 2009-09-10 15:25:23.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/m68k/kernel/traps.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/m68k/kernel/traps.c linux-2.6.32-vs2.3.0.36.26/arch/m68k/kernel/traps.c
+--- linux-2.6.32/arch/m68k/kernel/traps.c 2009-09-10 15:25:23.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/m68k/kernel/traps.c 2009-12-03 20:04:56.000000000 +0100
@@ -906,8 +906,8 @@ void show_registers(struct pt_regs *regs
printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
regs->d4, regs->d5, regs->a0, regs->a1);
addr = (unsigned long)&fp->un;
printk("Frame format=%X ", regs->format);
switch (regs->format) {
-diff -NurpP --minimal linux-2.6.31.6/arch/m68k/mm/fault.c linux-2.6.31.6-vs2.3.0.36.24/arch/m68k/mm/fault.c
---- linux-2.6.31.6/arch/m68k/mm/fault.c 2009-09-10 15:25:23.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/m68k/mm/fault.c 2009-09-29 17:27:45.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/m68k/mm/fault.c linux-2.6.32-vs2.3.0.36.26/arch/m68k/mm/fault.c
+--- linux-2.6.32/arch/m68k/mm/fault.c 2009-09-10 15:25:23.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/m68k/mm/fault.c 2009-12-03 20:04:56.000000000 +0100
@@ -186,7 +186,8 @@ out_of_memory:
goto survive;
}
if (user_mode(regs))
do_group_exit(SIGKILL);
-diff -NurpP --minimal linux-2.6.31.6/arch/m68knommu/Kconfig linux-2.6.31.6-vs2.3.0.36.24/arch/m68knommu/Kconfig
---- linux-2.6.31.6/arch/m68knommu/Kconfig 2009-06-11 17:11:59.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/m68knommu/Kconfig 2009-09-10 16:11:43.000000000 +0200
-@@ -721,6 +721,8 @@ source "fs/Kconfig"
+diff -NurpP --minimal linux-2.6.32/arch/m68knommu/Kconfig linux-2.6.32-vs2.3.0.36.26/arch/m68knommu/Kconfig
+--- linux-2.6.32/arch/m68knommu/Kconfig 2009-12-03 20:01:57.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/m68knommu/Kconfig 2009-12-03 20:04:56.000000000 +0100
+@@ -727,6 +727,8 @@ source "fs/Kconfig"
source "arch/m68knommu/Kconfig.debug"
source "security/Kconfig"
source "crypto/Kconfig"
-diff -NurpP --minimal linux-2.6.31.6/arch/m68knommu/kernel/traps.c linux-2.6.31.6-vs2.3.0.36.24/arch/m68knommu/kernel/traps.c
---- linux-2.6.31.6/arch/m68knommu/kernel/traps.c 2009-09-10 15:25:23.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/m68knommu/kernel/traps.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/m68knommu/kernel/traps.c linux-2.6.32-vs2.3.0.36.26/arch/m68knommu/kernel/traps.c
+--- linux-2.6.32/arch/m68knommu/kernel/traps.c 2009-09-10 15:25:23.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/m68knommu/kernel/traps.c 2009-12-03 20:04:56.000000000 +0100
@@ -78,8 +78,9 @@ void die_if_kernel(char *str, struct pt_
printk(KERN_EMERG "d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
fp->d4, fp->d5, fp->a0, fp->a1);
show_stack(NULL, (unsigned long *)(fp + 1));
add_taint(TAINT_DIE);
do_exit(SIGSEGV);
-diff -NurpP --minimal linux-2.6.31.6/arch/microblaze/mm/fault.c linux-2.6.31.6-vs2.3.0.36.24/arch/microblaze/mm/fault.c
---- linux-2.6.31.6/arch/microblaze/mm/fault.c 2009-09-10 15:25:24.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/microblaze/mm/fault.c 2009-09-29 17:28:08.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/microblaze/mm/fault.c linux-2.6.32-vs2.3.0.36.26/arch/microblaze/mm/fault.c
+--- linux-2.6.32/arch/microblaze/mm/fault.c 2009-09-10 15:25:24.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/microblaze/mm/fault.c 2009-12-03 20:04:56.000000000 +0100
@@ -279,7 +279,8 @@ out_of_memory:
goto survive;
}
if (user_mode(regs))
do_exit(SIGKILL);
bad_page_fault(regs, address, SIGKILL);
-diff -NurpP --minimal linux-2.6.31.6/arch/mips/Kconfig linux-2.6.31.6-vs2.3.0.36.24/arch/mips/Kconfig
---- linux-2.6.31.6/arch/mips/Kconfig 2009-09-10 15:25:24.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/mips/Kconfig 2009-09-10 16:11:43.000000000 +0200
-@@ -2186,6 +2186,8 @@ source "fs/Kconfig"
+diff -NurpP --minimal linux-2.6.32/arch/mips/Kconfig linux-2.6.32-vs2.3.0.36.26/arch/mips/Kconfig
+--- linux-2.6.32/arch/mips/Kconfig 2009-12-03 20:01:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/mips/Kconfig 2009-12-03 20:04:56.000000000 +0100
+@@ -2188,6 +2188,8 @@ source "fs/Kconfig"
source "arch/mips/Kconfig.debug"
source "security/Kconfig"
source "crypto/Kconfig"
-diff -NurpP --minimal linux-2.6.31.6/arch/mips/kernel/ptrace.c linux-2.6.31.6-vs2.3.0.36.24/arch/mips/kernel/ptrace.c
---- linux-2.6.31.6/arch/mips/kernel/ptrace.c 2008-12-25 00:26:37.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/mips/kernel/ptrace.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/mips/kernel/ptrace.c linux-2.6.32-vs2.3.0.36.26/arch/mips/kernel/ptrace.c
+--- linux-2.6.32/arch/mips/kernel/ptrace.c 2008-12-25 00:26:37.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/mips/kernel/ptrace.c 2009-12-03 20:04:56.000000000 +0100
@@ -25,6 +25,7 @@
#include <linux/security.h>
#include <linux/audit.h>
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
-diff -NurpP --minimal linux-2.6.31.6/arch/mips/kernel/scall32-o32.S linux-2.6.31.6-vs2.3.0.36.24/arch/mips/kernel/scall32-o32.S
---- linux-2.6.31.6/arch/mips/kernel/scall32-o32.S 2009-09-10 15:25:38.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/mips/kernel/scall32-o32.S 2009-09-10 16:11:43.000000000 +0200
-@@ -597,7 +597,7 @@ einval: li v0, -ENOSYS
+diff -NurpP --minimal linux-2.6.32/arch/mips/kernel/scall32-o32.S linux-2.6.32-vs2.3.0.36.26/arch/mips/kernel/scall32-o32.S
+--- linux-2.6.32/arch/mips/kernel/scall32-o32.S 2009-12-03 20:01:59.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/mips/kernel/scall32-o32.S 2009-12-03 20:04:56.000000000 +0100
+@@ -525,7 +525,7 @@ einval: li v0, -ENOSYS
sys sys_mq_timedreceive 5
sys sys_mq_notify 2 /* 4275 */
sys sys_mq_getsetattr 3
sys sys_waitid 5
sys sys_ni_syscall 0 /* available, was setaltroot */
sys sys_add_key 5 /* 4280 */
-diff -NurpP --minimal linux-2.6.31.6/arch/mips/kernel/scall64-64.S linux-2.6.31.6-vs2.3.0.36.24/arch/mips/kernel/scall64-64.S
---- linux-2.6.31.6/arch/mips/kernel/scall64-64.S 2009-09-10 15:25:38.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/mips/kernel/scall64-64.S 2009-09-10 16:11:43.000000000 +0200
-@@ -434,7 +434,7 @@ sys_call_table:
+diff -NurpP --minimal linux-2.6.32/arch/mips/kernel/scall64-64.S linux-2.6.32-vs2.3.0.36.26/arch/mips/kernel/scall64-64.S
+--- linux-2.6.32/arch/mips/kernel/scall64-64.S 2009-12-03 20:01:59.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/mips/kernel/scall64-64.S 2009-12-03 20:04:56.000000000 +0100
+@@ -362,7 +362,7 @@ sys_call_table:
PTR sys_mq_timedreceive
PTR sys_mq_notify
PTR sys_mq_getsetattr /* 5235 */
PTR sys_waitid
PTR sys_ni_syscall /* available, was setaltroot */
PTR sys_add_key
-diff -NurpP --minimal linux-2.6.31.6/arch/mips/kernel/scall64-n32.S linux-2.6.31.6-vs2.3.0.36.24/arch/mips/kernel/scall64-n32.S
---- linux-2.6.31.6/arch/mips/kernel/scall64-n32.S 2009-09-10 15:25:38.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/mips/kernel/scall64-n32.S 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/mips/kernel/scall64-n32.S linux-2.6.32-vs2.3.0.36.26/arch/mips/kernel/scall64-n32.S
+--- linux-2.6.32/arch/mips/kernel/scall64-n32.S 2009-12-03 20:01:59.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/mips/kernel/scall64-n32.S 2009-12-03 20:04:56.000000000 +0100
@@ -360,7 +360,7 @@ EXPORT(sysn32_call_table)
PTR compat_sys_mq_timedreceive
PTR compat_sys_mq_notify
PTR compat_sys_waitid
PTR sys_ni_syscall /* available, was setaltroot */
PTR sys_add_key
-diff -NurpP --minimal linux-2.6.31.6/arch/mips/kernel/scall64-o32.S linux-2.6.31.6-vs2.3.0.36.24/arch/mips/kernel/scall64-o32.S
---- linux-2.6.31.6/arch/mips/kernel/scall64-o32.S 2009-09-10 15:25:38.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/mips/kernel/scall64-o32.S 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/mips/kernel/scall64-o32.S linux-2.6.32-vs2.3.0.36.26/arch/mips/kernel/scall64-o32.S
+--- linux-2.6.32/arch/mips/kernel/scall64-o32.S 2009-12-03 20:01:59.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/mips/kernel/scall64-o32.S 2009-12-03 20:04:56.000000000 +0100
@@ -480,7 +480,7 @@ sys_call_table:
PTR compat_sys_mq_timedreceive
PTR compat_sys_mq_notify /* 4275 */
PTR sys_32_waitid
PTR sys_ni_syscall /* available, was setaltroot */
PTR sys_add_key /* 4280 */
-diff -NurpP --minimal linux-2.6.31.6/arch/mips/kernel/traps.c linux-2.6.31.6-vs2.3.0.36.24/arch/mips/kernel/traps.c
---- linux-2.6.31.6/arch/mips/kernel/traps.c 2009-09-10 15:25:38.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/mips/kernel/traps.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/mips/kernel/traps.c linux-2.6.32-vs2.3.0.36.26/arch/mips/kernel/traps.c
+--- linux-2.6.32/arch/mips/kernel/traps.c 2009-12-03 20:01:59.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/mips/kernel/traps.c 2009-12-03 20:04:56.000000000 +0100
@@ -335,9 +335,10 @@ void show_registers(const struct pt_regs
__show_regs(regs);
if (cpu_has_userlocal) {
unsigned long tls;
-diff -NurpP --minimal linux-2.6.31.6/arch/mn10300/mm/fault.c linux-2.6.31.6-vs2.3.0.36.24/arch/mn10300/mm/fault.c
---- linux-2.6.31.6/arch/mn10300/mm/fault.c 2009-09-10 15:25:39.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/mn10300/mm/fault.c 2009-09-29 17:28:34.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/mn10300/mm/fault.c linux-2.6.32-vs2.3.0.36.26/arch/mn10300/mm/fault.c
+--- linux-2.6.32/arch/mn10300/mm/fault.c 2009-09-10 15:25:39.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/mn10300/mm/fault.c 2009-12-03 20:04:56.000000000 +0100
@@ -339,7 +339,8 @@ no_context:
out_of_memory:
up_read(&mm->mmap_sem);
if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR)
do_exit(SIGKILL);
goto no_context;
-diff -NurpP --minimal linux-2.6.31.6/arch/parisc/Kconfig linux-2.6.31.6-vs2.3.0.36.24/arch/parisc/Kconfig
---- linux-2.6.31.6/arch/parisc/Kconfig 2009-09-10 15:25:39.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/parisc/Kconfig 2009-09-10 16:11:43.000000000 +0200
-@@ -293,6 +293,8 @@ source "fs/Kconfig"
+diff -NurpP --minimal linux-2.6.32/arch/parisc/Kconfig linux-2.6.32-vs2.3.0.36.26/arch/parisc/Kconfig
+--- linux-2.6.32/arch/parisc/Kconfig 2009-12-03 20:02:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/parisc/Kconfig 2009-12-03 20:04:56.000000000 +0100
+@@ -294,6 +294,8 @@ source "fs/Kconfig"
source "arch/parisc/Kconfig.debug"
source "security/Kconfig"
source "crypto/Kconfig"
-diff -NurpP --minimal linux-2.6.31.6/arch/parisc/kernel/syscall_table.S linux-2.6.31.6-vs2.3.0.36.24/arch/parisc/kernel/syscall_table.S
---- linux-2.6.31.6/arch/parisc/kernel/syscall_table.S 2009-09-10 15:25:40.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/parisc/kernel/syscall_table.S 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/parisc/kernel/syscall_table.S linux-2.6.32-vs2.3.0.36.26/arch/parisc/kernel/syscall_table.S
+--- linux-2.6.32/arch/parisc/kernel/syscall_table.S 2009-12-03 20:02:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/parisc/kernel/syscall_table.S 2009-12-03 20:04:56.000000000 +0100
@@ -361,7 +361,7 @@
ENTRY_COMP(mbind) /* 260 */
ENTRY_COMP(get_mempolicy)
ENTRY_SAME(add_key)
ENTRY_SAME(request_key) /* 265 */
ENTRY_SAME(keyctl)
-diff -NurpP --minimal linux-2.6.31.6/arch/parisc/kernel/traps.c linux-2.6.31.6-vs2.3.0.36.24/arch/parisc/kernel/traps.c
---- linux-2.6.31.6/arch/parisc/kernel/traps.c 2009-09-10 15:25:40.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/parisc/kernel/traps.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/parisc/kernel/traps.c linux-2.6.32-vs2.3.0.36.26/arch/parisc/kernel/traps.c
+--- linux-2.6.32/arch/parisc/kernel/traps.c 2009-09-10 15:25:40.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/parisc/kernel/traps.c 2009-12-03 20:04:56.000000000 +0100
@@ -236,8 +236,9 @@ void die_if_kernel(char *str, struct pt_
if (err == 0)
return; /* STFU */
/* Wot's wrong wif bein' racy? */
if (current->thread.flags & PARISC_KERNEL_DEATH) {
-diff -NurpP --minimal linux-2.6.31.6/arch/parisc/mm/fault.c linux-2.6.31.6-vs2.3.0.36.24/arch/parisc/mm/fault.c
---- linux-2.6.31.6/arch/parisc/mm/fault.c 2009-09-10 15:25:40.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/parisc/mm/fault.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/parisc/mm/fault.c linux-2.6.32-vs2.3.0.36.26/arch/parisc/mm/fault.c
+--- linux-2.6.32/arch/parisc/mm/fault.c 2009-09-10 15:25:40.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/parisc/mm/fault.c 2009-12-03 20:04:56.000000000 +0100
@@ -237,8 +237,9 @@ bad_area:
#ifdef PRINT_USER_FAULTS
if (user_mode(regs))
do_group_exit(SIGKILL);
goto no_context;
-diff -NurpP --minimal linux-2.6.31.6/arch/powerpc/include/asm/unistd.h linux-2.6.31.6-vs2.3.0.36.24/arch/powerpc/include/asm/unistd.h
---- linux-2.6.31.6/arch/powerpc/include/asm/unistd.h 2009-09-10 15:25:41.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/powerpc/include/asm/unistd.h 2009-10-22 01:07:37.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/powerpc/include/asm/unistd.h linux-2.6.32-vs2.3.0.36.26/arch/powerpc/include/asm/unistd.h
+--- linux-2.6.32/arch/powerpc/include/asm/unistd.h 2009-12-03 20:02:01.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/powerpc/include/asm/unistd.h 2009-12-03 20:04:56.000000000 +0100
@@ -275,7 +275,7 @@
#endif
#define __NR_rtas 255
#define __NR_migrate_pages 258
#define __NR_mbind 259
#define __NR_get_mempolicy 260
-diff -NurpP --minimal linux-2.6.31.6/arch/powerpc/Kconfig linux-2.6.31.6-vs2.3.0.36.24/arch/powerpc/Kconfig
---- linux-2.6.31.6/arch/powerpc/Kconfig 2009-09-10 15:25:40.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/powerpc/Kconfig 2009-09-10 16:11:43.000000000 +0200
-@@ -933,6 +933,8 @@ source "lib/Kconfig"
+diff -NurpP --minimal linux-2.6.32/arch/powerpc/Kconfig linux-2.6.32-vs2.3.0.36.26/arch/powerpc/Kconfig
+--- linux-2.6.32/arch/powerpc/Kconfig 2009-12-03 20:02:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/powerpc/Kconfig 2009-12-03 20:04:56.000000000 +0100
+@@ -943,6 +943,8 @@ source "lib/Kconfig"
source "arch/powerpc/Kconfig.debug"
source "security/Kconfig"
config KEYS_COMPAT
-diff -NurpP --minimal linux-2.6.31.6/arch/powerpc/kernel/irq.c linux-2.6.31.6-vs2.3.0.36.24/arch/powerpc/kernel/irq.c
---- linux-2.6.31.6/arch/powerpc/kernel/irq.c 2009-09-10 15:25:41.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/powerpc/kernel/irq.c 2009-09-10 16:15:56.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/powerpc/kernel/irq.c linux-2.6.32-vs2.3.0.36.26/arch/powerpc/kernel/irq.c
+--- linux-2.6.32/arch/powerpc/kernel/irq.c 2009-12-03 20:02:01.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/powerpc/kernel/irq.c 2009-12-03 20:04:56.000000000 +0100
@@ -54,6 +54,7 @@
#include <linux/pci.h>
#include <linux/debugfs.h>
- #include <linux/perf_counter.h>
-+#include <linux/vs_context.h>
+ #include <linux/perf_event.h>
++// #include <linux/vs_context.h>
#include <asm/uaccess.h>
#include <asm/system.h>
-diff -NurpP --minimal linux-2.6.31.6/arch/powerpc/kernel/process.c linux-2.6.31.6-vs2.3.0.36.24/arch/powerpc/kernel/process.c
---- linux-2.6.31.6/arch/powerpc/kernel/process.c 2009-09-10 15:25:41.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/powerpc/kernel/process.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/powerpc/kernel/process.c linux-2.6.32-vs2.3.0.36.26/arch/powerpc/kernel/process.c
+--- linux-2.6.32/arch/powerpc/kernel/process.c 2009-12-03 20:02:02.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/powerpc/kernel/process.c 2009-12-03 20:04:56.000000000 +0100
@@ -519,8 +519,9 @@ void show_regs(struct pt_regs * regs)
#else
printk("DAR: "REG", DSISR: "REG"\n", regs->dar, regs->dsisr);
#ifdef CONFIG_SMP
printk(" CPU: %d", raw_smp_processor_id());
-diff -NurpP --minimal linux-2.6.31.6/arch/powerpc/kernel/traps.c linux-2.6.31.6-vs2.3.0.36.24/arch/powerpc/kernel/traps.c
---- linux-2.6.31.6/arch/powerpc/kernel/traps.c 2009-09-10 15:25:41.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/powerpc/kernel/traps.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/powerpc/kernel/traps.c linux-2.6.32-vs2.3.0.36.26/arch/powerpc/kernel/traps.c
+--- linux-2.6.32/arch/powerpc/kernel/traps.c 2009-09-10 15:25:41.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/powerpc/kernel/traps.c 2009-12-03 20:04:56.000000000 +0100
@@ -931,8 +931,9 @@ void nonrecoverable_exception(struct pt_
void trace_syscall(struct pt_regs *regs)
regs->ccr&0x10000000?"Error=":"", regs->gpr[3], print_tainted());
}
-diff -NurpP --minimal linux-2.6.31.6/arch/powerpc/kernel/vdso.c linux-2.6.31.6-vs2.3.0.36.24/arch/powerpc/kernel/vdso.c
---- linux-2.6.31.6/arch/powerpc/kernel/vdso.c 2009-03-24 14:18:35.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/powerpc/kernel/vdso.c 2009-09-10 16:11:43.000000000 +0200
-@@ -22,6 +22,7 @@
+diff -NurpP --minimal linux-2.6.32/arch/powerpc/kernel/vdso.c linux-2.6.32-vs2.3.0.36.26/arch/powerpc/kernel/vdso.c
+--- linux-2.6.32/arch/powerpc/kernel/vdso.c 2009-12-03 20:02:02.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/powerpc/kernel/vdso.c 2009-12-03 20:04:56.000000000 +0100
+@@ -23,6 +23,7 @@
#include <linux/security.h>
#include <linux/bootmem.h>
#include <linux/lmb.h>
#include <asm/pgtable.h>
#include <asm/system.h>
-diff -NurpP --minimal linux-2.6.31.6/arch/powerpc/mm/fault.c linux-2.6.31.6-vs2.3.0.36.24/arch/powerpc/mm/fault.c
---- linux-2.6.31.6/arch/powerpc/mm/fault.c 2009-09-10 15:25:41.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/powerpc/mm/fault.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/powerpc/mm/fault.c linux-2.6.32-vs2.3.0.36.26/arch/powerpc/mm/fault.c
+--- linux-2.6.32/arch/powerpc/mm/fault.c 2009-12-03 20:02:02.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/powerpc/mm/fault.c 2009-12-03 20:04:56.000000000 +0100
@@ -358,7 +358,8 @@ out_of_memory:
down_read(&mm->mmap_sem);
goto survive;
if (user_mode(regs))
do_group_exit(SIGKILL);
return SIGKILL;
-diff -NurpP --minimal linux-2.6.31.6/arch/s390/Kconfig linux-2.6.31.6-vs2.3.0.36.24/arch/s390/Kconfig
---- linux-2.6.31.6/arch/s390/Kconfig 2009-09-10 15:25:42.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/s390/Kconfig 2009-09-10 16:11:43.000000000 +0200
-@@ -624,6 +624,8 @@ source "fs/Kconfig"
+diff -NurpP --minimal linux-2.6.32/arch/s390/Kconfig linux-2.6.32-vs2.3.0.36.26/arch/s390/Kconfig
+--- linux-2.6.32/arch/s390/Kconfig 2009-12-03 20:02:03.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/s390/Kconfig 2009-12-03 20:04:56.000000000 +0100
+@@ -616,6 +616,8 @@ source "fs/Kconfig"
source "arch/s390/Kconfig.debug"
source "security/Kconfig"
source "crypto/Kconfig"
-diff -NurpP --minimal linux-2.6.31.6/arch/s390/kernel/ptrace.c linux-2.6.31.6-vs2.3.0.36.24/arch/s390/kernel/ptrace.c
---- linux-2.6.31.6/arch/s390/kernel/ptrace.c 2009-09-10 15:25:43.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/s390/kernel/ptrace.c 2009-09-10 16:17:22.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/s390/kernel/ptrace.c linux-2.6.32-vs2.3.0.36.26/arch/s390/kernel/ptrace.c
+--- linux-2.6.32/arch/s390/kernel/ptrace.c 2009-12-03 20:02:03.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/s390/kernel/ptrace.c 2009-12-03 20:04:56.000000000 +0100
@@ -36,6 +36,7 @@
#include <linux/regset.h>
#include <linux/tracehook.h>
#include <trace/syscall.h>
#include <asm/compat.h>
#include <asm/segment.h>
-diff -NurpP --minimal linux-2.6.31.6/arch/s390/kernel/syscalls.S linux-2.6.31.6-vs2.3.0.36.24/arch/s390/kernel/syscalls.S
---- linux-2.6.31.6/arch/s390/kernel/syscalls.S 2009-09-10 15:25:43.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/s390/kernel/syscalls.S 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/s390/kernel/syscalls.S linux-2.6.32-vs2.3.0.36.26/arch/s390/kernel/syscalls.S
+--- linux-2.6.32/arch/s390/kernel/syscalls.S 2009-12-03 20:02:03.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/s390/kernel/syscalls.S 2009-12-03 20:04:56.000000000 +0100
@@ -271,7 +271,7 @@ SYSCALL(sys_clock_settime,sys_clock_sett
SYSCALL(sys_clock_gettime,sys_clock_gettime,sys32_clock_gettime_wrapper) /* 260 */
SYSCALL(sys_clock_getres,sys_clock_getres,sys32_clock_getres_wrapper)
SYSCALL(sys_s390_fadvise64_64,sys_ni_syscall,sys32_fadvise64_64_wrapper)
SYSCALL(sys_statfs64,sys_statfs64,compat_sys_statfs64_wrapper)
SYSCALL(sys_fstatfs64,sys_fstatfs64,compat_sys_fstatfs64_wrapper)
-diff -NurpP --minimal linux-2.6.31.6/arch/s390/lib/uaccess_pt.c linux-2.6.31.6-vs2.3.0.36.24/arch/s390/lib/uaccess_pt.c
---- linux-2.6.31.6/arch/s390/lib/uaccess_pt.c 2009-09-10 15:25:43.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/s390/lib/uaccess_pt.c 2009-09-29 17:29:02.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/s390/lib/uaccess_pt.c linux-2.6.32-vs2.3.0.36.26/arch/s390/lib/uaccess_pt.c
+--- linux-2.6.32/arch/s390/lib/uaccess_pt.c 2009-09-10 15:25:43.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/s390/lib/uaccess_pt.c 2009-12-03 20:04:56.000000000 +0100
@@ -90,7 +90,8 @@ out_of_memory:
down_read(&mm->mmap_sem);
goto survive;
return ret;
out_sigbus:
-diff -NurpP --minimal linux-2.6.31.6/arch/sh/Kconfig linux-2.6.31.6-vs2.3.0.36.24/arch/sh/Kconfig
---- linux-2.6.31.6/arch/sh/Kconfig 2009-09-10 15:25:43.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/sh/Kconfig 2009-09-10 16:11:43.000000000 +0200
-@@ -813,6 +813,8 @@ source "fs/Kconfig"
+diff -NurpP --minimal linux-2.6.32/arch/sh/Kconfig linux-2.6.32-vs2.3.0.36.26/arch/sh/Kconfig
+--- linux-2.6.32/arch/sh/Kconfig 2009-12-03 20:02:03.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/sh/Kconfig 2009-12-03 20:04:56.000000000 +0100
+@@ -853,6 +853,8 @@ source "fs/Kconfig"
source "arch/sh/Kconfig.debug"
source "security/Kconfig"
source "crypto/Kconfig"
-diff -NurpP --minimal linux-2.6.31.6/arch/sh/kernel/irq.c linux-2.6.31.6-vs2.3.0.36.24/arch/sh/kernel/irq.c
---- linux-2.6.31.6/arch/sh/kernel/irq.c 2009-09-10 15:25:45.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/sh/kernel/irq.c 2009-09-10 16:11:43.000000000 +0200
-@@ -11,6 +11,7 @@
- #include <linux/module.h>
+diff -NurpP --minimal linux-2.6.32/arch/sh/kernel/irq.c linux-2.6.32-vs2.3.0.36.26/arch/sh/kernel/irq.c
+--- linux-2.6.32/arch/sh/kernel/irq.c 2009-12-03 20:02:10.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/sh/kernel/irq.c 2009-12-03 20:04:56.000000000 +0100
+@@ -12,6 +12,7 @@
#include <linux/kernel_stat.h>
#include <linux/seq_file.h>
-+#include <linux/vs_context.h>
+ #include <linux/ftrace.h>
++// #include <linux/vs_context.h>
#include <asm/processor.h>
#include <asm/machvec.h>
#include <asm/uaccess.h>
-diff -NurpP --minimal linux-2.6.31.6/arch/sh/kernel/vsyscall/vsyscall.c linux-2.6.31.6-vs2.3.0.36.24/arch/sh/kernel/vsyscall/vsyscall.c
---- linux-2.6.31.6/arch/sh/kernel/vsyscall/vsyscall.c 2009-03-24 14:18:42.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/sh/kernel/vsyscall/vsyscall.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/sh/kernel/vsyscall/vsyscall.c linux-2.6.32-vs2.3.0.36.26/arch/sh/kernel/vsyscall/vsyscall.c
+--- linux-2.6.32/arch/sh/kernel/vsyscall/vsyscall.c 2009-03-24 14:18:42.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/sh/kernel/vsyscall/vsyscall.c 2009-12-03 20:04:56.000000000 +0100
@@ -19,6 +19,7 @@
#include <linux/elf.h>
#include <linux/sched.h>
/*
* Should the kernel map a VDSO page into processes and pass its
-diff -NurpP --minimal linux-2.6.31.6/arch/sh/mm/fault_32.c linux-2.6.31.6-vs2.3.0.36.24/arch/sh/mm/fault_32.c
---- linux-2.6.31.6/arch/sh/mm/fault_32.c 2009-09-10 15:25:45.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/sh/mm/fault_32.c 2009-09-29 17:29:36.000000000 +0200
-@@ -246,7 +246,8 @@ out_of_memory:
+diff -NurpP --minimal linux-2.6.32/arch/sh/mm/fault_32.c linux-2.6.32-vs2.3.0.36.26/arch/sh/mm/fault_32.c
+--- linux-2.6.32/arch/sh/mm/fault_32.c 2009-12-03 20:02:14.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/sh/mm/fault_32.c 2009-12-03 20:04:56.000000000 +0100
+@@ -292,7 +292,8 @@ out_of_memory:
down_read(&mm->mmap_sem);
goto survive;
}
if (user_mode(regs))
do_group_exit(SIGKILL);
goto no_context;
-diff -NurpP --minimal linux-2.6.31.6/arch/sh/mm/tlbflush_64.c linux-2.6.31.6-vs2.3.0.36.24/arch/sh/mm/tlbflush_64.c
---- linux-2.6.31.6/arch/sh/mm/tlbflush_64.c 2009-09-10 15:25:45.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/sh/mm/tlbflush_64.c 2009-09-29 17:29:54.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/sh/mm/tlbflush_64.c linux-2.6.32-vs2.3.0.36.26/arch/sh/mm/tlbflush_64.c
+--- linux-2.6.32/arch/sh/mm/tlbflush_64.c 2009-12-03 20:02:14.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/sh/mm/tlbflush_64.c 2009-12-03 20:04:56.000000000 +0100
@@ -306,7 +306,8 @@ out_of_memory:
down_read(&mm->mmap_sem);
goto survive;
if (user_mode(regs))
do_group_exit(SIGKILL);
goto no_context;
-diff -NurpP --minimal linux-2.6.31.6/arch/sparc/include/asm/tlb_64.h linux-2.6.31.6-vs2.3.0.36.24/arch/sparc/include/asm/tlb_64.h
---- linux-2.6.31.6/arch/sparc/include/asm/tlb_64.h 2009-09-10 15:25:45.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/sparc/include/asm/tlb_64.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/sparc/include/asm/tlb_64.h linux-2.6.32-vs2.3.0.36.26/arch/sparc/include/asm/tlb_64.h
+--- linux-2.6.32/arch/sparc/include/asm/tlb_64.h 2009-09-10 15:25:45.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/sparc/include/asm/tlb_64.h 2009-12-03 20:04:56.000000000 +0100
@@ -3,6 +3,7 @@
#include <linux/swap.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
#include <asm/mmu_context.h>
-diff -NurpP --minimal linux-2.6.31.6/arch/sparc/include/asm/unistd.h linux-2.6.31.6-vs2.3.0.36.24/arch/sparc/include/asm/unistd.h
---- linux-2.6.31.6/arch/sparc/include/asm/unistd.h 2009-09-10 15:25:45.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/sparc/include/asm/unistd.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/sparc/include/asm/unistd.h linux-2.6.32-vs2.3.0.36.26/arch/sparc/include/asm/unistd.h
+--- linux-2.6.32/arch/sparc/include/asm/unistd.h 2009-12-03 20:02:15.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/sparc/include/asm/unistd.h 2009-12-03 20:04:56.000000000 +0100
@@ -335,7 +335,7 @@
#define __NR_timer_getoverrun 264
#define __NR_timer_delete 265
#define __NR_io_setup 268
#define __NR_io_destroy 269
#define __NR_io_submit 270
-diff -NurpP --minimal linux-2.6.31.6/arch/sparc/Kconfig linux-2.6.31.6-vs2.3.0.36.24/arch/sparc/Kconfig
---- linux-2.6.31.6/arch/sparc/Kconfig 2009-09-10 15:25:45.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/sparc/Kconfig 2009-09-10 16:11:43.000000000 +0200
-@@ -530,6 +530,8 @@ source "fs/Kconfig"
+diff -NurpP --minimal linux-2.6.32/arch/sparc/Kconfig linux-2.6.32-vs2.3.0.36.26/arch/sparc/Kconfig
+--- linux-2.6.32/arch/sparc/Kconfig 2009-12-03 20:02:14.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/sparc/Kconfig 2009-12-03 20:04:56.000000000 +0100
+@@ -550,6 +550,8 @@ source "fs/Kconfig"
source "arch/sparc/Kconfig.debug"
source "security/Kconfig"
source "crypto/Kconfig"
-diff -NurpP --minimal linux-2.6.31.6/arch/sparc/kernel/systbls_32.S linux-2.6.31.6-vs2.3.0.36.24/arch/sparc/kernel/systbls_32.S
---- linux-2.6.31.6/arch/sparc/kernel/systbls_32.S 2009-09-10 15:25:45.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/sparc/kernel/systbls_32.S 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/sparc/kernel/systbls_32.S linux-2.6.32-vs2.3.0.36.26/arch/sparc/kernel/systbls_32.S
+--- linux-2.6.32/arch/sparc/kernel/systbls_32.S 2009-12-03 20:02:15.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/sparc/kernel/systbls_32.S 2009-12-03 20:04:56.000000000 +0100
@@ -70,7 +70,7 @@ sys_call_table:
/*250*/ .long sparc_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
/*255*/ .long sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
/*270*/ .long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
/*275*/ .long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
/*280*/ .long sys_tee, sys_add_key, sys_request_key, sys_keyctl, sys_openat
-diff -NurpP --minimal linux-2.6.31.6/arch/sparc/kernel/systbls_64.S linux-2.6.31.6-vs2.3.0.36.24/arch/sparc/kernel/systbls_64.S
---- linux-2.6.31.6/arch/sparc/kernel/systbls_64.S 2009-09-10 15:25:45.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/sparc/kernel/systbls_64.S 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/sparc/kernel/systbls_64.S linux-2.6.32-vs2.3.0.36.26/arch/sparc/kernel/systbls_64.S
+--- linux-2.6.32/arch/sparc/kernel/systbls_64.S 2009-12-03 20:02:15.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/sparc/kernel/systbls_64.S 2009-12-03 20:04:56.000000000 +0100
@@ -71,7 +71,7 @@ sys_call_table32:
/*250*/ .word sys32_mremap, sys32_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl
.word sys32_sync_file_range, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep
/*270*/ .word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
.word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
/*280*/ .word sys_tee, sys_add_key, sys_request_key, sys_keyctl, sys_openat
-diff -NurpP --minimal linux-2.6.31.6/arch/x86/ia32/ia32entry.S linux-2.6.31.6-vs2.3.0.36.24/arch/x86/ia32/ia32entry.S
---- linux-2.6.31.6/arch/x86/ia32/ia32entry.S 2009-11-12 12:10:08.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/x86/ia32/ia32entry.S 2009-11-12 12:26:38.000000000 +0100
+diff -NurpP --minimal linux-2.6.32/arch/x86/ia32/ia32entry.S linux-2.6.32-vs2.3.0.36.26/arch/x86/ia32/ia32entry.S
+--- linux-2.6.32/arch/x86/ia32/ia32entry.S 2009-12-03 20:02:15.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/x86/ia32/ia32entry.S 2009-12-03 20:04:56.000000000 +0100
@@ -777,7 +777,7 @@ ia32_sys_call_table:
.quad sys_tgkill /* 270 */
.quad compat_sys_utimes
.quad sys_mbind
.quad compat_sys_get_mempolicy /* 275 */
.quad sys_set_mempolicy
-diff -NurpP --minimal linux-2.6.31.6/arch/x86/include/asm/unistd_64.h linux-2.6.31.6-vs2.3.0.36.24/arch/x86/include/asm/unistd_64.h
---- linux-2.6.31.6/arch/x86/include/asm/unistd_64.h 2009-09-10 15:25:47.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/x86/include/asm/unistd_64.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/x86/include/asm/unistd_64.h linux-2.6.32-vs2.3.0.36.26/arch/x86/include/asm/unistd_64.h
+--- linux-2.6.32/arch/x86/include/asm/unistd_64.h 2009-12-03 20:02:16.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/x86/include/asm/unistd_64.h 2009-12-03 20:04:56.000000000 +0100
@@ -535,7 +535,7 @@ __SYSCALL(__NR_tgkill, sys_tgkill)
#define __NR_utimes 235
__SYSCALL(__NR_utimes, sys_utimes)
#define __NR_mbind 237
__SYSCALL(__NR_mbind, sys_mbind)
#define __NR_set_mempolicy 238
-diff -NurpP --minimal linux-2.6.31.6/arch/x86/Kconfig linux-2.6.31.6-vs2.3.0.36.24/arch/x86/Kconfig
---- linux-2.6.31.6/arch/x86/Kconfig 2009-09-10 15:25:46.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/x86/Kconfig 2009-09-10 16:11:43.000000000 +0200
-@@ -2088,6 +2088,8 @@ source "fs/Kconfig"
+diff -NurpP --minimal linux-2.6.32/arch/x86/Kconfig linux-2.6.32-vs2.3.0.36.26/arch/x86/Kconfig
+--- linux-2.6.32/arch/x86/Kconfig 2009-12-03 20:02:15.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/x86/Kconfig 2009-12-03 20:04:56.000000000 +0100
+@@ -2085,6 +2085,8 @@ source "fs/Kconfig"
source "arch/x86/Kconfig.debug"
source "security/Kconfig"
source "crypto/Kconfig"
-diff -NurpP --minimal linux-2.6.31.6/arch/x86/kernel/syscall_table_32.S linux-2.6.31.6-vs2.3.0.36.24/arch/x86/kernel/syscall_table_32.S
---- linux-2.6.31.6/arch/x86/kernel/syscall_table_32.S 2009-09-10 15:25:47.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/x86/kernel/syscall_table_32.S 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/x86/kernel/syscall_table_32.S linux-2.6.32-vs2.3.0.36.26/arch/x86/kernel/syscall_table_32.S
+--- linux-2.6.32/arch/x86/kernel/syscall_table_32.S 2009-12-03 20:02:16.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/arch/x86/kernel/syscall_table_32.S 2009-12-03 20:04:56.000000000 +0100
@@ -272,7 +272,7 @@ ENTRY(sys_call_table)
.long sys_tgkill /* 270 */
.long sys_utimes
.long sys_mbind
.long sys_get_mempolicy
.long sys_set_mempolicy
-diff -NurpP --minimal linux-2.6.31.6/arch/xtensa/mm/fault.c linux-2.6.31.6-vs2.3.0.36.24/arch/xtensa/mm/fault.c
---- linux-2.6.31.6/arch/xtensa/mm/fault.c 2009-09-10 15:25:48.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/arch/xtensa/mm/fault.c 2009-09-29 17:30:14.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/arch/xtensa/mm/fault.c linux-2.6.32-vs2.3.0.36.26/arch/xtensa/mm/fault.c
+--- linux-2.6.32/arch/xtensa/mm/fault.c 2009-09-10 15:25:48.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/arch/xtensa/mm/fault.c 2009-12-03 20:04:56.000000000 +0100
@@ -151,7 +151,8 @@ out_of_memory:
down_read(&mm->mmap_sem);
goto survive;
if (user_mode(regs))
do_group_exit(SIGKILL);
bad_page_fault(regs, address, SIGKILL);
-diff -NurpP --minimal linux-2.6.31.6/Documentation/scheduler/sched-cfs-hard-limits.txt linux-2.6.31.6-vs2.3.0.36.24/Documentation/scheduler/sched-cfs-hard-limits.txt
---- linux-2.6.31.6/Documentation/scheduler/sched-cfs-hard-limits.txt 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/Documentation/scheduler/sched-cfs-hard-limits.txt 2009-10-06 04:39:46.000000000 +0200
-@@ -0,0 +1,52 @@
+diff -NurpP --minimal linux-2.6.32/Documentation/scheduler/sched-cfs-hard-limits.txt linux-2.6.32-vs2.3.0.36.26/Documentation/scheduler/sched-cfs-hard-limits.txt
+--- linux-2.6.32/Documentation/scheduler/sched-cfs-hard-limits.txt 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/Documentation/scheduler/sched-cfs-hard-limits.txt 2009-12-03 20:04:56.000000000 +0100
+@@ -0,0 +1,48 @@
+CPU HARD LIMITS FOR CFS GROUPS
+==============================
+
+2. Interface
+------------
+
-+Hard limit feature adds 3 cgroup files for CFS group scheduler:
++Hard limit feature adds 2 cgroup files for CFS group scheduler:
+
+cfs_runtime_us: Hard limit for the group in microseconds.
+
+cfs_period_us: Time period in microseconds within which hard limits is
+enforced.
+
-+cfs_hard_limit: The control file to enable or disable hard limiting for the
-+group.
-+
-+A group gets created with default values for runtime and period and with
-+hard limit disabled. Each group can set its own values for runtime and period
-+independent of other groups in the system.
++A group gets created with default values for runtime (infinite runtime which
++means hard limits disabled) and period (0.5s). Each group can set its own
++values for runtime and period independent of other groups in the system.
+
+3. Examples
+-----------
+# cd 1/
+# echo 250000 > cfs_runtime_us /* set a 250ms runtime or limit */
+# echo 500000 > cfs_period_us /* set a 500ms period */
-+# echo 1 > cfs_hard_limit /* enable hard limiting for group 1/ */
-diff -NurpP --minimal linux-2.6.31.6/Documentation/vserver/debug.txt linux-2.6.31.6-vs2.3.0.36.24/Documentation/vserver/debug.txt
---- linux-2.6.31.6/Documentation/vserver/debug.txt 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/Documentation/vserver/debug.txt 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/Documentation/vserver/debug.txt linux-2.6.32-vs2.3.0.36.26/Documentation/vserver/debug.txt
+--- linux-2.6.32/Documentation/vserver/debug.txt 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/Documentation/vserver/debug.txt 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,154 @@
+
+debug_cvirt:
+ m 2^m "vx_acc_page[%5d,%s,%2d]: %5d%s"
+ "vx_acc_pages[%5d,%s,%2d]: %5d += %5d"
+ "vx_pages_avail[%5d,%s,%2d]: %5ld > %5d + %5d"
-diff -NurpP --minimal linux-2.6.31.6/drivers/block/Kconfig linux-2.6.31.6-vs2.3.0.36.24/drivers/block/Kconfig
---- linux-2.6.31.6/drivers/block/Kconfig 2009-09-10 15:25:49.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/drivers/block/Kconfig 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/drivers/block/Kconfig linux-2.6.32-vs2.3.0.36.26/drivers/block/Kconfig
+--- linux-2.6.32/drivers/block/Kconfig 2009-09-10 15:25:49.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/drivers/block/Kconfig 2009-12-03 20:04:56.000000000 +0100
@@ -271,6 +271,13 @@ config BLK_DEV_CRYPTOLOOP
instead, which can be configured to be on-disk compatible with the
cryptoloop device.
config BLK_DEV_NBD
tristate "Network block device support"
depends on NET
-diff -NurpP --minimal linux-2.6.31.6/drivers/block/loop.c linux-2.6.31.6-vs2.3.0.36.24/drivers/block/loop.c
---- linux-2.6.31.6/drivers/block/loop.c 2009-09-10 15:25:49.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/drivers/block/loop.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/drivers/block/loop.c linux-2.6.32-vs2.3.0.36.26/drivers/block/loop.c
+--- linux-2.6.32/drivers/block/loop.c 2009-12-03 20:02:19.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/drivers/block/loop.c 2009-12-03 20:04:56.000000000 +0100
@@ -74,6 +74,7 @@
#include <linux/gfp.h>
#include <linux/kthread.h>
mutex_lock(&lo->lo_ctl_mutex);
lo->lo_refcnt++;
mutex_unlock(&lo->lo_ctl_mutex);
-diff -NurpP --minimal linux-2.6.31.6/drivers/block/Makefile linux-2.6.31.6-vs2.3.0.36.24/drivers/block/Makefile
---- linux-2.6.31.6/drivers/block/Makefile 2009-09-10 15:25:49.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/drivers/block/Makefile 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/drivers/block/Makefile linux-2.6.32-vs2.3.0.36.26/drivers/block/Makefile
+--- linux-2.6.32/drivers/block/Makefile 2009-09-10 15:25:49.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/drivers/block/Makefile 2009-12-03 20:04:56.000000000 +0100
@@ -34,6 +34,7 @@ obj-$(CONFIG_VIODASD) += viodasd.o
obj-$(CONFIG_BLK_DEV_SX8) += sx8.o
obj-$(CONFIG_BLK_DEV_UB) += ub.o
obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o
-diff -NurpP --minimal linux-2.6.31.6/drivers/block/vroot.c linux-2.6.31.6-vs2.3.0.36.24/drivers/block/vroot.c
---- linux-2.6.31.6/drivers/block/vroot.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/drivers/block/vroot.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/drivers/block/vroot.c linux-2.6.32-vs2.3.0.36.26/drivers/block/vroot.c
+--- linux-2.6.32/drivers/block/vroot.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/drivers/block/vroot.c 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,281 @@
+/*
+ * linux/drivers/block/vroot.c
+
+#endif
+
-diff -NurpP --minimal linux-2.6.31.6/drivers/char/sysrq.c linux-2.6.31.6-vs2.3.0.36.24/drivers/char/sysrq.c
---- linux-2.6.31.6/drivers/char/sysrq.c 2009-09-10 15:25:50.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/drivers/char/sysrq.c 2009-09-10 16:11:43.000000000 +0200
-@@ -37,6 +37,7 @@
+diff -NurpP --minimal linux-2.6.32/drivers/char/sysrq.c linux-2.6.32-vs2.3.0.36.26/drivers/char/sysrq.c
+--- linux-2.6.32/drivers/char/sysrq.c 2009-12-03 20:02:20.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/drivers/char/sysrq.c 2009-12-03 20:04:56.000000000 +0100
+@@ -38,6 +38,7 @@
#include <linux/workqueue.h>
#include <linux/hrtimer.h>
#include <linux/oom.h>
#include <asm/ptrace.h>
#include <asm/irq_regs.h>
-@@ -382,6 +383,21 @@ static struct sysrq_key_op sysrq_unrt_op
+@@ -391,6 +392,21 @@ static struct sysrq_key_op sysrq_unrt_op
.enable_mask = SYSRQ_ENABLE_RTNICE,
};
/* Key Operations table and lock */
static DEFINE_SPINLOCK(sysrq_key_table_lock);
-@@ -436,7 +452,11 @@ static struct sysrq_key_op *sysrq_key_ta
+@@ -445,7 +461,11 @@ static struct sysrq_key_op *sysrq_key_ta
NULL, /* v */
&sysrq_showstate_blocked_op, /* w */
/* x: May be registered on ppc/powerpc for xmon */
/* y: May be registered on sparc64 for global register dump */
NULL, /* y */
&sysrq_ftrace_dump_op, /* z */
-@@ -451,6 +471,8 @@ static int sysrq_key_table_key2index(int
+@@ -460,6 +480,8 @@ static int sysrq_key_table_key2index(int
retval = key - '0';
else if ((key >= 'a') && (key <= 'z'))
retval = key + 10 - 'a';
else
retval = -1;
return retval;
-diff -NurpP --minimal linux-2.6.31.6/drivers/char/tty_io.c linux-2.6.31.6-vs2.3.0.36.24/drivers/char/tty_io.c
---- linux-2.6.31.6/drivers/char/tty_io.c 2009-11-12 12:10:09.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/drivers/char/tty_io.c 2009-10-05 23:35:52.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/drivers/char/tty_io.c linux-2.6.32-vs2.3.0.36.26/drivers/char/tty_io.c
+--- linux-2.6.32/drivers/char/tty_io.c 2009-12-03 20:02:20.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/drivers/char/tty_io.c 2009-12-03 20:04:56.000000000 +0100
@@ -106,6 +106,7 @@
#include <linux/kmod.h>
#undef TTY_DEBUG_HANGUP
-@@ -2236,6 +2237,7 @@ static int tiocspgrp(struct tty_struct *
+@@ -1966,7 +1967,8 @@ static int tiocsti(struct tty_struct *tt
+ char ch, mbz = 0;
+ struct tty_ldisc *ld;
+
+- if ((current->signal->tty != tty) && !capable(CAP_SYS_ADMIN))
++ if (((current->signal->tty != tty) && !capable(CAP_SYS_ADMIN)) ||
++ !vx_ccaps(VXC_TIOCSTI))
+ return -EPERM;
+ if (get_user(ch, p))
+ return -EFAULT;
+@@ -2254,6 +2256,7 @@ static int tiocspgrp(struct tty_struct *
return -ENOTTY;
if (get_user(pgrp_nr, p))
return -EFAULT;
if (pgrp_nr < 0)
return -EINVAL;
rcu_read_lock();
-diff -NurpP --minimal linux-2.6.31.6/drivers/infiniband/hw/ipath/ipath_user_pages.c linux-2.6.31.6-vs2.3.0.36.24/drivers/infiniband/hw/ipath/ipath_user_pages.c
---- linux-2.6.31.6/drivers/infiniband/hw/ipath/ipath_user_pages.c 2009-06-11 17:12:30.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/drivers/infiniband/hw/ipath/ipath_user_pages.c 2009-09-10 16:11:43.000000000 +0200
-@@ -33,6 +33,7 @@
-
+diff -NurpP --minimal linux-2.6.32/drivers/infiniband/hw/ipath/ipath_user_pages.c linux-2.6.32-vs2.3.0.36.26/drivers/infiniband/hw/ipath/ipath_user_pages.c
+--- linux-2.6.32/drivers/infiniband/hw/ipath/ipath_user_pages.c 2009-12-03 20:02:23.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/drivers/infiniband/hw/ipath/ipath_user_pages.c 2009-12-03 20:04:56.000000000 +0100
+@@ -34,6 +34,7 @@
#include <linux/mm.h>
#include <linux/device.h>
-+#include <linux/vs_memory.h>
+ #include <linux/sched.h>
++// #include <linux/vs_memory.h>
#include "ipath_kernel.h"
-@@ -61,7 +62,8 @@ static int __get_user_pages(unsigned lon
+@@ -62,7 +63,8 @@ static int __get_user_pages(unsigned lon
lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >>
PAGE_SHIFT;
ret = -ENOMEM;
goto bail;
}
-@@ -78,7 +80,7 @@ static int __get_user_pages(unsigned lon
+@@ -79,7 +81,7 @@ static int __get_user_pages(unsigned lon
goto bail_release;
}
ret = 0;
goto bail;
-@@ -177,7 +179,7 @@ void ipath_release_user_pages(struct pag
+@@ -178,7 +180,7 @@ void ipath_release_user_pages(struct pag
__ipath_release_user_pages(p, num_pages, 1);
up_write(¤t->mm->mmap_sem);
}
-@@ -194,7 +196,7 @@ static void user_pages_account(struct wo
+@@ -195,7 +197,7 @@ static void user_pages_account(struct wo
container_of(_work, struct ipath_user_pages_work, work);
down_write(&work->mm->mmap_sem);
up_write(&work->mm->mmap_sem);
mmput(work->mm);
kfree(work);
-diff -NurpP --minimal linux-2.6.31.6/drivers/md/dm.c linux-2.6.31.6-vs2.3.0.36.24/drivers/md/dm.c
---- linux-2.6.31.6/drivers/md/dm.c 2009-11-12 12:10:10.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/drivers/md/dm.c 2009-11-12 12:26:38.000000000 +0100
+diff -NurpP --minimal linux-2.6.32/drivers/md/dm.c linux-2.6.32-vs2.3.0.36.26/drivers/md/dm.c
+--- linux-2.6.32/drivers/md/dm.c 2009-12-03 20:02:25.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/drivers/md/dm.c 2009-12-03 20:04:56.000000000 +0100
@@ -19,6 +19,7 @@
#include <linux/slab.h>
#include <linux/idr.h>
}
static int dm_blk_close(struct gendisk *disk, fmode_t mode)
-@@ -551,6 +555,14 @@ int dm_set_geometry(struct mapped_device
+@@ -553,6 +557,14 @@ int dm_set_geometry(struct mapped_device
return 0;
}
/*-----------------------------------------------------------------
* CRUD START:
* A more elegant soln is in the works that uses the queue
-@@ -1760,6 +1772,7 @@ static struct mapped_device *alloc_dev(i
+@@ -1762,6 +1774,7 @@ static struct mapped_device *alloc_dev(i
INIT_LIST_HEAD(&md->uevent_list);
spin_lock_init(&md->uevent_lock);
md->queue = blk_init_queue(dm_request_fn, NULL);
if (!md->queue)
goto bad_queue;
-diff -NurpP --minimal linux-2.6.31.6/drivers/md/dm.h linux-2.6.31.6-vs2.3.0.36.24/drivers/md/dm.h
---- linux-2.6.31.6/drivers/md/dm.h 2009-09-10 15:25:55.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/drivers/md/dm.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/drivers/md/dm.h linux-2.6.32-vs2.3.0.36.26/drivers/md/dm.h
+--- linux-2.6.32/drivers/md/dm.h 2009-09-10 15:25:55.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/drivers/md/dm.h 2009-12-03 20:04:56.000000000 +0100
@@ -41,6 +41,8 @@ struct dm_dev_internal {
struct dm_table;
struct dm_md_mempools;
/*-----------------------------------------------------------------
* Internal table functions.
*---------------------------------------------------------------*/
-diff -NurpP --minimal linux-2.6.31.6/drivers/md/dm-ioctl.c linux-2.6.31.6-vs2.3.0.36.24/drivers/md/dm-ioctl.c
---- linux-2.6.31.6/drivers/md/dm-ioctl.c 2009-09-10 15:25:55.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/drivers/md/dm-ioctl.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/drivers/md/dm-ioctl.c linux-2.6.32-vs2.3.0.36.26/drivers/md/dm-ioctl.c
+--- linux-2.6.32/drivers/md/dm-ioctl.c 2009-12-03 20:02:25.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/drivers/md/dm-ioctl.c 2009-12-03 20:04:56.000000000 +0100
@@ -16,6 +16,7 @@
#include <linux/dm-ioctl.h>
#include <linux/hdreg.h>
return -EACCES;
if (_IOC_TYPE(command) != DM_IOCTL)
-diff -NurpP --minimal linux-2.6.31.6/drivers/net/tun.c linux-2.6.31.6-vs2.3.0.36.24/drivers/net/tun.c
---- linux-2.6.31.6/drivers/net/tun.c 2009-11-12 12:10:10.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/drivers/net/tun.c 2009-10-15 03:50:05.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/drivers/net/tun.c linux-2.6.32-vs2.3.0.36.26/drivers/net/tun.c
+--- linux-2.6.32/drivers/net/tun.c 2009-12-03 20:02:32.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/drivers/net/tun.c 2009-12-03 20:04:56.000000000 +0100
@@ -61,6 +61,7 @@
#include <linux/crc32.h>
#include <linux/nsproxy.h>
gid_t group;
+ nid_t nid;
- struct sk_buff_head readq;
-
-@@ -138,7 +140,7 @@ static int tun_attach(struct tun_struct
- /* Check permissions */
- if (((tun->owner != -1 && cred->euid != tun->owner) ||
- (tun->group != -1 && !in_egroup_p(tun->group))) &&
-- !capable(CAP_NET_ADMIN))
-+ !cap_raised(current_cap(), CAP_NET_ADMIN))
- return -EPERM;
-
- netif_tx_lock_bh(tun->dev);
-@@ -823,6 +825,7 @@ static void tun_setup(struct net_device
+ struct net_device *dev;
+ struct fasync_struct *fasync;
+@@ -816,6 +818,7 @@ static void tun_setup(struct net_device
tun->owner = -1;
tun->group = -1;
dev->ethtool_ops = &tun_ethtool_ops;
dev->destructor = tun_free_netdev;
-@@ -935,6 +938,9 @@ static int tun_set_iff(struct net *net,
- else
- return -EINVAL;
+@@ -932,7 +935,7 @@ static int tun_set_iff(struct net *net,
-+ if (!nx_check(tun->nid, VS_IDENT | VS_HOSTID | VS_ADMIN_P))
-+ return -EPERM;
-+
- err = tun_attach(tun, file);
+ if (((tun->owner != -1 && cred->euid != tun->owner) ||
+ (tun->group != -1 && !in_egroup_p(tun->group))) &&
+- !capable(CAP_NET_ADMIN))
++ !cap_raised(current_cap(), CAP_NET_ADMIN))
+ return -EPERM;
+ err = security_tun_dev_attach(tun->socket.sk);
if (err < 0)
- return err;
-@@ -943,7 +949,7 @@ static int tun_set_iff(struct net *net,
+@@ -946,7 +949,7 @@ static int tun_set_iff(struct net *net,
char *name;
unsigned long flags = 0;
- if (!capable(CAP_NET_ADMIN))
+ if (!nx_capable(CAP_NET_ADMIN, NXC_TUN_CREATE))
return -EPERM;
+ err = security_tun_dev_create();
+ if (err < 0)
+@@ -1013,6 +1016,9 @@ static int tun_set_iff(struct net *net,
+
+ sk->sk_destruct = tun_sock_destruct;
- /* Set dev type */
-@@ -1190,6 +1196,16 @@ static long tun_chr_ioctl(struct file *f
++ if (!nx_check(tun->nid, VS_IDENT | VS_HOSTID | VS_ADMIN_P))
++ return -EPERM;
++
+ err = tun_attach(tun, file);
+ if (err < 0)
+ goto failed;
+@@ -1202,6 +1208,16 @@ static long tun_chr_ioctl(struct file *f
DBG(KERN_INFO "%s: group set to %d\n", tun->dev->name, tun->group);
break;
case TUNSETLINK:
/* Only allow setting the type when the interface is down */
if (tun->dev->flags & IFF_UP) {
-diff -NurpP --minimal linux-2.6.31.6/fs/attr.c linux-2.6.31.6-vs2.3.0.36.24/fs/attr.c
---- linux-2.6.31.6/fs/attr.c 2009-06-11 17:13:01.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/attr.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/attr.c linux-2.6.32-vs2.3.0.36.26/fs/attr.c
+--- linux-2.6.32/fs/attr.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/attr.c 2009-12-03 20:04:56.000000000 +0100
@@ -14,6 +14,9 @@
#include <linux/fcntl.h>
#include <linux/quotaops.h>
/* Taken over from the old code... */
-@@ -55,6 +58,10 @@ int inode_change_ok(struct inode *inode,
+@@ -55,6 +58,10 @@ int inode_change_ok(const struct inode *
if (!is_owner_or_cap(inode))
goto error;
}
fine:
retval = 0;
error:
-@@ -78,6 +85,8 @@ int inode_setattr(struct inode * inode,
+@@ -120,6 +127,8 @@ int inode_setattr(struct inode * inode,
inode->i_uid = attr->ia_uid;
if (ia_valid & ATTR_GID)
inode->i_gid = attr->ia_gid;
if (ia_valid & ATTR_ATIME)
inode->i_atime = timespec_trunc(attr->ia_atime,
inode->i_sb->s_time_gran);
-@@ -172,7 +181,8 @@ int notify_change(struct dentry * dentry
+@@ -214,7 +223,8 @@ int notify_change(struct dentry * dentry
error = inode_change_ok(inode, attr);
if (!error) {
if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
error = vfs_dq_transfer(inode, attr) ?
-EDQUOT : 0;
if (!error)
-diff -NurpP --minimal linux-2.6.31.6/fs/binfmt_aout.c linux-2.6.31.6-vs2.3.0.36.24/fs/binfmt_aout.c
---- linux-2.6.31.6/fs/binfmt_aout.c 2009-03-24 14:22:24.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/binfmt_aout.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/binfmt_aout.c linux-2.6.32-vs2.3.0.36.26/fs/binfmt_aout.c
+--- linux-2.6.32/fs/binfmt_aout.c 2009-03-24 14:22:24.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/binfmt_aout.c 2009-12-03 20:04:56.000000000 +0100
@@ -24,6 +24,7 @@
#include <linux/binfmts.h>
#include <linux/personality.h>
#include <asm/system.h>
#include <asm/uaccess.h>
-diff -NurpP --minimal linux-2.6.31.6/fs/binfmt_elf.c linux-2.6.31.6-vs2.3.0.36.24/fs/binfmt_elf.c
---- linux-2.6.31.6/fs/binfmt_elf.c 2009-11-12 12:10:11.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/binfmt_elf.c 2009-09-29 17:02:58.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/binfmt_elf.c linux-2.6.32-vs2.3.0.36.26/fs/binfmt_elf.c
+--- linux-2.6.32/fs/binfmt_elf.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/binfmt_elf.c 2009-12-03 20:04:56.000000000 +0100
@@ -31,6 +31,7 @@
#include <linux/random.h>
#include <linux/elf.h>
#include <asm/uaccess.h>
#include <asm/param.h>
#include <asm/page.h>
-diff -NurpP --minimal linux-2.6.31.6/fs/binfmt_flat.c linux-2.6.31.6-vs2.3.0.36.24/fs/binfmt_flat.c
---- linux-2.6.31.6/fs/binfmt_flat.c 2009-09-10 15:26:20.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/binfmt_flat.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/binfmt_flat.c linux-2.6.32-vs2.3.0.36.26/fs/binfmt_flat.c
+--- linux-2.6.32/fs/binfmt_flat.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/binfmt_flat.c 2009-12-03 20:04:56.000000000 +0100
@@ -35,6 +35,7 @@
#include <linux/init.h>
#include <linux/flat.h>
#include <asm/byteorder.h>
#include <asm/system.h>
-diff -NurpP --minimal linux-2.6.31.6/fs/binfmt_som.c linux-2.6.31.6-vs2.3.0.36.24/fs/binfmt_som.c
---- linux-2.6.31.6/fs/binfmt_som.c 2009-06-11 17:13:02.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/binfmt_som.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/binfmt_som.c linux-2.6.32-vs2.3.0.36.26/fs/binfmt_som.c
+--- linux-2.6.32/fs/binfmt_som.c 2009-06-11 17:13:02.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/binfmt_som.c 2009-12-03 20:04:56.000000000 +0100
@@ -28,6 +28,7 @@
#include <linux/shm.h>
#include <linux/personality.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
-diff -NurpP --minimal linux-2.6.31.6/fs/block_dev.c linux-2.6.31.6-vs2.3.0.36.24/fs/block_dev.c
---- linux-2.6.31.6/fs/block_dev.c 2009-09-10 15:26:20.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/block_dev.c 2009-09-10 17:01:13.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/block_dev.c linux-2.6.32-vs2.3.0.36.26/fs/block_dev.c
+--- linux-2.6.32/fs/block_dev.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/block_dev.c 2009-12-03 20:04:56.000000000 +0100
@@ -26,6 +26,7 @@
#include <linux/namei.h>
#include <linux/log2.h>
#include <asm/uaccess.h>
#include "internal.h"
-@@ -550,6 +551,7 @@ struct block_device *bdget(dev_t dev)
+@@ -555,6 +556,7 @@ struct block_device *bdget(dev_t dev)
bdev->bd_invalidated = 0;
inode->i_mode = S_IFBLK;
inode->i_rdev = dev;
inode->i_bdev = bdev;
inode->i_data.a_ops = &def_blk_aops;
mapping_set_gfp_mask(&inode->i_data, GFP_USER);
-@@ -596,6 +598,11 @@ EXPORT_SYMBOL(bdput);
+@@ -601,6 +603,11 @@ EXPORT_SYMBOL(bdput);
static struct block_device *bd_acquire(struct inode *inode)
{
struct block_device *bdev;
spin_lock(&bdev_lock);
bdev = inode->i_bdev;
-@@ -606,7 +613,7 @@ static struct block_device *bd_acquire(s
+@@ -611,7 +618,7 @@ static struct block_device *bd_acquire(s
}
spin_unlock(&bdev_lock);
if (bdev) {
spin_lock(&bdev_lock);
if (!inode->i_bdev) {
-diff -NurpP --minimal linux-2.6.31.6/fs/btrfs/ctree.h linux-2.6.31.6-vs2.3.0.36.24/fs/btrfs/ctree.h
---- linux-2.6.31.6/fs/btrfs/ctree.h 2009-09-10 15:26:20.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/btrfs/ctree.h 2009-10-08 07:39:48.000000000 +0200
-@@ -540,11 +540,14 @@ struct btrfs_inode_item {
+diff -NurpP --minimal linux-2.6.32/fs/btrfs/ctree.h linux-2.6.32-vs2.3.0.36.26/fs/btrfs/ctree.h
+--- linux-2.6.32/fs/btrfs/ctree.h 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/btrfs/ctree.h 2009-12-03 20:04:56.000000000 +0100
+@@ -544,11 +544,14 @@ struct btrfs_inode_item {
/* modification sequence number for NFS */
__le64 sequence;
struct btrfs_timespec atime;
struct btrfs_timespec ctime;
struct btrfs_timespec mtime;
-@@ -1119,6 +1122,8 @@ struct btrfs_root {
- #define BTRFS_MOUNT_SSD_SPREAD (1 << 8)
+@@ -1155,6 +1158,8 @@ struct btrfs_root {
#define BTRFS_MOUNT_NOSSD (1 << 9)
+ #define BTRFS_MOUNT_DISCARD (1 << 10)
+#define BTRFS_MOUNT_TAGGED (1 << 24)
+
#define btrfs_clear_opt(o, opt) ((o) &= ~BTRFS_MOUNT_##opt)
#define btrfs_set_opt(o, opt) ((o) |= BTRFS_MOUNT_##opt)
#define btrfs_test_opt(root, opt) ((root)->fs_info->mount_opt & \
-@@ -1138,6 +1143,10 @@ struct btrfs_root {
+@@ -1174,6 +1179,10 @@ struct btrfs_root {
#define BTRFS_INODE_NOATIME (1 << 9)
#define BTRFS_INODE_DIRSYNC (1 << 10)
/* some macros to generate set/get funcs for the struct fields. This
* assumes there is a lefoo_to_cpu for every type, so lets make a simple
-@@ -1340,6 +1349,7 @@ BTRFS_SETGET_FUNCS(inode_block_group, st
+@@ -1376,6 +1385,7 @@ BTRFS_SETGET_FUNCS(inode_block_group, st
BTRFS_SETGET_FUNCS(inode_nlink, struct btrfs_inode_item, nlink, 32);
BTRFS_SETGET_FUNCS(inode_uid, struct btrfs_inode_item, uid, 32);
BTRFS_SETGET_FUNCS(inode_gid, struct btrfs_inode_item, gid, 32);
BTRFS_SETGET_FUNCS(inode_mode, struct btrfs_inode_item, mode, 32);
BTRFS_SETGET_FUNCS(inode_rdev, struct btrfs_inode_item, rdev, 64);
BTRFS_SETGET_FUNCS(inode_flags, struct btrfs_inode_item, flags, 64);
-@@ -2280,6 +2290,7 @@ int btrfs_cont_expand(struct inode *inod
+@@ -2338,6 +2348,7 @@ extern const struct dentry_operations bt
long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
void btrfs_update_iflags(struct inode *inode);
void btrfs_inherit_iflags(struct inode *inode, struct inode *dir);
/* file.c */
int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync);
-diff -NurpP --minimal linux-2.6.31.6/fs/btrfs/disk-io.c linux-2.6.31.6-vs2.3.0.36.24/fs/btrfs/disk-io.c
---- linux-2.6.31.6/fs/btrfs/disk-io.c 2009-09-10 15:26:20.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/btrfs/disk-io.c 2009-10-08 06:43:17.000000000 +0200
-@@ -1673,6 +1673,9 @@ struct btrfs_root *open_ctree(struct sup
+diff -NurpP --minimal linux-2.6.32/fs/btrfs/disk-io.c linux-2.6.32-vs2.3.0.36.26/fs/btrfs/disk-io.c
+--- linux-2.6.32/fs/btrfs/disk-io.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/btrfs/disk-io.c 2009-12-03 20:04:56.000000000 +0100
+@@ -1723,6 +1723,9 @@ struct btrfs_root *open_ctree(struct sup
goto fail_iput;
}
features = btrfs_super_incompat_flags(disk_super) &
~BTRFS_FEATURE_INCOMPAT_SUPP;
if (features) {
-diff -NurpP --minimal linux-2.6.31.6/fs/btrfs/inode.c linux-2.6.31.6-vs2.3.0.36.24/fs/btrfs/inode.c
---- linux-2.6.31.6/fs/btrfs/inode.c 2009-09-10 15:26:21.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/btrfs/inode.c 2009-10-08 14:17:12.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/btrfs/inode.c linux-2.6.32-vs2.3.0.36.26/fs/btrfs/inode.c
+--- linux-2.6.32/fs/btrfs/inode.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/btrfs/inode.c 2009-12-03 20:04:56.000000000 +0100
@@ -36,6 +36,8 @@
#include <linux/xattr.h>
#include <linux/posix_acl.h>
#include "compat.h"
#include "ctree.h"
#include "disk-io.h"
-@@ -2072,6 +2074,8 @@ static void btrfs_read_locked_inode(stru
+@@ -2242,6 +2244,8 @@ static void btrfs_read_locked_inode(stru
int maybe_acls;
u64 alloc_group_block;
u32 rdev;
int ret;
path = btrfs_alloc_path();
-@@ -2088,8 +2092,13 @@ static void btrfs_read_locked_inode(stru
+@@ -2258,8 +2262,13 @@ static void btrfs_read_locked_inode(stru
inode->i_mode = btrfs_inode_mode(leaf, inode_item);
inode->i_nlink = btrfs_inode_nlink(leaf, inode_item);
btrfs_i_size_write(inode, btrfs_inode_size(leaf, inode_item));
tspec = btrfs_inode_atime(inode_item);
-@@ -2171,8 +2180,15 @@ static void fill_inode_item(struct btrfs
+@@ -2341,8 +2350,15 @@ static void fill_inode_item(struct btrfs
struct btrfs_inode_item *item,
struct inode *inode)
{
btrfs_set_inode_size(leaf, item, BTRFS_I(inode)->disk_i_size);
btrfs_set_inode_mode(leaf, item, inode->i_mode);
btrfs_set_inode_nlink(leaf, item, inode->i_nlink);
-@@ -3615,6 +3631,7 @@ static struct inode *btrfs_new_inode(str
+@@ -4065,6 +4081,7 @@ static struct inode *btrfs_new_inode(str
} else
inode->i_gid = current_fsgid();
inode->i_mode = mode;
inode->i_ino = objectid;
inode_set_bytes(inode, 0);
-@@ -5218,6 +5235,7 @@ static struct inode_operations btrfs_dir
+@@ -5836,6 +5853,7 @@ static const struct inode_operations btr
.listxattr = btrfs_listxattr,
.removexattr = btrfs_removexattr,
.permission = btrfs_permission,
+ .sync_flags = btrfs_sync_flags,
};
- static struct inode_operations btrfs_dir_ro_inode_operations = {
+ static const struct inode_operations btrfs_dir_ro_inode_operations = {
.lookup = btrfs_lookup,
-@@ -5289,6 +5307,7 @@ static struct inode_operations btrfs_fil
+@@ -5911,6 +5929,7 @@ static const struct inode_operations btr
.permission = btrfs_permission,
.fallocate = btrfs_fallocate,
.fiemap = btrfs_fiemap,
+ .sync_flags = btrfs_sync_flags,
};
- static struct inode_operations btrfs_special_inode_operations = {
+ static const struct inode_operations btrfs_special_inode_operations = {
.getattr = btrfs_getattr,
-diff -NurpP --minimal linux-2.6.31.6/fs/btrfs/ioctl.c linux-2.6.31.6-vs2.3.0.36.24/fs/btrfs/ioctl.c
---- linux-2.6.31.6/fs/btrfs/ioctl.c 2009-09-10 15:26:21.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/btrfs/ioctl.c 2009-10-08 05:58:29.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/btrfs/ioctl.c linux-2.6.32-vs2.3.0.36.26/fs/btrfs/ioctl.c
+--- linux-2.6.32/fs/btrfs/ioctl.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/btrfs/ioctl.c 2009-12-03 20:04:56.000000000 +0100
@@ -67,10 +67,13 @@ static unsigned int btrfs_flags_to_ioctl
{
unsigned int iflags = 0;
if (flags & FS_APPEND_FL)
ip->flags |= BTRFS_INODE_APPEND;
else
-diff -NurpP --minimal linux-2.6.31.6/fs/btrfs/super.c linux-2.6.31.6-vs2.3.0.36.24/fs/btrfs/super.c
---- linux-2.6.31.6/fs/btrfs/super.c 2009-09-10 15:26:21.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/btrfs/super.c 2009-10-08 07:27:04.000000000 +0200
-@@ -66,7 +66,8 @@ enum {
- Opt_degraded, Opt_subvol, Opt_device, Opt_nodatasum, Opt_nodatacow,
+diff -NurpP --minimal linux-2.6.32/fs/btrfs/super.c linux-2.6.32-vs2.3.0.36.26/fs/btrfs/super.c
+--- linux-2.6.32/fs/btrfs/super.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/btrfs/super.c 2009-12-03 20:04:56.000000000 +0100
+@@ -67,7 +67,7 @@ enum {
Opt_max_extent, Opt_max_inline, Opt_alloc_start, Opt_nobarrier,
Opt_ssd, Opt_nossd, Opt_ssd_spread, Opt_thread_pool, Opt_noacl,
-- Opt_compress, Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_err,
-+ Opt_compress, Opt_notreelog, Opt_ratio, Opt_flushoncommit,
-+ Opt_tag, Opt_notag, Opt_tagid, Opt_err,
+ Opt_compress, Opt_notreelog, Opt_ratio, Opt_flushoncommit,
+- Opt_discard, Opt_err,
++ Opt_tag, Opt_notag, Opt_tagid, Opt_discard, Opt_err,
};
static match_table_t tokens = {
-@@ -88,6 +89,9 @@ static match_table_t tokens = {
- {Opt_notreelog, "notreelog"},
+@@ -90,6 +90,9 @@ static match_table_t tokens = {
{Opt_flushoncommit, "flushoncommit"},
{Opt_ratio, "metadata_ratio=%d"},
+ {Opt_discard, "discard"},
+ {Opt_tag, "tag"},
+ {Opt_notag, "notag"},
+ {Opt_tagid, "tagid=%u"},
{Opt_err, NULL},
};
-@@ -257,6 +261,22 @@ int btrfs_parse_options(struct btrfs_roo
- info->metadata_ratio);
- }
+@@ -262,6 +265,22 @@ int btrfs_parse_options(struct btrfs_roo
+ case Opt_discard:
+ btrfs_set_opt(info->mount_opt, DISCARD);
break;
+#ifndef CONFIG_TAGGING_NONE
+ case Opt_tag:
default:
break;
}
-@@ -568,6 +588,12 @@ static int btrfs_remount(struct super_bl
+@@ -575,6 +594,12 @@ static int btrfs_remount(struct super_bl
if (ret)
return -EINVAL;
if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
return 0;
-diff -NurpP --minimal linux-2.6.31.6/fs/char_dev.c linux-2.6.31.6-vs2.3.0.36.24/fs/char_dev.c
---- linux-2.6.31.6/fs/char_dev.c 2009-09-10 15:26:21.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/char_dev.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/char_dev.c linux-2.6.32-vs2.3.0.36.26/fs/char_dev.c
+--- linux-2.6.32/fs/char_dev.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/char_dev.c 2009-12-03 20:04:56.000000000 +0100
@@ -20,6 +20,8 @@
#include <linux/cdev.h>
#include <linux/mutex.h>
#include "internal.h"
-@@ -357,14 +359,21 @@ static int chrdev_open(struct inode *ino
+@@ -368,14 +370,21 @@ static int chrdev_open(struct inode *ino
struct cdev *p;
struct cdev *new = NULL;
int ret = 0;
if (!kobj)
return -ENXIO;
new = container_of(kobj, struct cdev, kobj);
-diff -NurpP --minimal linux-2.6.31.6/fs/dcache.c linux-2.6.31.6-vs2.3.0.36.24/fs/dcache.c
---- linux-2.6.31.6/fs/dcache.c 2009-09-10 15:26:21.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/dcache.c 2009-09-10 16:11:43.000000000 +0200
-@@ -32,6 +32,7 @@
- #include <linux/swap.h>
+diff -NurpP --minimal linux-2.6.32/fs/dcache.c linux-2.6.32-vs2.3.0.36.26/fs/dcache.c
+--- linux-2.6.32/fs/dcache.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/dcache.c 2009-12-03 20:04:56.000000000 +0100
+@@ -33,6 +33,7 @@
#include <linux/bootmem.h>
#include <linux/fs_struct.h>
+ #include <linux/hardirq.h>
+#include <linux/vs_limit.h>
#include "internal.h"
int sysctl_vfs_cache_pressure __read_mostly = 100;
-@@ -229,6 +230,8 @@ repeat:
+@@ -230,6 +231,8 @@ repeat:
return;
}
/*
* AV: ->d_delete() is _NOT_ allowed to block now.
*/
-@@ -320,6 +323,7 @@ static inline struct dentry * __dget_loc
+@@ -321,6 +324,7 @@ static inline struct dentry * __dget_loc
{
atomic_inc(&dentry->d_count);
dentry_lru_del_init(dentry);
return dentry;
}
-@@ -918,6 +922,9 @@ struct dentry *d_alloc(struct dentry * p
+@@ -919,6 +923,9 @@ struct dentry *d_alloc(struct dentry * p
struct dentry *dentry;
char *dname;
dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL);
if (!dentry)
return NULL;
-@@ -963,6 +970,7 @@ struct dentry *d_alloc(struct dentry * p
+@@ -964,6 +971,7 @@ struct dentry *d_alloc(struct dentry * p
if (parent)
list_add(&dentry->d_u.d_child, &parent->d_subdirs);
dentry_stat.nr_dentry++;
spin_unlock(&dcache_lock);
return dentry;
-@@ -1406,6 +1414,7 @@ struct dentry * __d_lookup(struct dentry
+@@ -1407,6 +1415,7 @@ struct dentry * __d_lookup(struct dentry
}
atomic_inc(&dentry->d_count);
found = dentry;
spin_unlock(&dentry->d_lock);
break;
-diff -NurpP --minimal linux-2.6.31.6/fs/devpts/inode.c linux-2.6.31.6-vs2.3.0.36.24/fs/devpts/inode.c
---- linux-2.6.31.6/fs/devpts/inode.c 2009-09-10 15:26:21.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/devpts/inode.c 2009-09-10 16:11:43.000000000 +0200
-@@ -19,12 +19,12 @@
- #include <linux/tty.h>
- #include <linux/mutex.h>
- #include <linux/idr.h>
-+#include <linux/magic.h>
- #include <linux/devpts_fs.h>
+diff -NurpP --minimal linux-2.6.32/fs/devpts/inode.c linux-2.6.32-vs2.3.0.36.26/fs/devpts/inode.c
+--- linux-2.6.32/fs/devpts/inode.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/devpts/inode.c 2009-12-03 20:04:56.000000000 +0100
+@@ -24,6 +24,7 @@
#include <linux/parser.h>
#include <linux/fsnotify.h>
#include <linux/seq_file.h>
--
--#define DEVPTS_SUPER_MAGIC 0x1cd1
+#include <linux/vs_base.h>
#define DEVPTS_DEFAULT_MODE 0600
/*
-@@ -36,6 +36,20 @@
+@@ -35,6 +36,20 @@
#define DEVPTS_DEFAULT_PTMX_MODE 0000
#define PTMX_MINOR 2
extern int pty_limit; /* Config limit on Unix98 ptys */
static DEFINE_MUTEX(allocated_ptys_lock);
-@@ -263,6 +277,25 @@ static int devpts_show_options(struct se
+@@ -262,6 +277,25 @@ static int devpts_show_options(struct se
return 0;
}
static const struct super_operations devpts_sops = {
.statfs = simple_statfs,
.remount_fs = devpts_remount,
-@@ -302,12 +335,15 @@ devpts_fill_super(struct super_block *s,
+@@ -301,12 +335,15 @@ devpts_fill_super(struct super_block *s,
inode = new_inode(s);
if (!inode)
goto free_fsi;
s->s_root = d_alloc_root(inode);
if (s->s_root)
-@@ -498,6 +534,9 @@ int devpts_pty_new(struct inode *ptmx_in
+@@ -497,6 +534,9 @@ int devpts_pty_new(struct inode *ptmx_in
inode->i_gid = opts->setgid ? opts->gid : current_fsgid();
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
init_special_inode(inode, S_IFCHR|opts->mode, device);
inode->i_private = tty;
tty->driver_data = inode;
-diff -NurpP --minimal linux-2.6.31.6/fs/exec.c linux-2.6.31.6-vs2.3.0.36.24/fs/exec.c
---- linux-2.6.31.6/fs/exec.c 2009-09-10 15:26:21.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/exec.c 2009-09-10 16:11:43.000000000 +0200
-@@ -249,7 +249,9 @@ static int __bprm_mm_init(struct linux_b
+diff -NurpP --minimal linux-2.6.32/fs/exec.c linux-2.6.32-vs2.3.0.36.26/fs/exec.c
+--- linux-2.6.32/fs/exec.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/exec.c 2009-12-03 20:04:56.000000000 +0100
+@@ -251,7 +251,9 @@ static int __bprm_mm_init(struct linux_b
if (err)
goto err;
up_write(&mm->mmap_sem);
bprm->p = vma->vm_end - sizeof(void *);
return 0;
-@@ -1471,7 +1473,7 @@ static int format_corename(char *corenam
+@@ -1474,7 +1476,7 @@ static int format_corename(char *corenam
/* UNIX time of coredump */
case 't': {
struct timeval tv;
rc = snprintf(out_ptr, out_end - out_ptr,
"%lu", tv.tv_sec);
if (rc > out_end - out_ptr)
-diff -NurpP --minimal linux-2.6.31.6/fs/ext2/balloc.c linux-2.6.31.6-vs2.3.0.36.24/fs/ext2/balloc.c
---- linux-2.6.31.6/fs/ext2/balloc.c 2009-06-11 17:13:03.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ext2/balloc.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/ext2/balloc.c linux-2.6.32-vs2.3.0.36.26/fs/ext2/balloc.c
+--- linux-2.6.32/fs/ext2/balloc.c 2009-06-11 17:13:03.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/ext2/balloc.c 2009-12-03 20:04:56.000000000 +0100
@@ -701,7 +701,6 @@ ext2_try_to_allocate(struct super_block
start = 0;
end = EXT2_BLOCKS_PER_GROUP(sb);
BUG_ON(start > EXT2_BLOCKS_PER_GROUP(sb));
repeat:
-diff -NurpP --minimal linux-2.6.31.6/fs/ext2/ext2.h linux-2.6.31.6-vs2.3.0.36.24/fs/ext2/ext2.h
---- linux-2.6.31.6/fs/ext2/ext2.h 2009-09-10 15:26:21.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ext2/ext2.h 2009-10-07 01:23:12.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/ext2/ext2.h linux-2.6.32-vs2.3.0.36.26/fs/ext2/ext2.h
+--- linux-2.6.32/fs/ext2/ext2.h 2009-09-10 15:26:21.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/ext2/ext2.h 2009-12-03 20:04:56.000000000 +0100
@@ -131,6 +131,7 @@ extern int ext2_fiemap(struct inode *ino
int __ext2_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
/* ioctl.c */
extern long ext2_ioctl(struct file *, unsigned int, unsigned long);
-diff -NurpP --minimal linux-2.6.31.6/fs/ext2/file.c linux-2.6.31.6-vs2.3.0.36.24/fs/ext2/file.c
---- linux-2.6.31.6/fs/ext2/file.c 2009-09-10 15:26:21.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ext2/file.c 2009-10-07 01:03:12.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/ext2/file.c linux-2.6.32-vs2.3.0.36.26/fs/ext2/file.c
+--- linux-2.6.32/fs/ext2/file.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ext2/file.c 2009-12-03 20:04:56.000000000 +0100
@@ -87,4 +87,5 @@ const struct inode_operations ext2_file_
.setattr = ext2_setattr,
- .permission = ext2_permission,
+ .check_acl = ext2_check_acl,
.fiemap = ext2_fiemap,
+ .sync_flags = ext2_sync_flags,
};
-diff -NurpP --minimal linux-2.6.31.6/fs/ext2/ialloc.c linux-2.6.31.6-vs2.3.0.36.24/fs/ext2/ialloc.c
---- linux-2.6.31.6/fs/ext2/ialloc.c 2009-06-11 17:13:03.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ext2/ialloc.c 2009-10-12 05:05:34.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/ext2/ialloc.c linux-2.6.32-vs2.3.0.36.26/fs/ext2/ialloc.c
+--- linux-2.6.32/fs/ext2/ialloc.c 2009-06-11 17:13:03.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/ext2/ialloc.c 2009-12-03 20:04:56.000000000 +0100
@@ -17,6 +17,7 @@
#include <linux/backing-dev.h>
#include <linux/buffer_head.h>
inode->i_ino = ino;
inode->i_blocks = 0;
-diff -NurpP --minimal linux-2.6.31.6/fs/ext2/inode.c linux-2.6.31.6-vs2.3.0.36.24/fs/ext2/inode.c
---- linux-2.6.31.6/fs/ext2/inode.c 2009-09-10 15:26:21.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ext2/inode.c 2009-10-06 19:45:13.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/ext2/inode.c linux-2.6.32-vs2.3.0.36.26/fs/ext2/inode.c
+--- linux-2.6.32/fs/ext2/inode.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ext2/inode.c 2009-12-03 20:04:56.000000000 +0100
@@ -33,6 +33,7 @@
#include <linux/mpage.h>
#include <linux/fiemap.h>
#include "ext2.h"
#include "acl.h"
#include "xip.h"
-@@ -1038,7 +1039,7 @@ void ext2_truncate(struct inode *inode)
+@@ -1040,7 +1041,7 @@ void ext2_truncate(struct inode *inode)
return;
if (ext2_inode_is_fast_symlink(inode))
return;
return;
blocksize = inode->i_sb->s_blocksize;
-@@ -1176,36 +1177,61 @@ void ext2_set_inode_flags(struct inode *
+@@ -1178,36 +1179,61 @@ void ext2_set_inode_flags(struct inode *
{
unsigned int flags = EXT2_I(inode)->i_flags;
}
struct inode *ext2_iget (struct super_block *sb, unsigned long ino)
-@@ -1215,6 +1241,8 @@ struct inode *ext2_iget (struct super_bl
+@@ -1217,6 +1243,8 @@ struct inode *ext2_iget (struct super_bl
struct ext2_inode *raw_inode;
struct inode *inode;
long ret = -EIO;
int n;
inode = iget_locked(sb, ino);
-@@ -1233,12 +1261,17 @@ struct inode *ext2_iget (struct super_bl
+@@ -1235,12 +1263,17 @@ struct inode *ext2_iget (struct super_bl
}
inode->i_mode = le16_to_cpu(raw_inode->i_mode);
inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
inode->i_size = le32_to_cpu(raw_inode->i_size);
inode->i_atime.tv_sec = (signed)le32_to_cpu(raw_inode->i_atime);
-@@ -1336,8 +1369,8 @@ int ext2_write_inode(struct inode *inode
+@@ -1338,8 +1371,8 @@ int ext2_write_inode(struct inode *inode
struct ext2_inode_info *ei = EXT2_I(inode);
struct super_block *sb = inode->i_sb;
ino_t ino = inode->i_ino;
struct buffer_head * bh;
struct ext2_inode * raw_inode = ext2_get_inode(sb, ino, &bh);
int n;
-@@ -1373,6 +1406,9 @@ int ext2_write_inode(struct inode *inode
+@@ -1375,6 +1408,9 @@ int ext2_write_inode(struct inode *inode
raw_inode->i_uid_high = 0;
raw_inode->i_gid_high = 0;
}
raw_inode->i_links_count = cpu_to_le16(inode->i_nlink);
raw_inode->i_size = cpu_to_le32(inode->i_size);
raw_inode->i_atime = cpu_to_le32(inode->i_atime.tv_sec);
-@@ -1454,7 +1490,8 @@ int ext2_setattr(struct dentry *dentry,
+@@ -1456,7 +1492,8 @@ int ext2_setattr(struct dentry *dentry,
if (error)
return error;
if ((iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid) ||
error = vfs_dq_transfer(inode, iattr) ? -EDQUOT : 0;
if (error)
return error;
-diff -NurpP --minimal linux-2.6.31.6/fs/ext2/ioctl.c linux-2.6.31.6-vs2.3.0.36.24/fs/ext2/ioctl.c
---- linux-2.6.31.6/fs/ext2/ioctl.c 2009-09-10 15:26:21.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ext2/ioctl.c 2009-10-07 01:01:20.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/ext2/ioctl.c linux-2.6.32-vs2.3.0.36.26/fs/ext2/ioctl.c
+--- linux-2.6.32/fs/ext2/ioctl.c 2009-09-10 15:26:21.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/ext2/ioctl.c 2009-12-03 20:04:56.000000000 +0100
@@ -17,6 +17,16 @@
#include <asm/uaccess.h>
flags |= oldflags & ~EXT2_FL_USER_MODIFIABLE;
ei->i_flags = flags;
mutex_unlock(&inode->i_mutex);
-diff -NurpP --minimal linux-2.6.31.6/fs/ext2/namei.c linux-2.6.31.6-vs2.3.0.36.24/fs/ext2/namei.c
---- linux-2.6.31.6/fs/ext2/namei.c 2009-09-10 15:26:21.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ext2/namei.c 2009-10-07 01:08:06.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/ext2/namei.c linux-2.6.32-vs2.3.0.36.26/fs/ext2/namei.c
+--- linux-2.6.32/fs/ext2/namei.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ext2/namei.c 2009-12-03 20:04:56.000000000 +0100
@@ -31,6 +31,7 @@
*/
@@ -401,6 +403,7 @@ const struct inode_operations ext2_dir_i
#endif
.setattr = ext2_setattr,
- .permission = ext2_permission,
+ .check_acl = ext2_check_acl,
+ .sync_flags = ext2_sync_flags,
};
const struct inode_operations ext2_special_inode_operations = {
-diff -NurpP --minimal linux-2.6.31.6/fs/ext2/super.c linux-2.6.31.6-vs2.3.0.36.24/fs/ext2/super.c
---- linux-2.6.31.6/fs/ext2/super.c 2009-09-10 15:26:21.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ext2/super.c 2009-10-06 22:47:11.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/ext2/super.c linux-2.6.32-vs2.3.0.36.26/fs/ext2/super.c
+--- linux-2.6.32/fs/ext2/super.c 2009-09-10 15:26:21.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/ext2/super.c 2009-12-03 20:04:56.000000000 +0100
@@ -382,7 +382,8 @@ enum {
Opt_err_ro, Opt_nouid32, Opt_nocheck, Opt_debug,
Opt_oldalloc, Opt_orlov, Opt_nobh, Opt_user_xattr, Opt_nouser_xattr,
sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
((sbi->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
-diff -NurpP --minimal linux-2.6.31.6/fs/ext3/file.c linux-2.6.31.6-vs2.3.0.36.24/fs/ext3/file.c
---- linux-2.6.31.6/fs/ext3/file.c 2009-06-11 17:13:03.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ext3/file.c 2009-10-06 23:23:15.000000000 +0200
-@@ -139,5 +139,6 @@ const struct inode_operations ext3_file_
+diff -NurpP --minimal linux-2.6.32/fs/ext3/file.c linux-2.6.32-vs2.3.0.36.26/fs/ext3/file.c
+--- linux-2.6.32/fs/ext3/file.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ext3/file.c 2009-12-03 20:04:56.000000000 +0100
+@@ -80,5 +80,6 @@ const struct inode_operations ext3_file_
#endif
- .permission = ext3_permission,
+ .check_acl = ext3_check_acl,
.fiemap = ext3_fiemap,
+ .sync_flags = ext3_sync_flags,
};
-diff -NurpP --minimal linux-2.6.31.6/fs/ext3/ialloc.c linux-2.6.31.6-vs2.3.0.36.24/fs/ext3/ialloc.c
---- linux-2.6.31.6/fs/ext3/ialloc.c 2009-09-10 15:26:21.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ext3/ialloc.c 2009-10-12 05:06:13.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/ext3/ialloc.c linux-2.6.32-vs2.3.0.36.26/fs/ext3/ialloc.c
+--- linux-2.6.32/fs/ext3/ialloc.c 2009-09-10 15:26:21.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/ext3/ialloc.c 2009-12-03 20:04:56.000000000 +0100
@@ -23,6 +23,7 @@
#include <linux/buffer_head.h>
#include <linux/random.h>
inode->i_ino = ino;
/* This is the optimal IO size (for stat), not the fs block size */
-diff -NurpP --minimal linux-2.6.31.6/fs/ext3/inode.c linux-2.6.31.6-vs2.3.0.36.24/fs/ext3/inode.c
---- linux-2.6.31.6/fs/ext3/inode.c 2009-09-10 15:26:21.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ext3/inode.c 2009-10-06 19:45:13.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/ext3/inode.c linux-2.6.32-vs2.3.0.36.26/fs/ext3/inode.c
+--- linux-2.6.32/fs/ext3/inode.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ext3/inode.c 2009-12-03 20:04:56.000000000 +0100
@@ -38,6 +38,7 @@
#include <linux/bio.h>
#include <linux/fiemap.h>
#include "xattr.h"
#include "acl.h"
-@@ -2312,7 +2313,7 @@ static void ext3_free_branches(handle_t
+@@ -2333,7 +2334,7 @@ static void ext3_free_branches(handle_t
int ext3_can_truncate(struct inode *inode)
{
return 0;
if (S_ISREG(inode->i_mode))
return 1;
-@@ -2697,36 +2698,60 @@ void ext3_set_inode_flags(struct inode *
+@@ -2718,36 +2719,60 @@ void ext3_set_inode_flags(struct inode *
{
unsigned int flags = EXT3_I(inode)->i_flags;
}
struct inode *ext3_iget(struct super_block *sb, unsigned long ino)
-@@ -2738,6 +2763,8 @@ struct inode *ext3_iget(struct super_blo
- struct inode *inode;
+@@ -2761,6 +2786,8 @@ struct inode *ext3_iget(struct super_blo
+ transaction_t *transaction;
long ret;
int block;
+ uid_t uid;
inode = iget_locked(sb, ino);
if (!inode)
-@@ -2754,12 +2781,17 @@ struct inode *ext3_iget(struct super_blo
+@@ -2777,12 +2804,17 @@ struct inode *ext3_iget(struct super_blo
bh = iloc.bh;
raw_inode = ext3_raw_inode(&iloc);
inode->i_mode = le16_to_cpu(raw_inode->i_mode);
inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
inode->i_size = le32_to_cpu(raw_inode->i_size);
inode->i_atime.tv_sec = (signed)le32_to_cpu(raw_inode->i_atime);
-@@ -2890,6 +2922,8 @@ static int ext3_do_update_inode(handle_t
+@@ -2937,6 +2969,8 @@ static int ext3_do_update_inode(handle_t
struct ext3_inode *raw_inode = ext3_raw_inode(iloc);
struct ext3_inode_info *ei = EXT3_I(inode);
struct buffer_head *bh = iloc->bh;
+ gid_t gid = TAGINO_GID(DX_TAG(inode), inode->i_gid, inode->i_tag);
int err = 0, rc, block;
- /* For fields not not tracking in the in-memory inode,
-@@ -2900,29 +2934,32 @@ static int ext3_do_update_inode(handle_t
+ again:
+@@ -2951,29 +2985,32 @@ again:
ext3_get_inode_flags(ei);
raw_inode->i_mode = cpu_to_le16(inode->i_mode);
if(!(test_opt(inode->i_sb, NO_UID32))) {
raw_inode->i_links_count = cpu_to_le16(inode->i_nlink);
raw_inode->i_size = cpu_to_le32(ei->i_disksize);
raw_inode->i_atime = cpu_to_le32(inode->i_atime.tv_sec);
-@@ -3074,7 +3111,8 @@ int ext3_setattr(struct dentry *dentry,
+@@ -3131,7 +3168,8 @@ int ext3_setattr(struct dentry *dentry,
return error;
if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
handle_t *handle;
/* (user+group)*(old+new) structure, inode write (sb,
-@@ -3096,6 +3134,8 @@ int ext3_setattr(struct dentry *dentry,
+@@ -3153,6 +3191,8 @@ int ext3_setattr(struct dentry *dentry,
inode->i_uid = attr->ia_uid;
if (attr->ia_valid & ATTR_GID)
inode->i_gid = attr->ia_gid;
error = ext3_mark_inode_dirty(handle, inode);
ext3_journal_stop(handle);
}
-diff -NurpP --minimal linux-2.6.31.6/fs/ext3/ioctl.c linux-2.6.31.6-vs2.3.0.36.24/fs/ext3/ioctl.c
---- linux-2.6.31.6/fs/ext3/ioctl.c 2009-06-11 17:13:03.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ext3/ioctl.c 2009-10-07 00:08:00.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/ext3/ioctl.c linux-2.6.32-vs2.3.0.36.26/fs/ext3/ioctl.c
+--- linux-2.6.32/fs/ext3/ioctl.c 2009-06-11 17:13:03.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/ext3/ioctl.c 2009-12-03 20:04:56.000000000 +0100
@@ -8,6 +8,7 @@
*/
flags |= oldflags & ~EXT3_FL_USER_MODIFIABLE;
ei->i_flags = flags;
-diff -NurpP --minimal linux-2.6.31.6/fs/ext3/namei.c linux-2.6.31.6-vs2.3.0.36.24/fs/ext3/namei.c
---- linux-2.6.31.6/fs/ext3/namei.c 2009-06-11 17:13:03.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ext3/namei.c 2009-10-06 23:24:04.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/ext3/namei.c linux-2.6.32-vs2.3.0.36.26/fs/ext3/namei.c
+--- linux-2.6.32/fs/ext3/namei.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ext3/namei.c 2009-12-03 20:04:56.000000000 +0100
@@ -36,6 +36,7 @@
#include <linux/quotaops.h>
#include <linux/buffer_head.h>
@@ -2446,6 +2448,7 @@ const struct inode_operations ext3_dir_i
.removexattr = generic_removexattr,
#endif
- .permission = ext3_permission,
+ .check_acl = ext3_check_acl,
+ .sync_flags = ext3_sync_flags,
};
const struct inode_operations ext3_special_inode_operations = {
-diff -NurpP --minimal linux-2.6.31.6/fs/ext3/super.c linux-2.6.31.6-vs2.3.0.36.24/fs/ext3/super.c
---- linux-2.6.31.6/fs/ext3/super.c 2009-09-10 15:26:21.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ext3/super.c 2009-10-06 22:46:25.000000000 +0200
-@@ -787,7 +787,7 @@ enum {
+diff -NurpP --minimal linux-2.6.32/fs/ext3/super.c linux-2.6.32-vs2.3.0.36.26/fs/ext3/super.c
+--- linux-2.6.32/fs/ext3/super.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ext3/super.c 2009-12-03 20:04:56.000000000 +0100
+@@ -789,7 +789,7 @@ enum {
Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
};
static const match_table_t tokens = {
-@@ -840,6 +840,9 @@ static const match_table_t tokens = {
+@@ -842,6 +842,9 @@ static const match_table_t tokens = {
{Opt_usrquota, "usrquota"},
{Opt_barrier, "barrier=%u"},
{Opt_resize, "resize"},
{Opt_err, NULL},
};
-@@ -932,6 +935,20 @@ static int parse_options (char *options,
+@@ -934,6 +937,20 @@ static int parse_options (char *options,
case Opt_nouid32:
set_opt (sbi->s_mount_opt, NO_UID32);
break;
case Opt_nocheck:
clear_opt (sbi->s_mount_opt, CHECK);
break;
-@@ -1656,6 +1673,9 @@ static int ext3_fill_super (struct super
+@@ -1658,6 +1675,9 @@ static int ext3_fill_super (struct super
NULL, 0))
goto failed_mount;
sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
((sbi->s_mount_opt & EXT3_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
-@@ -2514,6 +2534,14 @@ static int ext3_remount (struct super_bl
+@@ -2527,6 +2547,14 @@ static int ext3_remount (struct super_bl
if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
ext3_abort(sb, __func__, "Abort forced by user");
sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
((sbi->s_mount_opt & EXT3_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
-diff -NurpP --minimal linux-2.6.31.6/fs/ext4/ext4.h linux-2.6.31.6-vs2.3.0.36.24/fs/ext4/ext4.h
---- linux-2.6.31.6/fs/ext4/ext4.h 2009-09-10 15:26:21.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ext4/ext4.h 2009-10-07 01:23:25.000000000 +0200
-@@ -252,8 +252,12 @@ struct flex_groups {
+diff -NurpP --minimal linux-2.6.32/fs/ext4/ext4.h linux-2.6.32-vs2.3.0.36.26/fs/ext4/ext4.h
+--- linux-2.6.32/fs/ext4/ext4.h 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ext4/ext4.h 2009-12-03 20:04:56.000000000 +0100
+@@ -284,8 +284,12 @@ struct flex_groups {
+ #define EXT4_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
#define EXT4_HUGE_FILE_FL 0x00040000 /* Set to each huge file */
#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */
- #define EXT4_EXT_MIGRATE 0x00100000 /* Inode is migrating */
+#define EXT4_IXUNLINK_FL 0x08000000 /* Immutable invert on unlink */
#define EXT4_RESERVED_FL 0x80000000 /* reserved for ext4 lib */
#define EXT4_FL_USER_VISIBLE 0x000BDFFF /* User visible flags */
#define EXT4_FL_USER_MODIFIABLE 0x000B80FF /* User modifiable flags */
-@@ -423,7 +427,8 @@ struct ext4_inode {
+@@ -469,7 +473,8 @@ struct ext4_inode {
__le16 l_i_file_acl_high;
__le16 l_i_uid_high; /* these 2 fields */
__le16 l_i_gid_high; /* were reserved2[0] */
} linux2;
struct {
__le16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
-@@ -538,6 +543,7 @@ do { \
+@@ -583,6 +588,7 @@ do { \
#define i_gid_low i_gid
#define i_uid_high osd2.linux2.l_i_uid_high
#define i_gid_high osd2.linux2.l_i_gid_high
#define i_reserved2 osd2.linux2.l_i_reserved2
#elif defined(__GNU__)
-@@ -694,6 +700,7 @@ struct ext4_inode_info {
+@@ -744,6 +750,7 @@ struct ext4_inode_info {
#define EXT4_MOUNT_QUOTA 0x80000 /* Some quota option set */
#define EXT4_MOUNT_USRQUOTA 0x100000 /* "old" user quota */
#define EXT4_MOUNT_GRPQUOTA 0x200000 /* "old" group quota */
#define EXT4_MOUNT_JOURNAL_CHECKSUM 0x800000 /* Journal checksums */
#define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT 0x1000000 /* Journal Async Commit */
#define EXT4_MOUNT_I_VERSION 0x2000000 /* i_version support */
-@@ -1655,6 +1662,7 @@ extern int ext4_get_blocks(handle_t *han
+@@ -1734,6 +1741,7 @@ extern int ext4_get_blocks(handle_t *han
struct buffer_head *bh, int flags);
extern int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
__u64 start, __u64 len);
/* move_extent.c */
extern int ext4_move_extents(struct file *o_filp, struct file *d_filp,
__u64 start_orig, __u64 start_donor,
-diff -NurpP --minimal linux-2.6.31.6/fs/ext4/file.c linux-2.6.31.6-vs2.3.0.36.24/fs/ext4/file.c
---- linux-2.6.31.6/fs/ext4/file.c 2009-09-10 15:26:21.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ext4/file.c 2009-10-07 01:03:26.000000000 +0200
-@@ -210,5 +210,6 @@ const struct inode_operations ext4_file_
- .permission = ext4_permission,
+diff -NurpP --minimal linux-2.6.32/fs/ext4/file.c linux-2.6.32-vs2.3.0.36.26/fs/ext4/file.c
+--- linux-2.6.32/fs/ext4/file.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ext4/file.c 2009-12-03 20:04:56.000000000 +0100
+@@ -161,5 +161,6 @@ const struct inode_operations ext4_file_
+ .check_acl = ext4_check_acl,
.fallocate = ext4_fallocate,
.fiemap = ext4_fiemap,
+ .sync_flags = ext4_sync_flags,
};
-diff -NurpP --minimal linux-2.6.31.6/fs/ext4/ialloc.c linux-2.6.31.6-vs2.3.0.36.24/fs/ext4/ialloc.c
---- linux-2.6.31.6/fs/ext4/ialloc.c 2009-09-10 15:26:21.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ext4/ialloc.c 2009-10-12 05:06:42.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/ext4/ialloc.c linux-2.6.32-vs2.3.0.36.26/fs/ext4/ialloc.c
+--- linux-2.6.32/fs/ext4/ialloc.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ext4/ialloc.c 2009-12-03 20:04:56.000000000 +0100
@@ -22,6 +22,7 @@
#include <linux/random.h>
#include <linux/bitops.h>
inode->i_ino = ino + group * EXT4_INODES_PER_GROUP(sb);
/* This is the optimal IO size (for stat), not the fs block size */
-diff -NurpP --minimal linux-2.6.31.6/fs/ext4/inode.c linux-2.6.31.6-vs2.3.0.36.24/fs/ext4/inode.c
---- linux-2.6.31.6/fs/ext4/inode.c 2009-09-10 15:26:21.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ext4/inode.c 2009-10-06 19:45:13.000000000 +0200
-@@ -37,6 +37,7 @@
- #include <linux/namei.h>
+diff -NurpP --minimal linux-2.6.32/fs/ext4/inode.c linux-2.6.32-vs2.3.0.36.26/fs/ext4/inode.c
+--- linux-2.6.32/fs/ext4/inode.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ext4/inode.c 2009-12-03 20:04:56.000000000 +0100
+@@ -38,6 +38,7 @@
#include <linux/uio.h>
#include <linux/bio.h>
+ #include <linux/workqueue.h>
+#include <linux/vs_tag.h>
#include "ext4_jbd2.h"
#include "xattr.h"
-@@ -3901,7 +3902,7 @@ static void ext4_free_branches(handle_t
+@@ -4370,7 +4371,7 @@ static void ext4_free_branches(handle_t
int ext4_can_truncate(struct inode *inode)
{
return 0;
if (S_ISREG(inode->i_mode))
return 1;
-@@ -4253,36 +4254,60 @@ void ext4_set_inode_flags(struct inode *
+@@ -4721,36 +4722,60 @@ void ext4_set_inode_flags(struct inode *
{
unsigned int flags = EXT4_I(inode)->i_flags;
}
static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode,
-@@ -4317,6 +4342,8 @@ struct inode *ext4_iget(struct super_blo
+@@ -4785,6 +4810,8 @@ struct inode *ext4_iget(struct super_blo
struct inode *inode;
long ret;
int block;
inode = iget_locked(sb, ino);
if (!inode)
-@@ -4332,12 +4359,16 @@ struct inode *ext4_iget(struct super_blo
+@@ -4800,12 +4827,16 @@ struct inode *ext4_iget(struct super_blo
bh = iloc.bh;
raw_inode = ext4_raw_inode(&iloc);
inode->i_mode = le16_to_cpu(raw_inode->i_mode);
inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
ei->i_state = 0;
-@@ -4538,6 +4569,8 @@ static int ext4_do_update_inode(handle_t
+@@ -5006,6 +5037,8 @@ static int ext4_do_update_inode(handle_t
struct ext4_inode *raw_inode = ext4_raw_inode(iloc);
struct ext4_inode_info *ei = EXT4_I(inode);
struct buffer_head *bh = iloc->bh;
int err = 0, rc, block;
/* For fields not not tracking in the in-memory inode,
-@@ -4548,29 +4581,32 @@ static int ext4_do_update_inode(handle_t
+@@ -5016,29 +5049,32 @@ static int ext4_do_update_inode(handle_t
ext4_get_inode_flags(ei);
raw_inode->i_mode = cpu_to_le16(inode->i_mode);
if (!(test_opt(inode->i_sb, NO_UID32))) {
raw_inode->i_links_count = cpu_to_le16(inode->i_nlink);
EXT4_INODE_SET_XTIME(i_ctime, inode, raw_inode);
-@@ -4734,7 +4770,8 @@ int ext4_setattr(struct dentry *dentry,
+@@ -5222,7 +5258,8 @@ int ext4_setattr(struct dentry *dentry,
return error;
if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
handle_t *handle;
/* (user+group)*(old+new) structure, inode write (sb,
-@@ -4756,6 +4793,8 @@ int ext4_setattr(struct dentry *dentry,
+@@ -5244,6 +5281,8 @@ int ext4_setattr(struct dentry *dentry,
inode->i_uid = attr->ia_uid;
if (attr->ia_valid & ATTR_GID)
inode->i_gid = attr->ia_gid;
error = ext4_mark_inode_dirty(handle, inode);
ext4_journal_stop(handle);
}
-diff -NurpP --minimal linux-2.6.31.6/fs/ext4/ioctl.c linux-2.6.31.6-vs2.3.0.36.24/fs/ext4/ioctl.c
---- linux-2.6.31.6/fs/ext4/ioctl.c 2009-09-10 15:26:21.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ext4/ioctl.c 2009-10-07 04:03:02.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/ext4/ioctl.c linux-2.6.32-vs2.3.0.36.26/fs/ext4/ioctl.c
+--- linux-2.6.32/fs/ext4/ioctl.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ext4/ioctl.c 2009-12-03 20:04:56.000000000 +0100
@@ -14,10 +14,39 @@
#include <linux/compat.h>
#include <linux/mount.h>
if (!capable(CAP_LINUX_IMMUTABLE))
goto flags_out;
}
-diff -NurpP --minimal linux-2.6.31.6/fs/ext4/namei.c linux-2.6.31.6-vs2.3.0.36.24/fs/ext4/namei.c
---- linux-2.6.31.6/fs/ext4/namei.c 2009-09-10 15:26:21.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ext4/namei.c 2009-10-07 01:08:37.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/ext4/namei.c linux-2.6.32-vs2.3.0.36.26/fs/ext4/namei.c
+--- linux-2.6.32/fs/ext4/namei.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ext4/namei.c 2009-12-03 20:04:56.000000000 +0100
@@ -34,6 +34,7 @@
#include <linux/quotaops.h>
#include <linux/buffer_head.h>
}
if ((bh = bh_use[ra_ptr++]) == NULL)
goto next;
-@@ -2538,6 +2540,7 @@ const struct inode_operations ext4_dir_i
+@@ -2539,6 +2541,7 @@ const struct inode_operations ext4_dir_i
#endif
- .permission = ext4_permission,
+ .check_acl = ext4_check_acl,
.fiemap = ext4_fiemap,
+ .sync_flags = ext4_sync_flags,
};
const struct inode_operations ext4_special_inode_operations = {
-diff -NurpP --minimal linux-2.6.31.6/fs/ext4/super.c linux-2.6.31.6-vs2.3.0.36.24/fs/ext4/super.c
---- linux-2.6.31.6/fs/ext4/super.c 2009-09-10 15:26:21.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ext4/super.c 2009-10-06 22:47:27.000000000 +0200
-@@ -1057,7 +1057,8 @@ enum {
+diff -NurpP --minimal linux-2.6.32/fs/ext4/super.c linux-2.6.32-vs2.3.0.36.26/fs/ext4/super.c
+--- linux-2.6.32/fs/ext4/super.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ext4/super.c 2009-12-03 20:04:56.000000000 +0100
+@@ -1079,7 +1079,8 @@ enum {
Opt_usrquota, Opt_grpquota, Opt_i_version,
Opt_stripe, Opt_delalloc, Opt_nodelalloc,
Opt_block_validity, Opt_noblock_validity,
};
static const match_table_t tokens = {
-@@ -1123,6 +1124,9 @@ static const match_table_t tokens = {
+@@ -1144,6 +1145,9 @@ static const match_table_t tokens = {
{Opt_auto_da_alloc, "auto_da_alloc=%u"},
{Opt_auto_da_alloc, "auto_da_alloc"},
{Opt_noauto_da_alloc, "noauto_da_alloc"},
{Opt_err, NULL},
};
-@@ -1220,6 +1224,20 @@ static int parse_options(char *options,
+@@ -1241,6 +1245,20 @@ static int parse_options(char *options,
case Opt_nouid32:
set_opt(sbi->s_mount_opt, NO_UID32);
break;
case Opt_debug:
set_opt(sbi->s_mount_opt, DEBUG);
break;
-@@ -2385,6 +2403,9 @@ static int ext4_fill_super(struct super_
+@@ -2435,6 +2453,9 @@ static int ext4_fill_super(struct super_
&journal_ioprio, NULL, 0))
goto failed_mount;
sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
((sbi->s_mount_opt & EXT4_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
-@@ -3441,6 +3462,14 @@ static int ext4_remount(struct super_blo
+@@ -3492,6 +3513,14 @@ static int ext4_remount(struct super_blo
if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED)
ext4_abort(sb, __func__, "Abort forced by user");
sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
((sbi->s_mount_opt & EXT4_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
-diff -NurpP --minimal linux-2.6.31.6/fs/fcntl.c linux-2.6.31.6-vs2.3.0.36.24/fs/fcntl.c
---- linux-2.6.31.6/fs/fcntl.c 2009-09-10 15:26:22.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/fcntl.c 2009-09-10 17:00:41.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/fcntl.c linux-2.6.32-vs2.3.0.36.26/fs/fcntl.c
+--- linux-2.6.32/fs/fcntl.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/fcntl.c 2009-12-03 20:04:56.000000000 +0100
@@ -19,6 +19,7 @@
#include <linux/signal.h>
#include <linux/rcupdate.h>
return newfd;
-@@ -347,6 +350,8 @@ SYSCALL_DEFINE3(fcntl, unsigned int, fd,
+@@ -426,6 +429,8 @@ SYSCALL_DEFINE3(fcntl, unsigned int, fd,
filp = fget(fd);
if (!filp)
goto out;
err = security_file_fcntl(filp, cmd, arg);
if (err) {
-diff -NurpP --minimal linux-2.6.31.6/fs/file.c linux-2.6.31.6-vs2.3.0.36.24/fs/file.c
---- linux-2.6.31.6/fs/file.c 2008-12-25 00:26:37.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/file.c 2009-09-10 16:11:43.000000000 +0200
-@@ -19,6 +19,7 @@
+diff -NurpP --minimal linux-2.6.32/fs/file.c linux-2.6.32-vs2.3.0.36.26/fs/file.c
+--- linux-2.6.32/fs/file.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/file.c 2009-12-03 20:04:56.000000000 +0100
+@@ -20,6 +20,7 @@
#include <linux/spinlock.h>
#include <linux/rcupdate.h>
#include <linux/workqueue.h>
struct fdtable_defer {
spinlock_t lock;
-@@ -367,6 +368,8 @@ struct files_struct *dup_fd(struct files
+@@ -368,6 +369,8 @@ struct files_struct *dup_fd(struct files
struct file *f = *old_fds++;
if (f) {
get_file(f);
} else {
/*
* The fd may be claimed in the fd bitmap but not yet
-@@ -475,6 +478,7 @@ repeat:
+@@ -476,6 +479,7 @@ repeat:
else
FD_CLR(fd, fdt->close_on_exec);
error = fd;
#if 1
/* Sanity check */
if (rcu_dereference(fdt->fd[fd]) != NULL) {
-diff -NurpP --minimal linux-2.6.31.6/fs/file_table.c linux-2.6.31.6-vs2.3.0.36.24/fs/file_table.c
---- linux-2.6.31.6/fs/file_table.c 2009-09-10 15:26:22.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/file_table.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/file_table.c linux-2.6.32-vs2.3.0.36.26/fs/file_table.c
+--- linux-2.6.32/fs/file_table.c 2009-12-03 20:02:51.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/file_table.c 2009-12-03 20:04:56.000000000 +0100
@@ -22,6 +22,8 @@
#include <linux/fsnotify.h>
#include <linux/sysctl.h>
file_kill(file);
file_free(file);
}
-diff -NurpP --minimal linux-2.6.31.6/fs/fs_struct.c linux-2.6.31.6-vs2.3.0.36.24/fs/fs_struct.c
---- linux-2.6.31.6/fs/fs_struct.c 2009-06-11 17:13:04.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/fs_struct.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/fs_struct.c linux-2.6.32-vs2.3.0.36.26/fs/fs_struct.c
+--- linux-2.6.32/fs/fs_struct.c 2009-06-11 17:13:04.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/fs_struct.c 2009-12-03 20:04:56.000000000 +0100
@@ -4,6 +4,7 @@
#include <linux/path.h>
#include <linux/slab.h>
}
return fs;
}
-diff -NurpP --minimal linux-2.6.31.6/fs/gfs2/file.c linux-2.6.31.6-vs2.3.0.36.24/fs/gfs2/file.c
---- linux-2.6.31.6/fs/gfs2/file.c 2009-09-10 15:26:22.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/gfs2/file.c 2009-10-07 18:47:19.000000000 +0200
-@@ -133,6 +133,9 @@ static const u32 fsflags_to_gfs2[32] = {
+diff -NurpP --minimal linux-2.6.32/fs/gfs2/file.c linux-2.6.32-vs2.3.0.36.26/fs/gfs2/file.c
+--- linux-2.6.32/fs/gfs2/file.c 2009-12-03 20:02:52.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/gfs2/file.c 2009-12-03 20:04:56.000000000 +0100
+@@ -132,6 +132,9 @@ static const u32 fsflags_to_gfs2[32] = {
[7] = GFS2_DIF_NOATIME,
[12] = GFS2_DIF_EXHASH,
[14] = GFS2_DIF_INHERIT_JDATA,
};
static const u32 gfs2_to_fsflags[32] = {
-@@ -142,6 +145,9 @@ static const u32 gfs2_to_fsflags[32] = {
+@@ -141,6 +144,9 @@ static const u32 gfs2_to_fsflags[32] = {
[gfs2fl_NoAtime] = FS_NOATIME_FL,
[gfs2fl_ExHash] = FS_INDEX_FL,
[gfs2fl_InheritJdata] = FS_JOURNAL_DATA_FL,
};
static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
-@@ -172,10 +178,16 @@ void gfs2_set_inode_flags(struct inode *
+@@ -171,10 +177,16 @@ void gfs2_set_inode_flags(struct inode *
{
struct gfs2_inode *ip = GFS2_I(inode);
unsigned int flags = inode->i_flags;
if (ip->i_diskflags & GFS2_DIF_APPENDONLY)
flags |= S_APPEND;
if (ip->i_diskflags & GFS2_DIF_NOATIME)
-@@ -183,6 +195,43 @@ void gfs2_set_inode_flags(struct inode *
+@@ -182,6 +194,43 @@ void gfs2_set_inode_flags(struct inode *
if (ip->i_diskflags & GFS2_DIF_SYNC)
flags |= S_SYNC;
inode->i_flags = flags;
}
/* Flags that can be set by user space */
-@@ -287,6 +336,37 @@ static int gfs2_set_flags(struct file *f
+@@ -286,6 +335,37 @@ static int gfs2_set_flags(struct file *f
return do_gfs2_set_flags(filp, gfsflags, ~GFS2_DIF_JDATA);
}
static long gfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
switch(cmd) {
-diff -NurpP --minimal linux-2.6.31.6/fs/gfs2/inode.h linux-2.6.31.6-vs2.3.0.36.24/fs/gfs2/inode.h
---- linux-2.6.31.6/fs/gfs2/inode.h 2009-09-10 15:26:22.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/gfs2/inode.h 2009-10-07 18:16:33.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/gfs2/inode.h linux-2.6.32-vs2.3.0.36.26/fs/gfs2/inode.h
+--- linux-2.6.32/fs/gfs2/inode.h 2009-09-10 15:26:22.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/gfs2/inode.h 2009-12-03 20:04:56.000000000 +0100
@@ -109,6 +109,7 @@ extern const struct file_operations gfs2
extern const struct file_operations gfs2_dir_fops_nolock;
#ifdef CONFIG_GFS2_FS_LOCKING_DLM
extern const struct file_operations gfs2_file_fops;
-diff -NurpP --minimal linux-2.6.31.6/fs/gfs2/ops_inode.c linux-2.6.31.6-vs2.3.0.36.24/fs/gfs2/ops_inode.c
---- linux-2.6.31.6/fs/gfs2/ops_inode.c 2009-09-10 15:26:22.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/gfs2/ops_inode.c 2009-10-07 18:15:45.000000000 +0200
-@@ -1409,6 +1409,7 @@ const struct inode_operations gfs2_file_
+diff -NurpP --minimal linux-2.6.32/fs/gfs2/ops_inode.c linux-2.6.32-vs2.3.0.36.26/fs/gfs2/ops_inode.c
+--- linux-2.6.32/fs/gfs2/ops_inode.c 2009-12-03 20:02:52.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/gfs2/ops_inode.c 2009-12-03 20:04:56.000000000 +0100
+@@ -1400,6 +1400,7 @@ const struct inode_operations gfs2_file_
.listxattr = gfs2_listxattr,
.removexattr = gfs2_removexattr,
.fiemap = gfs2_fiemap,
};
const struct inode_operations gfs2_dir_iops = {
-@@ -1429,6 +1430,7 @@ const struct inode_operations gfs2_dir_i
+@@ -1420,6 +1421,7 @@ const struct inode_operations gfs2_dir_i
.listxattr = gfs2_listxattr,
.removexattr = gfs2_removexattr,
.fiemap = gfs2_fiemap,
};
const struct inode_operations gfs2_symlink_iops = {
-diff -NurpP --minimal linux-2.6.31.6/fs/hfsplus/ioctl.c linux-2.6.31.6-vs2.3.0.36.24/fs/hfsplus/ioctl.c
---- linux-2.6.31.6/fs/hfsplus/ioctl.c 2008-12-25 00:26:37.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/hfsplus/ioctl.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/hfsplus/ioctl.c linux-2.6.32-vs2.3.0.36.26/fs/hfsplus/ioctl.c
+--- linux-2.6.32/fs/hfsplus/ioctl.c 2008-12-25 00:26:37.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/hfsplus/ioctl.c 2009-12-03 20:04:56.000000000 +0100
@@ -17,6 +17,7 @@
#include <linux/mount.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
#include "hfsplus_fs.h"
-diff -NurpP --minimal linux-2.6.31.6/fs/inode.c linux-2.6.31.6-vs2.3.0.36.24/fs/inode.c
---- linux-2.6.31.6/fs/inode.c 2009-11-12 12:10:11.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/inode.c 2009-10-05 23:35:52.000000000 +0200
-@@ -128,6 +128,9 @@ int inode_init_always(struct super_block
+diff -NurpP --minimal linux-2.6.32/fs/inode.c linux-2.6.32-vs2.3.0.36.26/fs/inode.c
+--- linux-2.6.32/fs/inode.c 2009-12-03 20:02:52.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/inode.c 2009-12-03 20:04:56.000000000 +0100
+@@ -133,6 +133,9 @@ int inode_init_always(struct super_block
struct address_space *const mapping = &inode->i_data;
inode->i_sb = sb;
inode->i_blkbits = sb->s_blocksize_bits;
inode->i_flags = 0;
atomic_set(&inode->i_count, 1);
-@@ -148,6 +151,7 @@ int inode_init_always(struct super_block
+@@ -153,6 +156,7 @@ int inode_init_always(struct super_block
inode->i_bdev = NULL;
inode->i_cdev = NULL;
inode->i_rdev = 0;
inode->dirtied_when = 0;
if (security_inode_alloc(inode))
-@@ -304,6 +308,8 @@ void __iget(struct inode *inode)
+@@ -307,6 +311,8 @@ void __iget(struct inode *inode)
inodes_stat.nr_unused--;
}
/**
* clear_inode - clear an inode
* @inode: inode to clear
-@@ -1588,9 +1594,11 @@ void init_special_inode(struct inode *in
+@@ -1611,9 +1617,11 @@ void init_special_inode(struct inode *in
if (S_ISCHR(mode)) {
inode->i_fop = &def_chr_fops;
inode->i_rdev = rdev;
} else if (S_ISFIFO(mode))
inode->i_fop = &def_fifo_fops;
else if (S_ISSOCK(mode))
-diff -NurpP --minimal linux-2.6.31.6/fs/ioctl.c linux-2.6.31.6-vs2.3.0.36.24/fs/ioctl.c
---- linux-2.6.31.6/fs/ioctl.c 2009-09-10 15:26:22.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ioctl.c 2009-09-10 17:13:08.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/ioctl.c linux-2.6.32-vs2.3.0.36.26/fs/ioctl.c
+--- linux-2.6.32/fs/ioctl.c 2009-12-03 20:02:52.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ioctl.c 2009-12-03 20:04:56.000000000 +0100
@@ -16,6 +16,9 @@
#include <linux/writeback.h>
#include <linux/buffer_head.h>
#include <asm/ioctls.h>
-diff -NurpP --minimal linux-2.6.31.6/fs/ioprio.c linux-2.6.31.6-vs2.3.0.36.24/fs/ioprio.c
---- linux-2.6.31.6/fs/ioprio.c 2009-03-24 14:22:26.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ioprio.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/ioprio.c linux-2.6.32-vs2.3.0.36.26/fs/ioprio.c
+--- linux-2.6.32/fs/ioprio.c 2009-03-24 14:22:26.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ioprio.c 2009-12-03 20:04:56.000000000 +0100
@@ -26,6 +26,7 @@
#include <linux/syscalls.h>
#include <linux/security.h>
tmpio = get_task_ioprio(p);
if (tmpio < 0)
continue;
-diff -NurpP --minimal linux-2.6.31.6/fs/jfs/acl.c linux-2.6.31.6-vs2.3.0.36.24/fs/jfs/acl.c
---- linux-2.6.31.6/fs/jfs/acl.c 2009-09-10 15:26:22.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/jfs/acl.c 2009-09-10 16:11:43.000000000 +0200
-@@ -221,7 +221,8 @@ int jfs_setattr(struct dentry *dentry, s
+diff -NurpP --minimal linux-2.6.32/fs/jfs/acl.c linux-2.6.32-vs2.3.0.36.26/fs/jfs/acl.c
+--- linux-2.6.32/fs/jfs/acl.c 2009-12-03 20:02:52.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/jfs/acl.c 2009-12-03 20:04:56.000000000 +0100
+@@ -216,7 +216,8 @@ int jfs_setattr(struct dentry *dentry, s
return rc;
if ((iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid) ||
if (vfs_dq_transfer(inode, iattr))
return -EDQUOT;
}
-diff -NurpP --minimal linux-2.6.31.6/fs/jfs/file.c linux-2.6.31.6-vs2.3.0.36.24/fs/jfs/file.c
---- linux-2.6.31.6/fs/jfs/file.c 2008-12-25 00:26:37.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/jfs/file.c 2009-10-07 01:05:32.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/jfs/file.c linux-2.6.32-vs2.3.0.36.26/fs/jfs/file.c
+--- linux-2.6.32/fs/jfs/file.c 2009-12-03 20:02:52.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/jfs/file.c 2009-12-03 20:04:56.000000000 +0100
@@ -98,6 +98,7 @@ const struct inode_operations jfs_file_i
.setattr = jfs_setattr,
- .permission = jfs_permission,
+ .check_acl = jfs_check_acl,
#endif
+ .sync_flags = jfs_sync_flags,
};
const struct file_operations jfs_file_operations = {
-diff -NurpP --minimal linux-2.6.31.6/fs/jfs/ioctl.c linux-2.6.31.6-vs2.3.0.36.24/fs/jfs/ioctl.c
---- linux-2.6.31.6/fs/jfs/ioctl.c 2008-12-25 00:26:37.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/jfs/ioctl.c 2009-10-07 04:09:15.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/jfs/ioctl.c linux-2.6.32-vs2.3.0.36.26/fs/jfs/ioctl.c
+--- linux-2.6.32/fs/jfs/ioctl.c 2008-12-25 00:26:37.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/jfs/ioctl.c 2009-12-03 20:04:56.000000000 +0100
@@ -11,6 +11,7 @@
#include <linux/mount.h>
#include <linux/time.h>
flags |= oldflags & ~JFS_FL_USER_MODIFIABLE;
jfs_inode->mode2 = flags;
-diff -NurpP --minimal linux-2.6.31.6/fs/jfs/jfs_dinode.h linux-2.6.31.6-vs2.3.0.36.24/fs/jfs/jfs_dinode.h
---- linux-2.6.31.6/fs/jfs/jfs_dinode.h 2008-12-25 00:26:37.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/jfs/jfs_dinode.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/jfs/jfs_dinode.h linux-2.6.32-vs2.3.0.36.26/fs/jfs/jfs_dinode.h
+--- linux-2.6.32/fs/jfs/jfs_dinode.h 2008-12-25 00:26:37.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/jfs/jfs_dinode.h 2009-12-03 20:04:56.000000000 +0100
@@ -161,9 +161,13 @@ struct dinode {
#define JFS_APPEND_FL 0x01000000 /* writes to file may only append */
#define JFS_FL_INHERIT 0x03C80000
/* These are identical to EXT[23]_IOC_GETFLAGS/SETFLAGS */
-diff -NurpP --minimal linux-2.6.31.6/fs/jfs/jfs_filsys.h linux-2.6.31.6-vs2.3.0.36.24/fs/jfs/jfs_filsys.h
---- linux-2.6.31.6/fs/jfs/jfs_filsys.h 2008-12-25 00:26:37.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/jfs/jfs_filsys.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/jfs/jfs_filsys.h linux-2.6.32-vs2.3.0.36.26/fs/jfs/jfs_filsys.h
+--- linux-2.6.32/fs/jfs/jfs_filsys.h 2008-12-25 00:26:37.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/jfs/jfs_filsys.h 2009-12-03 20:04:56.000000000 +0100
@@ -263,6 +263,7 @@
#define JFS_NAME_MAX 255
#define JFS_PATH_MAX BPSIZE
/*
* file system state (superblock state)
-diff -NurpP --minimal linux-2.6.31.6/fs/jfs/jfs_imap.c linux-2.6.31.6-vs2.3.0.36.24/fs/jfs/jfs_imap.c
---- linux-2.6.31.6/fs/jfs/jfs_imap.c 2009-09-10 15:26:22.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/jfs/jfs_imap.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/jfs/jfs_imap.c linux-2.6.32-vs2.3.0.36.26/fs/jfs/jfs_imap.c
+--- linux-2.6.32/fs/jfs/jfs_imap.c 2009-09-10 15:26:22.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/jfs/jfs_imap.c 2009-12-03 20:04:56.000000000 +0100
@@ -45,6 +45,7 @@
#include <linux/buffer_head.h>
#include <linux/pagemap.h>
jfs_get_inode_flags(jfs_ip);
/*
* mode2 is only needed for storing the higher order bits.
-diff -NurpP --minimal linux-2.6.31.6/fs/jfs/jfs_inode.c linux-2.6.31.6-vs2.3.0.36.24/fs/jfs/jfs_inode.c
---- linux-2.6.31.6/fs/jfs/jfs_inode.c 2009-06-11 17:13:05.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/jfs/jfs_inode.c 2009-10-12 05:07:16.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/jfs/jfs_inode.c linux-2.6.32-vs2.3.0.36.26/fs/jfs/jfs_inode.c
+--- linux-2.6.32/fs/jfs/jfs_inode.c 2009-06-11 17:13:05.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/jfs/jfs_inode.c 2009-12-03 20:04:56.000000000 +0100
@@ -18,6 +18,7 @@
#include <linux/fs.h>
/*
* New inodes need to save sane values on disk when
-diff -NurpP --minimal linux-2.6.31.6/fs/jfs/jfs_inode.h linux-2.6.31.6-vs2.3.0.36.24/fs/jfs/jfs_inode.h
---- linux-2.6.31.6/fs/jfs/jfs_inode.h 2009-06-11 17:13:05.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/jfs/jfs_inode.h 2009-10-07 01:25:26.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/jfs/jfs_inode.h linux-2.6.32-vs2.3.0.36.26/fs/jfs/jfs_inode.h
+--- linux-2.6.32/fs/jfs/jfs_inode.h 2009-06-11 17:13:05.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/jfs/jfs_inode.h 2009-12-03 20:04:56.000000000 +0100
@@ -39,6 +39,7 @@ extern struct dentry *jfs_fh_to_dentry(s
extern struct dentry *jfs_fh_to_parent(struct super_block *sb, struct fid *fid,
int fh_len, int fh_type);
extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
extern const struct address_space_operations jfs_aops;
-diff -NurpP --minimal linux-2.6.31.6/fs/jfs/namei.c linux-2.6.31.6-vs2.3.0.36.24/fs/jfs/namei.c
---- linux-2.6.31.6/fs/jfs/namei.c 2009-06-11 17:13:05.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/jfs/namei.c 2009-10-07 01:09:16.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/jfs/namei.c linux-2.6.32-vs2.3.0.36.26/fs/jfs/namei.c
+--- linux-2.6.32/fs/jfs/namei.c 2009-12-03 20:02:52.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/jfs/namei.c 2009-12-03 20:04:56.000000000 +0100
@@ -21,6 +21,7 @@
#include <linux/ctype.h>
#include <linux/quotaops.h>
if (dentry && (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2))
@@ -1545,6 +1547,7 @@ const struct inode_operations jfs_dir_in
.setattr = jfs_setattr,
- .permission = jfs_permission,
+ .check_acl = jfs_check_acl,
#endif
+ .sync_flags = jfs_sync_flags,
};
const struct file_operations jfs_dir_operations = {
-diff -NurpP --minimal linux-2.6.31.6/fs/jfs/super.c linux-2.6.31.6-vs2.3.0.36.24/fs/jfs/super.c
---- linux-2.6.31.6/fs/jfs/super.c 2009-09-10 15:26:22.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/jfs/super.c 2009-09-10 17:10:55.000000000 +0200
-@@ -194,7 +194,8 @@ static void jfs_put_super(struct super_b
+diff -NurpP --minimal linux-2.6.32/fs/jfs/super.c linux-2.6.32-vs2.3.0.36.26/fs/jfs/super.c
+--- linux-2.6.32/fs/jfs/super.c 2009-12-03 20:02:52.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/jfs/super.c 2009-12-03 20:04:56.000000000 +0100
+@@ -192,7 +192,8 @@ static void jfs_put_super(struct super_b
enum {
Opt_integrity, Opt_nointegrity, Opt_iocharset, Opt_resize,
Opt_resize_nosize, Opt_errors, Opt_ignore, Opt_err, Opt_quota,
};
static const match_table_t tokens = {
-@@ -204,6 +205,10 @@ static const match_table_t tokens = {
+@@ -202,6 +203,10 @@ static const match_table_t tokens = {
{Opt_resize, "resize=%u"},
{Opt_resize_nosize, "resize"},
{Opt_errors, "errors=%s"},
{Opt_ignore, "noquota"},
{Opt_ignore, "quota"},
{Opt_usrquota, "usrquota"},
-@@ -338,6 +343,20 @@ static int parse_options(char *options,
+@@ -336,6 +341,20 @@ static int parse_options(char *options,
}
break;
}
default:
printk("jfs: Unrecognized mount option \"%s\" "
" or missing value\n", p);
-@@ -369,6 +388,12 @@ static int jfs_remount(struct super_bloc
+@@ -366,6 +385,12 @@ static int jfs_remount(struct super_bloc
if (!parse_options(data, sb, &newLVSize, &flag)) {
return -EINVAL;
}
lock_kernel();
if (newLVSize) {
if (sb->s_flags & MS_RDONLY) {
-@@ -452,6 +477,9 @@ static int jfs_fill_super(struct super_b
+@@ -449,6 +474,9 @@ static int jfs_fill_super(struct super_b
#ifdef CONFIG_JFS_POSIX_ACL
sb->s_flags |= MS_POSIXACL;
#endif
if (newLVSize) {
printk(KERN_ERR "resize option for remount only\n");
-diff -NurpP --minimal linux-2.6.31.6/fs/libfs.c linux-2.6.31.6-vs2.3.0.36.24/fs/libfs.c
---- linux-2.6.31.6/fs/libfs.c 2009-09-10 15:26:22.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/libfs.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/libfs.c linux-2.6.32-vs2.3.0.36.26/fs/libfs.c
+--- linux-2.6.32/fs/libfs.c 2009-12-03 20:02:52.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/libfs.c 2009-12-03 20:04:56.000000000 +0100
@@ -127,7 +127,8 @@ static inline unsigned char dt_type(stru
* both impossible due to the lock on directory.
*/
ssize_t generic_read_dir(struct file *filp, char __user *buf, size_t siz, loff_t *ppos)
{
return -EISDIR;
-@@ -836,6 +851,7 @@ EXPORT_SYMBOL(dcache_dir_close);
+@@ -841,6 +856,7 @@ EXPORT_SYMBOL(dcache_dir_close);
EXPORT_SYMBOL(dcache_dir_lseek);
EXPORT_SYMBOL(dcache_dir_open);
EXPORT_SYMBOL(dcache_readdir);
EXPORT_SYMBOL(generic_read_dir);
EXPORT_SYMBOL(get_sb_pseudo);
EXPORT_SYMBOL(simple_write_begin);
-diff -NurpP --minimal linux-2.6.31.6/fs/locks.c linux-2.6.31.6-vs2.3.0.36.24/fs/locks.c
---- linux-2.6.31.6/fs/locks.c 2009-09-10 15:26:22.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/locks.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/locks.c linux-2.6.32-vs2.3.0.36.26/fs/locks.c
+--- linux-2.6.32/fs/locks.c 2009-12-03 20:02:52.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/locks.c 2009-12-03 20:04:56.000000000 +0100
@@ -127,6 +127,8 @@
#include <linux/time.h>
#include <linux/rcupdate.h>
locks_free_lock(fl);
@@ -770,6 +788,7 @@ static int flock_lock_file(struct file *
if (found)
- cond_resched_bkl();
+ cond_resched();
+ new_fl->fl_xid = -1;
find_conflict:
f->private++;
return 0;
-diff -NurpP --minimal linux-2.6.31.6/fs/namei.c linux-2.6.31.6-vs2.3.0.36.24/fs/namei.c
---- linux-2.6.31.6/fs/namei.c 2009-11-12 12:10:11.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/namei.c 2009-10-15 03:49:19.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/namei.c linux-2.6.32-vs2.3.0.36.26/fs/namei.c
+--- linux-2.6.32/fs/namei.c 2009-12-03 20:02:52.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/namei.c 2009-12-03 20:04:56.000000000 +0100
@@ -33,6 +33,14 @@
#include <linux/fcntl.h>
#include <linux/device_cgroup.h>
EXPORT_SYMBOL(putname);
#endif
-+static inline int dx_barrier(struct inode *inode)
++static inline int dx_barrier(const struct inode *inode)
+{
+ if (IS_BARRIER(inode) && !vx_check(0, VS_ADMIN | VS_WATCH)) {
+ vxwprintk_task(1, "did hit the barrier.");
+ return 0;
+}
+
-+static int __dx_permission(struct inode *inode, int mask)
++static int __dx_permission(const struct inode *inode, int mask)
+{
+ if (dx_barrier(inode))
+ return -EACCES;
+ return -EACCES;
+}
+
-+int dx_permission(struct inode *inode, int mask)
++int dx_permission(const struct inode *inode, int mask)
+{
+ int ret = __dx_permission(inode, mask);
+ if (unlikely(ret)) {
+ return ret;
+}
+
-
- /**
- * generic_permission - check for access rights on a Posix-like filesystem
-@@ -255,10 +334,14 @@ int inode_permission(struct inode *inode
+ /*
+ * This does basic POSIX ACL permission checking
+ */
+@@ -268,10 +347,14 @@ int inode_permission(struct inode *inode
/*
* Nobody gets write access to an immutable file.
*/
if (inode->i_op->permission)
retval = inode->i_op->permission(inode, mask);
else
-@@ -434,6 +517,8 @@ static int exec_permission_lite(struct i
+@@ -447,6 +530,9 @@ static int exec_permission_lite(struct i
{
- umode_t mode = inode->i_mode;
+ int ret;
+ if (dx_barrier(inode))
+ return -EACCES;
- if (inode->i_op->permission)
- return -EAGAIN;
-
-@@ -756,7 +841,8 @@ static __always_inline void follow_dotdo
++
+ if (inode->i_op->permission) {
+ ret = inode->i_op->permission(inode, MAY_EXEC);
+ if (!ret)
+@@ -762,7 +848,8 @@ static __always_inline void follow_dotdo
if (nd->path.dentry == nd->root.dentry &&
nd->path.mnt == nd->root.mnt) {
}
spin_lock(&dcache_lock);
if (nd->path.dentry != nd->path.mnt->mnt_root) {
-@@ -792,16 +878,30 @@ static int do_lookup(struct nameidata *n
+@@ -798,16 +885,30 @@ static int do_lookup(struct nameidata *n
{
struct vfsmount *mnt = nd->path.mnt;
struct dentry *dentry = __d_lookup(nd->path.dentry, name);
need_lookup:
dentry = real_lookup(nd->path.dentry, name, nd);
-@@ -1389,7 +1489,7 @@ static int may_delete(struct inode *dir,
+@@ -1389,7 +1490,7 @@ static int may_delete(struct inode *dir,
if (IS_APPEND(dir))
return -EPERM;
if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)||
return -EPERM;
if (isdir) {
if (!S_ISDIR(victim->d_inode->i_mode))
-@@ -1529,6 +1629,14 @@ int may_open(struct path *path, int acc_
+@@ -1529,6 +1630,14 @@ int may_open(struct path *path, int acc_
break;
}
error = inode_permission(inode, acc_mode);
if (error)
return error;
-@@ -1677,7 +1785,11 @@ struct file *do_filp_open(int dfd, const
+@@ -1677,7 +1786,11 @@ struct file *do_filp_open(int dfd, const
int count = 0;
int will_write;
int flag = open_to_namei_flags(open_flag);
if (!acc_mode)
acc_mode = MAY_OPEN | ACC_MODE(flag);
-@@ -1825,6 +1937,25 @@ ok:
+@@ -1825,6 +1938,25 @@ ok:
goto exit;
}
error = may_open(&nd.path, acc_mode, flag);
if (error) {
if (will_write)
mnt_drop_write(nd.path.mnt);
-@@ -1987,9 +2118,17 @@ int vfs_mknod(struct inode *dir, struct
+@@ -1987,9 +2119,17 @@ int vfs_mknod(struct inode *dir, struct
if (error)
return error;
if (!dir->i_op->mknod)
return -EPERM;
-@@ -2456,7 +2595,7 @@ int vfs_link(struct dentry *old_dentry,
+@@ -2456,7 +2596,7 @@ int vfs_link(struct dentry *old_dentry,
/*
* A link to an append-only or immutable file cannot be created.
*/
return -EPERM;
if (!dir->i_op->link)
return -EPERM;
-@@ -2829,6 +2968,219 @@ int vfs_follow_link(struct nameidata *nd
+@@ -2829,6 +2969,219 @@ int vfs_follow_link(struct nameidata *nd
return __vfs_follow_link(nd, link);
}
/* get the link contents into pagecache */
static char *page_getlink(struct dentry * dentry, struct page **ppage)
{
-diff -NurpP --minimal linux-2.6.31.6/fs/namespace.c linux-2.6.31.6-vs2.3.0.36.24/fs/namespace.c
---- linux-2.6.31.6/fs/namespace.c 2009-09-10 15:26:22.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/namespace.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/namespace.c linux-2.6.32-vs2.3.0.36.26/fs/namespace.c
+--- linux-2.6.32/fs/namespace.c 2009-12-03 20:02:52.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/namespace.c 2009-12-03 20:04:56.000000000 +0100
@@ -29,6 +29,11 @@
#include <linux/log2.h>
#include <linux/idr.h>
return -EPERM;
lock_kernel();
-@@ -1891,6 +1952,7 @@ long do_mount(char *dev_name, char *dir_
+@@ -1908,6 +1969,7 @@ long do_mount(char *dev_name, char *dir_
struct path path;
int retval = 0;
int mnt_flags = 0;
/* Discard magic */
if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
-@@ -1910,6 +1972,12 @@ long do_mount(char *dev_name, char *dir_
+@@ -1925,6 +1987,12 @@ long do_mount(char *dev_name, char *dir_
if (!(flags & MS_NOATIME))
mnt_flags |= MNT_RELATIME;
/* Separate the per-mountpoint flags */
if (flags & MS_NOSUID)
mnt_flags |= MNT_NOSUID;
-@@ -1926,6 +1994,8 @@ long do_mount(char *dev_name, char *dir_
+@@ -1941,6 +2009,8 @@ long do_mount(char *dev_name, char *dir_
if (flags & MS_RDONLY)
mnt_flags |= MNT_READONLY;
flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE |
MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
MS_STRICTATIME);
-@@ -1942,9 +2012,9 @@ long do_mount(char *dev_name, char *dir_
+@@ -1957,9 +2027,9 @@ long do_mount(char *dev_name, char *dir_
if (flags & MS_REMOUNT)
retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags,
else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
retval = do_change_type(&path, flags);
else if (flags & MS_MOVE)
-@@ -2023,6 +2093,7 @@ static struct mnt_namespace *dup_mnt_ns(
+@@ -2038,6 +2108,7 @@ static struct mnt_namespace *dup_mnt_ns(
q = next_mnt(q, new_ns->root);
}
up_write(&namespace_sem);
if (rootmnt)
mntput(rootmnt);
-@@ -2165,9 +2236,10 @@ SYSCALL_DEFINE2(pivot_root, const char _
+@@ -2182,9 +2253,10 @@ SYSCALL_DEFINE2(pivot_root, const char _
down_write(&namespace_sem);
mutex_lock(&old.dentry->d_inode->i_mutex);
error = -EINVAL;
goto out2;
if (!check_mnt(root.mnt))
goto out2;
-@@ -2303,6 +2375,7 @@ void put_mnt_ns(struct mnt_namespace *ns
+@@ -2320,6 +2392,7 @@ void put_mnt_ns(struct mnt_namespace *ns
spin_unlock(&vfsmount_lock);
up_write(&namespace_sem);
release_mounts(&umount_list);
kfree(ns);
}
EXPORT_SYMBOL(put_mnt_ns);
-diff -NurpP --minimal linux-2.6.31.6/fs/nfs/client.c linux-2.6.31.6-vs2.3.0.36.24/fs/nfs/client.c
---- linux-2.6.31.6/fs/nfs/client.c 2009-11-12 12:10:11.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/nfs/client.c 2009-11-12 12:26:38.000000000 +0100
-@@ -732,6 +732,9 @@ static int nfs_init_server_rpcclient(str
+diff -NurpP --minimal linux-2.6.32/fs/nfs/client.c linux-2.6.32-vs2.3.0.36.26/fs/nfs/client.c
+--- linux-2.6.32/fs/nfs/client.c 2009-12-03 20:02:52.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/nfs/client.c 2009-12-03 20:04:56.000000000 +0100
+@@ -738,6 +738,9 @@ static int nfs_init_server_rpcclient(str
if (server->flags & NFS_MOUNT_SOFT)
server->client->cl_softrtry = 1;
return 0;
}
-@@ -899,6 +902,10 @@ static void nfs_server_set_fsinfo(struct
+@@ -909,6 +912,10 @@ static void nfs_server_set_fsinfo(struct
server->acdirmin = server->acdirmax = 0;
}
server->maxfilesize = fsinfo->maxfilesize;
/* We're airborne Set socket buffersize */
-diff -NurpP --minimal linux-2.6.31.6/fs/nfs/dir.c linux-2.6.31.6-vs2.3.0.36.24/fs/nfs/dir.c
---- linux-2.6.31.6/fs/nfs/dir.c 2009-11-12 12:10:11.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/nfs/dir.c 2009-11-12 12:26:38.000000000 +0100
+diff -NurpP --minimal linux-2.6.32/fs/nfs/dir.c linux-2.6.32-vs2.3.0.36.26/fs/nfs/dir.c
+--- linux-2.6.32/fs/nfs/dir.c 2009-12-03 20:02:52.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/nfs/dir.c 2009-12-03 20:04:56.000000000 +0100
@@ -33,6 +33,7 @@
#include <linux/namei.h>
#include <linux/mount.h>
no_entry:
res = d_materialise_unique(dentry, inode);
if (res != NULL) {
-diff -NurpP --minimal linux-2.6.31.6/fs/nfs/inode.c linux-2.6.31.6-vs2.3.0.36.24/fs/nfs/inode.c
---- linux-2.6.31.6/fs/nfs/inode.c 2009-09-10 15:26:23.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/nfs/inode.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/nfs/inode.c linux-2.6.32-vs2.3.0.36.26/fs/nfs/inode.c
+--- linux-2.6.32/fs/nfs/inode.c 2009-12-03 20:02:52.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/nfs/inode.c 2009-12-03 20:04:56.000000000 +0100
@@ -36,6 +36,7 @@
#include <linux/vfs.h>
#include <linux/inet.h>
#include <asm/system.h>
#include <asm/uaccess.h>
-@@ -278,6 +279,8 @@ nfs_fhget(struct super_block *sb, struct
+@@ -279,6 +280,8 @@ nfs_fhget(struct super_block *sb, struct
if (inode->i_state & I_NEW) {
struct nfs_inode *nfsi = NFS_I(inode);
unsigned long now = jiffies;
/* We set i_ino for the few things that still rely on it,
* such as stat(2) */
-@@ -321,8 +324,8 @@ nfs_fhget(struct super_block *sb, struct
+@@ -327,8 +330,8 @@ nfs_fhget(struct super_block *sb, struct
nfsi->change_attr = 0;
inode->i_size = 0;
inode->i_nlink = 0;
inode->i_blocks = 0;
memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf));
-@@ -341,9 +344,9 @@ nfs_fhget(struct super_block *sb, struct
- if (fattr->valid & NFS_ATTR_FATTR_NLINK)
- inode->i_nlink = fattr->nlink;
+@@ -365,13 +368,13 @@ nfs_fhget(struct super_block *sb, struct
+ else if (nfs_server_capable(inode, NFS_CAP_NLINK))
+ nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
if (fattr->valid & NFS_ATTR_FATTR_OWNER)
- inode->i_uid = fattr->uid;
+ uid = fattr->uid;
+ else if (nfs_server_capable(inode, NFS_CAP_OWNER))
+ nfsi->cache_validity |= NFS_INO_INVALID_ATTR
+ | NFS_INO_INVALID_ACCESS
+ | NFS_INO_INVALID_ACL;
if (fattr->valid & NFS_ATTR_FATTR_GROUP)
- inode->i_gid = fattr->gid;
+ gid = fattr->gid;
- if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED)
- inode->i_blocks = fattr->du.nfs2.blocks;
- if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) {
-@@ -352,6 +355,11 @@ nfs_fhget(struct super_block *sb, struct
+ else if (nfs_server_capable(inode, NFS_CAP_OWNER_GROUP))
+ nfsi->cache_validity |= NFS_INO_INVALID_ATTR
+ | NFS_INO_INVALID_ACCESS
+@@ -384,6 +387,11 @@ nfs_fhget(struct super_block *sb, struct
*/
inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used);
}
nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
nfsi->attrtimeo_timestamp = now;
nfsi->access_cache = RB_ROOT;
-@@ -492,6 +500,8 @@ void nfs_setattr_update_inode(struct ino
+@@ -496,6 +504,8 @@ void nfs_setattr_update_inode(struct ino
inode->i_uid = attr->ia_uid;
if ((attr->ia_valid & ATTR_GID) != 0)
inode->i_gid = attr->ia_gid;
NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
spin_unlock(&inode->i_lock);
}
-@@ -902,6 +912,9 @@ static int nfs_check_inode_attributes(st
+@@ -906,6 +916,9 @@ static int nfs_check_inode_attributes(st
struct nfs_inode *nfsi = NFS_I(inode);
loff_t cur_size, new_isize;
unsigned long invalid = 0;
/* Has the inode gone and changed behind our back? */
-@@ -925,13 +938,18 @@ static int nfs_check_inode_attributes(st
+@@ -929,13 +942,18 @@ static int nfs_check_inode_attributes(st
invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE;
}
/* Has the link count changed? */
if ((fattr->valid & NFS_ATTR_FATTR_NLINK) && inode->i_nlink != fattr->nlink)
-@@ -1145,6 +1163,9 @@ static int nfs_update_inode(struct inode
- loff_t cur_isize, new_isize;
+@@ -1150,6 +1168,9 @@ static int nfs_update_inode(struct inode
unsigned long invalid = 0;
unsigned long now = jiffies;
+ unsigned long save_cache_validity;
+ uid_t uid;
+ gid_t gid;
+ tag_t tag;
dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n",
__func__, inode->i_sb->s_id, inode->i_ino,
-@@ -1233,6 +1254,9 @@ static int nfs_update_inode(struct inode
- }
- }
+@@ -1252,6 +1273,9 @@ static int nfs_update_inode(struct inode
+ | NFS_INO_REVAL_PAGECACHE
+ | NFS_INO_REVAL_FORCED);
+ uid = INOTAG_UID(DX_TAG(inode), fattr->uid, fattr->gid);
+ gid = INOTAG_GID(DX_TAG(inode), fattr->uid, fattr->gid);
if (fattr->valid & NFS_ATTR_FATTR_ATIME)
memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime));
-@@ -1244,18 +1268,22 @@ static int nfs_update_inode(struct inode
- }
- }
+@@ -1271,9 +1295,9 @@ static int nfs_update_inode(struct inode
+ | NFS_INO_REVAL_FORCED);
+
if (fattr->valid & NFS_ATTR_FATTR_OWNER) {
- if (inode->i_uid != fattr->uid) {
+ if (uid != fattr->uid) {
- inode->i_uid = fattr->uid;
+ uid = fattr->uid;
}
- }
+ } else if (server->caps & NFS_CAP_OWNER)
+ invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR
+@@ -1282,9 +1306,9 @@ static int nfs_update_inode(struct inode
+ | NFS_INO_REVAL_FORCED);
+
if (fattr->valid & NFS_ATTR_FATTR_GROUP) {
- if (inode->i_gid != fattr->gid) {
+ if (gid != fattr->gid) {
- inode->i_gid = fattr->gid;
+ gid = fattr->gid;
}
- }
+ } else if (server->caps & NFS_CAP_OWNER_GROUP)
+ invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR
+@@ -1292,6 +1316,10 @@ static int nfs_update_inode(struct inode
+ | NFS_INO_INVALID_ACL
+ | NFS_INO_REVAL_FORCED);
+ inode->i_uid = uid;
+ inode->i_gid = gid;
if (fattr->valid & NFS_ATTR_FATTR_NLINK) {
if (inode->i_nlink != fattr->nlink) {
invalid |= NFS_INO_INVALID_ATTR;
-diff -NurpP --minimal linux-2.6.31.6/fs/nfs/nfs3xdr.c linux-2.6.31.6-vs2.3.0.36.24/fs/nfs/nfs3xdr.c
---- linux-2.6.31.6/fs/nfs/nfs3xdr.c 2009-06-11 17:13:06.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/nfs/nfs3xdr.c 2009-09-10 16:11:43.000000000 +0200
-@@ -22,6 +22,7 @@
+diff -NurpP --minimal linux-2.6.32/fs/nfs/nfs3xdr.c linux-2.6.32-vs2.3.0.36.26/fs/nfs/nfs3xdr.c
+--- linux-2.6.32/fs/nfs/nfs3xdr.c 2009-12-03 20:02:52.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/nfs/nfs3xdr.c 2009-12-03 20:04:56.000000000 +0100
+@@ -21,6 +21,7 @@
#include <linux/nfs3.h>
#include <linux/nfs_fs.h>
#include <linux/nfsacl.h>
#include "internal.h"
#define NFSDBG_FACILITY NFSDBG_XDR
-@@ -177,7 +178,7 @@ xdr_decode_fattr(__be32 *p, struct nfs_f
+@@ -176,7 +177,7 @@ xdr_decode_fattr(__be32 *p, struct nfs_f
}
static inline __be32 *
{
if (attr->ia_valid & ATTR_MODE) {
*p++ = xdr_one;
-@@ -185,15 +186,17 @@ xdr_encode_sattr(__be32 *p, struct iattr
+@@ -184,15 +185,17 @@ xdr_encode_sattr(__be32 *p, struct iattr
} else {
*p++ = xdr_zero;
}
} else {
*p++ = xdr_zero;
}
-@@ -280,7 +283,8 @@ static int
+@@ -279,7 +282,8 @@ static int
nfs3_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs3_sattrargs *args)
{
p = xdr_encode_fhandle(p, args->fh);
*p++ = htonl(args->guard);
if (args->guard)
p = xdr_encode_time3(p, &args->guardtime);
-@@ -385,7 +389,8 @@ nfs3_xdr_createargs(struct rpc_rqst *req
+@@ -384,7 +388,8 @@ nfs3_xdr_createargs(struct rpc_rqst *req
*p++ = args->verifier[0];
*p++ = args->verifier[1];
} else
req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
return 0;
-@@ -399,7 +404,8 @@ nfs3_xdr_mkdirargs(struct rpc_rqst *req,
+@@ -398,7 +403,8 @@ nfs3_xdr_mkdirargs(struct rpc_rqst *req,
{
p = xdr_encode_fhandle(p, args->fh);
p = xdr_encode_array(p, args->name, args->len);
req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
return 0;
}
-@@ -412,7 +418,8 @@ nfs3_xdr_symlinkargs(struct rpc_rqst *re
+@@ -411,7 +417,8 @@ nfs3_xdr_symlinkargs(struct rpc_rqst *re
{
p = xdr_encode_fhandle(p, args->fromfh);
p = xdr_encode_array(p, args->fromname, args->fromlen);
*p++ = htonl(args->pathlen);
req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
-@@ -430,7 +437,8 @@ nfs3_xdr_mknodargs(struct rpc_rqst *req,
+@@ -429,7 +436,8 @@ nfs3_xdr_mknodargs(struct rpc_rqst *req,
p = xdr_encode_fhandle(p, args->fh);
p = xdr_encode_array(p, args->name, args->len);
*p++ = htonl(args->type);
if (args->type == NF3CHR || args->type == NF3BLK) {
*p++ = htonl(MAJOR(args->rdev));
*p++ = htonl(MINOR(args->rdev));
-diff -NurpP --minimal linux-2.6.31.6/fs/nfs/nfsroot.c linux-2.6.31.6-vs2.3.0.36.24/fs/nfs/nfsroot.c
---- linux-2.6.31.6/fs/nfs/nfsroot.c 2009-09-10 15:26:23.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/nfs/nfsroot.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/nfs/nfsroot.c linux-2.6.32-vs2.3.0.36.26/fs/nfs/nfsroot.c
+--- linux-2.6.32/fs/nfs/nfsroot.c 2009-09-10 15:26:23.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/nfs/nfsroot.c 2009-12-03 20:04:56.000000000 +0100
@@ -122,12 +122,12 @@ static int mount_port __initdata = 0; /
enum {
/* Options that take integer arguments */
default:
printk(KERN_WARNING "Root-NFS: unknown "
"option: %s\n", p);
-diff -NurpP --minimal linux-2.6.31.6/fs/nfs/super.c linux-2.6.31.6-vs2.3.0.36.24/fs/nfs/super.c
---- linux-2.6.31.6/fs/nfs/super.c 2009-11-12 12:10:11.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/nfs/super.c 2009-11-12 12:26:38.000000000 +0100
+diff -NurpP --minimal linux-2.6.32/fs/nfs/super.c linux-2.6.32-vs2.3.0.36.26/fs/nfs/super.c
+--- linux-2.6.32/fs/nfs/super.c 2009-12-03 20:02:52.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/nfs/super.c 2009-12-03 20:04:56.000000000 +0100
@@ -53,6 +53,7 @@
#include <linux/nfs_xdr.h>
#include <linux/magic.h>
#include <asm/system.h>
#include <asm/uaccess.h>
-@@ -546,6 +547,7 @@ static void nfs_show_mount_options(struc
+@@ -551,6 +552,7 @@ static void nfs_show_mount_options(struc
{ NFS_MOUNT_NORDIRPLUS, ",nordirplus", "" },
{ NFS_MOUNT_UNSHARED, ",nosharecache", "" },
{ NFS_MOUNT_NORESVPORT, ",noresvport", "" },
{ 0, NULL, NULL }
};
const struct proc_nfs_info *nfs_infop;
-diff -NurpP --minimal linux-2.6.31.6/fs/nfsd/auth.c linux-2.6.31.6-vs2.3.0.36.24/fs/nfsd/auth.c
---- linux-2.6.31.6/fs/nfsd/auth.c 2009-03-24 14:22:26.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/nfsd/auth.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/nfsd/auth.c linux-2.6.32-vs2.3.0.36.26/fs/nfsd/auth.c
+--- linux-2.6.32/fs/nfsd/auth.c 2009-12-03 20:02:52.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/nfsd/auth.c 2009-12-03 20:04:56.000000000 +0100
@@ -10,6 +10,7 @@
#include <linux/sunrpc/svcauth.h>
#include <linux/nfsd/nfsd.h>
#include "auth.h"
int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)
-@@ -42,6 +43,9 @@ int nfsd_setuser(struct svc_rqst *rqstp,
+@@ -44,6 +45,9 @@ int nfsd_setuser(struct svc_rqst *rqstp,
new->fsuid = rqstp->rq_cred.cr_uid;
new->fsgid = rqstp->rq_cred.cr_gid;
rqgi = rqstp->rq_cred.cr_group_info;
-diff -NurpP --minimal linux-2.6.31.6/fs/nfsd/nfs3xdr.c linux-2.6.31.6-vs2.3.0.36.24/fs/nfsd/nfs3xdr.c
---- linux-2.6.31.6/fs/nfsd/nfs3xdr.c 2009-09-10 15:26:23.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/nfsd/nfs3xdr.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/nfsd/nfs3xdr.c linux-2.6.32-vs2.3.0.36.26/fs/nfsd/nfs3xdr.c
+--- linux-2.6.32/fs/nfsd/nfs3xdr.c 2009-12-03 20:02:52.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/nfsd/nfs3xdr.c 2009-12-03 20:04:56.000000000 +0100
@@ -21,6 +21,7 @@
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN) {
p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN);
} else {
-diff -NurpP --minimal linux-2.6.31.6/fs/nfsd/nfs4xdr.c linux-2.6.31.6-vs2.3.0.36.24/fs/nfsd/nfs4xdr.c
---- linux-2.6.31.6/fs/nfsd/nfs4xdr.c 2009-09-10 15:26:23.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/nfsd/nfs4xdr.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/nfsd/nfs4xdr.c linux-2.6.32-vs2.3.0.36.26/fs/nfsd/nfs4xdr.c
+--- linux-2.6.32/fs/nfsd/nfs4xdr.c 2009-12-03 20:02:52.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/nfsd/nfs4xdr.c 2009-12-03 20:04:56.000000000 +0100
@@ -57,6 +57,7 @@
#include <linux/nfs4_acl.h>
#include <linux/sunrpc/gss_api.h>
#define NFSDDBG_FACILITY NFSDDBG_XDR
-@@ -2052,14 +2053,18 @@ out_acl:
+@@ -2050,14 +2051,18 @@ out_acl:
WRITE32(stat.nlink);
}
if (bmval1 & FATTR4_WORD1_OWNER) {
if (status == nfserr_resource)
goto out_resource;
if (status)
-diff -NurpP --minimal linux-2.6.31.6/fs/nfsd/nfsxdr.c linux-2.6.31.6-vs2.3.0.36.24/fs/nfsd/nfsxdr.c
---- linux-2.6.31.6/fs/nfsd/nfsxdr.c 2008-12-25 00:26:37.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/nfsd/nfsxdr.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/nfsd/nfsxdr.c linux-2.6.32-vs2.3.0.36.26/fs/nfsd/nfsxdr.c
+--- linux-2.6.32/fs/nfsd/nfsxdr.c 2008-12-25 00:26:37.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/nfsd/nfsxdr.c 2009-12-03 20:04:56.000000000 +0100
@@ -15,6 +15,7 @@
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/xdr.h>
if (S_ISLNK(type) && stat->size > NFS_MAXPATHLEN) {
*p++ = htonl(NFS_MAXPATHLEN);
-diff -NurpP --minimal linux-2.6.31.6/fs/ocfs2/dlm/dlmfs.c linux-2.6.31.6-vs2.3.0.36.24/fs/ocfs2/dlm/dlmfs.c
---- linux-2.6.31.6/fs/ocfs2/dlm/dlmfs.c 2009-03-24 14:22:27.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ocfs2/dlm/dlmfs.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/ocfs2/dlm/dlmfs.c linux-2.6.32-vs2.3.0.36.26/fs/ocfs2/dlm/dlmfs.c
+--- linux-2.6.32/fs/ocfs2/dlm/dlmfs.c 2009-12-03 20:02:53.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ocfs2/dlm/dlmfs.c 2009-12-03 20:04:56.000000000 +0100
@@ -43,6 +43,7 @@
#include <linux/init.h>
#include <linux/string.h>
#include <asm/uaccess.h>
-@@ -341,6 +342,7 @@ static struct inode *dlmfs_get_root_inod
+@@ -342,6 +343,7 @@ static struct inode *dlmfs_get_root_inod
inode->i_mode = mode;
inode->i_uid = current_fsuid();
inode->i_gid = current_fsgid();
inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inc_nlink(inode);
-@@ -366,6 +368,7 @@ static struct inode *dlmfs_get_inode(str
+@@ -367,6 +369,7 @@ static struct inode *dlmfs_get_inode(str
inode->i_mode = mode;
inode->i_uid = current_fsuid();
inode->i_gid = current_fsgid();
inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-diff -NurpP --minimal linux-2.6.31.6/fs/ocfs2/dlmglue.c linux-2.6.31.6-vs2.3.0.36.24/fs/ocfs2/dlmglue.c
---- linux-2.6.31.6/fs/ocfs2/dlmglue.c 2009-09-10 15:26:23.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ocfs2/dlmglue.c 2009-09-10 16:11:43.000000000 +0200
-@@ -1960,6 +1960,7 @@ static void __ocfs2_stuff_meta_lvb(struc
+diff -NurpP --minimal linux-2.6.32/fs/ocfs2/dlmglue.c linux-2.6.32-vs2.3.0.36.26/fs/ocfs2/dlmglue.c
+--- linux-2.6.32/fs/ocfs2/dlmglue.c 2009-12-03 20:02:53.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ocfs2/dlmglue.c 2009-12-03 20:04:56.000000000 +0100
+@@ -1991,6 +1991,7 @@ static void __ocfs2_stuff_meta_lvb(struc
lvb->lvb_iclusters = cpu_to_be32(oi->ip_clusters);
lvb->lvb_iuid = cpu_to_be32(inode->i_uid);
lvb->lvb_igid = cpu_to_be32(inode->i_gid);
lvb->lvb_imode = cpu_to_be16(inode->i_mode);
lvb->lvb_inlink = cpu_to_be16(inode->i_nlink);
lvb->lvb_iatime_packed =
-@@ -2014,6 +2015,7 @@ static void ocfs2_refresh_inode_from_lvb
+@@ -2045,6 +2046,7 @@ static void ocfs2_refresh_inode_from_lvb
inode->i_uid = be32_to_cpu(lvb->lvb_iuid);
inode->i_gid = be32_to_cpu(lvb->lvb_igid);
inode->i_mode = be16_to_cpu(lvb->lvb_imode);
inode->i_nlink = be16_to_cpu(lvb->lvb_inlink);
ocfs2_unpack_timespec(&inode->i_atime,
-diff -NurpP --minimal linux-2.6.31.6/fs/ocfs2/dlmglue.h linux-2.6.31.6-vs2.3.0.36.24/fs/ocfs2/dlmglue.h
---- linux-2.6.31.6/fs/ocfs2/dlmglue.h 2009-09-10 15:26:23.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ocfs2/dlmglue.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/ocfs2/dlmglue.h linux-2.6.32-vs2.3.0.36.26/fs/ocfs2/dlmglue.h
+--- linux-2.6.32/fs/ocfs2/dlmglue.h 2009-12-03 20:02:53.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ocfs2/dlmglue.h 2009-12-03 20:04:56.000000000 +0100
@@ -46,7 +46,8 @@ struct ocfs2_meta_lvb {
__be16 lvb_inlink;
__be32 lvb_iattr;
};
#define OCFS2_QINFO_LVB_VERSION 1
-diff -NurpP --minimal linux-2.6.31.6/fs/ocfs2/file.c linux-2.6.31.6-vs2.3.0.36.24/fs/ocfs2/file.c
---- linux-2.6.31.6/fs/ocfs2/file.c 2009-09-10 15:26:23.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ocfs2/file.c 2009-10-06 19:45:13.000000000 +0200
-@@ -914,13 +914,15 @@ int ocfs2_setattr(struct dentry *dentry,
+diff -NurpP --minimal linux-2.6.32/fs/ocfs2/file.c linux-2.6.32-vs2.3.0.36.26/fs/ocfs2/file.c
+--- linux-2.6.32/fs/ocfs2/file.c 2009-12-03 20:02:53.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ocfs2/file.c 2009-12-03 20:04:56.000000000 +0100
+@@ -960,13 +960,15 @@ int ocfs2_setattr(struct dentry *dentry,
mlog(0, "uid change: %d\n", attr->ia_uid);
if (attr->ia_valid & ATTR_GID)
mlog(0, "gid change: %d\n", attr->ia_gid);
if (!(attr->ia_valid & OCFS2_VALID_ATTRS)) {
mlog(0, "can't handle attrs: 0x%x\n", attr->ia_valid);
return 0;
-diff -NurpP --minimal linux-2.6.31.6/fs/ocfs2/inode.c linux-2.6.31.6-vs2.3.0.36.24/fs/ocfs2/inode.c
---- linux-2.6.31.6/fs/ocfs2/inode.c 2009-09-10 15:26:23.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ocfs2/inode.c 2009-10-06 19:45:13.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/ocfs2/inode.c linux-2.6.32-vs2.3.0.36.26/fs/ocfs2/inode.c
+--- linux-2.6.32/fs/ocfs2/inode.c 2009-12-03 20:02:53.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ocfs2/inode.c 2009-12-03 20:04:56.000000000 +0100
@@ -29,6 +29,7 @@
#include <linux/highmem.h>
#include <linux/pagemap.h>
#include <asm/byteorder.h>
-@@ -78,11 +79,13 @@ void ocfs2_set_inode_flags(struct inode
+@@ -79,11 +80,13 @@ void ocfs2_set_inode_flags(struct inode
{
unsigned int flags = OCFS2_I(inode)->ip_attr;
if (flags & OCFS2_SYNC_FL)
inode->i_flags |= S_SYNC;
-@@ -92,25 +95,44 @@ void ocfs2_set_inode_flags(struct inode
+@@ -93,25 +96,44 @@ void ocfs2_set_inode_flags(struct inode
inode->i_flags |= S_NOATIME;
if (flags & OCFS2_DIRSYNC_FL)
inode->i_flags |= S_DIRSYNC;
}
struct inode *ocfs2_ilookup(struct super_block *sb, u64 blkno)
-@@ -245,6 +267,8 @@ void ocfs2_populate_inode(struct inode *
+@@ -246,6 +268,8 @@ void ocfs2_populate_inode(struct inode *
struct super_block *sb;
struct ocfs2_super *osb;
int use_plocks = 1;
mlog_entry("(0x%p, size:%llu)\n", inode,
(unsigned long long)le64_to_cpu(fe->i_size));
-@@ -276,8 +300,12 @@ void ocfs2_populate_inode(struct inode *
+@@ -277,8 +301,12 @@ void ocfs2_populate_inode(struct inode *
inode->i_generation = le32_to_cpu(fe->i_generation);
inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev));
inode->i_mode = le16_to_cpu(fe->i_mode);
/* Fast symlinks will have i_size but no allocated clusters. */
if (S_ISLNK(inode->i_mode) && !fe->i_clusters)
-diff -NurpP --minimal linux-2.6.31.6/fs/ocfs2/inode.h linux-2.6.31.6-vs2.3.0.36.24/fs/ocfs2/inode.h
---- linux-2.6.31.6/fs/ocfs2/inode.h 2009-06-11 17:13:07.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ocfs2/inode.h 2009-10-07 01:26:15.000000000 +0200
-@@ -152,6 +152,7 @@ struct buffer_head *ocfs2_bread(struct i
+diff -NurpP --minimal linux-2.6.32/fs/ocfs2/inode.h linux-2.6.32-vs2.3.0.36.26/fs/ocfs2/inode.h
+--- linux-2.6.32/fs/ocfs2/inode.h 2009-12-03 20:02:53.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ocfs2/inode.h 2009-12-03 20:04:56.000000000 +0100
+@@ -150,6 +150,7 @@ struct buffer_head *ocfs2_bread(struct i
void ocfs2_set_inode_flags(struct inode *inode);
void ocfs2_get_inode_flags(struct ocfs2_inode_info *oi);
static inline blkcnt_t ocfs2_inode_sector_count(struct inode *inode)
{
-diff -NurpP --minimal linux-2.6.31.6/fs/ocfs2/ioctl.c linux-2.6.31.6-vs2.3.0.36.24/fs/ocfs2/ioctl.c
---- linux-2.6.31.6/fs/ocfs2/ioctl.c 2009-09-10 15:26:23.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ocfs2/ioctl.c 2009-10-07 04:20:18.000000000 +0200
-@@ -41,7 +41,41 @@ static int ocfs2_get_inode_attr(struct i
+diff -NurpP --minimal linux-2.6.32/fs/ocfs2/ioctl.c linux-2.6.32-vs2.3.0.36.26/fs/ocfs2/ioctl.c
+--- linux-2.6.32/fs/ocfs2/ioctl.c 2009-12-03 20:02:53.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ocfs2/ioctl.c 2009-12-03 20:04:56.000000000 +0100
+@@ -42,7 +42,41 @@ static int ocfs2_get_inode_attr(struct i
return status;
}
unsigned mask)
{
struct ocfs2_inode_info *ocfs2_inode = OCFS2_I(inode);
-@@ -66,6 +100,11 @@ static int ocfs2_set_inode_attr(struct i
+@@ -67,6 +101,11 @@ static int ocfs2_set_inode_attr(struct i
if (!S_ISDIR(inode->i_mode))
flags &= ~OCFS2_DIRSYNC_FL;
handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
if (IS_ERR(handle)) {
status = PTR_ERR(handle);
-@@ -107,6 +146,7 @@ bail:
+@@ -108,6 +147,7 @@ bail:
return status;
}
long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct inode *inode = filp->f_path.dentry->d_inode;
-diff -NurpP --minimal linux-2.6.31.6/fs/ocfs2/namei.c linux-2.6.31.6-vs2.3.0.36.24/fs/ocfs2/namei.c
---- linux-2.6.31.6/fs/ocfs2/namei.c 2009-09-10 15:26:23.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ocfs2/namei.c 2009-10-06 19:45:13.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/ocfs2/namei.c linux-2.6.32-vs2.3.0.36.26/fs/ocfs2/namei.c
+--- linux-2.6.32/fs/ocfs2/namei.c 2009-12-03 20:02:53.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ocfs2/namei.c 2009-12-03 20:04:56.000000000 +0100
@@ -41,6 +41,7 @@
#include <linux/slab.h>
#include <linux/highmem.h>
#define MLOG_MASK_PREFIX ML_NAMEI
#include <cluster/masklog.h>
-@@ -478,6 +479,7 @@ static int ocfs2_mknod_locked(struct ocf
+@@ -481,6 +482,7 @@ static int ocfs2_mknod_locked(struct ocf
u64 fe_blkno = 0;
u16 suballoc_bit;
u16 feat;
+ tag_t tag;
- mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry,
- inode->i_mode, (unsigned long)dev, dentry->d_name.len,
+ *new_fe_bh = NULL;
+
@@ -524,8 +526,11 @@ static int ocfs2_mknod_locked(struct ocf
fe->i_blkno = cpu_to_le64(fe_blkno);
fe->i_suballoc_bit = cpu_to_le16(suballoc_bit);
fe->i_mode = cpu_to_le16(inode->i_mode);
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
fe->id1.dev1.i_rdev = cpu_to_le64(huge_encode_dev(dev));
-diff -NurpP --minimal linux-2.6.31.6/fs/ocfs2/ocfs2_fs.h linux-2.6.31.6-vs2.3.0.36.24/fs/ocfs2/ocfs2_fs.h
---- linux-2.6.31.6/fs/ocfs2/ocfs2_fs.h 2009-06-11 17:13:07.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ocfs2/ocfs2_fs.h 2009-09-10 16:11:43.000000000 +0200
-@@ -225,18 +225,23 @@
- #define OCFS2_INDEXED_DIR_FL (0x0008)
+diff -NurpP --minimal linux-2.6.32/fs/ocfs2/ocfs2_fs.h linux-2.6.32-vs2.3.0.36.26/fs/ocfs2/ocfs2_fs.h
+--- linux-2.6.32/fs/ocfs2/ocfs2_fs.h 2009-12-03 20:02:53.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ocfs2/ocfs2_fs.h 2009-12-03 20:04:56.000000000 +0100
+@@ -231,18 +231,23 @@
+ #define OCFS2_HAS_REFCOUNT_FL (0x0010)
/* Inode attributes, keep in sync with EXT2 */
-#define OCFS2_SECRM_FL (0x00000001) /* Secure deletion */
/*
* Extent record flags (e_node.leaf.flags)
-diff -NurpP --minimal linux-2.6.31.6/fs/ocfs2/ocfs2.h linux-2.6.31.6-vs2.3.0.36.24/fs/ocfs2/ocfs2.h
---- linux-2.6.31.6/fs/ocfs2/ocfs2.h 2009-09-10 15:26:23.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ocfs2/ocfs2.h 2009-09-10 16:11:43.000000000 +0200
-@@ -222,6 +222,7 @@ enum ocfs2_mount_options
+diff -NurpP --minimal linux-2.6.32/fs/ocfs2/ocfs2.h linux-2.6.32-vs2.3.0.36.26/fs/ocfs2/ocfs2.h
+--- linux-2.6.32/fs/ocfs2/ocfs2.h 2009-12-03 20:02:53.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ocfs2/ocfs2.h 2009-12-03 20:04:56.000000000 +0100
+@@ -248,6 +248,7 @@ enum ocfs2_mount_options
OCFS2_MOUNT_POSIX_ACL = 1 << 8, /* POSIX access control lists */
OCFS2_MOUNT_USRQUOTA = 1 << 9, /* We support user quotas */
OCFS2_MOUNT_GRPQUOTA = 1 << 10, /* We support group quotas */
};
#define OCFS2_OSB_SOFT_RO 0x0001
-diff -NurpP --minimal linux-2.6.31.6/fs/ocfs2/super.c linux-2.6.31.6-vs2.3.0.36.24/fs/ocfs2/super.c
---- linux-2.6.31.6/fs/ocfs2/super.c 2009-09-10 15:26:23.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/ocfs2/super.c 2009-10-06 22:50:39.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/ocfs2/super.c linux-2.6.32-vs2.3.0.36.26/fs/ocfs2/super.c
+--- linux-2.6.32/fs/ocfs2/super.c 2009-12-03 20:02:53.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/ocfs2/super.c 2009-12-03 20:04:56.000000000 +0100
@@ -173,6 +173,7 @@ enum {
Opt_noacl,
Opt_usrquota,
if ((osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) !=
(parsed_options.mount_opt & OCFS2_MOUNT_HB_LOCAL)) {
ret = -EINVAL;
-@@ -1146,6 +1157,9 @@ static int ocfs2_fill_super(struct super
+@@ -1148,6 +1159,9 @@ static int ocfs2_fill_super(struct super
ocfs2_complete_mount_recovery(osb);
if (ocfs2_mount_local(osb))
snprintf(nodestr, sizeof(nodestr), "local");
else
-@@ -1424,6 +1438,20 @@ static int ocfs2_parse_options(struct su
+@@ -1426,6 +1440,20 @@ static int ocfs2_parse_options(struct su
printk(KERN_INFO "ocfs2 (no)acl options not supported\n");
break;
#endif
default:
mlog(ML_ERROR,
"Unrecognized mount option \"%s\" "
-diff -NurpP --minimal linux-2.6.31.6/fs/open.c linux-2.6.31.6-vs2.3.0.36.24/fs/open.c
---- linux-2.6.31.6/fs/open.c 2009-09-10 15:26:23.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/open.c 2009-10-15 03:54:42.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/open.c linux-2.6.32-vs2.3.0.36.26/fs/open.c
+--- linux-2.6.32/fs/open.c 2009-12-03 20:02:53.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/open.c 2009-12-03 20:04:56.000000000 +0100
@@ -30,22 +30,30 @@
#include <linux/audit.h>
#include <linux/falloc.h>
}
return retval;
}
-@@ -639,6 +647,10 @@ SYSCALL_DEFINE3(fchmodat, int, dfd, cons
+@@ -640,6 +648,10 @@ SYSCALL_DEFINE3(fchmodat, int, dfd, cons
error = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
if (error)
goto out;
inode = path.dentry->d_inode;
error = mnt_want_write(path.mnt);
-@@ -672,11 +684,11 @@ static int chown_common(struct dentry *
+@@ -673,11 +685,11 @@ static int chown_common(struct dentry *
newattrs.ia_valid = ATTR_CTIME;
if (user != (uid_t) -1) {
newattrs.ia_valid |= ATTR_UID;
}
if (!S_ISDIR(inode->i_mode))
newattrs.ia_valid |=
-@@ -699,7 +711,11 @@ SYSCALL_DEFINE3(chown, const char __user
+@@ -700,7 +712,11 @@ SYSCALL_DEFINE3(chown, const char __user
error = mnt_want_write(path.mnt);
if (error)
goto out_release;
mnt_drop_write(path.mnt);
out_release:
path_put(&path);
-@@ -724,7 +740,11 @@ SYSCALL_DEFINE5(fchownat, int, dfd, cons
+@@ -725,7 +741,11 @@ SYSCALL_DEFINE5(fchownat, int, dfd, cons
error = mnt_want_write(path.mnt);
if (error)
goto out_release;
mnt_drop_write(path.mnt);
out_release:
path_put(&path);
-@@ -743,7 +763,11 @@ SYSCALL_DEFINE3(lchown, const char __use
+@@ -744,7 +764,11 @@ SYSCALL_DEFINE3(lchown, const char __use
error = mnt_want_write(path.mnt);
if (error)
goto out_release;
mnt_drop_write(path.mnt);
out_release:
path_put(&path);
-@@ -987,6 +1011,7 @@ static void __put_unused_fd(struct files
+@@ -990,6 +1014,7 @@ static void __put_unused_fd(struct files
__FD_CLR(fd, fdt->open_fds);
if (fd < files->next_fd)
files->next_fd = fd;
}
void put_unused_fd(unsigned int fd)
-diff -NurpP --minimal linux-2.6.31.6/fs/proc/array.c linux-2.6.31.6-vs2.3.0.36.24/fs/proc/array.c
---- linux-2.6.31.6/fs/proc/array.c 2009-06-11 17:13:07.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/proc/array.c 2009-09-10 16:11:43.000000000 +0200
-@@ -82,6 +82,8 @@
- #include <linux/pid_namespace.h>
+diff -NurpP --minimal linux-2.6.32/fs/proc/array.c linux-2.6.32-vs2.3.0.36.26/fs/proc/array.c
+--- linux-2.6.32/fs/proc/array.c 2009-12-03 20:02:53.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/proc/array.c 2009-12-03 20:04:56.000000000 +0100
+@@ -83,6 +83,8 @@
#include <linux/ptrace.h>
#include <linux/tracehook.h>
+ #include <linux/swapops.h>
+#include <linux/vs_context.h>
+#include <linux/vs_network.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
-@@ -138,8 +140,9 @@ static const char *task_state_array[] =
+@@ -139,8 +141,9 @@ static const char *task_state_array[] =
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"T (tracing stop)", /* 8 */
};
static inline const char *get_task_state(struct task_struct *tsk)
-@@ -166,6 +169,9 @@ static inline void task_state(struct seq
+@@ -167,6 +170,9 @@ static inline void task_state(struct seq
rcu_read_lock();
ppid = pid_alive(p) ?
task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
tpid = 0;
if (pid_alive(p)) {
struct task_struct *tracer = tracehook_tracer_task(p);
-@@ -281,7 +287,7 @@ static inline void task_sig(struct seq_f
+@@ -282,7 +288,7 @@ static inline void task_sig(struct seq_f
}
static void render_cap_t(struct seq_file *m, const char *header,
{
unsigned __capi;
-@@ -306,10 +312,11 @@ static inline void task_cap(struct seq_f
+@@ -307,10 +313,11 @@ static inline void task_cap(struct seq_f
cap_bset = cred->cap_bset;
rcu_read_unlock();
}
static inline void task_context_switch_counts(struct seq_file *m,
-@@ -321,6 +328,42 @@ static inline void task_context_switch_c
- p->nivcsw);
+@@ -410,6 +417,42 @@ static void task_show_stack_usage(struct
}
+ #endif /* CONFIG_MMU */
+int proc_pid_nsproxy(struct seq_file *m, struct pid_namespace *ns,
+ struct pid *pid, struct task_struct *task)
int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *task)
{
-@@ -336,6 +379,7 @@ int proc_pid_status(struct seq_file *m,
+@@ -425,6 +468,7 @@ int proc_pid_status(struct seq_file *m,
task_sig(m, task);
task_cap(m, task);
cpuset_task_status_allowed(m, task);
#if defined(CONFIG_S390)
task_show_regs(m, task);
#endif
-@@ -452,6 +496,17 @@ static int do_task_stat(struct seq_file
+@@ -542,6 +586,17 @@ static int do_task_stat(struct seq_file
/* convert nsec -> ticks */
start_time = nsec_to_clock_t(start_time);
seq_printf(m, "%d (%s) %c %d %d %d %d %d %u %lu \
%lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \
%lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld\n",
-diff -NurpP --minimal linux-2.6.31.6/fs/proc/base.c linux-2.6.31.6-vs2.3.0.36.24/fs/proc/base.c
---- linux-2.6.31.6/fs/proc/base.c 2009-09-10 15:26:23.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/proc/base.c 2009-10-03 01:56:26.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/proc/base.c linux-2.6.32-vs2.3.0.36.26/fs/proc/base.c
+--- linux-2.6.32/fs/proc/base.c 2009-12-03 20:02:53.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/proc/base.c 2009-12-03 20:04:56.000000000 +0100
@@ -81,6 +81,8 @@
#include <linux/elf.h>
#include <linux/pid_namespace.h>
#include "internal.h"
/* NOTE:
-@@ -1032,10 +1034,14 @@ static ssize_t oom_adjust_write(struct f
- task = get_proc_task(file->f_path.dentry->d_inode);
- if (!task)
+@@ -1047,12 +1049,17 @@ static ssize_t oom_adjust_write(struct f
return -ESRCH;
-- if (oom_adjust < task->oomkilladj && !capable(CAP_SYS_RESOURCE)) {
-+ if (oom_adjust < task->oomkilladj &&
+ }
+
+- if (oom_adjust < task->signal->oom_adj && !capable(CAP_SYS_RESOURCE)) {
++ if (oom_adjust < task->signal->oom_adj &&
+ !vx_capable(CAP_SYS_RESOURCE, VXC_OOM_ADJUST)) {
+ unlock_task_sighand(task, &flags);
put_task_struct(task);
return -EACCES;
}
+
+ /* prevent guest processes from circumventing the oom killer */
+ if (vx_current_xid() && (oom_adjust == OOM_DISABLE))
+ oom_adjust = OOM_ADJUST_MIN;
- task->oomkilladj = oom_adjust;
- put_task_struct(task);
- if (end - buffer == 0)
-@@ -1074,7 +1080,7 @@ static ssize_t proc_loginuid_write(struc
++
+ task->signal->oom_adj = oom_adjust;
+
+ unlock_task_sighand(task, &flags);
+@@ -1092,7 +1099,7 @@ static ssize_t proc_loginuid_write(struc
ssize_t length;
uid_t loginuid;
return -EPERM;
if (current != pid_task(proc_pid(inode), PIDTYPE_PID))
-@@ -1441,6 +1447,8 @@ static struct inode *proc_pid_make_inode
+@@ -1458,6 +1465,8 @@ static struct inode *proc_pid_make_inode
inode->i_gid = cred->egid;
rcu_read_unlock();
}
security_task_to_inode(task, inode);
out:
-@@ -1991,6 +1999,13 @@ static struct dentry *proc_pident_lookup
+@@ -2008,6 +2017,13 @@ static struct dentry *proc_pident_lookup
if (!task)
goto out_no_task;
/*
* Yes, it does not scale. And it should not. Don't add
* new entries into /proc/<tgid>/ without very good reasons.
-@@ -2382,7 +2397,7 @@ out_iput:
+@@ -2399,7 +2415,7 @@ out_iput:
static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry)
{
struct dentry *error;
const struct pid_entry *p, *last;
error = ERR_PTR(-ENOENT);
-@@ -2472,6 +2487,9 @@ static int proc_pid_personality(struct s
+@@ -2489,6 +2505,9 @@ static int proc_pid_personality(struct s
static const struct file_operations proc_task_operations;
static const struct inode_operations proc_task_inode_operations;
static const struct pid_entry tgid_base_stuff[] = {
DIR("task", S_IRUGO|S_IXUGO, proc_task_inode_operations, proc_task_operations),
DIR("fd", S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations),
-@@ -2530,6 +2548,8 @@ static const struct pid_entry tgid_base_
+@@ -2547,6 +2566,8 @@ static const struct pid_entry tgid_base_
#ifdef CONFIG_CGROUPS
REG("cgroup", S_IRUGO, proc_cgroup_operations),
#endif
INF("oom_score", S_IRUGO, proc_oom_score),
REG("oom_adj", S_IRUGO|S_IWUSR, proc_oom_adjust_operations),
#ifdef CONFIG_AUDITSYSCALL
-@@ -2545,6 +2565,7 @@ static const struct pid_entry tgid_base_
+@@ -2562,6 +2583,7 @@ static const struct pid_entry tgid_base_
#ifdef CONFIG_TASK_IO_ACCOUNTING
INF("io", S_IRUGO, proc_tgid_io_accounting),
#endif
};
static int proc_tgid_base_readdir(struct file * filp,
-@@ -2741,7 +2762,7 @@ retry:
+@@ -2753,7 +2775,7 @@ retry:
iter.task = NULL;
pid = find_ge_pid(iter.tgid, ns);
if (pid) {
iter.task = pid_task(pid, PIDTYPE_PID);
/* What we to know is if the pid we have find is the
* pid of a thread_group_leader. Testing for task
-@@ -2771,7 +2792,7 @@ static int proc_pid_fill_cache(struct fi
+@@ -2783,7 +2805,7 @@ static int proc_pid_fill_cache(struct fi
struct tgid_iter iter)
{
char name[PROC_NUMBUF];
return proc_fill_cache(filp, dirent, filldir, name, len,
proc_pid_instantiate, iter.task, NULL);
}
-@@ -2780,7 +2801,7 @@ static int proc_pid_fill_cache(struct fi
+@@ -2792,7 +2814,7 @@ static int proc_pid_fill_cache(struct fi
int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY;
struct tgid_iter iter;
struct pid_namespace *ns;
-@@ -2800,6 +2821,8 @@ int proc_pid_readdir(struct file * filp,
+@@ -2812,6 +2834,8 @@ int proc_pid_readdir(struct file * filp,
iter.task;
iter.tgid += 1, iter = next_tgid(ns, iter)) {
filp->f_pos = iter.tgid + TGID_OFFSET;
if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) {
put_task_struct(iter.task);
goto out;
-@@ -2946,6 +2969,8 @@ static struct dentry *proc_task_lookup(s
+@@ -2958,6 +2982,8 @@ static struct dentry *proc_task_lookup(s
tid = name_to_int(dentry);
if (tid == ~0U)
goto out;
ns = dentry->d_sb->s_fs_info;
rcu_read_lock();
-diff -NurpP --minimal linux-2.6.31.6/fs/proc/generic.c linux-2.6.31.6-vs2.3.0.36.24/fs/proc/generic.c
---- linux-2.6.31.6/fs/proc/generic.c 2009-06-11 17:13:07.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/proc/generic.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/proc/generic.c linux-2.6.32-vs2.3.0.36.26/fs/proc/generic.c
+--- linux-2.6.32/fs/proc/generic.c 2009-06-11 17:13:07.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/proc/generic.c 2009-12-03 20:04:56.000000000 +0100
@@ -20,6 +20,7 @@
#include <linux/bitops.h>
#include <linux/spinlock.h>
} else {
kfree(ent);
ent = NULL;
-diff -NurpP --minimal linux-2.6.31.6/fs/proc/inode.c linux-2.6.31.6-vs2.3.0.36.24/fs/proc/inode.c
---- linux-2.6.31.6/fs/proc/inode.c 2009-06-11 17:13:07.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/proc/inode.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/proc/inode.c linux-2.6.32-vs2.3.0.36.26/fs/proc/inode.c
+--- linux-2.6.32/fs/proc/inode.c 2009-06-11 17:13:07.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/proc/inode.c 2009-12-03 20:04:56.000000000 +0100
@@ -459,6 +459,8 @@ struct inode *proc_get_inode(struct supe
inode->i_uid = de->uid;
inode->i_gid = de->gid;
if (de->size)
inode->i_size = de->size;
if (de->nlink)
-diff -NurpP --minimal linux-2.6.31.6/fs/proc/internal.h linux-2.6.31.6-vs2.3.0.36.24/fs/proc/internal.h
---- linux-2.6.31.6/fs/proc/internal.h 2009-09-10 15:26:23.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/proc/internal.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/proc/internal.h linux-2.6.32-vs2.3.0.36.26/fs/proc/internal.h
+--- linux-2.6.32/fs/proc/internal.h 2009-09-10 15:26:23.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/proc/internal.h 2009-12-03 20:04:56.000000000 +0100
@@ -10,6 +10,7 @@
*/
static inline int proc_fd(struct inode *inode)
{
return PROC_I(inode)->fd;
-diff -NurpP --minimal linux-2.6.31.6/fs/proc/loadavg.c linux-2.6.31.6-vs2.3.0.36.24/fs/proc/loadavg.c
---- linux-2.6.31.6/fs/proc/loadavg.c 2009-09-10 15:26:23.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/proc/loadavg.c 2009-11-05 04:12:09.000000000 +0100
+diff -NurpP --minimal linux-2.6.32/fs/proc/loadavg.c linux-2.6.32-vs2.3.0.36.26/fs/proc/loadavg.c
+--- linux-2.6.32/fs/proc/loadavg.c 2009-09-10 15:26:23.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/proc/loadavg.c 2009-12-03 20:04:56.000000000 +0100
@@ -12,15 +12,27 @@
static int loadavg_proc_show(struct seq_file *m, void *v)
task_active_pid_ns(current)->last_pid);
return 0;
}
-diff -NurpP --minimal linux-2.6.31.6/fs/proc/meminfo.c linux-2.6.31.6-vs2.3.0.36.24/fs/proc/meminfo.c
---- linux-2.6.31.6/fs/proc/meminfo.c 2009-09-10 15:26:23.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/proc/meminfo.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/proc/meminfo.c linux-2.6.32-vs2.3.0.36.26/fs/proc/meminfo.c
+--- linux-2.6.32/fs/proc/meminfo.c 2009-12-03 20:02:53.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/proc/meminfo.c 2009-12-03 20:04:56.000000000 +0100
@@ -41,7 +41,7 @@ static int meminfo_proc_show(struct seq_
cached = global_page_state(NR_FILE_PAGES) -
cached = 0;
get_vmalloc_info(&vmi);
-diff -NurpP --minimal linux-2.6.31.6/fs/proc/root.c linux-2.6.31.6-vs2.3.0.36.24/fs/proc/root.c
---- linux-2.6.31.6/fs/proc/root.c 2009-06-11 17:13:07.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/proc/root.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/proc/root.c linux-2.6.32-vs2.3.0.36.26/fs/proc/root.c
+--- linux-2.6.32/fs/proc/root.c 2009-06-11 17:13:07.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/proc/root.c 2009-12-03 20:04:56.000000000 +0100
@@ -18,9 +18,14 @@
#include <linux/bitops.h>
#include <linux/mount.h>
};
int pid_ns_prepare_proc(struct pid_namespace *ns)
-diff -NurpP --minimal linux-2.6.31.6/fs/proc/uptime.c linux-2.6.31.6-vs2.3.0.36.24/fs/proc/uptime.c
---- linux-2.6.31.6/fs/proc/uptime.c 2009-11-12 12:10:11.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/proc/uptime.c 2009-10-05 23:35:52.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/proc/uptime.c linux-2.6.32-vs2.3.0.36.26/fs/proc/uptime.c
+--- linux-2.6.32/fs/proc/uptime.c 2009-12-03 20:02:53.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/proc/uptime.c 2009-12-03 20:04:56.000000000 +0100
@@ -4,22 +4,22 @@
#include <linux/sched.h>
#include <linux/seq_file.h>
seq_printf(m, "%lu.%02lu %lu.%02lu\n",
(unsigned long) uptime.tv_sec,
(uptime.tv_nsec / (NSEC_PER_SEC / 100)),
-diff -NurpP --minimal linux-2.6.31.6/fs/quota/quota.c linux-2.6.31.6-vs2.3.0.36.24/fs/quota/quota.c
---- linux-2.6.31.6/fs/quota/quota.c 2009-09-10 15:26:24.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/quota/quota.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/quota/quota.c linux-2.6.32-vs2.3.0.36.26/fs/quota/quota.c
+--- linux-2.6.32/fs/quota/quota.c 2009-09-10 15:26:24.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/quota/quota.c 2009-12-03 20:04:56.000000000 +0100
@@ -18,6 +18,7 @@
#include <linux/capability.h>
#include <linux/quotaops.h>
sb = get_super(bdev);
bdput(bdev);
if (!sb)
-diff -NurpP --minimal linux-2.6.31.6/fs/reiserfs/file.c linux-2.6.31.6-vs2.3.0.36.24/fs/reiserfs/file.c
---- linux-2.6.31.6/fs/reiserfs/file.c 2009-06-11 17:13:08.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/reiserfs/file.c 2009-10-07 01:04:14.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/reiserfs/file.c linux-2.6.32-vs2.3.0.36.26/fs/reiserfs/file.c
+--- linux-2.6.32/fs/reiserfs/file.c 2009-06-11 17:13:08.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/reiserfs/file.c 2009-12-03 20:04:56.000000000 +0100
@@ -307,4 +307,5 @@ const struct inode_operations reiserfs_f
.listxattr = reiserfs_listxattr,
.removexattr = reiserfs_removexattr,
.permission = reiserfs_permission,
+ .sync_flags = reiserfs_sync_flags,
};
-diff -NurpP --minimal linux-2.6.31.6/fs/reiserfs/inode.c linux-2.6.31.6-vs2.3.0.36.24/fs/reiserfs/inode.c
---- linux-2.6.31.6/fs/reiserfs/inode.c 2009-09-10 15:26:24.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/reiserfs/inode.c 2009-10-06 19:45:13.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/reiserfs/inode.c linux-2.6.32-vs2.3.0.36.26/fs/reiserfs/inode.c
+--- linux-2.6.32/fs/reiserfs/inode.c 2009-09-10 15:26:24.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/reiserfs/inode.c 2009-12-03 20:04:56.000000000 +0100
@@ -18,6 +18,7 @@
#include <linux/writeback.h>
#include <linux/quotaops.h>
mark_inode_dirty(inode);
error =
journal_end(&th, inode->i_sb, jbegin_count);
-diff -NurpP --minimal linux-2.6.31.6/fs/reiserfs/ioctl.c linux-2.6.31.6-vs2.3.0.36.24/fs/reiserfs/ioctl.c
---- linux-2.6.31.6/fs/reiserfs/ioctl.c 2009-06-11 17:13:08.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/reiserfs/ioctl.c 2009-10-12 03:53:52.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/reiserfs/ioctl.c linux-2.6.32-vs2.3.0.36.26/fs/reiserfs/ioctl.c
+--- linux-2.6.32/fs/reiserfs/ioctl.c 2009-06-11 17:13:08.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/reiserfs/ioctl.c 2009-12-03 20:04:56.000000000 +0100
@@ -7,11 +7,27 @@
#include <linux/mount.h>
#include <linux/reiserfs_fs.h>
sd_attrs_to_i_attrs(flags, inode);
REISERFS_I(inode)->i_attrs = flags;
inode->i_ctime = CURRENT_TIME_SEC;
-diff -NurpP --minimal linux-2.6.31.6/fs/reiserfs/namei.c linux-2.6.31.6-vs2.3.0.36.24/fs/reiserfs/namei.c
---- linux-2.6.31.6/fs/reiserfs/namei.c 2009-06-11 17:13:08.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/reiserfs/namei.c 2009-10-07 01:09:49.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/reiserfs/namei.c linux-2.6.32-vs2.3.0.36.26/fs/reiserfs/namei.c
+--- linux-2.6.32/fs/reiserfs/namei.c 2009-06-11 17:13:08.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/reiserfs/namei.c 2009-12-03 20:04:56.000000000 +0100
@@ -17,6 +17,7 @@
#include <linux/reiserfs_acl.h>
#include <linux/reiserfs_xattr.h>
};
/*
-diff -NurpP --minimal linux-2.6.31.6/fs/reiserfs/super.c linux-2.6.31.6-vs2.3.0.36.24/fs/reiserfs/super.c
---- linux-2.6.31.6/fs/reiserfs/super.c 2009-09-10 15:26:24.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/reiserfs/super.c 2009-10-07 03:27:01.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/reiserfs/super.c linux-2.6.32-vs2.3.0.36.26/fs/reiserfs/super.c
+--- linux-2.6.32/fs/reiserfs/super.c 2009-12-03 20:02:53.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/reiserfs/super.c 2009-12-03 20:04:56.000000000 +0100
@@ -884,6 +884,14 @@ static int reiserfs_parse_options(struct
{"user_xattr",.setmask = 1 << REISERFS_UNSUPPORTED_OPT},
{"nouser_xattr",.clrmask = 1 << REISERFS_UNSUPPORTED_OPT},
rs = SB_DISK_SUPER_BLOCK(s);
/* Let's do basic sanity check to verify that underlying device is not
smaller than the filesystem. If the check fails then abort and scream,
-diff -NurpP --minimal linux-2.6.31.6/fs/reiserfs/xattr.c linux-2.6.31.6-vs2.3.0.36.24/fs/reiserfs/xattr.c
---- linux-2.6.31.6/fs/reiserfs/xattr.c 2009-09-10 15:26:24.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/reiserfs/xattr.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/reiserfs/xattr.c linux-2.6.32-vs2.3.0.36.26/fs/reiserfs/xattr.c
+--- linux-2.6.32/fs/reiserfs/xattr.c 2009-09-10 15:26:24.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/reiserfs/xattr.c 2009-12-03 20:04:56.000000000 +0100
@@ -39,6 +39,7 @@
#include <linux/namei.h>
#include <linux/errno.h>
#include <linux/file.h>
#include <linux/pagemap.h>
#include <linux/xattr.h>
-diff -NurpP --minimal linux-2.6.31.6/fs/stat.c linux-2.6.31.6-vs2.3.0.36.24/fs/stat.c
---- linux-2.6.31.6/fs/stat.c 2009-06-11 17:13:08.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/stat.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/stat.c linux-2.6.32-vs2.3.0.36.26/fs/stat.c
+--- linux-2.6.32/fs/stat.c 2009-06-11 17:13:08.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/stat.c 2009-12-03 20:04:56.000000000 +0100
@@ -26,6 +26,7 @@ void generic_fillattr(struct inode *inod
stat->nlink = inode->i_nlink;
stat->uid = inode->i_uid;
stat->rdev = inode->i_rdev;
stat->atime = inode->i_atime;
stat->mtime = inode->i_mtime;
-diff -NurpP --minimal linux-2.6.31.6/fs/super.c linux-2.6.31.6-vs2.3.0.36.24/fs/super.c
---- linux-2.6.31.6/fs/super.c 2009-09-10 15:26:24.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/super.c 2009-09-10 17:00:57.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/super.c linux-2.6.32-vs2.3.0.36.26/fs/super.c
+--- linux-2.6.32/fs/super.c 2009-12-03 20:02:53.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/super.c 2009-12-03 20:04:56.000000000 +0100
@@ -37,6 +37,9 @@
#include <linux/kobject.h>
#include <linux/mutex.h>
#include <asm/uaccess.h>
#include "internal.h"
-@@ -859,12 +862,18 @@ struct vfsmount *
+@@ -913,12 +916,18 @@ struct vfsmount *
vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
{
struct vfsmount *mnt;
error = -ENOMEM;
mnt = alloc_vfsmnt(name);
if (!mnt)
-@@ -883,9 +892,17 @@ vfs_kern_mount(struct file_system_type *
+@@ -937,9 +946,17 @@ vfs_kern_mount(struct file_system_type *
error = type->get_sb(type, flags, name, data, mnt);
if (error < 0)
goto out_free_secdata;
if (error)
goto out_sb;
-diff -NurpP --minimal linux-2.6.31.6/fs/sysfs/mount.c linux-2.6.31.6-vs2.3.0.36.24/fs/sysfs/mount.c
---- linux-2.6.31.6/fs/sysfs/mount.c 2009-06-11 17:13:08.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/sysfs/mount.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/sysfs/mount.c linux-2.6.32-vs2.3.0.36.26/fs/sysfs/mount.c
+--- linux-2.6.32/fs/sysfs/mount.c 2009-06-11 17:13:08.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/sysfs/mount.c 2009-12-03 20:04:56.000000000 +0100
@@ -47,7 +47,7 @@ static int sysfs_fill_super(struct super
sb->s_blocksize = PAGE_CACHE_SIZE;
sb->s_op = &sysfs_ops;
sb->s_time_gran = 1;
sysfs_sb = sb;
-diff -NurpP --minimal linux-2.6.31.6/fs/utimes.c linux-2.6.31.6-vs2.3.0.36.24/fs/utimes.c
---- linux-2.6.31.6/fs/utimes.c 2009-03-24 14:22:37.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/utimes.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/.tmp_dcache.ver linux-2.6.32-vs2.3.0.36.26/fs/.tmp_dcache.ver
+--- linux-2.6.32/fs/.tmp_dcache.ver 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/.tmp_dcache.ver 2009-12-03 20:07:43.000000000 +0100
+@@ -0,0 +1,27 @@
++__crc_sysctl_vfs_cache_pressure = 0x82d79b51 ;
++__crc_dcache_lock = 0x58e482c7 ;
++__crc_d_instantiate_unique = 0x7c189418 ;
++__crc_d_obtain_alias = 0xbcd8dfe6 ;
++__crc_d_genocide = 0x761de69d ;
++__crc_d_alloc = 0x4491e67e ;
++__crc_d_alloc_root = 0xb6aa3916 ;
++__crc_d_delete = 0xc921f8ba ;
++__crc_d_find_alias = 0xe28b75d1 ;
++__crc_d_instantiate = 0x01b0011d ;
++__crc_d_invalidate = 0xfe4bec19 ;
++__crc_d_lookup = 0xb2a5ca18 ;
++__crc_d_move = 0xe574db65 ;
++__crc_d_materialise_unique = 0xa5c0aff6 ;
++__crc_d_path = 0x9db28e8c ;
++__crc_d_prune_aliases = 0x916c21f8 ;
++__crc_d_rehash = 0x57bab990 ;
++__crc_d_splice_alias = 0x65a3aa7d ;
++__crc_d_add_ci = 0x8097dd72 ;
++__crc_d_validate = 0xa68ca558 ;
++__crc_dget_locked = 0x860c45d4 ;
++__crc_dput = 0x9515eed3 ;
++__crc_find_inode_number = 0xb4fb4528 ;
++__crc_have_submounts = 0x9ea1ad9e ;
++__crc_names_cachep = 0x28306992 ;
++__crc_shrink_dcache_parent = 0x6876d637 ;
++__crc_shrink_dcache_sb = 0x0c87c8c6 ;
+diff -NurpP --minimal linux-2.6.32/fs/utimes.c linux-2.6.32-vs2.3.0.36.26/fs/utimes.c
+--- linux-2.6.32/fs/utimes.c 2009-03-24 14:22:37.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/utimes.c 2009-12-03 20:04:56.000000000 +0100
@@ -8,6 +8,8 @@
#include <linux/stat.h>
#include <linux/utime.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
-diff -NurpP --minimal linux-2.6.31.6/fs/xattr.c linux-2.6.31.6-vs2.3.0.36.24/fs/xattr.c
---- linux-2.6.31.6/fs/xattr.c 2009-09-10 15:26:24.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/xattr.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/xattr.c linux-2.6.32-vs2.3.0.36.26/fs/xattr.c
+--- linux-2.6.32/fs/xattr.c 2009-12-03 20:02:53.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/xattr.c 2009-12-03 20:04:56.000000000 +0100
@@ -18,6 +18,7 @@
#include <linux/module.h>
#include <linux/fsnotify.h>
#include <asm/uaccess.h>
-diff -NurpP --minimal linux-2.6.31.6/fs/xfs/linux-2.6/xfs_ioctl.c linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/linux-2.6/xfs_ioctl.c
---- linux-2.6.31.6/fs/xfs/linux-2.6/xfs_ioctl.c 2009-09-10 15:26:24.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/linux-2.6/xfs_ioctl.c 2009-10-07 15:57:55.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/xfs/linux-2.6/xfs_ioctl.c linux-2.6.32-vs2.3.0.36.26/fs/xfs/linux-2.6/xfs_ioctl.c
+--- linux-2.6.32/fs/xfs/linux-2.6/xfs_ioctl.c 2009-09-10 15:26:24.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/xfs/linux-2.6/xfs_ioctl.c 2009-12-03 20:04:56.000000000 +0100
@@ -34,7 +34,6 @@
#include "xfs_dir2_sf.h"
#include "xfs_dinode.h"
return xfs_ioc_setxflags(ip, filp, arg);
case XFS_IOC_FSSETDM: {
-diff -NurpP --minimal linux-2.6.31.6/fs/xfs/linux-2.6/xfs_ioctl.h linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/linux-2.6/xfs_ioctl.h
---- linux-2.6.31.6/fs/xfs/linux-2.6/xfs_ioctl.h 2009-03-24 14:22:37.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/linux-2.6/xfs_ioctl.h 2009-10-07 15:59:45.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/xfs/linux-2.6/xfs_ioctl.h linux-2.6.32-vs2.3.0.36.26/fs/xfs/linux-2.6/xfs_ioctl.h
+--- linux-2.6.32/fs/xfs/linux-2.6/xfs_ioctl.h 2009-03-24 14:22:37.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/xfs/linux-2.6/xfs_ioctl.h 2009-12-03 20:04:56.000000000 +0100
@@ -70,6 +70,12 @@ xfs_handle_to_dentry(
void __user *uhandle,
u32 hlen);
extern long
xfs_file_ioctl(
struct file *filp,
-diff -NurpP --minimal linux-2.6.31.6/fs/xfs/linux-2.6/xfs_iops.c linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/linux-2.6/xfs_iops.c
---- linux-2.6.31.6/fs/xfs/linux-2.6/xfs_iops.c 2009-09-10 15:26:24.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/linux-2.6/xfs_iops.c 2009-10-07 05:23:00.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/xfs/linux-2.6/xfs_iops.c linux-2.6.32-vs2.3.0.36.26/fs/xfs/linux-2.6/xfs_iops.c
+--- linux-2.6.32/fs/xfs/linux-2.6/xfs_iops.c 2009-12-03 20:02:53.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/xfs/linux-2.6/xfs_iops.c 2009-12-03 20:04:56.000000000 +0100
@@ -36,6 +36,7 @@
#include "xfs_attr_sf.h"
#include "xfs_dinode.h"
#include "xfs_bmap.h"
#include "xfs_btree.h"
#include "xfs_ialloc.h"
-@@ -56,6 +57,7 @@
+@@ -55,6 +56,7 @@
#include <linux/security.h>
#include <linux/falloc.h>
#include <linux/fiemap.h>
+#include <linux/vs_tag.h>
/*
- * Bring the atime in the XFS inode uptodate.
-@@ -513,6 +515,7 @@ xfs_vn_getattr(
+ * Bring the timestamps in the XFS inode uptodate.
+@@ -495,6 +497,7 @@ xfs_vn_getattr(
stat->nlink = ip->i_d.di_nlink;
stat->uid = ip->i_d.di_uid;
stat->gid = ip->i_d.di_gid;
+ stat->tag = ip->i_d.di_tag;
stat->ino = ip->i_ino;
stat->atime = inode->i_atime;
- stat->mtime.tv_sec = ip->i_d.di_mtime.t_sec;
-@@ -706,6 +709,7 @@ static const struct inode_operations xfs
+ stat->mtime = inode->i_mtime;
+@@ -686,6 +689,7 @@ static const struct inode_operations xfs
.listxattr = xfs_vn_listxattr,
.fallocate = xfs_vn_fallocate,
.fiemap = xfs_vn_fiemap,
};
static const struct inode_operations xfs_dir_inode_operations = {
-@@ -731,6 +735,7 @@ static const struct inode_operations xfs
+@@ -711,6 +715,7 @@ static const struct inode_operations xfs
.getxattr = generic_getxattr,
.removexattr = generic_removexattr,
.listxattr = xfs_vn_listxattr,
};
static const struct inode_operations xfs_dir_ci_inode_operations = {
-@@ -780,6 +785,10 @@ xfs_diflags_to_iflags(
+@@ -760,6 +765,10 @@ xfs_diflags_to_iflags(
inode->i_flags |= S_IMMUTABLE;
else
inode->i_flags &= ~S_IMMUTABLE;
if (ip->i_d.di_flags & XFS_DIFLAG_APPEND)
inode->i_flags |= S_APPEND;
else
-@@ -792,6 +801,15 @@ xfs_diflags_to_iflags(
+@@ -772,6 +781,15 @@ xfs_diflags_to_iflags(
inode->i_flags |= S_NOATIME;
else
inode->i_flags &= ~S_NOATIME;
}
/*
-@@ -820,6 +838,7 @@ xfs_setup_inode(
+@@ -800,6 +818,7 @@ xfs_setup_inode(
inode->i_nlink = ip->i_d.di_nlink;
inode->i_uid = ip->i_d.di_uid;
inode->i_gid = ip->i_d.di_gid;
switch (inode->i_mode & S_IFMT) {
case S_IFBLK:
-diff -NurpP --minimal linux-2.6.31.6/fs/xfs/linux-2.6/xfs_linux.h linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/linux-2.6/xfs_linux.h
---- linux-2.6.31.6/fs/xfs/linux-2.6/xfs_linux.h 2009-09-10 15:26:24.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/linux-2.6/xfs_linux.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/xfs/linux-2.6/xfs_linux.h linux-2.6.32-vs2.3.0.36.26/fs/xfs/linux-2.6/xfs_linux.h
+--- linux-2.6.32/fs/xfs/linux-2.6/xfs_linux.h 2009-09-10 15:26:24.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/xfs/linux-2.6/xfs_linux.h 2009-12-03 20:04:56.000000000 +0100
@@ -119,6 +119,7 @@
#define current_cpu() (raw_smp_processor_id())
#define current_test_flags(f) (current->flags & (f))
#define current_set_flags_nested(sp, f) \
(*(sp) = current->flags, current->flags |= (f))
-diff -NurpP --minimal linux-2.6.31.6/fs/xfs/linux-2.6/xfs_super.c linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/linux-2.6/xfs_super.c
---- linux-2.6.31.6/fs/xfs/linux-2.6/xfs_super.c 2009-09-10 15:26:24.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/linux-2.6/xfs_super.c 2009-09-10 17:01:53.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/xfs/linux-2.6/xfs_super.c linux-2.6.32-vs2.3.0.36.26/fs/xfs/linux-2.6/xfs_super.c
+--- linux-2.6.32/fs/xfs/linux-2.6/xfs_super.c 2009-12-03 20:02:53.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/xfs/linux-2.6/xfs_super.c 2009-12-03 20:04:56.000000000 +0100
@@ -117,6 +117,9 @@ mempool_t *xfs_ioend_pool;
#define MNTOPT_DMAPI "dmapi" /* DMI enabled (DMAPI / XDSM) */
#define MNTOPT_XDSM "xdsm" /* DMI enabled (DMAPI / XDSM) */
} else {
cmn_err(CE_WARN,
"XFS: unknown mount option [%s].", this_char);
-@@ -1244,6 +1264,16 @@ xfs_fs_remount(
+@@ -1270,6 +1290,16 @@ xfs_fs_remount(
case Opt_nobarrier:
mp->m_flags &= ~XFS_MOUNT_BARRIER;
break;
default:
/*
* Logically we would return an error here to prevent
-@@ -1451,6 +1481,9 @@ xfs_fs_fill_super(
+@@ -1477,6 +1507,9 @@ xfs_fs_fill_super(
XFS_SEND_MOUNT(mp, DM_RIGHT_NULL, mtpt, mp->m_fsname);
sb->s_magic = XFS_SB_MAGIC;
sb->s_blocksize = mp->m_sb.sb_blocksize;
sb->s_blocksize_bits = ffs(sb->s_blocksize) - 1;
-diff -NurpP --minimal linux-2.6.31.6/fs/xfs/xfs_dinode.h linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/xfs_dinode.h
---- linux-2.6.31.6/fs/xfs/xfs_dinode.h 2009-06-11 17:13:09.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/xfs_dinode.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/xfs/xfs_dinode.h linux-2.6.32-vs2.3.0.36.26/fs/xfs/xfs_dinode.h
+--- linux-2.6.32/fs/xfs/xfs_dinode.h 2009-06-11 17:13:09.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/xfs/xfs_dinode.h 2009-12-03 20:04:56.000000000 +0100
@@ -50,7 +50,9 @@ typedef struct xfs_dinode {
__be32 di_gid; /* owner's group id */
__be32 di_nlink; /* number of links to file */
+#define XFS_DIVFLAG_COW 0x02
#endif /* __XFS_DINODE_H__ */
-diff -NurpP --minimal linux-2.6.31.6/fs/xfs/xfs_fs.h linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/xfs_fs.h
---- linux-2.6.31.6/fs/xfs/xfs_fs.h 2009-09-10 15:26:24.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/xfs_fs.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/xfs/xfs_fs.h linux-2.6.32-vs2.3.0.36.26/fs/xfs/xfs_fs.h
+--- linux-2.6.32/fs/xfs/xfs_fs.h 2009-12-03 20:02:53.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/xfs/xfs_fs.h 2009-12-03 20:04:56.000000000 +0100
@@ -67,6 +67,9 @@ struct fsxattr {
#define XFS_XFLAG_EXTSZINHERIT 0x00001000 /* inherit inode extent size */
#define XFS_XFLAG_NODEFRAG 0x00002000 /* do not defragment */
__u32 bs_dmevmask; /* DMIG event mask */
__u16 bs_dmstate; /* DMIG state info */
__u16 bs_aextents; /* attribute number of extents */
-diff -NurpP --minimal linux-2.6.31.6/fs/xfs/xfs_ialloc.c linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/xfs_ialloc.c
---- linux-2.6.31.6/fs/xfs/xfs_ialloc.c 2009-06-11 17:13:09.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/xfs_ialloc.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/xfs/xfs_ialloc.c linux-2.6.32-vs2.3.0.36.26/fs/xfs/xfs_ialloc.c
+--- linux-2.6.32/fs/xfs/xfs_ialloc.c 2009-12-03 20:02:53.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/xfs/xfs_ialloc.c 2009-12-03 20:04:56.000000000 +0100
@@ -41,7 +41,6 @@
#include "xfs_error.h"
#include "xfs_bmap.h"
/*
* Allocation group level functions.
*/
-diff -NurpP --minimal linux-2.6.31.6/fs/xfs/xfs_inode.c linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/xfs_inode.c
---- linux-2.6.31.6/fs/xfs/xfs_inode.c 2009-09-10 15:26:24.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/xfs_inode.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/xfs/xfs_inode.c linux-2.6.32-vs2.3.0.36.26/fs/xfs/xfs_inode.c
+--- linux-2.6.32/fs/xfs/xfs_inode.c 2009-12-03 20:02:54.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/xfs/xfs_inode.c 2009-12-03 20:04:56.000000000 +0100
@@ -249,6 +249,7 @@ xfs_inotobp(
return 0;
}
/*
* This routine is called to map an inode to the buffer containing
@@ -654,15 +655,25 @@ xfs_iformat_btree(
- void
+ STATIC void
xfs_dinode_from_disk(
xfs_icdinode_t *to,
- xfs_dinode_t *from)
/* Wrap, we never let the log put out DI_MAX_FLUSH */
if (ip->i_d.di_flushiter == DI_MAX_FLUSH)
-diff -NurpP --minimal linux-2.6.31.6/fs/xfs/xfs_inode.h linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/xfs_inode.h
---- linux-2.6.31.6/fs/xfs/xfs_inode.h 2009-09-10 15:26:24.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/xfs_inode.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/xfs/xfs_inode.h linux-2.6.32-vs2.3.0.36.26/fs/xfs/xfs_inode.h
+--- linux-2.6.32/fs/xfs/xfs_inode.h 2009-12-03 20:02:54.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/xfs/xfs_inode.h 2009-12-03 20:04:56.000000000 +0100
@@ -135,7 +135,9 @@ typedef struct xfs_icdinode {
__uint32_t di_gid; /* owner's group id */
__uint32_t di_nlink; /* number of links to file */
__uint16_t di_flushiter; /* incremented on flush */
xfs_ictimestamp_t di_atime; /* time last accessed */
xfs_ictimestamp_t di_mtime; /* time last modified */
-@@ -573,9 +575,9 @@ int xfs_itobp(struct xfs_mount *, struc
+@@ -569,7 +571,7 @@ int xfs_itobp(struct xfs_mount *, struc
int xfs_iread(struct xfs_mount *, struct xfs_trans *,
struct xfs_inode *, xfs_daddr_t, uint);
- void xfs_dinode_from_disk(struct xfs_icdinode *,
-- struct xfs_dinode *);
-+ struct xfs_dinode *, int);
void xfs_dinode_to_disk(struct xfs_dinode *,
- struct xfs_icdinode *);
+ struct xfs_icdinode *, int);
void xfs_idestroy_fork(struct xfs_inode *, int);
void xfs_idata_realloc(struct xfs_inode *, int, int);
void xfs_iroot_realloc(struct xfs_inode *, int, int);
-diff -NurpP --minimal linux-2.6.31.6/fs/xfs/xfs_itable.c linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/xfs_itable.c
---- linux-2.6.31.6/fs/xfs/xfs_itable.c 2009-06-11 17:13:09.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/xfs_itable.c 2009-09-10 16:11:43.000000000 +0200
-@@ -82,6 +82,7 @@ xfs_bulkstat_one_iget(
+diff -NurpP --minimal linux-2.6.32/fs/xfs/xfs_itable.c linux-2.6.32-vs2.3.0.36.26/fs/xfs/xfs_itable.c
+--- linux-2.6.32/fs/xfs/xfs_itable.c 2009-12-03 20:02:54.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/xfs/xfs_itable.c 2009-12-03 20:04:56.000000000 +0100
+@@ -84,6 +84,7 @@ xfs_bulkstat_one_iget(
buf->bs_mode = dic->di_mode;
buf->bs_uid = dic->di_uid;
buf->bs_gid = dic->di_gid;
+ buf->bs_tag = dic->di_tag;
buf->bs_size = dic->di_size;
+
/*
- * We are reading the atime from the Linux inode because the
-diff -NurpP --minimal linux-2.6.31.6/fs/xfs/xfs_log_recover.c linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/xfs_log_recover.c
---- linux-2.6.31.6/fs/xfs/xfs_log_recover.c 2009-09-10 15:26:24.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/xfs_log_recover.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/xfs/xfs_log_recover.c linux-2.6.32-vs2.3.0.36.26/fs/xfs/xfs_log_recover.c
+--- linux-2.6.32/fs/xfs/xfs_log_recover.c 2009-12-03 20:02:54.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/xfs/xfs_log_recover.c 2009-12-03 20:04:56.000000000 +0100
@@ -2467,7 +2467,8 @@ xlog_recover_do_inode_trans(
}
/* the rest is in on-disk format */
if (item->ri_buf[1].i_len > sizeof(struct xfs_icdinode)) {
-diff -NurpP --minimal linux-2.6.31.6/fs/xfs/xfs_mount.h linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/xfs_mount.h
---- linux-2.6.31.6/fs/xfs/xfs_mount.h 2009-09-10 15:26:24.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/xfs_mount.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/xfs/xfs_mount.h linux-2.6.32-vs2.3.0.36.26/fs/xfs/xfs_mount.h
+--- linux-2.6.32/fs/xfs/xfs_mount.h 2009-12-03 20:02:54.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/xfs/xfs_mount.h 2009-12-03 20:04:56.000000000 +0100
@@ -283,6 +283,7 @@ typedef struct xfs_mount {
allocator */
#define XFS_MOUNT_NOATTR2 (1ULL << 25) /* disable use of attr2 format */
/*
* Default minimum read and write sizes.
-diff -NurpP --minimal linux-2.6.31.6/fs/xfs/xfs_vnodeops.c linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/xfs_vnodeops.c
---- linux-2.6.31.6/fs/xfs/xfs_vnodeops.c 2009-09-10 15:26:24.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/xfs_vnodeops.c 2009-10-07 15:57:06.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/xfs/xfs_vnodeops.c linux-2.6.32-vs2.3.0.36.26/fs/xfs/xfs_vnodeops.c
+--- linux-2.6.32/fs/xfs/xfs_vnodeops.c 2009-12-03 20:02:54.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/fs/xfs/xfs_vnodeops.c 2009-12-03 20:04:56.000000000 +0100
@@ -54,6 +54,80 @@
#include "xfs_filestream.h"
#include "xfs_vnodeops.h"
if (iuid != uid) {
if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_UQUOTA_ON(mp)) {
ASSERT(mask & ATTR_UID);
-diff -NurpP --minimal linux-2.6.31.6/fs/xfs/xfs_vnodeops.h linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/xfs_vnodeops.h
---- linux-2.6.31.6/fs/xfs/xfs_vnodeops.h 2009-09-10 15:26:24.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/fs/xfs/xfs_vnodeops.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/fs/xfs/xfs_vnodeops.h linux-2.6.32-vs2.3.0.36.26/fs/xfs/xfs_vnodeops.h
+--- linux-2.6.32/fs/xfs/xfs_vnodeops.h 2009-09-10 15:26:24.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/fs/xfs/xfs_vnodeops.h 2009-12-03 20:04:56.000000000 +0100
@@ -14,6 +14,7 @@ struct xfs_inode;
struct xfs_iomap;
int xfs_setattr(struct xfs_inode *ip, struct iattr *vap, int flags);
#define XFS_ATTR_DMI 0x01 /* invocation from a DMI function */
#define XFS_ATTR_NONBLOCK 0x02 /* return EAGAIN if operation would block */
-diff -NurpP --minimal linux-2.6.31.6/include/asm-generic/tlb.h linux-2.6.31.6-vs2.3.0.36.24/include/asm-generic/tlb.h
---- linux-2.6.31.6/include/asm-generic/tlb.h 2009-09-10 15:26:24.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/asm-generic/tlb.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/asm-generic/tlb.h linux-2.6.32-vs2.3.0.36.26/include/asm-generic/tlb.h
+--- linux-2.6.32/include/asm-generic/tlb.h 2009-09-10 15:26:24.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/include/asm-generic/tlb.h 2009-12-03 20:04:56.000000000 +0100
@@ -14,6 +14,7 @@
#define _ASM_GENERIC__TLB_H
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
-diff -NurpP --minimal linux-2.6.31.6/include/linux/capability.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/capability.h
---- linux-2.6.31.6/include/linux/capability.h 2009-06-11 17:13:13.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/capability.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/capability.h linux-2.6.32-vs2.3.0.36.26/include/linux/capability.h
+--- linux-2.6.32/include/linux/capability.h 2009-12-03 20:02:54.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/capability.h 2009-12-03 20:04:56.000000000 +0100
@@ -285,6 +285,7 @@ struct cpu_vfs_cap_data {
arbitrary SCSI commands */
/* Allow setting encryption key on loopback filesystem */
#define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
-diff -NurpP --minimal linux-2.6.31.6/include/linux/devpts_fs.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/devpts_fs.h
---- linux-2.6.31.6/include/linux/devpts_fs.h 2008-12-25 00:26:37.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/devpts_fs.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/devpts_fs.h linux-2.6.32-vs2.3.0.36.26/include/linux/devpts_fs.h
+--- linux-2.6.32/include/linux/devpts_fs.h 2008-12-25 00:26:37.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/devpts_fs.h 2009-12-03 20:04:56.000000000 +0100
@@ -45,5 +45,4 @@ static inline void devpts_pty_kill(struc
#endif
-
#endif /* _LINUX_DEVPTS_FS_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/ext2_fs.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/ext2_fs.h
---- linux-2.6.31.6/include/linux/ext2_fs.h 2009-03-24 14:22:41.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/ext2_fs.h 2009-10-12 05:20:23.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/ext2_fs.h linux-2.6.32-vs2.3.0.36.26/include/linux/ext2_fs.h
+--- linux-2.6.32/include/linux/ext2_fs.h 2009-03-24 14:22:41.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/ext2_fs.h 2009-12-03 20:04:56.000000000 +0100
@@ -189,8 +189,12 @@ struct ext2_group_desc
#define EXT2_NOTAIL_FL FS_NOTAIL_FL /* file tail should not be merged */
#define EXT2_DIRSYNC_FL FS_DIRSYNC_FL /* dirsync behaviour (directories only) */
#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
-diff -NurpP --minimal linux-2.6.31.6/include/linux/ext3_fs.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/ext3_fs.h
---- linux-2.6.31.6/include/linux/ext3_fs.h 2009-09-10 15:26:25.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/ext3_fs.h 2009-10-12 05:20:40.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/ext3_fs.h linux-2.6.32-vs2.3.0.36.26/include/linux/ext3_fs.h
+--- linux-2.6.32/include/linux/ext3_fs.h 2009-09-10 15:26:25.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/ext3_fs.h 2009-12-03 20:04:56.000000000 +0100
@@ -173,10 +173,14 @@ struct ext3_group_desc
#define EXT3_NOTAIL_FL 0x00008000 /* file tail should not be merged */
#define EXT3_DIRSYNC_FL 0x00010000 /* dirsync behaviour (directories only) */
/* ioctl.c */
extern long ext3_ioctl(struct file *, unsigned int, unsigned long);
-diff -NurpP --minimal linux-2.6.31.6/include/linux/fs.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/fs.h
---- linux-2.6.31.6/include/linux/fs.h 2009-09-10 15:26:25.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/fs.h 2009-10-06 23:35:53.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/fs.h linux-2.6.32-vs2.3.0.36.26/include/linux/fs.h
+--- linux-2.6.32/include/linux/fs.h 2009-12-03 20:02:55.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/fs.h 2009-12-03 20:04:56.000000000 +0100
@@ -205,6 +205,9 @@ struct inodes_stat_t {
#define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */
#define MS_I_VERSION (1<<23) /* Update inode I_version field */
/* the read-only stuff doesn't really belong here, but any other place is
probably as bad and I don't want to create yet another include file. */
-@@ -343,11 +367,14 @@ struct inodes_stat_t {
+@@ -347,11 +371,14 @@ struct inodes_stat_t {
#define FS_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
#define FS_EXTENT_FL 0x00080000 /* Extents */
#define FS_DIRECTIO_FL 0x00100000 /* Use direct i/o */
#define SYNC_FILE_RANGE_WAIT_BEFORE 1
#define SYNC_FILE_RANGE_WRITE 2
-@@ -429,6 +456,7 @@ typedef void (dio_iodone_t)(struct kiocb
+@@ -433,6 +460,7 @@ typedef void (dio_iodone_t)(struct kiocb
#define ATTR_KILL_PRIV (1 << 14)
#define ATTR_OPEN (1 << 15) /* Truncating from open(O_TRUNC) */
#define ATTR_TIMES_SET (1 << 16)
/*
* This is the Inode Attributes structure, used for notify_change(). It
-@@ -444,6 +472,7 @@ struct iattr {
+@@ -448,6 +476,7 @@ struct iattr {
umode_t ia_mode;
uid_t ia_uid;
gid_t ia_gid;
loff_t ia_size;
struct timespec ia_atime;
struct timespec ia_mtime;
-@@ -457,6 +486,9 @@ struct iattr {
+@@ -461,6 +490,9 @@ struct iattr {
struct file *ia_file;
};
/*
* Includes for diskquotas.
*/
-@@ -723,7 +755,9 @@ struct inode {
+@@ -726,7 +758,9 @@ struct inode {
unsigned int i_nlink;
uid_t i_uid;
gid_t i_gid;
u64 i_version;
loff_t i_size;
#ifdef __NEED_I_SIZE_ORDERED
-@@ -770,7 +804,8 @@ struct inode {
+@@ -773,7 +807,8 @@ struct inode {
unsigned long i_state;
unsigned long dirtied_when; /* jiffies of first dirtying */
atomic_t i_writecount;
#ifdef CONFIG_SECURITY
-@@ -858,12 +893,12 @@ static inline void i_size_write(struct i
+@@ -861,12 +896,12 @@ static inline void i_size_write(struct i
static inline unsigned iminor(const struct inode *inode)
{
}
extern struct block_device *I_BDEV(struct inode *inode);
-@@ -922,6 +957,7 @@ struct file {
+@@ -925,6 +960,7 @@ struct file {
loff_t f_pos;
struct fown_struct f_owner;
const struct cred *f_cred;
struct file_ra_state f_ra;
u64 f_version;
-@@ -1063,6 +1099,7 @@ struct file_lock {
+@@ -1066,6 +1102,7 @@ struct file_lock {
struct file *fl_file;
loff_t fl_start;
loff_t fl_end;
struct fasync_struct * fl_fasync; /* for lease break notifications */
unsigned long fl_break_time; /* for nonblocking lease breaks */
-@@ -1534,6 +1571,7 @@ struct inode_operations {
+@@ -1531,6 +1568,7 @@ struct inode_operations {
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
ssize_t (*listxattr) (struct dentry *, char *, size_t);
int (*removexattr) (struct dentry *, const char *);
void (*truncate_range)(struct inode *, loff_t, loff_t);
long (*fallocate)(struct inode *inode, int mode, loff_t offset,
loff_t len);
-@@ -1554,6 +1592,7 @@ extern ssize_t vfs_readv(struct file *,
+@@ -1551,6 +1589,7 @@ extern ssize_t vfs_readv(struct file *,
unsigned long, loff_t *);
extern ssize_t vfs_writev(struct file *, const struct iovec __user *,
unsigned long, loff_t *);
struct super_operations {
struct inode *(*alloc_inode)(struct super_block *sb);
-@@ -2328,6 +2367,7 @@ extern int dcache_dir_open(struct inode
+@@ -2347,6 +2386,7 @@ extern int dcache_dir_open(struct inode
extern int dcache_dir_close(struct inode *, struct file *);
extern loff_t dcache_dir_lseek(struct file *, loff_t, int);
extern int dcache_readdir(struct file *, void *, filldir_t);
extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *);
extern int simple_statfs(struct dentry *, struct kstatfs *);
extern int simple_link(struct dentry *, struct inode *, struct dentry *);
-diff -NurpP --minimal linux-2.6.31.6/include/linux/gfs2_ondisk.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/gfs2_ondisk.h
---- linux-2.6.31.6/include/linux/gfs2_ondisk.h 2009-03-24 14:22:41.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/gfs2_ondisk.h 2009-10-07 18:20:44.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/gfs2_ondisk.h linux-2.6.32-vs2.3.0.36.26/include/linux/gfs2_ondisk.h
+--- linux-2.6.32/include/linux/gfs2_ondisk.h 2009-12-03 20:02:55.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/gfs2_ondisk.h 2009-12-03 20:04:56.000000000 +0100
@@ -235,6 +235,9 @@ enum {
gfs2fl_NoAtime = 7,
gfs2fl_Sync = 8,
#define GFS2_DIF_TRUNC_IN_PROG 0x20000000 /* New in gfs2 */
#define GFS2_DIF_INHERIT_DIRECTIO 0x40000000
#define GFS2_DIF_INHERIT_JDATA 0x80000000
-diff -NurpP --minimal linux-2.6.31.6/include/linux/if_tun.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/if_tun.h
---- linux-2.6.31.6/include/linux/if_tun.h 2009-09-10 15:26:25.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/if_tun.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/if_tun.h linux-2.6.32-vs2.3.0.36.26/include/linux/if_tun.h
+--- linux-2.6.32/include/linux/if_tun.h 2009-12-03 20:02:55.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/if_tun.h 2009-12-03 20:04:56.000000000 +0100
@@ -48,6 +48,7 @@
#define TUNGETIFF _IOR('T', 210, unsigned int)
#define TUNGETSNDBUF _IOR('T', 211, int)
/* TUNSETIFF ifr flags */
#define IFF_TUN 0x0001
-diff -NurpP --minimal linux-2.6.31.6/include/linux/init_task.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/init_task.h
---- linux-2.6.31.6/include/linux/init_task.h 2009-09-10 15:26:25.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/init_task.h 2009-09-10 17:13:45.000000000 +0200
-@@ -173,6 +173,10 @@ extern struct cred init_cred;
- INIT_LOCKDEP \
+diff -NurpP --minimal linux-2.6.32/include/linux/init_task.h linux-2.6.32-vs2.3.0.36.26/include/linux/init_task.h
+--- linux-2.6.32/include/linux/init_task.h 2009-12-03 20:02:55.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/init_task.h 2009-12-03 20:04:56.000000000 +0100
+@@ -184,6 +184,10 @@ extern struct cred init_cred;
INIT_FTRACE_GRAPH \
INIT_TRACE_RECURSION \
+ INIT_TASK_RCU_PREEMPT(tsk) \
+ .xid = 0, \
+ .vx_info = NULL, \
+ .nid = 0, \
}
-diff -NurpP --minimal linux-2.6.31.6/include/linux/interrupt.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/interrupt.h
---- linux-2.6.31.6/include/linux/interrupt.h 2009-09-10 15:26:25.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/interrupt.h 2009-09-10 16:11:43.000000000 +0200
-@@ -9,8 +9,8 @@
- #include <linux/cpumask.h>
- #include <linux/irqreturn.h>
- #include <linux/irqnr.h>
--#include <linux/hardirq.h>
- #include <linux/sched.h>
-+#include <linux/hardirq.h>
- #include <linux/irqflags.h>
- #include <linux/smp.h>
- #include <linux/percpu.h>
-diff -NurpP --minimal linux-2.6.31.6/include/linux/ipc.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/ipc.h
---- linux-2.6.31.6/include/linux/ipc.h 2008-12-25 00:26:37.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/ipc.h 2009-09-10 16:11:43.000000000 +0200
-@@ -93,6 +93,7 @@ struct kern_ipc_perm
+diff -NurpP --minimal linux-2.6.32/include/linux/ipc.h linux-2.6.32-vs2.3.0.36.26/include/linux/ipc.h
+--- linux-2.6.32/include/linux/ipc.h 2009-12-03 20:02:55.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/ipc.h 2009-12-03 20:04:56.000000000 +0100
+@@ -91,6 +91,7 @@ struct kern_ipc_perm
key_t key;
uid_t uid;
gid_t gid;
uid_t cuid;
gid_t cgid;
mode_t mode;
-diff -NurpP --minimal linux-2.6.31.6/include/linux/Kbuild linux-2.6.31.6-vs2.3.0.36.24/include/linux/Kbuild
---- linux-2.6.31.6/include/linux/Kbuild 2009-09-10 15:26:24.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/Kbuild 2009-09-10 16:11:43.000000000 +0200
-@@ -376,5 +376,8 @@ unifdef-y += xattr.h
+diff -NurpP --minimal linux-2.6.32/include/linux/Kbuild linux-2.6.32-vs2.3.0.36.26/include/linux/Kbuild
+--- linux-2.6.32/include/linux/Kbuild 2009-12-03 20:02:54.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/Kbuild 2009-12-03 20:04:56.000000000 +0100
+@@ -382,5 +382,8 @@ unifdef-y += xattr.h
unifdef-y += xfrm.h
objhdr-y += version.h
header-y += wimax.h
header-y += wimax/
+
-diff -NurpP --minimal linux-2.6.31.6/include/linux/loop.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/loop.h
---- linux-2.6.31.6/include/linux/loop.h 2009-09-10 15:26:25.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/loop.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/loop.h linux-2.6.32-vs2.3.0.36.26/include/linux/loop.h
+--- linux-2.6.32/include/linux/loop.h 2009-09-10 15:26:25.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/loop.h 2009-12-03 20:04:56.000000000 +0100
@@ -45,6 +45,7 @@ struct loop_device {
struct loop_func_table *lo_encryption;
__u32 lo_init[2];
int (*ioctl)(struct loop_device *, int cmd,
unsigned long arg);
-diff -NurpP --minimal linux-2.6.31.6/include/linux/magic.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/magic.h
---- linux-2.6.31.6/include/linux/magic.h 2009-09-10 15:26:25.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/magic.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/magic.h linux-2.6.32-vs2.3.0.36.26/include/linux/magic.h
+--- linux-2.6.32/include/linux/magic.h 2009-12-03 20:02:55.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/magic.h 2009-12-03 20:04:56.000000000 +0100
@@ -3,7 +3,7 @@
#define ADFS_SUPER_MAGIC 0xadf5
#define AUTOFS_SUPER_MAGIC 0x0187
#define CODA_SUPER_MAGIC 0x73757245
#define CRAMFS_MAGIC 0x28cd3d45 /* some random number */
-@@ -36,6 +36,7 @@
+@@ -38,6 +38,7 @@
#define NFS_SUPER_MAGIC 0x6969
#define OPENPROM_SUPER_MAGIC 0x9fa1
#define PROC_SUPER_MAGIC 0x9fa0
#define QNX4_SUPER_MAGIC 0x002f /* qnx4 fs detection */
#define REISERFS_SUPER_MAGIC 0x52654973 /* used by gcc */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/major.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/major.h
---- linux-2.6.31.6/include/linux/major.h 2009-09-10 15:26:25.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/major.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/major.h linux-2.6.32-vs2.3.0.36.26/include/linux/major.h
+--- linux-2.6.32/include/linux/major.h 2009-09-10 15:26:25.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/major.h 2009-12-03 20:04:56.000000000 +0100
@@ -15,6 +15,7 @@
#define HD_MAJOR IDE0_MAJOR
#define PTY_SLAVE_MAJOR 3
#define TTYAUX_MAJOR 5
#define LP_MAJOR 6
#define VCS_MAJOR 7
-diff -NurpP --minimal linux-2.6.31.6/include/linux/mm_types.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/mm_types.h
---- linux-2.6.31.6/include/linux/mm_types.h 2009-09-10 15:26:25.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/mm_types.h 2009-09-10 16:11:43.000000000 +0200
-@@ -244,6 +244,7 @@ struct mm_struct {
+diff -NurpP --minimal linux-2.6.32/include/linux/mm_types.h linux-2.6.32-vs2.3.0.36.26/include/linux/mm_types.h
+--- linux-2.6.32/include/linux/mm_types.h 2009-12-03 20:02:55.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/mm_types.h 2009-12-03 20:04:56.000000000 +0100
+@@ -246,6 +246,7 @@ struct mm_struct {
/* Architecture-specific MM context */
mm_context_t context;
/* Swap token stuff */
/*
-diff -NurpP --minimal linux-2.6.31.6/include/linux/mount.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/mount.h
---- linux-2.6.31.6/include/linux/mount.h 2009-09-10 15:26:25.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/mount.h 2009-09-10 17:14:39.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/mount.h linux-2.6.32-vs2.3.0.36.26/include/linux/mount.h
+--- linux-2.6.32/include/linux/mount.h 2009-09-10 15:26:25.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/mount.h 2009-12-03 20:04:56.000000000 +0100
@@ -36,6 +36,9 @@ struct mnt_namespace;
#define MNT_UNBINDABLE 0x2000 /* if the vfsmount is a unbindable mount */
#define MNT_PNODE_MASK 0x3000 /* propagation flag mask */
};
static inline int *get_mnt_writers_ptr(struct vfsmount *mnt)
-diff -NurpP --minimal linux-2.6.31.6/include/linux/net.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/net.h
---- linux-2.6.31.6/include/linux/net.h 2009-06-11 17:13:15.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/net.h 2009-09-10 16:11:43.000000000 +0200
-@@ -68,6 +68,7 @@ struct net;
+diff -NurpP --minimal linux-2.6.32/include/linux/net.h linux-2.6.32-vs2.3.0.36.26/include/linux/net.h
+--- linux-2.6.32/include/linux/net.h 2009-12-03 20:02:55.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/net.h 2009-12-03 20:04:56.000000000 +0100
+@@ -69,6 +69,7 @@ struct net;
#define SOCK_NOSPACE 2
#define SOCK_PASSCRED 3
#define SOCK_PASSSEC 4
#ifndef ARCH_HAS_SOCKET_TYPES
/**
-diff -NurpP --minimal linux-2.6.31.6/include/linux/nfs_mount.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/nfs_mount.h
---- linux-2.6.31.6/include/linux/nfs_mount.h 2009-03-24 14:22:43.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/nfs_mount.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/nfs_mount.h linux-2.6.32-vs2.3.0.36.26/include/linux/nfs_mount.h
+--- linux-2.6.32/include/linux/nfs_mount.h 2009-03-24 14:22:43.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/nfs_mount.h 2009-12-03 20:04:56.000000000 +0100
@@ -63,7 +63,8 @@ struct nfs_mount_data {
#define NFS_MOUNT_SECFLAVOUR 0x2000 /* 5 */
#define NFS_MOUNT_NORDIRPLUS 0x4000 /* 5 */
/* The following are for internal use only */
#define NFS_MOUNT_LOOKUP_CACHE_NONEG 0x10000
-diff -NurpP --minimal linux-2.6.31.6/include/linux/nsproxy.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/nsproxy.h
---- linux-2.6.31.6/include/linux/nsproxy.h 2009-06-11 17:13:17.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/nsproxy.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/nsproxy.h linux-2.6.32-vs2.3.0.36.26/include/linux/nsproxy.h
+--- linux-2.6.32/include/linux/nsproxy.h 2009-06-11 17:13:17.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/nsproxy.h 2009-12-03 20:04:56.000000000 +0100
@@ -3,6 +3,7 @@
#include <linux/spinlock.h>
}
#ifdef CONFIG_CGROUP_NS
-diff -NurpP --minimal linux-2.6.31.6/include/linux/pid.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/pid.h
---- linux-2.6.31.6/include/linux/pid.h 2009-03-24 14:22:43.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/pid.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/pid.h linux-2.6.32-vs2.3.0.36.26/include/linux/pid.h
+--- linux-2.6.32/include/linux/pid.h 2009-03-24 14:22:43.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/pid.h 2009-12-03 20:04:56.000000000 +0100
@@ -8,7 +8,8 @@ enum pid_type
PIDTYPE_PID,
PIDTYPE_PGID,
pid_t pid_vnr(struct pid *pid);
#define do_each_pid_task(pid, type, task) \
-diff -NurpP --minimal linux-2.6.31.6/include/linux/proc_fs.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/proc_fs.h
---- linux-2.6.31.6/include/linux/proc_fs.h 2009-09-10 15:26:26.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/proc_fs.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/proc_fs.h linux-2.6.32-vs2.3.0.36.26/include/linux/proc_fs.h
+--- linux-2.6.32/include/linux/proc_fs.h 2009-12-03 20:02:56.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/proc_fs.h 2009-12-03 20:04:56.000000000 +0100
@@ -56,6 +56,7 @@ struct proc_dir_entry {
nlink_t nlink;
uid_t uid;
loff_t size;
const struct inode_operations *proc_iops;
/*
-@@ -240,12 +241,18 @@ static inline void kclist_add(struct kco
- extern void kclist_add(struct kcore_list *, void *, size_t);
+@@ -250,12 +251,18 @@ kclist_add(struct kcore_list *new, void
+ extern void kclist_add(struct kcore_list *, void *, size_t, int type);
#endif
+struct vx_info;
};
struct ctl_table_header;
-@@ -253,6 +260,7 @@ struct ctl_table;
+@@ -263,6 +270,7 @@ struct ctl_table;
struct proc_inode {
struct pid *pid;
int fd;
union proc_op op;
struct proc_dir_entry *pde;
-diff -NurpP --minimal linux-2.6.31.6/include/linux/quotaops.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/quotaops.h
---- linux-2.6.31.6/include/linux/quotaops.h 2009-09-10 15:26:26.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/quotaops.h 2009-10-12 02:07:55.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/quotaops.h linux-2.6.32-vs2.3.0.36.26/include/linux/quotaops.h
+--- linux-2.6.32/include/linux/quotaops.h 2009-12-03 20:02:56.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/quotaops.h 2009-12-03 20:04:56.000000000 +0100
@@ -8,6 +8,7 @@
#define _LINUX_QUOTAOPS_
inode_sub_bytes(inode, nr);
}
-diff -NurpP --minimal linux-2.6.31.6/include/linux/reiserfs_fs.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/reiserfs_fs.h
---- linux-2.6.31.6/include/linux/reiserfs_fs.h 2009-09-10 15:26:26.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/reiserfs_fs.h 2009-10-07 01:27:41.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/reiserfs_fs.h linux-2.6.32-vs2.3.0.36.26/include/linux/reiserfs_fs.h
+--- linux-2.6.32/include/linux/reiserfs_fs.h 2009-09-10 15:26:26.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/reiserfs_fs.h 2009-12-03 20:04:56.000000000 +0100
@@ -899,6 +899,11 @@ struct stat_data_v1 {
#define REISERFS_COMPR_FL FS_COMPR_FL
#define REISERFS_NOTAIL_FL FS_NOTAIL_FL
/* namei.c */
void set_de_name_and_namelen(struct reiserfs_dir_entry *de);
-diff -NurpP --minimal linux-2.6.31.6/include/linux/reiserfs_fs_sb.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/reiserfs_fs_sb.h
---- linux-2.6.31.6/include/linux/reiserfs_fs_sb.h 2009-09-10 15:26:26.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/reiserfs_fs_sb.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/reiserfs_fs_sb.h linux-2.6.32-vs2.3.0.36.26/include/linux/reiserfs_fs_sb.h
+--- linux-2.6.32/include/linux/reiserfs_fs_sb.h 2009-09-10 15:26:26.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/reiserfs_fs_sb.h 2009-12-03 20:04:56.000000000 +0100
@@ -456,6 +456,7 @@ enum reiserfs_mount_options {
REISERFS_EXPOSE_PRIVROOT,
REISERFS_BARRIER_NONE,
/* Actions on error */
REISERFS_ERROR_PANIC,
-diff -NurpP --minimal linux-2.6.31.6/include/linux/sched.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/sched.h
---- linux-2.6.31.6/include/linux/sched.h 2009-09-10 15:26:26.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/sched.h 2009-10-06 04:39:26.000000000 +0200
-@@ -383,25 +383,28 @@ extern void arch_unmap_area_topdown(stru
+diff -NurpP --minimal linux-2.6.32/include/linux/sched.h linux-2.6.32-vs2.3.0.36.26/include/linux/sched.h
+--- linux-2.6.32/include/linux/sched.h 2009-12-03 20:02:56.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/sched.h 2009-12-03 20:04:56.000000000 +0100
+@@ -390,25 +390,28 @@ extern void arch_unmap_area_topdown(stru
* The mm counters are not protected by its page_table_lock,
* so must be incremented atomically.
*/
#define get_mm_rss(mm) \
(get_mm_counter(mm, file_rss) + get_mm_counter(mm, anon_rss))
#define update_hiwater_rss(mm) do { \
-@@ -1024,7 +1027,7 @@ struct sched_domain;
- struct sched_class {
- const struct sched_class *next;
-
-- void (*enqueue_task) (struct rq *rq, struct task_struct *p, int wakeup);
-+ int (*enqueue_task) (struct rq *rq, struct task_struct *p, int wakeup);
- void (*dequeue_task) (struct rq *rq, struct task_struct *p, int sleep);
- void (*yield_task) (struct rq *rq);
-
-@@ -1124,6 +1127,7 @@ struct sched_entity {
- u64 nr_failed_migrations_affine;
- u64 nr_failed_migrations_running;
- u64 nr_failed_migrations_hot;
-+ u64 nr_failed_migrations_throttled;
- u64 nr_forced_migrations;
- u64 nr_forced2_migrations;
-
-@@ -1136,6 +1140,12 @@ struct sched_entity {
+@@ -1183,6 +1186,12 @@ struct sched_entity {
u64 nr_wakeups_affine_attempts;
u64 nr_wakeups_passive;
u64 nr_wakeups_idle;
#endif
#ifdef CONFIG_FAIR_GROUP_SCHED
-@@ -1335,6 +1345,14 @@ struct task_struct {
+@@ -1393,6 +1402,14 @@ struct task_struct {
#endif
seccomp_t seccomp;
/* Thread group tracking */
u32 parent_exec_id;
u32 self_exec_id;
-@@ -1559,6 +1577,11 @@ struct pid_namespace;
+@@ -1618,6 +1635,11 @@ struct pid_namespace;
pid_t __task_pid_nr_ns(struct task_struct *task, enum pid_type type,
struct pid_namespace *ns);
static inline pid_t task_pid_nr(struct task_struct *tsk)
{
return tsk->pid;
-@@ -1572,7 +1595,8 @@ static inline pid_t task_pid_nr_ns(struc
+@@ -1631,7 +1653,8 @@ static inline pid_t task_pid_nr_ns(struc
static inline pid_t task_pid_vnr(struct task_struct *tsk)
{
}
-@@ -1585,7 +1609,7 @@ pid_t task_tgid_nr_ns(struct task_struct
+@@ -1644,7 +1667,7 @@ pid_t task_tgid_nr_ns(struct task_struct
static inline pid_t task_tgid_vnr(struct task_struct *tsk)
{
}
-diff -NurpP --minimal linux-2.6.31.6/include/linux/shmem_fs.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/shmem_fs.h
---- linux-2.6.31.6/include/linux/shmem_fs.h 2009-09-10 15:26:26.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/shmem_fs.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/shmem_fs.h linux-2.6.32-vs2.3.0.36.26/include/linux/shmem_fs.h
+--- linux-2.6.32/include/linux/shmem_fs.h 2009-12-03 20:02:56.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/shmem_fs.h 2009-12-03 20:04:56.000000000 +0100
@@ -8,6 +8,9 @@
#define SHMEM_NR_DIRECT 16
struct shmem_inode_info {
spinlock_t lock;
unsigned long flags;
-diff -NurpP --minimal linux-2.6.31.6/include/linux/stat.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/stat.h
---- linux-2.6.31.6/include/linux/stat.h 2008-12-25 00:26:37.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/stat.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/stat.h linux-2.6.32-vs2.3.0.36.26/include/linux/stat.h
+--- linux-2.6.32/include/linux/stat.h 2008-12-25 00:26:37.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/stat.h 2009-12-03 20:04:56.000000000 +0100
@@ -66,6 +66,7 @@ struct kstat {
unsigned int nlink;
uid_t uid;
dev_t rdev;
loff_t size;
struct timespec atime;
-diff -NurpP --minimal linux-2.6.31.6/include/linux/sunrpc/auth.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/sunrpc/auth.h
---- linux-2.6.31.6/include/linux/sunrpc/auth.h 2008-12-25 00:26:37.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/sunrpc/auth.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/sunrpc/auth.h linux-2.6.32-vs2.3.0.36.26/include/linux/sunrpc/auth.h
+--- linux-2.6.32/include/linux/sunrpc/auth.h 2009-12-03 20:02:56.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/sunrpc/auth.h 2009-12-03 20:04:56.000000000 +0100
@@ -25,6 +25,7 @@
struct auth_cred {
uid_t uid;
struct group_info *group_info;
unsigned char machine_cred : 1;
};
-diff -NurpP --minimal linux-2.6.31.6/include/linux/sunrpc/clnt.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/sunrpc/clnt.h
---- linux-2.6.31.6/include/linux/sunrpc/clnt.h 2009-09-10 15:26:26.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/sunrpc/clnt.h 2009-09-10 16:11:43.000000000 +0200
-@@ -43,7 +43,8 @@ struct rpc_clnt {
+diff -NurpP --minimal linux-2.6.32/include/linux/sunrpc/clnt.h linux-2.6.32-vs2.3.0.36.26/include/linux/sunrpc/clnt.h
+--- linux-2.6.32/include/linux/sunrpc/clnt.h 2009-12-03 20:02:56.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/sunrpc/clnt.h 2009-12-03 20:04:56.000000000 +0100
+@@ -49,7 +49,8 @@ struct rpc_clnt {
unsigned int cl_softrtry : 1,/* soft timeouts */
cl_discrtry : 1,/* disconnect before retry */
cl_autobind : 1,/* use getport() */
struct rpc_rtt * cl_rtt; /* RTO estimator data */
const struct rpc_timeout *cl_timeout; /* Timeout strategy */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/syscalls.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/syscalls.h
---- linux-2.6.31.6/include/linux/syscalls.h 2009-09-10 15:26:26.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/syscalls.h 2009-09-10 16:11:43.000000000 +0200
-@@ -428,6 +428,8 @@ asmlinkage long sys_symlink(const char _
+diff -NurpP --minimal linux-2.6.32/include/linux/syscalls.h linux-2.6.32-vs2.3.0.36.26/include/linux/syscalls.h
+--- linux-2.6.32/include/linux/syscalls.h 2009-12-03 20:02:56.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/syscalls.h 2009-12-03 20:04:56.000000000 +0100
+@@ -546,6 +546,8 @@ asmlinkage long sys_symlink(const char _
asmlinkage long sys_unlink(const char __user *pathname);
asmlinkage long sys_rename(const char __user *oldname,
const char __user *newname);
asmlinkage long sys_chmod(const char __user *filename, mode_t mode);
asmlinkage long sys_fchmod(unsigned int fd, mode_t mode);
-diff -NurpP --minimal linux-2.6.31.6/include/linux/sysctl.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/sysctl.h
---- linux-2.6.31.6/include/linux/sysctl.h 2009-06-11 17:13:18.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/sysctl.h 2009-09-10 16:11:43.000000000 +0200
-@@ -70,6 +70,7 @@ enum
+diff -NurpP --minimal linux-2.6.32/include/linux/sysctl.h linux-2.6.32-vs2.3.0.36.26/include/linux/sysctl.h
+--- linux-2.6.32/include/linux/sysctl.h 2009-12-03 20:02:56.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/sysctl.h 2009-12-03 20:04:56.000000000 +0100
+@@ -69,6 +69,7 @@ enum
CTL_ABI=9, /* Binary emulation */
CTL_CPU=10, /* CPU stuff (speed scaling, etc) */
CTL_ARLAN=254, /* arlan wireless driver */
CTL_S390DBF=5677, /* s390 debug */
CTL_SUNRPC=7249, /* sunrpc debug */
CTL_PM=9899, /* frv power management */
-@@ -104,6 +105,7 @@ enum
+@@ -103,6 +104,7 @@ enum
KERN_PANIC=15, /* int: panic timeout */
KERN_REALROOTDEV=16, /* real root device to mount after initrd */
KERN_SPARC_REBOOT=21, /* reboot command on Sparc */
KERN_CTLALTDEL=22, /* int: allow ctl-alt-del to reboot */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/sysfs.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/sysfs.h
---- linux-2.6.31.6/include/linux/sysfs.h 2008-12-25 00:26:37.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/sysfs.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/sysfs.h linux-2.6.32-vs2.3.0.36.26/include/linux/sysfs.h
+--- linux-2.6.32/include/linux/sysfs.h 2008-12-25 00:26:37.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/sysfs.h 2009-12-03 20:04:56.000000000 +0100
@@ -17,6 +17,8 @@
#include <linux/list.h>
#include <asm/atomic.h>
struct kobject;
struct module;
-diff -NurpP --minimal linux-2.6.31.6/include/linux/time.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/time.h
---- linux-2.6.31.6/include/linux/time.h 2009-09-10 15:26:26.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/time.h 2009-09-10 16:11:43.000000000 +0200
-@@ -205,6 +205,9 @@ static __always_inline void timespec_add
+diff -NurpP --minimal linux-2.6.32/include/linux/time.h linux-2.6.32-vs2.3.0.36.26/include/linux/time.h
+--- linux-2.6.32/include/linux/time.h 2009-12-03 20:02:56.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/time.h 2009-12-03 20:04:56.000000000 +0100
+@@ -237,6 +237,9 @@ static __always_inline void timespec_add
a->tv_sec += __iter_div_u64_rem(a->tv_nsec + ns, NSEC_PER_SEC, &ns);
a->tv_nsec = ns;
}
#endif /* __KERNEL__ */
#define NFDBITS __NFDBITS
-diff -NurpP --minimal linux-2.6.31.6/include/linux/types.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/types.h
---- linux-2.6.31.6/include/linux/types.h 2009-09-10 15:26:26.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/types.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/types.h linux-2.6.32-vs2.3.0.36.26/include/linux/types.h
+--- linux-2.6.32/include/linux/types.h 2009-09-10 15:26:26.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/types.h 2009-12-03 20:04:56.000000000 +0100
@@ -37,6 +37,9 @@ typedef __kernel_uid32_t uid_t;
typedef __kernel_gid32_t gid_t;
typedef __kernel_uid16_t uid16_t;
typedef unsigned long uintptr_t;
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vroot.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vroot.h
---- linux-2.6.31.6/include/linux/vroot.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vroot.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vroot.h linux-2.6.32-vs2.3.0.36.26/include/linux/vroot.h
+--- linux-2.6.32/include/linux/vroot.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vroot.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,51 @@
+
+/*
+#define VROOT_CLR_DEV 0x5601
+
+#endif /* _LINUX_VROOT_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vs_base.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_base.h
---- linux-2.6.31.6/include/linux/vs_base.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_base.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vs_base.h linux-2.6.32-vs2.3.0.36.26/include/linux/vs_base.h
+--- linux-2.6.32/include/linux/vs_base.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vs_base.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,10 @@
+#ifndef _VS_BASE_H
+#define _VS_BASE_H
+#else
+#warning duplicate inclusion
+#endif
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vs_context.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_context.h
---- linux-2.6.31.6/include/linux/vs_context.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_context.h 2009-09-30 02:28:59.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vs_context.h linux-2.6.32-vs2.3.0.36.26/include/linux/vs_context.h
+--- linux-2.6.32/include/linux/vs_context.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vs_context.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,242 @@
+#ifndef _VS_CONTEXT_H
+#define _VS_CONTEXT_H
+#else
+#warning duplicate inclusion
+#endif
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vs_cowbl.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_cowbl.h
---- linux-2.6.31.6/include/linux/vs_cowbl.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_cowbl.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vs_cowbl.h linux-2.6.32-vs2.3.0.36.26/include/linux/vs_cowbl.h
+--- linux-2.6.32/include/linux/vs_cowbl.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vs_cowbl.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,47 @@
+#ifndef _VS_COWBL_H
+#define _VS_COWBL_H
+#else
+#warning duplicate inclusion
+#endif
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vs_cvirt.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_cvirt.h
---- linux-2.6.31.6/include/linux/vs_cvirt.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_cvirt.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vs_cvirt.h linux-2.6.32-vs2.3.0.36.26/include/linux/vs_cvirt.h
+--- linux-2.6.32/include/linux/vs_cvirt.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vs_cvirt.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,50 @@
+#ifndef _VS_CVIRT_H
+#define _VS_CVIRT_H
+#else
+#warning duplicate inclusion
+#endif
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vs_device.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_device.h
---- linux-2.6.31.6/include/linux/vs_device.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_device.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vs_device.h linux-2.6.32-vs2.3.0.36.26/include/linux/vs_device.h
+--- linux-2.6.32/include/linux/vs_device.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vs_device.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,45 @@
+#ifndef _VS_DEVICE_H
+#define _VS_DEVICE_H
+#else
+#warning duplicate inclusion
+#endif
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vs_dlimit.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_dlimit.h
---- linux-2.6.31.6/include/linux/vs_dlimit.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_dlimit.h 2009-10-12 02:50:50.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vs_dlimit.h linux-2.6.32-vs2.3.0.36.26/include/linux/vs_dlimit.h
+--- linux-2.6.32/include/linux/vs_dlimit.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vs_dlimit.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,216 @@
+#ifndef _VS_DLIMIT_H
+#define _VS_DLIMIT_H
+#else
+#warning duplicate inclusion
+#endif
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/base.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/base.h
---- linux-2.6.31.6/include/linux/vserver/base.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/base.h 2009-11-05 04:16:31.000000000 +0100
-@@ -0,0 +1,159 @@
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/base.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/base.h
+--- linux-2.6.32/include/linux/vserver/base.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/base.h 2009-12-03 20:04:56.000000000 +0100
+@@ -0,0 +1,170 @@
+#ifndef _VX_BASE_H
+#define _VX_BASE_H
+
+#define vx_current_initpid(n) vx_task_initpid(current, n)
+
+
++/* context unshare mask */
++
++#define __vx_umask(v) ((v)->vx_umask)
++
++#define vx_current_umask() __vx_umask(current_vx_info())
++
++#define vx_can_unshare(b, f) (capable(b) || \
++ (cap_raised(current_cap(), b) && \
++ !((f) & ~vx_current_umask())))
++
++
+#define __vx_state(v) ((v) ? ((v)->vx_state) : 0)
+
+#define vx_info_state(v, m) (__vx_state(v) & (m))
+#define nx_info_state(n, m) (__nx_state(n) & (m))
+
+#endif
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/cacct_cmd.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/cacct_cmd.h
---- linux-2.6.31.6/include/linux/vserver/cacct_cmd.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/cacct_cmd.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/cacct_cmd.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/cacct_cmd.h
+--- linux-2.6.32/include/linux/vserver/cacct_cmd.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/cacct_cmd.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,23 @@
+#ifndef _VX_CACCT_CMD_H
+#define _VX_CACCT_CMD_H
+
+#endif /* __KERNEL__ */
+#endif /* _VX_CACCT_CMD_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/cacct_def.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/cacct_def.h
---- linux-2.6.31.6/include/linux/vserver/cacct_def.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/cacct_def.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/cacct_def.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/cacct_def.h
+--- linux-2.6.32/include/linux/vserver/cacct_def.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/cacct_def.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,43 @@
+#ifndef _VX_CACCT_DEF_H
+#define _VX_CACCT_DEF_H
+#endif
+
+#endif /* _VX_CACCT_DEF_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/cacct.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/cacct.h
---- linux-2.6.31.6/include/linux/vserver/cacct.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/cacct.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/cacct.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/cacct.h
+--- linux-2.6.32/include/linux/vserver/cacct.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/cacct.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,15 @@
+#ifndef _VX_CACCT_H
+#define _VX_CACCT_H
+};
+
+#endif /* _VX_CACCT_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/cacct_int.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/cacct_int.h
---- linux-2.6.31.6/include/linux/vserver/cacct_int.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/cacct_int.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/cacct_int.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/cacct_int.h
+--- linux-2.6.32/include/linux/vserver/cacct_int.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/cacct_int.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,21 @@
+#ifndef _VX_CACCT_INT_H
+#define _VX_CACCT_INT_H
+
+#endif /* __KERNEL__ */
+#endif /* _VX_CACCT_INT_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/check.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/check.h
---- linux-2.6.31.6/include/linux/vserver/check.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/check.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/check.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/check.h
+--- linux-2.6.32/include/linux/vserver/check.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/check.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,89 @@
+#ifndef _VS_CHECK_H
+#define _VS_CHECK_H
+#define nx_weak_check(c, m) ((m) ? nx_check(c, m) : 1)
+
+#endif
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/context_cmd.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/context_cmd.h
---- linux-2.6.31.6/include/linux/vserver/context_cmd.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/context_cmd.h 2009-09-10 16:11:43.000000000 +0200
-@@ -0,0 +1,128 @@
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/context_cmd.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/context_cmd.h
+--- linux-2.6.32/include/linux/vserver/context_cmd.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/context_cmd.h 2009-12-03 20:04:56.000000000 +0100
+@@ -0,0 +1,145 @@
+#ifndef _VX_CONTEXT_CMD_H
+#define _VX_CONTEXT_CMD_H
+
+#endif /* __KERNEL__ */
+
+
++/* umask commands */
++
++#define VCMD_get_umask VC_CMD(FLAGS, 13, 0)
++#define VCMD_set_umask VC_CMD(FLAGS, 14, 0)
++
++struct vcmd_umask {
++ uint64_t umask;
++ uint64_t mask;
++};
++
++#ifdef __KERNEL__
++extern int vc_get_umask(struct vx_info *, void __user *);
++extern int vc_set_umask(struct vx_info *, void __user *);
++
++#endif /* __KERNEL__ */
++
++
+/* OOM badness */
+
+#define VCMD_get_badness VC_CMD(MEMCTRL, 5, 0)
+
+#endif /* __KERNEL__ */
+#endif /* _VX_CONTEXT_CMD_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/context.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/context.h
---- linux-2.6.31.6/include/linux/vserver/context.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/context.h 2009-10-03 01:55:20.000000000 +0200
-@@ -0,0 +1,182 @@
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/context.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/context.h
+--- linux-2.6.32/include/linux/vserver/context.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/context.h 2009-12-03 20:04:56.000000000 +0100
+@@ -0,0 +1,183 @@
+#ifndef _VX_CONTEXT_H
+#define _VX_CONTEXT_H
+
+#define VXC_SET_UTSNAME 0x00000001
+#define VXC_SET_RLIMIT 0x00000002
+#define VXC_FS_SECURITY 0x00000004
++#define VXC_TIOCSTI 0x00000010
+
+/* was VXC_RAW_ICMP 0x00000100 */
+#define VXC_SYSLOG 0x00001000
+ uint64_t vx_flags; /* context flags */
+ uint64_t vx_ccaps; /* context caps (vserver) */
+ kernel_cap_t vx_bcaps; /* bounding caps (system) */
-+ // kernel_cap_t vx_cap_bset; /* the guest's bset */
++ unsigned long vx_umask; /* unshare mask (guest) */
+
+ struct task_struct *vx_reaper; /* guest reaper process */
+ pid_t vx_initpid; /* PID of guest init */
+
+#endif /* __KERNEL__ */
+#endif /* _VX_CONTEXT_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/cvirt_cmd.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/cvirt_cmd.h
---- linux-2.6.31.6/include/linux/vserver/cvirt_cmd.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/cvirt_cmd.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/cvirt_cmd.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/cvirt_cmd.h
+--- linux-2.6.32/include/linux/vserver/cvirt_cmd.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/cvirt_cmd.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,53 @@
+#ifndef _VX_CVIRT_CMD_H
+#define _VX_CVIRT_CMD_H
+
+#endif /* __KERNEL__ */
+#endif /* _VX_CVIRT_CMD_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/cvirt_def.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/cvirt_def.h
---- linux-2.6.31.6/include/linux/vserver/cvirt_def.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/cvirt_def.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/cvirt_def.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/cvirt_def.h
+--- linux-2.6.32/include/linux/vserver/cvirt_def.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/cvirt_def.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,80 @@
+#ifndef _VX_CVIRT_DEF_H
+#define _VX_CVIRT_DEF_H
+#endif
+
+#endif /* _VX_CVIRT_DEF_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/cvirt.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/cvirt.h
---- linux-2.6.31.6/include/linux/vserver/cvirt.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/cvirt.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/cvirt.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/cvirt.h
+--- linux-2.6.32/include/linux/vserver/cvirt.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/cvirt.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,20 @@
+#ifndef _VX_CVIRT_H
+#define _VX_CVIRT_H
+
+#endif /* __KERNEL__ */
+#endif /* _VX_CVIRT_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/debug_cmd.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/debug_cmd.h
---- linux-2.6.31.6/include/linux/vserver/debug_cmd.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/debug_cmd.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/debug_cmd.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/debug_cmd.h
+--- linux-2.6.32/include/linux/vserver/debug_cmd.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/debug_cmd.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,58 @@
+#ifndef _VX_DEBUG_CMD_H
+#define _VX_DEBUG_CMD_H
+
+#endif /* __KERNEL__ */
+#endif /* _VX_DEBUG_CMD_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/debug.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/debug.h
---- linux-2.6.31.6/include/linux/vserver/debug.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/debug.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/debug.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/debug.h
+--- linux-2.6.32/include/linux/vserver/debug.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/debug.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,127 @@
+#ifndef _VX_DEBUG_H
+#define _VX_DEBUG_H
+
+
+#endif /* _VX_DEBUG_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/device_cmd.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/device_cmd.h
---- linux-2.6.31.6/include/linux/vserver/device_cmd.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/device_cmd.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/device_cmd.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/device_cmd.h
+--- linux-2.6.32/include/linux/vserver/device_cmd.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/device_cmd.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,44 @@
+#ifndef _VX_DEVICE_CMD_H
+#define _VX_DEVICE_CMD_H
+
+#endif /* __KERNEL__ */
+#endif /* _VX_DEVICE_CMD_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/device_def.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/device_def.h
---- linux-2.6.31.6/include/linux/vserver/device_def.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/device_def.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/device_def.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/device_def.h
+--- linux-2.6.32/include/linux/vserver/device_def.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/device_def.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,17 @@
+#ifndef _VX_DEVICE_DEF_H
+#define _VX_DEVICE_DEF_H
+};
+
+#endif /* _VX_DEVICE_DEF_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/device.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/device.h
---- linux-2.6.31.6/include/linux/vserver/device.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/device.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/device.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/device.h
+--- linux-2.6.32/include/linux/vserver/device.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/device.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,15 @@
+#ifndef _VX_DEVICE_H
+#define _VX_DEVICE_H
+#else /* _VX_DEVICE_H */
+#warning duplicate inclusion
+#endif /* _VX_DEVICE_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/dlimit_cmd.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/dlimit_cmd.h
---- linux-2.6.31.6/include/linux/vserver/dlimit_cmd.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/dlimit_cmd.h 2009-09-10 16:11:43.000000000 +0200
-@@ -0,0 +1,74 @@
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/dlimit_cmd.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/dlimit_cmd.h
+--- linux-2.6.32/include/linux/vserver/dlimit_cmd.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/dlimit_cmd.h 2009-12-03 20:04:56.000000000 +0100
+@@ -0,0 +1,109 @@
+#ifndef _VX_DLIMIT_CMD_H
+#define _VX_DLIMIT_CMD_H
+
+#define CDLIM_INFINITY ((uint32_t)~0UL)
+#define CDLIM_KEEP ((uint32_t)~1UL)
+
++#define DLIME_UNIT 0
++#define DLIME_KILO 1
++#define DLIME_MEGA 2
++#define DLIME_GIGA 3
++
++#define DLIMF_SHIFT 0x10
++
++#define DLIMS_USED 0
++#define DLIMS_TOTAL 2
++
++static inline
++uint64_t dlimit_space_32to64(uint32_t val, uint32_t flags, int shift)
++{
++ int exp = (flags & DLIMF_SHIFT) ?
++ (flags >> shift) & DLIME_GIGA : DLIME_KILO;
++ return val << (10LL * exp);
++}
++
++static inline
++uint32_t dlimit_space_64to32(uint64_t val, uint32_t *flags, int shift)
++{
++ int exp = 0;
++
++ if (*flags & DLIMF_SHIFT) {
++ while (val > (1LL << 32) && (exp < 3)) {
++ val >>= 10LL;
++ exp++;
++ }
++ *flags &= ~(DLIME_GIGA << shift);
++ *flags |= exp << shift;
++ } else
++ val >>= 10LL;
++ return val;
++}
++
+#ifdef __KERNEL__
+
+#ifdef CONFIG_COMPAT
+
+#endif /* __KERNEL__ */
+#endif /* _VX_DLIMIT_CMD_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/dlimit.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/dlimit.h
---- linux-2.6.31.6/include/linux/vserver/dlimit.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/dlimit.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/dlimit.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/dlimit.h
+--- linux-2.6.32/include/linux/vserver/dlimit.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/dlimit.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,54 @@
+#ifndef _VX_DLIMIT_H
+#define _VX_DLIMIT_H
+#else /* _VX_DLIMIT_H */
+#warning duplicate inclusion
+#endif /* _VX_DLIMIT_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/global.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/global.h
---- linux-2.6.31.6/include/linux/vserver/global.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/global.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/global.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/global.h
+--- linux-2.6.32/include/linux/vserver/global.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/global.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,19 @@
+#ifndef _VX_GLOBAL_H
+#define _VX_GLOBAL_H
+
+
+#endif /* _VX_GLOBAL_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/history.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/history.h
---- linux-2.6.31.6/include/linux/vserver/history.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/history.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/history.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/history.h
+--- linux-2.6.32/include/linux/vserver/history.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/history.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,197 @@
+#ifndef _VX_HISTORY_H
+#define _VX_HISTORY_H
+#endif /* CONFIG_VSERVER_HISTORY */
+
+#endif /* _VX_HISTORY_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/inode_cmd.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/inode_cmd.h
---- linux-2.6.31.6/include/linux/vserver/inode_cmd.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/inode_cmd.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/inode_cmd.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/inode_cmd.h
+--- linux-2.6.32/include/linux/vserver/inode_cmd.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/inode_cmd.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,59 @@
+#ifndef _VX_INODE_CMD_H
+#define _VX_INODE_CMD_H
+
+#endif /* __KERNEL__ */
+#endif /* _VX_INODE_CMD_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/inode.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/inode.h
---- linux-2.6.31.6/include/linux/vserver/inode.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/inode.h 2009-10-06 23:34:11.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/inode.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/inode.h
+--- linux-2.6.32/include/linux/vserver/inode.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/inode.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,39 @@
+#ifndef _VX_INODE_H
+#define _VX_INODE_H
+#else /* _VX_INODE_H */
+#warning duplicate inclusion
+#endif /* _VX_INODE_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/Kbuild linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/Kbuild
---- linux-2.6.31.6/include/linux/vserver/Kbuild 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/Kbuild 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/Kbuild linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/Kbuild
+--- linux-2.6.32/include/linux/vserver/Kbuild 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/Kbuild 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,8 @@
+
+unifdef-y += context_cmd.h network_cmd.h space_cmd.h \
+
+unifdef-y += switch.h network.h monitor.h inode.h device.h
+
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/limit_cmd.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/limit_cmd.h
---- linux-2.6.31.6/include/linux/vserver/limit_cmd.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/limit_cmd.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/limit_cmd.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/limit_cmd.h
+--- linux-2.6.32/include/linux/vserver/limit_cmd.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/limit_cmd.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,71 @@
+#ifndef _VX_LIMIT_CMD_H
+#define _VX_LIMIT_CMD_H
+
+#endif /* __KERNEL__ */
+#endif /* _VX_LIMIT_CMD_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/limit_def.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/limit_def.h
---- linux-2.6.31.6/include/linux/vserver/limit_def.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/limit_def.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/limit_def.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/limit_def.h
+--- linux-2.6.32/include/linux/vserver/limit_def.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/limit_def.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,47 @@
+#ifndef _VX_LIMIT_DEF_H
+#define _VX_LIMIT_DEF_H
+#endif
+
+#endif /* _VX_LIMIT_DEF_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/limit.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/limit.h
---- linux-2.6.31.6/include/linux/vserver/limit.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/limit.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/limit.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/limit.h
+--- linux-2.6.32/include/linux/vserver/limit.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/limit.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,70 @@
+#ifndef _VX_LIMIT_H
+#define _VX_LIMIT_H
+
+#endif /* __KERNEL__ */
+#endif /* _VX_LIMIT_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/limit_int.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/limit_int.h
---- linux-2.6.31.6/include/linux/vserver/limit_int.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/limit_int.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/limit_int.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/limit_int.h
+--- linux-2.6.32/include/linux/vserver/limit_int.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/limit_int.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,198 @@
+#ifndef _VX_LIMIT_INT_H
+#define _VX_LIMIT_INT_H
+
+#endif /* __KERNEL__ */
+#endif /* _VX_LIMIT_INT_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/monitor.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/monitor.h
---- linux-2.6.31.6/include/linux/vserver/monitor.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/monitor.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/monitor.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/monitor.h
+--- linux-2.6.32/include/linux/vserver/monitor.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/monitor.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,96 @@
+#ifndef _VX_MONITOR_H
+#define _VX_MONITOR_H
+
+
+#endif /* _VX_MONITOR_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/network_cmd.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/network_cmd.h
---- linux-2.6.31.6/include/linux/vserver/network_cmd.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/network_cmd.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/network_cmd.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/network_cmd.h
+--- linux-2.6.32/include/linux/vserver/network_cmd.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/network_cmd.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,150 @@
+#ifndef _VX_NETWORK_CMD_H
+#define _VX_NETWORK_CMD_H
+
+#endif /* __KERNEL__ */
+#endif /* _VX_CONTEXT_CMD_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/network.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/network.h
---- linux-2.6.31.6/include/linux/vserver/network.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/network.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/network.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/network.h
+--- linux-2.6.32/include/linux/vserver/network.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/network.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,146 @@
+#ifndef _VX_NETWORK_H
+#define _VX_NETWORK_H
+
+#endif /* __KERNEL__ */
+#endif /* _VX_NETWORK_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/percpu.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/percpu.h
---- linux-2.6.31.6/include/linux/vserver/percpu.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/percpu.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/percpu.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/percpu.h
+--- linux-2.6.32/include/linux/vserver/percpu.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/percpu.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,14 @@
+#ifndef _VX_PERCPU_H
+#define _VX_PERCPU_H
+#define PERCPU_PERCTX (sizeof(struct _vx_percpu))
+
+#endif /* _VX_PERCPU_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/pid.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/pid.h
---- linux-2.6.31.6/include/linux/vserver/pid.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/pid.h 2009-11-05 04:17:16.000000000 +0100
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/pid.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/pid.h
+--- linux-2.6.32/include/linux/vserver/pid.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/pid.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,51 @@
+#ifndef _VSERVER_PID_H
+#define _VSERVER_PID_H
+}
+
+#endif
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/sched_cmd.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/sched_cmd.h
---- linux-2.6.31.6/include/linux/vserver/sched_cmd.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/sched_cmd.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/sched_cmd.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/sched_cmd.h
+--- linux-2.6.32/include/linux/vserver/sched_cmd.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/sched_cmd.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,108 @@
+#ifndef _VX_SCHED_CMD_H
+#define _VX_SCHED_CMD_H
+
+#endif /* __KERNEL__ */
+#endif /* _VX_SCHED_CMD_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/sched_def.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/sched_def.h
---- linux-2.6.31.6/include/linux/vserver/sched_def.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/sched_def.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/sched_def.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/sched_def.h
+--- linux-2.6.32/include/linux/vserver/sched_def.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/sched_def.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,68 @@
+#ifndef _VX_SCHED_DEF_H
+#define _VX_SCHED_DEF_H
+#endif
+
+#endif /* _VX_SCHED_DEF_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/sched.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/sched.h
---- linux-2.6.31.6/include/linux/vserver/sched.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/sched.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/sched.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/sched.h
+--- linux-2.6.32/include/linux/vserver/sched.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/sched.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,26 @@
+#ifndef _VX_SCHED_H
+#define _VX_SCHED_H
+#else /* _VX_SCHED_H */
+#warning duplicate inclusion
+#endif /* _VX_SCHED_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/signal_cmd.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/signal_cmd.h
---- linux-2.6.31.6/include/linux/vserver/signal_cmd.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/signal_cmd.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/signal_cmd.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/signal_cmd.h
+--- linux-2.6.32/include/linux/vserver/signal_cmd.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/signal_cmd.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,43 @@
+#ifndef _VX_SIGNAL_CMD_H
+#define _VX_SIGNAL_CMD_H
+
+#endif /* __KERNEL__ */
+#endif /* _VX_SIGNAL_CMD_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/signal.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/signal.h
---- linux-2.6.31.6/include/linux/vserver/signal.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/signal.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/signal.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/signal.h
+--- linux-2.6.32/include/linux/vserver/signal.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/signal.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,14 @@
+#ifndef _VX_SIGNAL_H
+#define _VX_SIGNAL_H
+#else /* _VX_SIGNAL_H */
+#warning duplicate inclusion
+#endif /* _VX_SIGNAL_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/space_cmd.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/space_cmd.h
---- linux-2.6.31.6/include/linux/vserver/space_cmd.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/space_cmd.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/space_cmd.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/space_cmd.h
+--- linux-2.6.32/include/linux/vserver/space_cmd.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/space_cmd.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,38 @@
+#ifndef _VX_SPACE_CMD_H
+#define _VX_SPACE_CMD_H
+
+#endif /* __KERNEL__ */
+#endif /* _VX_SPACE_CMD_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/space.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/space.h
---- linux-2.6.31.6/include/linux/vserver/space.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/space.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/space.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/space.h
+--- linux-2.6.32/include/linux/vserver/space.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/space.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,12 @@
+#ifndef _VX_SPACE_H
+#define _VX_SPACE_H
+#else /* _VX_SPACE_H */
+#warning duplicate inclusion
+#endif /* _VX_SPACE_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/switch.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/switch.h
---- linux-2.6.31.6/include/linux/vserver/switch.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/switch.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/switch.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/switch.h
+--- linux-2.6.32/include/linux/vserver/switch.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/switch.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,98 @@
+#ifndef _VX_SWITCH_H
+#define _VX_SWITCH_H
+
+#endif /* _VX_SWITCH_H */
+
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/tag_cmd.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/tag_cmd.h
---- linux-2.6.31.6/include/linux/vserver/tag_cmd.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/tag_cmd.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/tag_cmd.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/tag_cmd.h
+--- linux-2.6.32/include/linux/vserver/tag_cmd.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/tag_cmd.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,22 @@
+#ifndef _VX_TAG_CMD_H
+#define _VX_TAG_CMD_H
+
+#endif /* __KERNEL__ */
+#endif /* _VX_TAG_CMD_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vserver/tag.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/tag.h
---- linux-2.6.31.6/include/linux/vserver/tag.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/tag.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vserver/tag.h linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/tag.h
+--- linux-2.6.32/include/linux/vserver/tag.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vserver/tag.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,143 @@
+#ifndef _DX_TAG_H
+#define _DX_TAG_H
+#endif
+
+#endif /* _DX_TAG_H */
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vs_inet6.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_inet6.h
---- linux-2.6.31.6/include/linux/vs_inet6.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_inet6.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vs_inet6.h linux-2.6.32-vs2.3.0.36.26/include/linux/vs_inet6.h
+--- linux-2.6.32/include/linux/vs_inet6.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vs_inet6.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,246 @@
+#ifndef _VS_INET6_H
+#define _VS_INET6_H
+#else
+#warning duplicate inclusion
+#endif
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vs_inet.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_inet.h
---- linux-2.6.31.6/include/linux/vs_inet.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_inet.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vs_inet.h linux-2.6.32-vs2.3.0.36.26/include/linux/vs_inet.h
+--- linux-2.6.32/include/linux/vs_inet.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vs_inet.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,342 @@
+#ifndef _VS_INET_H
+#define _VS_INET_H
+#else
+// #warning duplicate inclusion
+#endif
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vs_limit.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_limit.h
---- linux-2.6.31.6/include/linux/vs_limit.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_limit.h 2009-11-05 04:14:38.000000000 +0100
+diff -NurpP --minimal linux-2.6.32/include/linux/vs_limit.h linux-2.6.32-vs2.3.0.36.26/include/linux/vs_limit.h
+--- linux-2.6.32/include/linux/vs_limit.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vs_limit.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,140 @@
+#ifndef _VS_LIMIT_H
+#define _VS_LIMIT_H
+#else
+#warning duplicate inclusion
+#endif
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vs_memory.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_memory.h
---- linux-2.6.31.6/include/linux/vs_memory.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_memory.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vs_memory.h linux-2.6.32-vs2.3.0.36.26/include/linux/vs_memory.h
+--- linux-2.6.32/include/linux/vs_memory.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vs_memory.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,159 @@
+#ifndef _VS_MEMORY_H
+#define _VS_MEMORY_H
+#else
+#warning duplicate inclusion
+#endif
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vs_network.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_network.h
---- linux-2.6.31.6/include/linux/vs_network.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_network.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vs_network.h linux-2.6.32-vs2.3.0.36.26/include/linux/vs_network.h
+--- linux-2.6.32/include/linux/vs_network.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vs_network.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,169 @@
+#ifndef _NX_VS_NETWORK_H
+#define _NX_VS_NETWORK_H
+#else
+#warning duplicate inclusion
+#endif
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vs_pid.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_pid.h
---- linux-2.6.31.6/include/linux/vs_pid.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_pid.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vs_pid.h linux-2.6.32-vs2.3.0.36.26/include/linux/vs_pid.h
+--- linux-2.6.32/include/linux/vs_pid.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vs_pid.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,95 @@
+#ifndef _VS_PID_H
+#define _VS_PID_H
+#else
+#warning duplicate inclusion
+#endif
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vs_sched.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_sched.h
---- linux-2.6.31.6/include/linux/vs_sched.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_sched.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vs_sched.h linux-2.6.32-vs2.3.0.36.26/include/linux/vs_sched.h
+--- linux-2.6.32/include/linux/vs_sched.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vs_sched.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,110 @@
+#ifndef _VS_SCHED_H
+#define _VS_SCHED_H
+#else
+#warning duplicate inclusion
+#endif
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vs_socket.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_socket.h
---- linux-2.6.31.6/include/linux/vs_socket.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_socket.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vs_socket.h linux-2.6.32-vs2.3.0.36.26/include/linux/vs_socket.h
+--- linux-2.6.32/include/linux/vs_socket.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vs_socket.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,67 @@
+#ifndef _VS_SOCKET_H
+#define _VS_SOCKET_H
+#else
+#warning duplicate inclusion
+#endif
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vs_tag.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_tag.h
---- linux-2.6.31.6/include/linux/vs_tag.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_tag.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vs_tag.h linux-2.6.32-vs2.3.0.36.26/include/linux/vs_tag.h
+--- linux-2.6.32/include/linux/vs_tag.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vs_tag.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,47 @@
+#ifndef _VS_TAG_H
+#define _VS_TAG_H
+}
+
+struct inode;
-+int dx_permission(struct inode *inode, int mask);
++int dx_permission(const struct inode *inode, int mask);
+
+
+#else
+#warning duplicate inclusion
+#endif
-diff -NurpP --minimal linux-2.6.31.6/include/linux/vs_time.h linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_time.h
---- linux-2.6.31.6/include/linux/vs_time.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/linux/vs_time.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/linux/vs_time.h linux-2.6.32-vs2.3.0.36.26/include/linux/vs_time.h
+--- linux-2.6.32/include/linux/vs_time.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/linux/vs_time.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,19 @@
+#ifndef _VS_TIME_H
+#define _VS_TIME_H
+#else
+#warning duplicate inclusion
+#endif
-diff -NurpP --minimal linux-2.6.31.6/include/net/addrconf.h linux-2.6.31.6-vs2.3.0.36.24/include/net/addrconf.h
---- linux-2.6.31.6/include/net/addrconf.h 2009-06-11 17:13:18.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/net/addrconf.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/net/addrconf.h linux-2.6.32-vs2.3.0.36.26/include/net/addrconf.h
+--- linux-2.6.32/include/net/addrconf.h 2009-12-03 20:02:57.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/net/addrconf.h 2009-12-03 20:04:56.000000000 +0100
@@ -84,7 +84,8 @@ extern int ipv6_dev_get_saddr(struct n
struct net_device *dev,
const struct in6_addr *daddr,
extern int ipv6_get_lladdr(struct net_device *dev,
struct in6_addr *addr,
unsigned char banned_flags);
-diff -NurpP --minimal linux-2.6.31.6/include/net/af_unix.h linux-2.6.31.6-vs2.3.0.36.24/include/net/af_unix.h
---- linux-2.6.31.6/include/net/af_unix.h 2008-12-25 00:26:37.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/net/af_unix.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/net/af_unix.h linux-2.6.32-vs2.3.0.36.26/include/net/af_unix.h
+--- linux-2.6.32/include/net/af_unix.h 2008-12-25 00:26:37.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/net/af_unix.h 2009-12-03 20:04:56.000000000 +0100
@@ -4,6 +4,7 @@
#include <linux/socket.h>
#include <linux/un.h>
#include <net/sock.h>
extern void unix_inflight(struct file *fp);
-diff -NurpP --minimal linux-2.6.31.6/include/net/inet_timewait_sock.h linux-2.6.31.6-vs2.3.0.36.24/include/net/inet_timewait_sock.h
---- linux-2.6.31.6/include/net/inet_timewait_sock.h 2009-09-10 15:26:27.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/net/inet_timewait_sock.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/net/inet_timewait_sock.h linux-2.6.32-vs2.3.0.36.26/include/net/inet_timewait_sock.h
+--- linux-2.6.32/include/net/inet_timewait_sock.h 2009-12-03 20:02:57.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/net/inet_timewait_sock.h 2009-12-03 20:04:56.000000000 +0100
@@ -117,6 +117,10 @@ struct inet_timewait_sock {
#define tw_hash __tw_common.skc_hash
#define tw_prot __tw_common.skc_prot
int tw_timeout;
volatile unsigned char tw_substate;
/* 3 bits hole, try to pack */
-diff -NurpP --minimal linux-2.6.31.6/include/net/route.h linux-2.6.31.6-vs2.3.0.36.24/include/net/route.h
---- linux-2.6.31.6/include/net/route.h 2009-09-10 15:26:27.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/net/route.h 2009-11-05 03:48:31.000000000 +0100
+diff -NurpP --minimal linux-2.6.32/include/net/route.h linux-2.6.32-vs2.3.0.36.26/include/net/route.h
+--- linux-2.6.32/include/net/route.h 2009-09-10 15:26:27.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/include/net/route.h 2009-12-03 20:04:56.000000000 +0100
@@ -135,6 +135,9 @@ static inline void ip_rt_put(struct rtab
dst_release(&rt->u.dst);
}
err = __ip_route_output_key(net, rp, &fl);
if (err)
return err;
-diff -NurpP --minimal linux-2.6.31.6/include/net/sock.h linux-2.6.31.6-vs2.3.0.36.24/include/net/sock.h
---- linux-2.6.31.6/include/net/sock.h 2009-09-10 15:26:27.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/include/net/sock.h 2009-09-10 17:15:39.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/include/net/sock.h linux-2.6.32-vs2.3.0.36.26/include/net/sock.h
+--- linux-2.6.32/include/net/sock.h 2009-12-03 20:02:57.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/include/net/sock.h 2009-12-03 20:04:56.000000000 +0100
@@ -139,6 +139,10 @@ struct sock_common {
#ifdef CONFIG_NET_NS
struct net *skc_net;
+#define sk_nid __sk_common.skc_nid
+#define sk_nx_info __sk_common.skc_nx_info
kmemcheck_bitfield_begin(flags);
- unsigned char sk_shutdown : 2,
- sk_no_check : 2,
-diff -NurpP --minimal linux-2.6.31.6/init/Kconfig linux-2.6.31.6-vs2.3.0.36.24/init/Kconfig
---- linux-2.6.31.6/init/Kconfig 2009-09-10 15:26:27.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/init/Kconfig 2009-10-06 04:38:47.000000000 +0200
-@@ -492,6 +492,19 @@ config CGROUP_SCHED
+ unsigned int sk_shutdown : 2,
+ sk_no_check : 2,
+diff -NurpP --minimal linux-2.6.32/init/Kconfig linux-2.6.32-vs2.3.0.36.26/init/Kconfig
+--- linux-2.6.32/init/Kconfig 2009-12-03 20:02:57.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/init/Kconfig 2009-12-03 20:04:56.000000000 +0100
+@@ -477,6 +477,19 @@ config CGROUP_SCHED
endchoice
menuconfig CGROUPS
boolean "Control Group support"
help
-diff -NurpP --minimal linux-2.6.31.6/init/main.c linux-2.6.31.6-vs2.3.0.36.24/init/main.c
---- linux-2.6.31.6/init/main.c 2009-09-10 15:26:27.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/init/main.c 2009-09-10 16:11:43.000000000 +0200
-@@ -69,6 +69,7 @@
- #include <linux/kmemcheck.h>
- #include <linux/kmemtrace.h>
+diff -NurpP --minimal linux-2.6.32/init/main.c linux-2.6.32-vs2.3.0.36.26/init/main.c
+--- linux-2.6.32/init/main.c 2009-12-03 20:02:57.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/init/main.c 2009-12-03 20:04:56.000000000 +0100
+@@ -70,6 +70,7 @@
+ #include <linux/sfi.h>
+ #include <linux/shmem_fs.h>
#include <trace/boot.h>
+#include <linux/vserver/percpu.h>
#include <asm/io.h>
#include <asm/bugs.h>
-@@ -381,12 +382,14 @@ EXPORT_SYMBOL(__per_cpu_offset);
-
- static void __init setup_per_cpu_areas(void)
- {
-- unsigned long size, i;
-+ unsigned long size, vspc, i;
- char *ptr;
- unsigned long nr_possible_cpus = num_possible_cpus();
-
-+ vspc = PERCPU_PERCTX * CONFIG_VSERVER_CONTEXTS;
-+
- /* Copy section for each CPU (we discard the original) */
-- size = ALIGN(PERCPU_ENOUGH_ROOM, PAGE_SIZE);
-+ size = ALIGN(PERCPU_ENOUGH_ROOM + vspc, PAGE_SIZE);
- ptr = alloc_bootmem_pages(size * nr_possible_cpus);
-
- for_each_possible_cpu(i) {
-diff -NurpP --minimal linux-2.6.31.6/ipc/mqueue.c linux-2.6.31.6-vs2.3.0.36.24/ipc/mqueue.c
---- linux-2.6.31.6/ipc/mqueue.c 2009-09-10 15:26:27.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/ipc/mqueue.c 2009-09-10 16:31:20.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/ipc/mqueue.c linux-2.6.32-vs2.3.0.36.26/ipc/mqueue.c
+--- linux-2.6.32/ipc/mqueue.c 2009-12-03 20:02:57.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/ipc/mqueue.c 2009-12-03 20:04:56.000000000 +0100
@@ -33,6 +33,8 @@
#include <linux/pid.h>
#include <linux/ipc_namespace.h>
free_uid(user);
}
if (ipc_ns)
-diff -NurpP --minimal linux-2.6.31.6/ipc/msg.c linux-2.6.31.6-vs2.3.0.36.24/ipc/msg.c
---- linux-2.6.31.6/ipc/msg.c 2009-03-24 14:22:44.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/ipc/msg.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/ipc/msg.c linux-2.6.32-vs2.3.0.36.26/ipc/msg.c
+--- linux-2.6.32/ipc/msg.c 2009-03-24 14:22:44.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/ipc/msg.c 2009-12-03 20:04:56.000000000 +0100
@@ -38,6 +38,7 @@
#include <linux/rwsem.h>
#include <linux/nsproxy.h>
msq->q_perm.security = NULL;
retval = security_msg_queue_alloc(msq);
-diff -NurpP --minimal linux-2.6.31.6/ipc/namespace.c linux-2.6.31.6-vs2.3.0.36.24/ipc/namespace.c
---- linux-2.6.31.6/ipc/namespace.c 2009-09-10 15:26:27.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/ipc/namespace.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/ipc/namespace.c linux-2.6.32-vs2.3.0.36.26/ipc/namespace.c
+--- linux-2.6.32/ipc/namespace.c 2009-09-10 15:26:27.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/ipc/namespace.c 2009-12-03 20:04:56.000000000 +0100
@@ -11,6 +11,8 @@
#include <linux/slab.h>
#include <linux/fs.h>
#include "util.h"
-diff -NurpP --minimal linux-2.6.31.6/ipc/sem.c linux-2.6.31.6-vs2.3.0.36.24/ipc/sem.c
---- linux-2.6.31.6/ipc/sem.c 2009-09-10 15:26:27.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/ipc/sem.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/ipc/sem.c linux-2.6.32-vs2.3.0.36.26/ipc/sem.c
+--- linux-2.6.32/ipc/sem.c 2009-09-10 15:26:27.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/ipc/sem.c 2009-12-03 20:04:56.000000000 +0100
@@ -83,6 +83,8 @@
#include <linux/rwsem.h>
#include <linux/nsproxy.h>
security_sem_free(sma);
ipc_rcu_putref(sma);
}
-diff -NurpP --minimal linux-2.6.31.6/ipc/shm.c linux-2.6.31.6-vs2.3.0.36.24/ipc/shm.c
---- linux-2.6.31.6/ipc/shm.c 2009-11-12 12:10:11.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/ipc/shm.c 2009-11-05 04:17:37.000000000 +0100
+diff -NurpP --minimal linux-2.6.32/ipc/shm.c linux-2.6.32-vs2.3.0.36.26/ipc/shm.c
+--- linux-2.6.32/ipc/shm.c 2009-12-03 20:02:57.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/ipc/shm.c 2009-12-03 20:04:56.000000000 +0100
@@ -40,6 +40,8 @@
#include <linux/mount.h>
#include <linux/ipc_namespace.h>
return error;
no_id:
-diff -NurpP --minimal linux-2.6.31.6/kernel/capability.c linux-2.6.31.6-vs2.3.0.36.24/kernel/capability.c
---- linux-2.6.31.6/kernel/capability.c 2009-03-24 14:22:44.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/capability.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/capability.c linux-2.6.32-vs2.3.0.36.26/kernel/capability.c
+--- linux-2.6.32/kernel/capability.c 2009-03-24 14:22:44.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/capability.c 2009-12-03 20:04:56.000000000 +0100
@@ -14,6 +14,7 @@
#include <linux/security.h>
#include <linux/syscalls.h>
if (unlikely(!cap_valid(cap))) {
printk(KERN_CRIT "capable() called with invalid cap=%u\n", cap);
BUG();
-diff -NurpP --minimal linux-2.6.31.6/kernel/compat.c linux-2.6.31.6-vs2.3.0.36.24/kernel/compat.c
---- linux-2.6.31.6/kernel/compat.c 2009-09-10 15:26:27.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/compat.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/compat.c linux-2.6.32-vs2.3.0.36.26/kernel/compat.c
+--- linux-2.6.32/kernel/compat.c 2009-09-10 15:26:27.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/kernel/compat.c 2009-12-03 20:04:56.000000000 +0100
@@ -902,7 +902,7 @@ asmlinkage long compat_sys_time(compat_t
compat_time_t i;
struct timeval tv;
return 0;
}
-diff -NurpP --minimal linux-2.6.31.6/kernel/exit.c linux-2.6.31.6-vs2.3.0.36.24/kernel/exit.c
---- linux-2.6.31.6/kernel/exit.c 2009-11-12 12:10:11.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/exit.c 2009-10-15 03:49:19.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/exit.c linux-2.6.32-vs2.3.0.36.26/kernel/exit.c
+--- linux-2.6.32/kernel/exit.c 2009-12-03 20:02:57.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/exit.c 2009-12-03 20:04:56.000000000 +0100
@@ -48,6 +48,10 @@
#include <linux/fs_struct.h>
#include <linux/init_task.h>
- #include <linux/perf_counter.h>
+ #include <linux/perf_event.h>
+#include <linux/vs_limit.h>
+#include <linux/vs_context.h>
+#include <linux/vs_network.h>
}
}
}
-@@ -1007,10 +1013,15 @@ NORET_TYPE void do_exit(long code)
- if (tsk->splice_pipe)
- __free_pipe_info(tsk->splice_pipe);
+@@ -1011,11 +1017,16 @@ NORET_TYPE void do_exit(long code)
+
+ validate_creds_for_do_exit(tsk);
+ /* needs to stay after exit_notify() */
+ exit_vx_info(tsk, code);
+ exit_nx_info(tsk);
+
preempt_disable();
+ exit_rcu();
/* causes final put_task_struct in finish_task_switch(). */
tsk->state = TASK_DEAD;
schedule();
BUG();
/* Avoid "noreturn function does return". */
for (;;)
-diff -NurpP --minimal linux-2.6.31.6/kernel/fork.c linux-2.6.31.6-vs2.3.0.36.24/kernel/fork.c
---- linux-2.6.31.6/kernel/fork.c 2009-11-12 12:10:11.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/fork.c 2009-11-05 04:17:43.000000000 +0100
-@@ -62,6 +62,10 @@
- #include <linux/fs_struct.h>
+diff -NurpP --minimal linux-2.6.32/kernel/fork.c linux-2.6.32-vs2.3.0.36.26/kernel/fork.c
+--- linux-2.6.32/kernel/fork.c 2009-12-03 20:02:57.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/fork.c 2009-12-03 20:04:56.000000000 +0100
+@@ -64,6 +64,10 @@
#include <linux/magic.h>
- #include <linux/perf_counter.h>
+ #include <linux/perf_event.h>
+ #include <linux/posix-timers.h>
+#include <linux/vs_context.h>
+#include <linux/vs_network.h>
+#include <linux/vs_limit.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
-@@ -141,6 +145,8 @@ void free_task(struct task_struct *tsk)
- prop_local_destroy_single(&tsk->dirties);
+@@ -151,6 +155,8 @@ void free_task(struct task_struct *tsk)
+ account_kernel_stack(tsk->stack, -1);
free_thread_info(tsk->stack);
rt_mutex_debug_task_free(tsk);
+ clr_vx_info(&tsk->vx_info);
ftrace_graph_exit_task(tsk);
free_task_struct(tsk);
}
-@@ -284,6 +290,8 @@ static int dup_mmap(struct mm_struct *mm
+@@ -296,6 +302,8 @@ static int dup_mmap(struct mm_struct *mm
mm->free_area_cache = oldmm->mmap_base;
mm->cached_hole_size = ~0UL;
mm->map_count = 0;
cpumask_clear(mm_cpumask(mm));
mm->mm_rb = RB_ROOT;
rb_link = &mm->mm_rb.rb_node;
-@@ -295,7 +303,7 @@ static int dup_mmap(struct mm_struct *mm
+@@ -310,7 +318,7 @@ static int dup_mmap(struct mm_struct *mm
if (mpnt->vm_flags & VM_DONTCOPY) {
long pages = vma_pages(mpnt);
vm_stat_account(mm, mpnt->vm_flags, mpnt->vm_file,
-pages);
continue;
-@@ -428,8 +436,8 @@ static struct mm_struct * mm_init(struct
- mm->flags = (current->mm) ? current->mm->flags : default_dump_filter;
+@@ -452,8 +460,8 @@ static struct mm_struct * mm_init(struct
+ (current->mm->flags & MMF_INIT_MASK) : default_dump_filter;
mm->core_state = NULL;
mm->nr_ptes = 0;
- set_mm_counter(mm, file_rss, 0);
+ __set_mm_counter(mm, file_rss, 0);
+ __set_mm_counter(mm, anon_rss, 0);
spin_lock_init(&mm->page_table_lock);
- spin_lock_init(&mm->ioctx_lock);
- INIT_HLIST_HEAD(&mm->ioctx_list);
-@@ -440,6 +448,7 @@ static struct mm_struct * mm_init(struct
+ mm->free_area_cache = TASK_UNMAPPED_BASE;
+ mm->cached_hole_size = ~0UL;
+@@ -463,6 +471,7 @@ static struct mm_struct * mm_init(struct
if (likely(!mm_alloc_pgd(mm))) {
mm->def_flags = 0;
mmu_notifier_mm_init(mm);
return mm;
}
-@@ -473,6 +482,7 @@ void __mmdrop(struct mm_struct *mm)
+@@ -496,6 +505,7 @@ void __mmdrop(struct mm_struct *mm)
mm_free_pgd(mm);
destroy_context(mm);
mmu_notifier_mm_destroy(mm);
free_mm(mm);
}
EXPORT_SYMBOL_GPL(__mmdrop);
-@@ -605,6 +615,7 @@ struct mm_struct *dup_mm(struct task_str
+@@ -631,6 +641,7 @@ struct mm_struct *dup_mm(struct task_str
goto fail_nomem;
memcpy(mm, oldmm, sizeof(*mm));
/* Initializing for Swap token stuff */
mm->token_priority = 0;
-@@ -638,6 +649,7 @@ fail_nocontext:
+@@ -669,6 +680,7 @@ fail_nocontext:
* If init_new_context() failed, we cannot use mmput() to free the mm
* because it calls destroy_context()
*/
mm_free_pgd(mm);
free_mm(mm);
return NULL;
-@@ -946,6 +958,8 @@ static struct task_struct *copy_process(
+@@ -980,6 +992,8 @@ static struct task_struct *copy_process(
int retval;
struct task_struct *p;
int cgroup_callbacks_done = 0;
if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
return ERR_PTR(-EINVAL);
-@@ -982,12 +996,28 @@ static struct task_struct *copy_process(
+@@ -1026,12 +1040,28 @@ static struct task_struct *copy_process(
DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled);
DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled);
#endif
}
retval = copy_creds(p, clone_flags);
-@@ -1260,6 +1290,18 @@ static struct task_struct *copy_process(
+@@ -1300,6 +1330,18 @@ static struct task_struct *copy_process(
total_forks++;
spin_unlock(¤t->sighand->siglock);
write_unlock_irq(&tasklist_lock);
proc_fork_connector(p);
cgroup_post_fork(p);
-@@ -1305,6 +1347,9 @@ bad_fork_cleanup_count:
+@@ -1341,6 +1383,9 @@ bad_fork_cleanup_cgroup:
+ bad_fork_cleanup_count:
atomic_dec(&p->cred->user->processes);
- put_cred(p->real_cred);
- put_cred(p->cred);
+ exit_creds(p);
+bad_fork_cleanup_vm:
+ if (p->mm && !(clone_flags & CLONE_VM))
+ vx_pages_sub(p->vx_info, RLIMIT_AS, p->mm->total_vm);
bad_fork_free:
free_task(p);
fork_out:
-diff -NurpP --minimal linux-2.6.31.6/kernel/kthread.c linux-2.6.31.6-vs2.3.0.36.24/kernel/kthread.c
---- linux-2.6.31.6/kernel/kthread.c 2009-09-10 15:26:28.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/kthread.c 2009-09-10 16:43:27.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/kthread.c linux-2.6.32-vs2.3.0.36.26/kernel/kthread.c
+--- linux-2.6.32/kernel/kthread.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/kthread.c 2009-12-03 20:04:56.000000000 +0100
@@ -14,6 +14,7 @@
#include <linux/file.h>
#include <linux/module.h>
+#include <linux/vs_pid.h>
#include <trace/events/sched.h>
- #define KTHREAD_NICE_LEVEL (-5)
-diff -NurpP --minimal linux-2.6.31.6/kernel/Makefile linux-2.6.31.6-vs2.3.0.36.24/kernel/Makefile
---- linux-2.6.31.6/kernel/Makefile 2009-09-10 15:26:27.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/Makefile 2009-09-10 16:11:43.000000000 +0200
+ static DEFINE_SPINLOCK(kthread_create_lock);
+diff -NurpP --minimal linux-2.6.32/kernel/Makefile linux-2.6.32-vs2.3.0.36.26/kernel/Makefile
+--- linux-2.6.32/kernel/Makefile 2009-12-03 20:02:57.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/Makefile 2009-12-03 20:04:56.000000000 +0100
@@ -23,6 +23,7 @@ CFLAGS_REMOVE_cgroup-debug.o = -pg
CFLAGS_REMOVE_sched_clock.o = -pg
endif
obj-$(CONFIG_FREEZER) += freezer.o
obj-$(CONFIG_PROFILING) += profile.o
obj-$(CONFIG_SYSCTL_SYSCALL_CHECK) += sysctl_check.o
-diff -NurpP --minimal linux-2.6.31.6/kernel/nsproxy.c linux-2.6.31.6-vs2.3.0.36.24/kernel/nsproxy.c
---- linux-2.6.31.6/kernel/nsproxy.c 2009-09-10 15:26:28.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/nsproxy.c 2009-09-10 17:37:49.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/nsproxy.c linux-2.6.32-vs2.3.0.36.26/kernel/nsproxy.c
+--- linux-2.6.32/kernel/nsproxy.c 2009-09-10 15:26:28.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/kernel/nsproxy.c 2009-12-03 20:04:56.000000000 +0100
@@ -19,6 +19,8 @@
#include <linux/mnt_namespace.h>
#include <linux/utsname.h>
return 0;
- if (!capable(CAP_SYS_ADMIN)) {
-+ if (!vx_capable(CAP_SYS_ADMIN, VXC_NAMESPACE)) {
++ if (!vx_can_unshare(CAP_SYS_ADMIN, flags)) {
err = -EPERM;
goto out;
}
return 0;
- if (!capable(CAP_SYS_ADMIN))
-+ if (!vx_capable(CAP_SYS_ADMIN, VXC_NAMESPACE))
++ if (!vx_can_unshare(CAP_SYS_ADMIN, unshare_flags))
return -EPERM;
*new_nsp = create_new_namespaces(unshare_flags, current,
-diff -NurpP --minimal linux-2.6.31.6/kernel/pid.c linux-2.6.31.6-vs2.3.0.36.24/kernel/pid.c
---- linux-2.6.31.6/kernel/pid.c 2009-09-10 15:26:28.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/pid.c 2009-09-10 16:36:49.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/pid.c linux-2.6.32-vs2.3.0.36.26/kernel/pid.c
+--- linux-2.6.32/kernel/pid.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/pid.c 2009-12-03 20:04:56.000000000 +0100
@@ -36,6 +36,7 @@
#include <linux/pid_namespace.h>
#include <linux/init_task.h>
pid_t pid_vnr(struct pid *pid)
{
return pid_nr_ns(pid, current->nsproxy->pid_ns);
-diff -NurpP --minimal linux-2.6.31.6/kernel/pid_namespace.c linux-2.6.31.6-vs2.3.0.36.24/kernel/pid_namespace.c
---- linux-2.6.31.6/kernel/pid_namespace.c 2009-09-10 15:26:28.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/pid_namespace.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/pid_namespace.c linux-2.6.32-vs2.3.0.36.26/kernel/pid_namespace.c
+--- linux-2.6.32/kernel/pid_namespace.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/pid_namespace.c 2009-12-03 20:04:56.000000000 +0100
@@ -13,6 +13,7 @@
#include <linux/syscalls.h>
#include <linux/err.h>
kmem_cache_free(pid_ns_cachep, ns);
}
-diff -NurpP --minimal linux-2.6.31.6/kernel/posix-timers.c linux-2.6.31.6-vs2.3.0.36.24/kernel/posix-timers.c
---- linux-2.6.31.6/kernel/posix-timers.c 2009-09-10 15:26:28.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/posix-timers.c 2009-10-24 23:47:04.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/posix-timers.c linux-2.6.32-vs2.3.0.36.26/kernel/posix-timers.c
+--- linux-2.6.32/kernel/posix-timers.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/posix-timers.c 2009-12-03 20:04:56.000000000 +0100
@@ -46,6 +46,7 @@
#include <linux/wait.h>
#include <linux/workqueue.h>
/*
* Management arrays for POSIX timers. Timers are kept in slab memory
-@@ -328,6 +329,7 @@ int posix_timer_event(struct k_itimer *t
+@@ -363,6 +364,7 @@ int posix_timer_event(struct k_itimer *t
{
struct task_struct *task;
int shared, ret = -1;
/*
* FIXME: if ->sigq is queued we can race with
* dequeue_signal()->do_schedule_next_timer().
-@@ -344,10 +346,18 @@ int posix_timer_event(struct k_itimer *t
+@@ -379,10 +381,18 @@ int posix_timer_event(struct k_itimer *t
rcu_read_lock();
task = pid_task(timr->it_pid, PIDTYPE_PID);
if (task) {
/* If we failed to send the signal the timer stops. */
return ret > 0;
}
-diff -NurpP --minimal linux-2.6.31.6/kernel/printk.c linux-2.6.31.6-vs2.3.0.36.24/kernel/printk.c
---- linux-2.6.31.6/kernel/printk.c 2009-09-10 15:26:28.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/printk.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/printk.c linux-2.6.32-vs2.3.0.36.26/kernel/printk.c
+--- linux-2.6.32/kernel/printk.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/printk.c 2009-12-03 20:04:56.000000000 +0100
@@ -33,6 +33,7 @@
#include <linux/bootmem.h>
#include <linux/syscalls.h>
#include <asm/uaccess.h>
-@@ -270,18 +271,13 @@ int do_syslog(int type, char __user *buf
+@@ -276,18 +277,13 @@ int do_syslog(int type, char __user *buf
unsigned i, j, limit, count;
int do_clear = 0;
char c;
error = -EINVAL;
if (!buf || len < 0)
goto out;
-@@ -292,6 +288,16 @@ int do_syslog(int type, char __user *buf
+@@ -298,6 +294,16 @@ int do_syslog(int type, char __user *buf
error = -EFAULT;
goto out;
}
error = wait_event_interruptible(log_wait,
(log_start - log_end));
if (error)
-@@ -316,16 +322,6 @@ int do_syslog(int type, char __user *buf
+@@ -322,16 +328,6 @@ int do_syslog(int type, char __user *buf
do_clear = 1;
/* FALL THRU */
case 3: /* Read last kernel messages */
count = len;
if (count > log_buf_len)
count = log_buf_len;
-diff -NurpP --minimal linux-2.6.31.6/kernel/ptrace.c linux-2.6.31.6-vs2.3.0.36.24/kernel/ptrace.c
---- linux-2.6.31.6/kernel/ptrace.c 2009-09-10 15:26:28.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/ptrace.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/ptrace.c linux-2.6.32-vs2.3.0.36.26/kernel/ptrace.c
+--- linux-2.6.32/kernel/ptrace.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/ptrace.c 2009-12-03 20:04:56.000000000 +0100
@@ -22,6 +22,7 @@
#include <linux/pid_namespace.h>
#include <linux/syscalls.h>
+ !task_vx_flags(task, VXF_STATE_ADMIN, 0))
+ return -EACCES;
- return security_ptrace_may_access(task, mode);
+ return security_ptrace_access_check(task, mode);
}
-@@ -618,6 +624,10 @@ SYSCALL_DEFINE4(ptrace, long, request, l
+@@ -621,6 +627,10 @@ SYSCALL_DEFINE4(ptrace, long, request, l
goto out;
}
if (request == PTRACE_ATTACH) {
ret = ptrace_attach(child);
/*
-diff -NurpP --minimal linux-2.6.31.6/kernel/sched.c linux-2.6.31.6-vs2.3.0.36.24/kernel/sched.c
---- linux-2.6.31.6/kernel/sched.c 2009-09-10 15:26:28.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/sched.c 2009-11-05 04:17:49.000000000 +0100
-@@ -72,6 +72,8 @@
+diff -NurpP --minimal linux-2.6.32/kernel/sched.c linux-2.6.32-vs2.3.0.36.26/kernel/sched.c
+--- linux-2.6.32/kernel/sched.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/sched.c 2009-12-03 20:04:56.000000000 +0100
+@@ -71,6 +71,8 @@
#include <linux/debugfs.h>
#include <linux/ctype.h>
#include <linux/ftrace.h>
#include <asm/tlb.h>
#include <asm/irq_regs.h>
-@@ -262,6 +264,15 @@ static DEFINE_MUTEX(sched_domains_mutex)
+@@ -237,6 +239,15 @@ static DEFINE_MUTEX(sched_domains_mutex)
#include <linux/cgroup.h>
struct cfs_rq;
static LIST_HEAD(task_groups);
-@@ -282,6 +293,11 @@ struct task_group {
+@@ -257,6 +268,9 @@ struct task_group {
/* runqueue "owned" by this group on each cpu */
struct cfs_rq **cfs_rq;
unsigned long shares;
+#ifdef CONFIG_CFS_HARD_LIMITS
+ struct cfs_bandwidth cfs_bandwidth;
-+ /* If set, throttle when the group exceeds its bandwidth */
-+ int hard_limit_enabled;
+#endif
#endif
#ifdef CONFIG_RT_GROUP_SCHED
-@@ -477,6 +493,20 @@ struct cfs_rq {
+@@ -446,6 +460,19 @@ struct cfs_rq {
unsigned long rq_weight;
#endif
#endif
+
+ /* runtime available to the group on this rq */
+ u64 cfs_runtime;
++
++ /* Protects the cfs runtime related fields of this cfs_rq */
++ spinlock_t cfs_runtime_lock;
+#endif
-+ /*
-+ * Number of tasks at this heirarchy.
-+ */
-+ unsigned long nr_tasks_running;
};
/* Real-Time classes' related field in a runqueue: */
-@@ -661,6 +691,11 @@ struct rq {
- /* BKL stats */
- unsigned int bkl_count;
- #endif
-+ /*
-+ * Protects the cfs runtime related fields of all cfs_rqs under
-+ * this rq
-+ */
-+ spinlock_t runtime_lock;
- };
-
- static DEFINE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues);
-@@ -1552,6 +1587,7 @@ update_group_shares_cpu(struct task_grou
+@@ -1607,6 +1634,7 @@ static void update_group_shares_cpu(stru
}
}
/*
* Re-compute the task group their per cpu shares over the given domain.
* This needs to be done in a bottom-up fashion because the rq weight of a
-@@ -1569,9 +1605,11 @@ static int tg_shares_up(struct task_grou
+@@ -1634,8 +1662,10 @@ static int tg_shares_up(struct task_grou
* If there are currently no tasks on the cpu pretend there
* is one of average load so that when a new task gets to
* run here it will not get delayed by group starvation.
+ * Also if the group is throttled on this cpu, pretend that
+ * it has no tasks.
*/
- weight = tg->cfs_rq[i]->load.weight;
- if (!weight)
+ if (!weight || cfs_rq_throttled(tg->cfs_rq[i]))
weight = NICE_0_LOAD;
- tg->cfs_rq[i]->rq_weight = weight;
-@@ -1595,6 +1633,7 @@ static int tg_shares_up(struct task_grou
- * Compute the cpu's hierarchical load factor for each task group.
- * This needs to be done in a top-down fashion because the load of a child
- * group is a fraction of its parents load.
-+ * A throttled group's h_load is set to 0.
- */
- static int tg_load_down(struct task_group *tg, void *data)
- {
-@@ -1603,6 +1642,8 @@ static int tg_load_down(struct task_grou
-
- if (!tg->parent) {
- load = cpu_rq(cpu)->load.weight;
-+ } else if (cfs_rq_throttled(tg->cfs_rq[cpu])) {
-+ load = 0;
- } else {
- load = tg->parent->cfs_rq[cpu]->h_load;
- load *= tg->cfs_rq[cpu]->shares;
-@@ -1732,6 +1773,187 @@ static void cfs_rq_set_shares(struct cfs
+ rq_weight += weight;
+@@ -1811,6 +1841,175 @@ static void cfs_rq_set_shares(struct cfs
static void calc_load_account_active(struct rq *this_rq);
+ return RUNTIME_INF;
+}
+
-+int task_group_throttled(struct task_group *tg, int cpu);
+void do_sched_cfs_period_timer(struct cfs_bandwidth *cfs_b);
+
-+static inline int cfs_bandwidth_enabled(struct task_group *tg)
-+{
-+ return tg->hard_limit_enabled;
-+}
-+
-+static inline void rq_runtime_lock(struct rq *rq)
++static inline void cfs_rq_runtime_lock(struct cfs_rq *cfs_rq)
+{
-+ spin_lock(&rq->runtime_lock);
++ spin_lock(&cfs_rq->cfs_runtime_lock);
+}
+
-+static inline void rq_runtime_unlock(struct rq *rq)
++static inline void cfs_rq_runtime_unlock(struct cfs_rq *cfs_rq)
+{
-+ spin_unlock(&rq->runtime_lock);
++ spin_unlock(&cfs_rq->cfs_runtime_lock);
+}
+
+/*
+ struct cfs_bandwidth *cfs_b = &tg->cfs_bandwidth;
+
+ /*
-+ * Timer isn't setup for groups with infinite runtime or for groups
-+ * for which hard limiting isn't enabled.
++ * Timer isn't setup for groups with infinite runtime
+ */
-+ if (!cfs_bandwidth_enabled(tg) || (cfs_b->cfs_runtime == RUNTIME_INF))
++ if (cfs_b->cfs_runtime == RUNTIME_INF)
+ return;
+
+ if (hrtimer_active(&cfs_b->cfs_period_timer))
+ cfs_rq->cfs_time = 0;
+ cfs_rq->cfs_throttled = 0;
+ cfs_rq->cfs_runtime = tg->cfs_bandwidth.cfs_runtime;
-+ tg->hard_limit_enabled = 0;
++ spin_lock_init(&cfs_rq->cfs_runtime_lock);
+}
+
+#else /* !CONFIG_CFS_HARD_LIMITS */
+ return;
+}
+
-+static inline void rq_runtime_lock(struct rq *rq)
++static inline void cfs_rq_runtime_lock(struct cfs_rq *cfs_rq)
+{
+ return;
+}
+
-+static inline void rq_runtime_unlock(struct rq *rq)
++static inline void cfs_rq_runtime_unlock(struct cfs_rq *cfs_rq)
+{
+ return;
+}
+#endif /* CONFIG_CFS_HARD_LIMITS */
+#else /* !CONFIG_FAIR_GROUP_SCHED */
+
-+static inline void rq_runtime_lock(struct rq *rq)
++static inline void cfs_rq_runtime_lock(struct cfs_rq *cfs_rq)
+{
+ return;
+}
+
-+static inline void rq_runtime_unlock(struct rq *rq)
++static inline void cfs_rq_runtime_unlock(struct cfs_rq *cfs_rq)
+{
+ return;
+}
+
-+int task_group_throttled(struct task_group *tg, int cpu)
-+{
-+ return 0;
-+}
-+
+static inline int cfs_rq_throttled(struct cfs_rq *cfs_rq)
+{
+ return 0;
#include "sched_stats.h"
#include "sched_idletask.c"
#include "sched_fair.c"
-@@ -1781,14 +2003,17 @@ static void update_avg(u64 *avg, u64 sam
- *avg += diff >> 3;
- }
-
--static void enqueue_task(struct rq *rq, struct task_struct *p, int wakeup)
-+static int enqueue_task(struct rq *rq, struct task_struct *p, int wakeup)
- {
-+ int ret;
-+
- if (wakeup)
- p->se.start_runtime = p->se.sum_exec_runtime;
-
- sched_info_queued(p);
-- p->sched_class->enqueue_task(rq, p, wakeup);
-+ ret = p->sched_class->enqueue_task(rq, p, wakeup);
- p->se.on_rq = 1;
-+ return ret;
- }
-
- static void dequeue_task(struct rq *rq, struct task_struct *p, int sleep)
-@@ -1863,8 +2088,15 @@ static void activate_task(struct rq *rq,
- if (task_contributes_to_load(p))
- rq->nr_uninterruptible--;
-
-- enqueue_task(rq, p, wakeup);
-- inc_nr_running(rq);
-+ /*
-+ * Increment rq->nr_running only if enqueue_task() succeeds.
-+ * enqueue_task() can fail when the task being activated belongs
-+ * to a throttled group. In this case, the task gets enqueued to
-+ * throttled group and the group will be enqueued later when it
-+ * gets unthrottled. rq->nr_running gets incremented at that time.
-+ */
-+ if (!enqueue_task(rq, p, wakeup))
-+ inc_nr_running(rq);
- }
-
- /*
-@@ -2981,9 +3213,17 @@ EXPORT_SYMBOL(avenrun);
+@@ -2965,9 +3164,17 @@ EXPORT_SYMBOL(avenrun);
*/
void get_avenrun(unsigned long *loads, unsigned long offset, int shift)
{
}
static unsigned long
-@@ -3201,6 +3441,7 @@ int can_migrate_task(struct task_struct
- * 1) running (obviously), or
- * 2) cannot be migrated to this CPU due to cpus_allowed, or
- * 3) are cache-hot on their current CPU.
-+ * 4) end up in throttled task groups on this CPU.
- */
- if (!cpumask_test_cpu(this_cpu, &p->cpus_allowed)) {
- schedstat_inc(p, se.nr_failed_migrations_affine);
-@@ -3214,6 +3455,18 @@ int can_migrate_task(struct task_struct
- }
-
- /*
-+ * Don't migrate the task if it belongs to a
-+ * - throttled group on its current cpu
-+ * - throttled group on this_cpu
-+ * - group whose hierarchy is throttled on this_cpu
-+ */
-+ if (cfs_rq_throttled(cfs_rq_of(&p->se)) ||
-+ task_group_throttled(task_group(p), this_cpu)) {
-+ schedstat_inc(p, se.nr_failed_migrations_throttled);
-+ return 0;
-+ }
-+
-+ /*
- * Aggressive migration if:
- * 1) task is cache cold, or
- * 2) too many balance attempts have failed.
-@@ -4912,16 +5165,19 @@ void account_user_time(struct task_struc
+@@ -5006,16 +5213,19 @@ void account_user_time(struct task_struc
cputime_t cputime_scaled)
{
struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
cpustat->nice = cputime64_add(cpustat->nice, tmp);
else
cpustat->user = cputime64_add(cpustat->user, tmp);
-@@ -4967,6 +5223,7 @@ void account_system_time(struct task_str
+@@ -5061,6 +5271,7 @@ void account_system_time(struct task_str
cputime_t cputime, cputime_t cputime_scaled)
{
struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
cputime64_t tmp;
if ((p->flags & PF_VCPU) && (irq_count() - hardirq_offset == 0)) {
-@@ -4977,6 +5234,7 @@ void account_system_time(struct task_str
+@@ -5071,6 +5282,7 @@ void account_system_time(struct task_str
/* Add system time to process. */
p->stime = cputime_add(p->stime, cputime);
p->stimescaled = cputime_add(p->stimescaled, cputime_scaled);
account_group_system_time(p, cputime);
/* Add system time to cpustat. */
-@@ -5896,8 +6154,10 @@ void rt_mutex_setprio(struct task_struct
- oldprio = p->prio;
- on_rq = p->se.on_rq;
- running = task_current(rq, p);
-- if (on_rq)
-+ if (on_rq) {
- dequeue_task(rq, p, 0);
-+ dec_nr_running(rq);
-+ }
- if (running)
- p->sched_class->put_prev_task(rq, p);
-
-@@ -5911,7 +6171,8 @@ void rt_mutex_setprio(struct task_struct
- if (running)
- p->sched_class->set_curr_task(rq);
- if (on_rq) {
-- enqueue_task(rq, p, 0);
-+ if (!enqueue_task(rq, p, 0))
-+ inc_nr_running(rq);
-
- check_class_changed(rq, p, prev_class, oldprio, running);
- }
-@@ -5945,8 +6206,10 @@ void set_user_nice(struct task_struct *p
- goto out_unlock;
- }
- on_rq = p->se.on_rq;
-- if (on_rq)
-+ if (on_rq) {
- dequeue_task(rq, p, 0);
-+ dec_nr_running(rq);
-+ }
-
- p->static_prio = NICE_TO_PRIO(nice);
- set_load_weight(p);
-@@ -5955,7 +6218,8 @@ void set_user_nice(struct task_struct *p
- delta = p->prio - old_prio;
-
- if (on_rq) {
-- enqueue_task(rq, p, 0);
-+ if (!enqueue_task(rq, p, 0))
-+ inc_nr_running(rq);
- /*
- * If the task increased its priority or is running and
- * lowered its priority, then reschedule its CPU:
-@@ -6012,7 +6276,7 @@ SYSCALL_DEFINE1(nice, int, increment)
+@@ -6106,7 +6318,7 @@ SYSCALL_DEFINE1(nice, int, increment)
nice = 19;
if (increment < 0 && !can_nice(current, nice))
retval = security_task_setnice(current, nice);
if (retval)
-@@ -9119,6 +9383,7 @@ static void init_tg_cfs_entry(struct tas
+@@ -9164,6 +9376,32 @@ static int update_sched_domains(struct n
+ }
+ #endif
+
++#ifdef CONFIG_SMP
++static void disable_runtime(struct rq *rq)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&rq->lock, flags);
++#if defined(CONFIG_FAIR_GROUP_SCHED) && defined(CONFIG_CFS_HARD_LIMITS)
++ disable_runtime_cfs(rq);
++#endif
++ disable_runtime_rt(rq);
++ spin_unlock_irqrestore(&rq->lock, flags);
++}
++
++static void enable_runtime(struct rq *rq)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&rq->lock, flags);
++#if defined(CONFIG_FAIR_GROUP_SCHED) && defined(CONFIG_CFS_HARD_LIMITS)
++ enable_runtime_cfs(rq);
++#endif
++ enable_runtime_rt(rq);
++ spin_unlock_irqrestore(&rq->lock, flags);
++}
++#endif
++
+ static int update_runtime(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+ {
+@@ -9296,6 +9534,7 @@ static void init_tg_cfs_entry(struct tas
struct rq *rq = cpu_rq(cpu);
tg->cfs_rq[cpu] = cfs_rq;
init_cfs_rq(cfs_rq, rq);
cfs_rq->tg = tg;
if (add)
list_add(&cfs_rq->leaf_cfs_rq_list, &rq->leaf_cfs_rq_list);
-@@ -9248,6 +9513,10 @@ void __init sched_init(void)
+@@ -9425,6 +9664,10 @@ void __init sched_init(void)
#endif /* CONFIG_USER_SCHED */
#endif /* CONFIG_RT_GROUP_SCHED */
#ifdef CONFIG_GROUP_SCHED
list_add(&init_task_group.list, &task_groups);
INIT_LIST_HEAD(&init_task_group.children);
-@@ -9264,6 +9533,7 @@ void __init sched_init(void)
-
- rq = cpu_rq(i);
- spin_lock_init(&rq->lock);
-+ spin_lock_init(&rq->runtime_lock);
- rq->nr_running = 0;
- rq->calc_load_active = 0;
- rq->calc_load_update = jiffies + LOAD_FREQ;
-@@ -9537,6 +9807,7 @@ static void free_fair_sched_group(struct
+@@ -9451,6 +9694,7 @@ void __init sched_init(void)
+ init_cfs_rq(&rq->cfs, rq);
+ init_rt_rq(&rq->rt, rq);
+ #ifdef CONFIG_FAIR_GROUP_SCHED
++ init_cfs_hard_limits(&rq->cfs, &init_task_group);
+ init_task_group.shares = init_task_group_load;
+ INIT_LIST_HEAD(&rq->leaf_cfs_rq_list);
+ #ifdef CONFIG_CGROUP_SCHED
+@@ -9726,6 +9970,7 @@ static void free_fair_sched_group(struct
{
int i;
for_each_possible_cpu(i) {
if (tg->cfs_rq)
kfree(tg->cfs_rq[i]);
-@@ -9563,6 +9834,7 @@ int alloc_fair_sched_group(struct task_g
+@@ -9752,6 +9997,7 @@ int alloc_fair_sched_group(struct task_g
if (!tg->se)
goto err;
tg->shares = NICE_0_LOAD;
for_each_possible_cpu(i) {
-@@ -9795,8 +10067,10 @@ void sched_move_task(struct task_struct
- running = task_current(rq, tsk);
- on_rq = tsk->se.on_rq;
-
-- if (on_rq)
-+ if (on_rq) {
- dequeue_task(rq, tsk, 0);
-+ dec_nr_running(rq);
-+ }
- if (unlikely(running))
- tsk->sched_class->put_prev_task(rq, tsk);
-
-@@ -9810,7 +10084,8 @@ void sched_move_task(struct task_struct
- if (unlikely(running))
- tsk->sched_class->set_curr_task(rq);
- if (on_rq)
-- enqueue_task(rq, tsk, 0);
-+ if (!enqueue_task(rq, tsk, 0))
-+ inc_nr_running(rq);
-
- task_rq_unlock(rq, &flags);
- }
-@@ -10257,6 +10532,134 @@ static u64 cpu_shares_read_u64(struct cg
+@@ -10475,6 +10721,100 @@ static u64 cpu_shares_read_u64(struct cg
return (u64) tg->shares;
}
+static int tg_set_cfs_bandwidth(struct task_group *tg,
+ u64 cfs_period, u64 cfs_runtime)
+{
-+ int i, err = 0;
++ int i;
+
+ spin_lock_irq(&tg->cfs_bandwidth.cfs_runtime_lock);
+ tg->cfs_bandwidth.cfs_period = ns_to_ktime(cfs_period);
+ for_each_possible_cpu(i) {
+ struct cfs_rq *cfs_rq = tg->cfs_rq[i];
+
-+ rq_runtime_lock(rq_of(cfs_rq));
++ cfs_rq_runtime_lock(cfs_rq);
+ cfs_rq->cfs_runtime = cfs_runtime;
-+ rq_runtime_unlock(rq_of(cfs_rq));
++ cfs_rq_runtime_unlock(cfs_rq);
+ }
+
+ start_cfs_bandwidth(tg);
+ spin_unlock_irq(&tg->cfs_bandwidth.cfs_runtime_lock);
-+ return err;
++ return 0;
+}
+
+int tg_set_cfs_runtime(struct task_group *tg, long cfs_runtime_us)
+ return cfs_period_us;
+}
+
-+int tg_set_hard_limit_enabled(struct task_group *tg, u64 val)
-+{
-+ local_irq_disable();
-+ spin_lock(&tg->cfs_bandwidth.cfs_runtime_lock);
-+ if (val > 0) {
-+ tg->hard_limit_enabled = 1;
-+ start_cfs_bandwidth(tg);
-+ spin_unlock(&tg->cfs_bandwidth.cfs_runtime_lock);
-+ } else {
-+ destroy_cfs_bandwidth(tg);
-+ tg->hard_limit_enabled = 0;
-+ spin_unlock(&tg->cfs_bandwidth.cfs_runtime_lock);
-+ /*
-+ * Hard limiting is being disabled for this group.
-+ * Refresh runtimes and put the throttled entities
-+ * of the group back onto runqueue.
-+ */
-+ do_sched_cfs_period_timer(&tg->cfs_bandwidth);
-+ }
-+ local_irq_enable();
-+ return 0;
-+}
-+
+static s64 cpu_cfs_runtime_read_s64(struct cgroup *cgrp, struct cftype *cft)
+{
+ return tg_get_cfs_runtime(cgroup_tg(cgrp));
+ return tg_set_cfs_period(cgroup_tg(cgrp), cfs_period_us);
+}
+
-+static u64 cpu_cfs_hard_limit_read_u64(struct cgroup *cgrp, struct cftype *cft)
-+{
-+ return cfs_bandwidth_enabled(cgroup_tg(cgrp));
-+}
-+
-+static int cpu_cfs_hard_limit_write_u64(struct cgroup *cgrp,
-+ struct cftype *cftype, u64 val)
-+{
-+ return tg_set_hard_limit_enabled(cgroup_tg(cgrp), val);
-+}
-+
+#endif /* CONFIG_CFS_HARD_LIMITS */
#endif /* CONFIG_FAIR_GROUP_SCHED */
#ifdef CONFIG_RT_GROUP_SCHED
-@@ -10290,6 +10693,23 @@ static struct cftype cpu_files[] = {
+@@ -10508,6 +10848,18 @@ static struct cftype cpu_files[] = {
.read_u64 = cpu_shares_read_u64,
.write_u64 = cpu_shares_write_u64,
},
+ .read_u64 = cpu_cfs_period_read_u64,
+ .write_u64 = cpu_cfs_period_write_u64,
+ },
-+ {
-+ .name = "cfs_hard_limit",
-+ .read_u64 = cpu_cfs_hard_limit_read_u64,
-+ .write_u64 = cpu_cfs_hard_limit_write_u64,
-+ },
+#endif /* CONFIG_CFS_HARD_LIMITS */
#endif
#ifdef CONFIG_RT_GROUP_SCHED
{
-diff -NurpP --minimal linux-2.6.31.6/kernel/sched_debug.c linux-2.6.31.6-vs2.3.0.36.24/kernel/sched_debug.c
---- linux-2.6.31.6/kernel/sched_debug.c 2009-09-10 15:26:28.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/sched_debug.c 2009-10-06 04:39:26.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/sched_debug.c linux-2.6.32-vs2.3.0.36.26/kernel/sched_debug.c
+--- linux-2.6.32/kernel/sched_debug.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/sched_debug.c 2009-12-03 20:04:56.000000000 +0100
@@ -80,6 +80,11 @@ static void print_cfs_group_stats(struct
PN(se->wait_max);
PN(se->wait_sum);
#endif
P(se->load.weight);
#undef PN
-@@ -214,6 +219,18 @@ void print_cfs_rq(struct seq_file *m, in
+@@ -214,6 +219,16 @@ void print_cfs_rq(struct seq_file *m, in
#ifdef CONFIG_SMP
SEQ_printf(m, " .%-30s: %lu\n", "shares", cfs_rq->shares);
#endif
-+ SEQ_printf(m, " .%-30s: %ld\n", "nr_tasks_running",
-+ cfs_rq->nr_tasks_running);
+#ifdef CONFIG_CFS_HARD_LIMITS
+ spin_lock_irqsave(&rq->lock, flags);
+ SEQ_printf(m, " .%-30s: %d\n", "cfs_throttled",
+ SEQ_printf(m, " .%-30s: %Ld.%06ld\n", "cfs_runtime",
+ SPLIT_NS(cfs_rq->cfs_runtime));
+ spin_unlock_irqrestore(&rq->lock, flags);
-+#endif
++#endif /* CONFIG_CFS_HARD_LIMITS */
print_cfs_group_stats(m, cpu, cfs_rq->tg);
#endif
}
-@@ -310,7 +327,7 @@ static int sched_debug_show(struct seq_f
+@@ -310,7 +325,7 @@ static int sched_debug_show(struct seq_f
u64 now = ktime_to_ns(ktime_get());
int cpu;
init_utsname()->release,
(int)strcspn(init_utsname()->version, " "),
init_utsname()->version);
-@@ -415,6 +432,7 @@ void proc_sched_show_task(struct task_st
- P(se.nr_failed_migrations_affine);
- P(se.nr_failed_migrations_running);
- P(se.nr_failed_migrations_hot);
-+ P(se.nr_failed_migrations_throttled);
- P(se.nr_forced_migrations);
- P(se.nr_forced2_migrations);
- P(se.nr_wakeups);
-@@ -489,6 +507,7 @@ void proc_sched_set_task(struct task_str
- p->se.nr_failed_migrations_affine = 0;
- p->se.nr_failed_migrations_running = 0;
- p->se.nr_failed_migrations_hot = 0;
-+ p->se.nr_failed_migrations_throttled = 0;
- p->se.nr_forced_migrations = 0;
- p->se.nr_forced2_migrations = 0;
- p->se.nr_wakeups = 0;
-diff -NurpP --minimal linux-2.6.31.6/kernel/sched_fair.c linux-2.6.31.6-vs2.3.0.36.24/kernel/sched_fair.c
---- linux-2.6.31.6/kernel/sched_fair.c 2009-09-10 15:26:28.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/sched_fair.c 2009-10-06 04:39:37.000000000 +0200
-@@ -186,6 +186,286 @@ find_matching_se(struct sched_entity **s
+diff -NurpP --minimal linux-2.6.32/kernel/sched_fair.c linux-2.6.32-vs2.3.0.36.26/kernel/sched_fair.c
+--- linux-2.6.32/kernel/sched_fair.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/sched_fair.c 2009-12-03 20:04:56.000000000 +0100
+@@ -189,7 +189,308 @@ find_matching_se(struct sched_entity **s
}
}
+-#else /* !CONFIG_FAIR_GROUP_SCHED */
+#ifdef CONFIG_CFS_HARD_LIMITS
+
+static inline void update_stats_throttle_start(struct cfs_rq *cfs_rq,
+ schedstat_set(se->throttle_start, 0);
+}
+
-+static void double_rq_runtime_lock(struct rq *rq1, struct rq *rq2)
-+ __acquires(rq1->runtime_lock)
-+ __acquires(rq2->runtime_lock)
-+{
-+ BUG_ON(!irqs_disabled());
-+ if (rq1 == rq2) {
-+ spin_lock(&rq1->runtime_lock);
-+ __acquire(rq2->runtime_lock); /* Fake it out ;) */
-+ } else {
-+ if (rq1 < rq2) {
-+ spin_lock(&rq1->runtime_lock);
-+ spin_lock_nested(&rq2->runtime_lock,
-+ SINGLE_DEPTH_NESTING);
-+ } else {
-+ spin_lock(&rq2->runtime_lock);
-+ spin_lock_nested(&rq1->runtime_lock,
-+ SINGLE_DEPTH_NESTING);
-+ }
-+ }
-+ update_rq_clock(rq1);
-+ update_rq_clock(rq2);
-+}
-+
-+static void double_rq_runtime_unlock(struct rq *rq1, struct rq *rq2)
-+ __releases(rq1->runtime_lock)
-+ __releases(rq2->runtime_lock)
++static inline
++struct cfs_rq *sched_cfs_period_cfs_rq(struct cfs_bandwidth *cfs_b, int cpu)
+{
-+ spin_unlock(&rq1->runtime_lock);
-+ if (rq1 != rq2)
-+ spin_unlock(&rq2->runtime_lock);
-+ else
-+ __release(rq2->runtime_lock);
++ return container_of(cfs_b, struct task_group,
++ cfs_bandwidth)->cfs_rq[cpu];
+}
+
+static inline int cfs_rq_throttled(struct cfs_rq *cfs_rq)
+ return cfs_rq->cfs_throttled;
+}
+
++#ifdef CONFIG_SMP
+/*
-+ * Ran out of runtime, check if we can borrow some from others
-+ * instead of getting throttled right away.
++ * Ensure this RQ takes back all the runtime it lend to its neighbours.
++ */
++static void disable_runtime_cfs(struct rq *rq)
++{
++ struct root_domain *rd = rq->rd;
++ struct cfs_rq *cfs_rq;
++
++ if (unlikely(!scheduler_running))
++ return;
++
++ for_each_leaf_cfs_rq(rq, cfs_rq) {
++ struct cfs_bandwidth *cfs_b = &cfs_rq->tg->cfs_bandwidth;
++ s64 want;
++ int i;
++
++ spin_lock(&cfs_b->cfs_runtime_lock);
++ spin_lock(&cfs_rq->cfs_runtime_lock);
++
++ /*
++ * Either we're all are infinity and nobody needs to borrow,
++ * or we're already disabled and this have nothing to do, or
++ * we have exactly the right amount of runtime to take out.
++ */
++ if (cfs_rq->cfs_runtime == RUNTIME_INF ||
++ cfs_rq->cfs_runtime == cfs_b->cfs_runtime)
++ goto balanced;
++ spin_unlock(&cfs_rq->cfs_runtime_lock);
++
++ /*
++ * Calculate the difference between what we started out with
++ * and what we current have, that's the amount of runtime
++ * we lend and now have to reclaim.
++ */
++ want = cfs_b->cfs_runtime - cfs_rq->cfs_runtime;
++
++ /*
++ * Greedy reclaim, take back as much as possible.
++ */
++ for_each_cpu(i, rd->span) {
++ struct cfs_rq *iter = sched_cfs_period_cfs_rq(cfs_b, i);
++ s64 diff;
++
++ /*
++ * Can't reclaim from ourselves or disabled runqueues.
++ */
++ if (iter == cfs_rq || iter->cfs_runtime == RUNTIME_INF)
++ continue;
++
++ spin_lock(&iter->cfs_runtime_lock);
++ if (want > 0) {
++ diff = min_t(s64, iter->cfs_runtime, want);
++ iter->cfs_runtime -= diff;
++ want -= diff;
++ } else {
++ iter->cfs_runtime -= want;
++ want -= want;
++ }
++
++ spin_unlock(&iter->cfs_runtime_lock);
++ if (!want)
++ break;
++ }
++
++ spin_lock(&cfs_rq->cfs_runtime_lock);
++ /*
++ * We cannot be left wanting - that would mean some
++ * runtime leaked out of the system.
++ */
++ BUG_ON(want);
++balanced:
++ /*
++ * Disable all the borrow logic by pretending we have infinite
++ * runtime - in which case borrowing doesn't make sense.
++ */
++ cfs_rq->cfs_runtime = RUNTIME_INF;
++ spin_unlock(&cfs_rq->cfs_runtime_lock);
++ spin_unlock(&cfs_b->cfs_runtime_lock);
++ }
++}
++
++static void enable_runtime_cfs(struct rq *rq)
++{
++ struct cfs_rq *cfs_rq;
++
++ if (unlikely(!scheduler_running))
++ return;
++
++ /*
++ * Reset each runqueue's bandwidth settings
++ */
++ for_each_leaf_cfs_rq(rq, cfs_rq) {
++ struct cfs_bandwidth *cfs_b = &cfs_rq->tg->cfs_bandwidth;
++
++ spin_lock(&cfs_b->cfs_runtime_lock);
++ spin_lock(&cfs_rq->cfs_runtime_lock);
++ cfs_rq->cfs_runtime = cfs_b->cfs_runtime;
++ cfs_rq->cfs_time = 0;
++ cfs_rq->cfs_throttled = 0;
++ spin_unlock(&cfs_rq->cfs_runtime_lock);
++ spin_unlock(&cfs_b->cfs_runtime_lock);
++ }
++}
++
++/*
++ * Ran out of runtime, check if we can borrow some from others
++ * instead of getting throttled right away.
+ */
+static void do_cfs_balance_runtime(struct cfs_rq *cfs_rq)
+{
-+ struct rq *rq = rq_of(cfs_rq);
+ struct cfs_bandwidth *cfs_b = &cfs_rq->tg->cfs_bandwidth;
+ const struct cpumask *span = sched_bw_period_mask();
+ int i, weight;
+ u64 cfs_period;
-+ struct task_group *tg = container_of(cfs_b, struct task_group,
-+ cfs_bandwidth);
+
+ weight = cpumask_weight(span);
+ spin_lock(&cfs_b->cfs_runtime_lock);
+ cfs_period = ktime_to_ns(cfs_b->cfs_period);
+
+ for_each_cpu(i, span) {
-+ struct cfs_rq *borrow_cfs_rq = tg->cfs_rq[i];
-+ struct rq *borrow_rq = rq_of(borrow_cfs_rq);
++ struct cfs_rq *borrow_cfs_rq =
++ sched_cfs_period_cfs_rq(cfs_b, i);
+ s64 diff;
+
+ if (borrow_cfs_rq == cfs_rq)
+ continue;
+
-+ double_rq_runtime_lock(rq, borrow_rq);
++ cfs_rq_runtime_lock(borrow_cfs_rq);
+ if (borrow_cfs_rq->cfs_runtime == RUNTIME_INF) {
-+ double_rq_runtime_unlock(rq, borrow_rq);
++ cfs_rq_runtime_unlock(borrow_cfs_rq);
+ continue;
+ }
+
+ borrow_cfs_rq->cfs_runtime -= diff;
+ cfs_rq->cfs_runtime += diff;
+ if (cfs_rq->cfs_runtime == cfs_period) {
-+ double_rq_runtime_unlock(rq, borrow_rq);
++ cfs_rq_runtime_unlock(borrow_cfs_rq);
+ break;
+ }
+ }
-+ double_rq_runtime_unlock(rq, borrow_rq);
++ cfs_rq_runtime_unlock(borrow_cfs_rq);
+ }
+ spin_unlock(&cfs_b->cfs_runtime_lock);
+}
+ */
+static void cfs_balance_runtime(struct cfs_rq *cfs_rq)
+{
-+ struct rq *rq = rq_of(cfs_rq);
-+
-+ rq_runtime_unlock(rq);
++ cfs_rq_runtime_unlock(cfs_rq);
+ do_cfs_balance_runtime(cfs_rq);
-+ rq_runtime_lock(rq);
++ cfs_rq_runtime_lock(cfs_rq);
++}
++
++#else /* !CONFIG_SMP */
++
++static void cfs_balance_runtime(struct cfs_rq *cfs_rq)
++{
++ return;
+}
++#endif /* CONFIG_SMP */
+
+/*
+ * Check if group entity exceeded its runtime. If so, mark the cfs_rq as
+
+ cfs_rq = group_cfs_rq(se);
+
-+ if (!cfs_bandwidth_enabled(cfs_rq->tg))
-+ return;
-+
+ if (cfs_rq->cfs_runtime == RUNTIME_INF)
+ return;
+
+ }
+}
+
-+/*
-+ * Check if the entity is throttled.
-+ */
-+static int entity_throttled(struct sched_entity *se)
++static inline void update_curr_group(struct sched_entity *curr,
++ unsigned long delta_exec, struct task_struct *tsk_curr)
+{
-+ struct cfs_rq *cfs_rq;
-+
-+ /* Only group entities can be throttled */
-+ if (entity_is_task(se))
-+ return 0;
-+
-+ cfs_rq = group_cfs_rq(se);
-+ if (cfs_rq_throttled(cfs_rq))
-+ return 1;
-+ return 0;
-+}
-+
-+int task_group_throttled(struct task_group *tg, int cpu)
-+{
-+ struct sched_entity *se = tg->se[cpu];
-+
-+ for_each_sched_entity(se) {
-+ if (entity_throttled(se))
-+ return 1;
-+ }
-+ return 0;
++ sched_cfs_runtime_exceeded(curr, tsk_curr, delta_exec);
+}
+
+static void enqueue_entity_locked(struct cfs_rq *cfs_rq,
+ struct sched_entity *se, int wakeup);
-+static void add_cfs_rq_tasks_running(struct sched_entity *se,
-+ unsigned long count);
-+static void sub_cfs_rq_tasks_running(struct sched_entity *se,
-+ unsigned long count);
+
+static void enqueue_throttled_entity(struct rq *rq, struct sched_entity *se)
+{
-+ unsigned long nr_tasks = 0;
-+ struct sched_entity *se_tmp = se;
-+ int throttled = 0;
-+
+ for_each_sched_entity(se) {
-+ if (se->on_rq)
-+ break;
++ struct cfs_rq *gcfs_rq = group_cfs_rq(se);
+
-+ if (entity_throttled(se)) {
-+ throttled = 1;
++ if (se->on_rq || cfs_rq_throttled(gcfs_rq) ||
++ !gcfs_rq->nr_running)
+ break;
-+ }
-+
+ enqueue_entity_locked(cfs_rq_of(se), se, 0);
-+ nr_tasks += group_cfs_rq(se)->nr_tasks_running;
+ }
-+
-+ if (!nr_tasks)
-+ return;
-+
-+ /*
-+ * Add the number of tasks this entity has to
-+ * all of its parent entities.
-+ */
-+ add_cfs_rq_tasks_running(se_tmp, nr_tasks);
-+
-+ /*
-+ * Add the number of tasks this entity has to
-+ * this cpu's rq only if the entity got enqueued all the
-+ * way up without any throttled entity in the hierarchy.
-+ */
-+ if (!throttled)
-+ rq->nr_running += nr_tasks;
+}
+
+/*
+{
+ int i;
+ const struct cpumask *span = sched_bw_period_mask();
-+ struct task_group *tg = container_of(cfs_b, struct task_group,
-+ cfs_bandwidth);
+ unsigned long flags;
+
+ for_each_cpu(i, span) {
+ struct rq *rq = cpu_rq(i);
-+ struct cfs_rq *cfs_rq = tg->cfs_rq[i];
-+ struct sched_entity *se = tg->se[i];
++ struct cfs_rq *cfs_rq = sched_cfs_period_cfs_rq(cfs_b, i);
++ struct sched_entity *se = cfs_rq->tg->se[i];
+
+ spin_lock_irqsave(&rq->lock, flags);
-+ rq_runtime_lock(rq);
++ cfs_rq_runtime_lock(cfs_rq);
+ cfs_rq->cfs_time = 0;
+ if (cfs_rq_throttled(cfs_rq)) {
+ update_rq_clock(rq);
+ cfs_rq->cfs_throttled = 0;
+ enqueue_throttled_entity(rq, se);
+ }
-+ rq_runtime_unlock(rq);
++ cfs_rq_runtime_unlock(cfs_rq);
+ spin_unlock_irqrestore(&rq->lock, flags);
+ }
+}
+
+#else
+
-+static inline int cfs_rq_throttled(struct cfs_rq *cfs_rq)
-+{
-+ return 0;
-+}
-+
-+int task_group_throttled(struct task_group *tg, int cpu)
-+{
-+ return 0;
-+}
-+
-+static void sched_cfs_runtime_exceeded(struct sched_entity *se,
-+ struct task_struct *tsk_curr, unsigned long delta_exec)
++static inline void update_curr_group(struct sched_entity *curr,
++ unsigned long delta_exec, struct task_struct *tsk_curr)
+{
+ return;
+}
+
-+static int entity_throttled(struct sched_entity *se)
++static inline int cfs_rq_throttled(struct cfs_rq *cfs_rq)
+{
+ return 0;
+}
+
+#endif /* CONFIG_CFS_HARD_LIMITS */
+
- #else /* CONFIG_FAIR_GROUP_SCHED */
-
- static inline struct rq *rq_of(struct cfs_rq *cfs_rq)
-@@ -241,8 +521,47 @@ find_matching_se(struct sched_entity **s
- {
- }
-
-+static void sched_cfs_runtime_exceeded(struct sched_entity *se,
-+ struct task_struct *tsk_curr, unsigned long delta_exec)
-+{
-+ return;
-+}
++#else /* CONFIG_FAIR_GROUP_SCHED */
+
-+static int entity_throttled(struct sched_entity *se)
++static inline void update_curr_group(struct sched_entity *curr,
++ unsigned long delta_exec, struct task_struct *tsk_curr)
+{
-+ return 0;
++ return;
+}
-+
- #endif /* CONFIG_FAIR_GROUP_SCHED */
-+static void add_cfs_rq_tasks_running(struct sched_entity *se,
-+ unsigned long count)
-+{
-+ struct cfs_rq *cfs_rq;
-+
-+ for_each_sched_entity(se) {
-+ /*
-+ * If any entity in the hierarchy is throttled, don't
-+ * propogate the tasks count up since this entity isn't
-+ * on rq yet.
-+ */
-+ if (entity_throttled(se))
-+ break;
-+ cfs_rq = cfs_rq_of(se);
-+ cfs_rq->nr_tasks_running += count;
-+ }
-+}
-+
-+static void sub_cfs_rq_tasks_running(struct sched_entity *se,
-+ unsigned long count)
-+{
-+ struct cfs_rq *cfs_rq;
-+
-+ for_each_sched_entity(se) {
-+ cfs_rq = cfs_rq_of(se);
-+ cfs_rq->nr_tasks_running -= count;
-+ }
-+}
+ static inline struct task_struct *task_of(struct sched_entity *se)
+ {
+@@ -251,7 +552,6 @@ find_matching_se(struct sched_entity **s
+
+ #endif /* CONFIG_FAIR_GROUP_SCHED */
+-
/**************************************************************
* Scheduling class tree data structure manipulation methods:
-@@ -481,10 +800,12 @@ __update_curr(struct cfs_rq *cfs_rq, str
+ */
+@@ -489,14 +789,25 @@ __update_curr(struct cfs_rq *cfs_rq, str
update_min_vruntime(cfs_rq);
}
-static void update_curr(struct cfs_rq *cfs_rq)
-+static void update_curr_common(struct cfs_rq *cfs_rq)
++static void update_curr_task(struct sched_entity *curr,
++ unsigned long delta_exec)
++{
++ struct task_struct *curtask = task_of(curr);
++
++ trace_sched_stat_runtime(curtask, delta_exec, curr->vruntime);
++ cpuacct_charge(curtask, delta_exec);
++ account_group_exec_runtime(curtask, delta_exec);
++}
++
++static int update_curr_common(struct cfs_rq *cfs_rq, unsigned long *delta)
{
struct sched_entity *curr = cfs_rq->curr;
- u64 now = rq_of(cfs_rq)->clock;
+ struct rq *rq = rq_of(cfs_rq);
-+ struct task_struct *tsk_curr = rq->curr;
+ u64 now = rq->clock;
unsigned long delta_exec;
if (unlikely(!curr))
-@@ -507,9 +828,23 @@ static void update_curr(struct cfs_rq *c
+- return;
++ return 1;
- cpuacct_charge(curtask, delta_exec);
- account_group_exec_runtime(curtask, delta_exec);
-+ } else {
-+ sched_cfs_runtime_exceeded(curr, tsk_curr, delta_exec);
- }
- }
+ /*
+ * Get the amount of time the current task was running
+@@ -505,20 +816,47 @@ static void update_curr(struct cfs_rq *c
+ */
+ delta_exec = (unsigned long)(now - curr->exec_start);
+ if (!delta_exec)
+- return;
++ return 1;
+ __update_curr(cfs_rq, curr, delta_exec);
+ curr->exec_start = now;
++ *delta = delta_exec;
++ return 0;
++}
+
+- if (entity_is_task(curr)) {
+- struct task_struct *curtask = task_of(curr);
+static void update_curr(struct cfs_rq *cfs_rq)
+{
-+ rq_runtime_lock(rq_of(cfs_rq));
-+ update_curr_common(cfs_rq);
-+ rq_runtime_unlock(rq_of(cfs_rq));
-+}
++ struct sched_entity *curr = cfs_rq->curr;
++ struct rq *rq = rq_of(cfs_rq);
++ unsigned long delta_exec;
+
+- trace_sched_stat_runtime(curtask, delta_exec, curr->vruntime);
+- cpuacct_charge(curtask, delta_exec);
+- account_group_exec_runtime(curtask, delta_exec);
++ if (update_curr_common(cfs_rq, &delta_exec))
++ return ;
+
-+static inline void update_curr_locked(struct cfs_rq *cfs_rq)
++ if (entity_is_task(curr))
++ update_curr_task(curr, delta_exec);
++ else {
++ cfs_rq_runtime_lock(group_cfs_rq(curr));
++ update_curr_group(curr, delta_exec, rq->curr);
++ cfs_rq_runtime_unlock(group_cfs_rq(curr));
+ }
+ }
+
++static void update_curr_locked(struct cfs_rq *cfs_rq)
+{
-+ update_curr_common(cfs_rq);
++ struct sched_entity *curr = cfs_rq->curr;
++ struct rq *rq = rq_of(cfs_rq);
++ unsigned long delta_exec;
++
++ if (update_curr_common(cfs_rq, &delta_exec))
++ return ;
++
++ if (entity_is_task(curr))
++ update_curr_task(curr, delta_exec);
++ else
++ update_curr_group(curr, delta_exec, rq->curr);
+}
+
static inline void
update_stats_wait_start(struct cfs_rq *cfs_rq, struct sched_entity *se)
{
-@@ -713,13 +1048,9 @@ place_entity(struct cfs_rq *cfs_rq, stru
+@@ -740,13 +1078,9 @@ place_entity(struct cfs_rq *cfs_rq, stru
se->vruntime = vruntime;
}
account_entity_enqueue(cfs_rq, se);
if (wakeup) {
-@@ -731,6 +1062,29 @@ enqueue_entity(struct cfs_rq *cfs_rq, st
+@@ -758,6 +1092,29 @@ enqueue_entity(struct cfs_rq *cfs_rq, st
check_spread(cfs_rq, se);
if (se != cfs_rq->curr)
__enqueue_entity(cfs_rq, se);
}
static void __clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se)
-@@ -774,6 +1128,8 @@ dequeue_entity(struct cfs_rq *cfs_rq, st
+@@ -801,6 +1158,8 @@ dequeue_entity(struct cfs_rq *cfs_rq, st
if (se != cfs_rq->curr)
__dequeue_entity(cfs_rq, se);
account_entity_dequeue(cfs_rq, se);
update_min_vruntime(cfs_rq);
}
-@@ -844,8 +1200,40 @@ static struct sched_entity *pick_next_en
+@@ -897,6 +1256,32 @@ static struct sched_entity *pick_next_en
return se;
}
+ * If a group entity (@se) is found to be throttled, it will not be put back
+ * on @cfs_rq, which is equivalent to dequeing it.
+ */
-+static void dequeue_throttled_entity(struct cfs_rq *cfs_rq,
++static int dequeue_throttled_entity(struct cfs_rq *cfs_rq,
+ struct sched_entity *se)
+{
-+ unsigned long nr_tasks = group_cfs_rq(se)->nr_tasks_running;
++ struct cfs_rq *gcfs_rq = group_cfs_rq(se);
++
++ if (entity_is_task(se))
++ return 0;
++
++ cfs_rq_runtime_lock(gcfs_rq);
++ if (!cfs_rq_throttled(gcfs_rq) && gcfs_rq->nr_running) {
++ cfs_rq_runtime_unlock(gcfs_rq);
++ return 0;
++ }
+
+ __clear_buddies(cfs_rq, se);
+ account_entity_dequeue(cfs_rq, se);
+ cfs_rq->curr = NULL;
-+
-+ if (!nr_tasks)
-+ return;
-+
-+ /*
-+ * Decrement the number of tasks this entity has from
-+ * all of its parent entities.
-+ */
-+ sub_cfs_rq_tasks_running(se, nr_tasks);
-+
-+ /*
-+ * Decrement the number of tasks this entity has from
-+ * this cpu's rq.
-+ */
-+ rq_of(cfs_rq)->nr_running -= nr_tasks;
++ cfs_rq_runtime_unlock(gcfs_rq);
++ return 1;
+}
+
static void put_prev_entity(struct cfs_rq *cfs_rq, struct sched_entity *prev)
{
-+ struct cfs_rq *gcfs_rq = group_cfs_rq(prev);
-+
/*
- * If still on the runqueue then deactivate_task()
- * was not called and update_curr() has to be done:
-@@ -855,6 +1243,18 @@ static void put_prev_entity(struct cfs_r
+@@ -908,6 +1293,8 @@ static void put_prev_entity(struct cfs_r
check_spread(cfs_rq, prev);
if (prev->on_rq) {
-+ /*
-+ * If the group entity is throttled or if it has no
-+ * no child entities, then don't enqueue it back.
-+ */
-+ rq_runtime_lock(rq_of(cfs_rq));
-+ if (entity_throttled(prev) ||
-+ (gcfs_rq && !gcfs_rq->nr_running)) {
-+ dequeue_throttled_entity(cfs_rq, prev);
-+ rq_runtime_unlock(rq_of(cfs_rq));
++ if (dequeue_throttled_entity(cfs_rq, prev))
+ return;
-+ }
-+ rq_runtime_unlock(rq_of(cfs_rq));
update_stats_wait_start(cfs_rq, prev);
/* Put 'current' back into the tree. */
__enqueue_entity(cfs_rq, prev);
-@@ -955,21 +1355,32 @@ static inline void hrtick_update(struct
+@@ -1004,10 +1391,28 @@ static inline void hrtick_update(struct
+ }
+ #endif
+
++static int enqueue_group_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
++ int wakeup)
++{
++ struct cfs_rq *gcfs_rq = group_cfs_rq(se);
++ int ret = 0;
++
++ cfs_rq_runtime_lock(gcfs_rq);
++ if (cfs_rq_throttled(gcfs_rq)) {
++ ret = 1;
++ goto out;
++ }
++ enqueue_entity_locked(cfs_rq, se, wakeup);
++out:
++ cfs_rq_runtime_unlock(gcfs_rq);
++ return ret;
++}
++
+ /*
* The enqueue_task method is called before nr_running is
* increased. Here we update the fair scheduling stats and
* then put the task into the rbtree:
+ * Don't enqueue a throttled entity further into the hierarchy.
*/
--static void enqueue_task_fair(struct rq *rq, struct task_struct *p, int wakeup)
-+static int enqueue_task_fair(struct rq *rq, struct task_struct *p, int wakeup)
+ static void enqueue_task_fair(struct rq *rq, struct task_struct *p, int wakeup)
{
- struct cfs_rq *cfs_rq;
- struct sched_entity *se = &p->se;
-+ int throttled = 0;
-
-+ rq_runtime_lock(rq);
+@@ -1017,11 +1422,15 @@ static void enqueue_task_fair(struct rq
for_each_sched_entity(se) {
if (se->on_rq)
break;
-+ if (entity_throttled(se)) {
-+ throttled = 1;
-+ break;
-+ }
++
cfs_rq = cfs_rq_of(se);
- enqueue_entity(cfs_rq, se, wakeup);
-+ enqueue_entity_locked(cfs_rq, se, wakeup);
++ if (entity_is_task(se))
++ enqueue_entity(cfs_rq, se, wakeup);
++ else
++ if (enqueue_group_entity(cfs_rq, se, wakeup))
++ break;
wakeup = 1;
}
-
-+ add_cfs_rq_tasks_running(&p->se, 1);
-+ rq_runtime_unlock(rq);
-+
+-
hrtick_update(rq);
-+ return throttled;
}
- /*
-@@ -991,6 +1402,7 @@ static void dequeue_task_fair(struct rq
+@@ -1041,6 +1450,17 @@ static void dequeue_task_fair(struct rq
+ /* Don't dequeue parent if it has other entities besides us */
+ if (cfs_rq->load.weight)
+ break;
++
++ /*
++ * If this cfs_rq is throttled, then it is already
++ * dequeued.
++ */
++ cfs_rq_runtime_lock(cfs_rq);
++ if (cfs_rq_throttled(cfs_rq)) {
++ cfs_rq_runtime_unlock(cfs_rq);
++ break;
++ }
++ cfs_rq_runtime_unlock(cfs_rq);
sleep = 1;
}
-+ sub_cfs_rq_tasks_running(&p->se, 1);
- hrtick_update(rq);
- }
-
-@@ -1518,6 +1930,7 @@ static struct task_struct *pick_next_tas
-
- do {
- se = pick_next_entity(cfs_rq);
-+
- /*
- * If se was a buddy, clear it so that it will have to earn
- * the favour again.
-@@ -1627,9 +2040,9 @@ load_balance_fair(struct rq *this_rq, in
+@@ -1788,9 +2208,10 @@ load_balance_fair(struct rq *this_rq, in
u64 rem_load, moved_load;
/*
- * empty group
-+ * empty group or a group with no h_load (throttled)
++ * empty group or throttled group
*/
- if (!busiest_cfs_rq->task_weight)
-+ if (!busiest_cfs_rq->task_weight || !busiest_h_load)
++ if (!busiest_cfs_rq->task_weight ||
++ cfs_rq_throttled(busiest_cfs_rq))
continue;
rem_load = (u64)rem_load_move * busiest_weight;
-diff -NurpP --minimal linux-2.6.31.6/kernel/sched_rt.c linux-2.6.31.6-vs2.3.0.36.24/kernel/sched_rt.c
---- linux-2.6.31.6/kernel/sched_rt.c 2009-09-10 15:26:28.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/sched_rt.c 2009-10-06 04:39:02.000000000 +0200
-@@ -222,18 +222,6 @@ static int rt_se_boosted(struct sched_rt
+@@ -1839,6 +2260,12 @@ move_one_task_fair(struct rq *this_rq, i
+
+ for_each_leaf_cfs_rq(busiest, busy_cfs_rq) {
+ /*
++ * Don't move task from a throttled cfs_rq
++ */
++ if (cfs_rq_throttled(busy_cfs_rq))
++ continue;
++
++ /*
+ * pass busy_cfs_rq argument into
+ * load_balance_[start|next]_fair iterators
+ */
+diff -NurpP --minimal linux-2.6.32/kernel/sched_rt.c linux-2.6.32-vs2.3.0.36.26/kernel/sched_rt.c
+--- linux-2.6.32/kernel/sched_rt.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/sched_rt.c 2009-12-03 20:04:56.000000000 +0100
+@@ -235,18 +235,6 @@ static int rt_se_boosted(struct sched_rt
return p->prio != p->normal_prio;
}
static inline
struct rt_rq *sched_rt_period_rt_rq(struct rt_bandwidth *rt_b, int cpu)
{
-@@ -283,11 +271,6 @@ static inline int rt_rq_throttled(struct
+@@ -296,11 +284,6 @@ static inline int rt_rq_throttled(struct
return rt_rq->rt_throttled;
}
static inline
struct rt_rq *sched_rt_period_rt_rq(struct rt_bandwidth *rt_b, int cpu)
{
-@@ -505,7 +488,7 @@ static int do_sched_rt_period_timer(stru
+@@ -373,7 +356,7 @@ next:
+ /*
+ * Ensure this RQ takes back all the runtime it lend to its neighbours.
+ */
+-static void __disable_runtime(struct rq *rq)
++static void disable_runtime_rt(struct rq *rq)
+ {
+ struct root_domain *rd = rq->rd;
+ struct rt_rq *rt_rq;
+@@ -450,16 +433,7 @@ balanced:
+ }
+ }
+
+-static void disable_runtime(struct rq *rq)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&rq->lock, flags);
+- __disable_runtime(rq);
+- spin_unlock_irqrestore(&rq->lock, flags);
+-}
+-
+-static void __enable_runtime(struct rq *rq)
++static void enable_runtime_rt(struct rq *rq)
+ {
+ struct rt_rq *rt_rq;
+
+@@ -482,15 +456,6 @@ static void __enable_runtime(struct rq *
+ }
+ }
+
+-static void enable_runtime(struct rq *rq)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&rq->lock, flags);
+- __enable_runtime(rq);
+- spin_unlock_irqrestore(&rq->lock, flags);
+-}
+-
+ static int balance_runtime(struct rt_rq *rt_rq)
+ {
+ int more = 0;
+@@ -518,7 +483,7 @@ static int do_sched_rt_period_timer(stru
if (!rt_bandwidth_enabled() || rt_b->rt_runtime == RUNTIME_INF)
return 1;
for_each_cpu(i, span) {
int enqueue = 0;
struct rt_rq *rt_rq = sched_rt_period_rt_rq(rt_b, i);
-@@ -863,7 +846,7 @@ static void dequeue_rt_entity(struct sch
- /*
- * Adding/removing a task to/from a priority array:
- */
--static void enqueue_task_rt(struct rq *rq, struct task_struct *p, int wakeup)
-+static int enqueue_task_rt(struct rq *rq, struct task_struct *p, int wakeup)
- {
- struct sched_rt_entity *rt_se = &p->rt;
+@@ -1564,7 +1529,7 @@ static void rq_online_rt(struct rq *rq)
+ if (rq->rt.overloaded)
+ rt_set_overload(rq);
-@@ -876,6 +859,7 @@ static void enqueue_task_rt(struct rq *r
- enqueue_pushable_task(rq, p);
+- __enable_runtime(rq);
++ enable_runtime_rt(rq);
- inc_cpu_load(rq, p->se.load.weight);
-+ return 0;
+ cpupri_set(&rq->rd->cpupri, rq->cpu, rq->rt.highest_prio.curr);
}
+@@ -1575,7 +1540,7 @@ static void rq_offline_rt(struct rq *rq)
+ if (rq->rt.overloaded)
+ rt_clear_overload(rq);
- static void dequeue_task_rt(struct rq *rq, struct task_struct *p, int sleep)
-diff -NurpP --minimal linux-2.6.31.6/kernel/signal.c linux-2.6.31.6-vs2.3.0.36.24/kernel/signal.c
---- linux-2.6.31.6/kernel/signal.c 2009-09-10 15:26:28.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/signal.c 2009-09-10 16:43:45.000000000 +0200
+- __disable_runtime(rq);
++ disable_runtime_rt(rq);
+
+ cpupri_set(&rq->rd->cpupri, rq->cpu, CPUPRI_INVALID);
+ }
+diff -NurpP --minimal linux-2.6.32/kernel/signal.c linux-2.6.32-vs2.3.0.36.26/kernel/signal.c
+--- linux-2.6.32/kernel/signal.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/signal.c 2009-12-03 20:04:56.000000000 +0100
@@ -27,6 +27,8 @@
#include <linux/freezer.h>
#include <linux/pid_namespace.h>
int err = group_send_sig_info(sig, info, p);
++count;
if (err != -EPERM)
-@@ -1892,6 +1918,11 @@ relock:
+@@ -1871,6 +1897,11 @@ relock:
!sig_kernel_only(signr))
continue;
if (sig_kernel_stop(signr)) {
/*
* The default action is to stop all threads in
-diff -NurpP --minimal linux-2.6.31.6/kernel/softirq.c linux-2.6.31.6-vs2.3.0.36.24/kernel/softirq.c
---- linux-2.6.31.6/kernel/softirq.c 2009-09-10 15:26:28.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/softirq.c 2009-09-10 16:33:13.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/softirq.c linux-2.6.32-vs2.3.0.36.26/kernel/softirq.c
+--- linux-2.6.32/kernel/softirq.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/softirq.c 2009-12-03 20:04:56.000000000 +0100
@@ -24,6 +24,7 @@
#include <linux/ftrace.h>
#include <linux/smp.h>
#define CREATE_TRACE_POINTS
#include <trace/events/irq.h>
-diff -NurpP --minimal linux-2.6.31.6/kernel/sys.c linux-2.6.31.6-vs2.3.0.36.24/kernel/sys.c
---- linux-2.6.31.6/kernel/sys.c 2009-09-10 15:26:28.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/sys.c 2009-10-06 03:52:09.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/sys.c linux-2.6.32-vs2.3.0.36.26/kernel/sys.c
+--- linux-2.6.32/kernel/sys.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/sys.c 2009-12-03 20:04:56.000000000 +0100
@@ -41,6 +41,7 @@
#include <linux/syscalls.h>
#include <linux/kprobes.h>
lock_kernel();
switch (cmd) {
case LINUX_REBOOT_CMD_RESTART:
-@@ -1131,7 +1145,7 @@ SYSCALL_DEFINE2(sethostname, char __user
+@@ -1133,7 +1147,7 @@ SYSCALL_DEFINE2(sethostname, char __user
int errno;
char tmp[__NEW_UTS_LEN];
return -EPERM;
if (len < 0 || len > __NEW_UTS_LEN)
return -EINVAL;
-@@ -1180,7 +1194,7 @@ SYSCALL_DEFINE2(setdomainname, char __us
+@@ -1182,7 +1196,7 @@ SYSCALL_DEFINE2(setdomainname, char __us
int errno;
char tmp[__NEW_UTS_LEN];
return -EPERM;
if (len < 0 || len > __NEW_UTS_LEN)
return -EINVAL;
-@@ -1249,7 +1263,7 @@ SYSCALL_DEFINE2(setrlimit, unsigned int,
+@@ -1251,7 +1265,7 @@ SYSCALL_DEFINE2(setrlimit, unsigned int,
return -EINVAL;
old_rlim = current->signal->rlim + resource;
if ((new_rlim.rlim_max > old_rlim->rlim_max) &&
return -EPERM;
if (resource == RLIMIT_NOFILE && new_rlim.rlim_max > sysctl_nr_open)
return -EPERM;
-diff -NurpP --minimal linux-2.6.31.6/kernel/sysctl.c linux-2.6.31.6-vs2.3.0.36.24/kernel/sysctl.c
---- linux-2.6.31.6/kernel/sysctl.c 2009-09-10 15:26:28.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/sysctl.c 2009-09-10 16:11:43.000000000 +0200
-@@ -119,6 +119,7 @@ static int ngroups_max = NGROUPS_MAX;
+diff -NurpP --minimal linux-2.6.32/kernel/sysctl.c linux-2.6.32-vs2.3.0.36.26/kernel/sysctl.c
+--- linux-2.6.32/kernel/sysctl.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/sysctl.c 2009-12-03 20:04:56.000000000 +0100
+@@ -124,6 +124,7 @@ static int ngroups_max = NGROUPS_MAX;
extern char modprobe_path[];
extern int modules_disabled;
#endif
#ifdef CONFIG_CHR_DEV_SG
extern int sg_big_buff;
#endif
-@@ -572,6 +573,15 @@ static struct ctl_table kern_table[] = {
+@@ -593,6 +594,15 @@ static struct ctl_table kern_table[] = {
.strategy = &sysctl_string,
},
#endif
#ifdef CONFIG_CHR_DEV_SG
{
.ctl_name = KERN_SG_BIG_BUFF,
-diff -NurpP --minimal linux-2.6.31.6/kernel/sysctl_check.c linux-2.6.31.6-vs2.3.0.36.24/kernel/sysctl_check.c
---- linux-2.6.31.6/kernel/sysctl_check.c 2009-06-11 17:13:26.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/sysctl_check.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/sysctl_check.c linux-2.6.32-vs2.3.0.36.26/kernel/sysctl_check.c
+--- linux-2.6.32/kernel/sysctl_check.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/sysctl_check.c 2009-12-03 20:04:56.000000000 +0100
@@ -39,6 +39,7 @@ static const struct trans_ctl_table tran
{ KERN_PANIC, "panic" },
{}
};
-diff -NurpP --minimal linux-2.6.31.6/kernel/time.c linux-2.6.31.6-vs2.3.0.36.24/kernel/time.c
---- linux-2.6.31.6/kernel/time.c 2009-03-24 14:22:45.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/time.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/time.c linux-2.6.32-vs2.3.0.36.26/kernel/time.c
+--- linux-2.6.32/kernel/time.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/time.c 2009-12-03 20:04:56.000000000 +0100
@@ -63,6 +63,7 @@ EXPORT_SYMBOL(sys_tz);
SYSCALL_DEFINE1(time, time_t __user *, tloc)
{
tv->tv_sec = x.tv_sec;
tv->tv_nsec = x.tv_usec * NSEC_PER_USEC;
}
-diff -NurpP --minimal linux-2.6.31.6/kernel/timer.c linux-2.6.31.6-vs2.3.0.36.24/kernel/timer.c
---- linux-2.6.31.6/kernel/timer.c 2009-09-10 15:26:28.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/timer.c 2009-10-06 04:09:06.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/timer.c linux-2.6.32-vs2.3.0.36.26/kernel/timer.c
+--- linux-2.6.32/kernel/timer.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/timer.c 2009-12-03 20:04:56.000000000 +0100
@@ -39,6 +39,10 @@
#include <linux/kallsyms.h>
- #include <linux/perf_counter.h>
+ #include <linux/perf_event.h>
#include <linux/sched.h>
+#include <linux/vs_base.h>
+#include <linux/vs_cvirt.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
-@@ -1214,12 +1218,6 @@ SYSCALL_DEFINE1(alarm, unsigned int, sec
+@@ -1255,12 +1259,6 @@ SYSCALL_DEFINE1(alarm, unsigned int, sec
#endif
/**
* sys_getpid - return the thread group id of the current process
-@@ -1248,10 +1246,23 @@ SYSCALL_DEFINE0(getppid)
+@@ -1289,10 +1287,23 @@ SYSCALL_DEFINE0(getppid)
rcu_read_lock();
pid = task_tgid_vnr(current->real_parent);
rcu_read_unlock();
SYSCALL_DEFINE0(getuid)
{
/* Only we change this so SMP safe */
-diff -NurpP --minimal linux-2.6.31.6/kernel/user.c linux-2.6.31.6-vs2.3.0.36.24/kernel/user.c
---- linux-2.6.31.6/kernel/user.c 2009-09-10 15:26:28.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/user.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/user.c linux-2.6.32-vs2.3.0.36.26/kernel/user.c
+--- linux-2.6.32/kernel/user.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/user.c 2009-12-03 20:04:56.000000000 +0100
@@ -251,10 +251,10 @@ static struct kobj_type uids_ktype = {
*
* See Documentation/scheduler/sched-design-CFS.txt for ramifications.
goto out_destoy_sched;
/*
-diff -NurpP --minimal linux-2.6.31.6/kernel/user_namespace.c linux-2.6.31.6-vs2.3.0.36.24/kernel/user_namespace.c
---- linux-2.6.31.6/kernel/user_namespace.c 2009-03-24 14:22:45.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/user_namespace.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/user_namespace.c linux-2.6.32-vs2.3.0.36.26/kernel/user_namespace.c
+--- linux-2.6.32/kernel/user_namespace.c 2009-03-24 14:22:45.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/user_namespace.c 2009-12-03 20:04:56.000000000 +0100
@@ -10,6 +10,7 @@
#include <linux/slab.h>
#include <linux/user_namespace.h>
INIT_WORK(&ns->destroyer, free_user_ns_work);
schedule_work(&ns->destroyer);
}
-diff -NurpP --minimal linux-2.6.31.6/kernel/utsname.c linux-2.6.31.6-vs2.3.0.36.24/kernel/utsname.c
---- linux-2.6.31.6/kernel/utsname.c 2009-09-10 15:26:28.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/utsname.c 2009-09-10 16:44:37.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/utsname.c linux-2.6.32-vs2.3.0.36.26/kernel/utsname.c
+--- linux-2.6.32/kernel/utsname.c 2009-09-10 15:26:28.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/kernel/utsname.c 2009-12-03 20:04:56.000000000 +0100
@@ -14,14 +14,17 @@
#include <linux/utsname.h>
#include <linux/err.h>
+ atomic_dec(&vs_global_uts_ns);
kfree(ns);
}
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/cacct.c linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/cacct.c
---- linux-2.6.31.6/kernel/vserver/cacct.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/cacct.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/cacct.c linux-2.6.32-vs2.3.0.36.26/kernel/vserver/cacct.c
+--- linux-2.6.32/kernel/vserver/cacct.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/cacct.c 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,42 @@
+/*
+ * linux/kernel/vserver/cacct.c
+ return 0;
+}
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/cacct_init.h linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/cacct_init.h
---- linux-2.6.31.6/kernel/vserver/cacct_init.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/cacct_init.h 2009-09-29 17:15:22.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/cacct_init.h linux-2.6.32-vs2.3.0.36.26/kernel/vserver/cacct_init.h
+--- linux-2.6.32/kernel/vserver/cacct_init.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/cacct_init.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,25 @@
+
+
+ return;
+}
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/cacct_proc.h linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/cacct_proc.h
---- linux-2.6.31.6/kernel/vserver/cacct_proc.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/cacct_proc.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/cacct_proc.h linux-2.6.32-vs2.3.0.36.26/kernel/vserver/cacct_proc.h
+--- linux-2.6.32/kernel/vserver/cacct_proc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/cacct_proc.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,53 @@
+#ifndef _VX_CACCT_PROC_H
+#define _VX_CACCT_PROC_H
+}
+
+#endif /* _VX_CACCT_PROC_H */
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/context.c linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/context.c
---- linux-2.6.31.6/kernel/vserver/context.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/context.c 2009-11-05 04:18:09.000000000 +0100
-@@ -0,0 +1,1032 @@
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/context.c linux-2.6.32-vs2.3.0.36.26/kernel/vserver/context.c
+--- linux-2.6.32/kernel/vserver/context.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/context.c 2009-12-03 20:04:56.000000000 +0100
+@@ -0,0 +1,1057 @@
+/*
+ * linux/kernel/vserver/context.c
+ *
+ new->vx_flags = VXF_INIT_SET;
+ cap_set_init_eff(new->vx_bcaps);
+ new->vx_ccaps = 0;
-+ // new->vx_cap_bset = current->cap_bset;
++ new->vx_umask = 0;
+
+ new->reboot_cmd = 0;
+ new->exit_code = 0;
+}
+
+
++int vc_get_umask(struct vx_info *vxi, void __user *data)
++{
++ struct vcmd_umask vc_data;
++
++ vc_data.umask = vxi->vx_umask;
++ vc_data.mask = ~0ULL;
++
++ if (copy_to_user(data, &vc_data, sizeof(vc_data)))
++ return -EFAULT;
++ return 0;
++}
++
++int vc_set_umask(struct vx_info *vxi, void __user *data)
++{
++ struct vcmd_umask vc_data;
++
++ if (copy_from_user(&vc_data, data, sizeof(vc_data)))
++ return -EFAULT;
++
++ vxi->vx_umask = vs_mask_flags(vxi->vx_umask,
++ vc_data.umask, vc_data.mask);
++ return 0;
++}
++
++
+int vc_get_badness(struct vx_info *vxi, void __user *data)
+{
+ struct vcmd_badness_v0 vc_data;
+
+EXPORT_SYMBOL_GPL(free_vx_info);
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/cvirt.c linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/cvirt.c
---- linux-2.6.31.6/kernel/vserver/cvirt.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/cvirt.c 2009-11-05 04:21:59.000000000 +0100
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/cvirt.c linux-2.6.32-vs2.3.0.36.26/kernel/vserver/cvirt.c
+--- linux-2.6.32/kernel/vserver/cvirt.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/cvirt.c 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,304 @@
+/*
+ * linux/kernel/vserver/cvirt.c
+
+#endif
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/cvirt_init.h linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/cvirt_init.h
---- linux-2.6.31.6/kernel/vserver/cvirt_init.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/cvirt_init.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/cvirt_init.h linux-2.6.32-vs2.3.0.36.26/kernel/vserver/cvirt_init.h
+--- linux-2.6.32/kernel/vserver/cvirt_init.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/cvirt_init.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,69 @@
+
+
+ return;
+}
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/cvirt_proc.h linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/cvirt_proc.h
---- linux-2.6.31.6/kernel/vserver/cvirt_proc.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/cvirt_proc.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/cvirt_proc.h linux-2.6.32-vs2.3.0.36.26/kernel/vserver/cvirt_proc.h
+--- linux-2.6.32/kernel/vserver/cvirt_proc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/cvirt_proc.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,135 @@
+#ifndef _VX_CVIRT_PROC_H
+#define _VX_CVIRT_PROC_H
+}
+
+#endif /* _VX_CVIRT_PROC_H */
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/debug.c linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/debug.c
---- linux-2.6.31.6/kernel/vserver/debug.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/debug.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/debug.c linux-2.6.32-vs2.3.0.36.26/kernel/vserver/debug.c
+--- linux-2.6.32/kernel/vserver/debug.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/debug.c 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,32 @@
+/*
+ * kernel/vserver/debug.c
+
+EXPORT_SYMBOL_GPL(dump_vx_info);
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/device.c linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/device.c
---- linux-2.6.31.6/kernel/vserver/device.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/device.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/device.c linux-2.6.32-vs2.3.0.36.26/kernel/vserver/device.c
+--- linux-2.6.32/kernel/vserver/device.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/device.c 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,443 @@
+/*
+ * linux/kernel/vserver/device.c
+#endif /* CONFIG_COMPAT */
+
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/dlimit.c linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/dlimit.c
---- linux-2.6.31.6/kernel/vserver/dlimit.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/dlimit.c 2009-09-10 16:11:43.000000000 +0200
-@@ -0,0 +1,522 @@
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/dlimit.c linux-2.6.32-vs2.3.0.36.26/kernel/vserver/dlimit.c
+--- linux-2.6.32/kernel/vserver/dlimit.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/dlimit.c 2009-12-03 20:04:56.000000000 +0100
+@@ -0,0 +1,529 @@
+/*
+ * linux/kernel/vserver/dlimit.c
+ *
+ * Virtual Server: Context Disk Limits
+ *
-+ * Copyright (C) 2004-2007 Herbert Pötzl
++ * Copyright (C) 2004-2009 Herbert Pötzl
+ *
+ * V0.01 initial version
+ * V0.02 compat32 splitup
++ * V0.03 extended interface
+ *
+ */
+
+ goto out_release;
+ if (!(sb = path.dentry->d_inode->i_sb))
+ goto out_release;
++
++ /* sanity checks */
+ if ((reserved != CDLIM_KEEP &&
+ reserved > 100) ||
+ (inodes_used != CDLIM_KEEP &&
+ dli->dl_inodes_used = inodes_used;
+ if (inodes_total != CDLIM_KEEP)
+ dli->dl_inodes_total = inodes_total;
-+ if (space_used != CDLIM_KEEP) {
-+ dli->dl_space_used = space_used;
-+ dli->dl_space_used <<= 10;
-+ }
++ if (space_used != CDLIM_KEEP)
++ dli->dl_space_used = dlimit_space_32to64(
++ space_used, flags, DLIMS_USED);
++
+ if (space_total == CDLIM_INFINITY)
+ dli->dl_space_total = DLIM_INFINITY;
-+ else if (space_total != CDLIM_KEEP) {
-+ dli->dl_space_total = space_total;
-+ dli->dl_space_total <<= 10;
-+ }
++ else if (space_total != CDLIM_KEEP)
++ dli->dl_space_total = dlimit_space_32to64(
++ space_total, flags, DLIMS_TOTAL);
++
+ if (reserved != CDLIM_KEEP)
+ dli->dl_nrlmult = (1 << 10) * (100 - reserved) / 100;
+
+ spin_lock(&dli->dl_lock);
+ *inodes_used = dli->dl_inodes_used;
+ *inodes_total = dli->dl_inodes_total;
-+ *space_used = dli->dl_space_used >> 10;
++
++ *space_used = dlimit_space_64to32(
++ dli->dl_space_used, flags, DLIMS_USED);
++
+ if (dli->dl_space_total == DLIM_INFINITY)
+ *space_total = CDLIM_INFINITY;
+ else
-+ *space_total = dli->dl_space_total >> 10;
++ *space_total = dlimit_space_64to32(
++ dli->dl_space_total, flags, DLIMS_TOTAL);
+
+ *reserved = 100 - ((dli->dl_nrlmult * 100 + 512) >> 10);
+ spin_unlock(&dli->dl_lock);
+EXPORT_SYMBOL_GPL(locate_dl_info);
+EXPORT_SYMBOL_GPL(rcu_free_dl_info);
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/helper.c linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/helper.c
---- linux-2.6.31.6/kernel/vserver/helper.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/helper.c 2009-11-05 04:22:08.000000000 +0100
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/helper.c linux-2.6.32-vs2.3.0.36.26/kernel/vserver/helper.c
+--- linux-2.6.32/kernel/vserver/helper.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/helper.c 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,199 @@
+/*
+ * linux/kernel/vserver/helper.c
+ return do_vshelper(vshelper_path, argv, envp, 1);
+}
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/history.c linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/history.c
---- linux-2.6.31.6/kernel/vserver/history.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/history.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/history.c linux-2.6.32-vs2.3.0.36.26/kernel/vserver/history.c
+--- linux-2.6.32/kernel/vserver/history.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/history.c 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,258 @@
+/*
+ * kernel/vserver/history.c
+
+#endif /* CONFIG_COMPAT */
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/inet.c linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/inet.c
---- linux-2.6.31.6/kernel/vserver/inet.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/inet.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/inet.c linux-2.6.32-vs2.3.0.36.26/kernel/vserver/inet.c
+--- linux-2.6.32/kernel/vserver/inet.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/inet.c 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,225 @@
+
+#include <linux/in.h>
+
+EXPORT_SYMBOL_GPL(ip_v4_find_src);
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/init.c linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/init.c
---- linux-2.6.31.6/kernel/vserver/init.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/init.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/init.c linux-2.6.32-vs2.3.0.36.26/kernel/vserver/init.c
+--- linux-2.6.32/kernel/vserver/init.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/init.c 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,45 @@
+/*
+ * linux/kernel/init.c
+module_init(init_vserver);
+module_exit(exit_vserver);
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/inode.c linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/inode.c
---- linux-2.6.31.6/kernel/vserver/inode.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/inode.c 2009-10-09 20:55:03.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/inode.c linux-2.6.32-vs2.3.0.36.26/kernel/vserver/inode.c
+--- linux-2.6.32/kernel/vserver/inode.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/inode.c 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,433 @@
+/*
+ * linux/kernel/vserver/inode.c
+
+#endif /* CONFIG_PROPAGATE */
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/Kconfig linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/Kconfig
---- linux-2.6.31.6/kernel/vserver/Kconfig 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/Kconfig 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/Kconfig linux-2.6.32-vs2.3.0.36.26/kernel/vserver/Kconfig
+--- linux-2.6.32/kernel/vserver/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/Kconfig 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,251 @@
+#
+# Linux VServer configuration
+ default y
+ select SECURITY_CAPABILITIES
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/limit.c linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/limit.c
---- linux-2.6.31.6/kernel/vserver/limit.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/limit.c 2009-11-05 04:22:22.000000000 +0100
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/limit.c linux-2.6.32-vs2.3.0.36.26/kernel/vserver/limit.c
+--- linux-2.6.32/kernel/vserver/limit.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/limit.c 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,333 @@
+/*
+ * linux/kernel/vserver/limit.c
+ return points;
+}
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/limit_init.h linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/limit_init.h
---- linux-2.6.31.6/kernel/vserver/limit_init.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/limit_init.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/limit_init.h linux-2.6.32-vs2.3.0.36.26/kernel/vserver/limit_init.h
+--- linux-2.6.32/kernel/vserver/limit_init.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/limit_init.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,31 @@
+
+
+ }
+}
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/limit_proc.h linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/limit_proc.h
---- linux-2.6.31.6/kernel/vserver/limit_proc.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/limit_proc.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/limit_proc.h linux-2.6.32-vs2.3.0.36.26/kernel/vserver/limit_proc.h
+--- linux-2.6.32/kernel/vserver/limit_proc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/limit_proc.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,57 @@
+#ifndef _VX_LIMIT_PROC_H
+#define _VX_LIMIT_PROC_H
+#endif /* _VX_LIMIT_PROC_H */
+
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/Makefile linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/Makefile
---- linux-2.6.31.6/kernel/vserver/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/Makefile 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/Makefile linux-2.6.32-vs2.3.0.36.26/kernel/vserver/Makefile
+--- linux-2.6.32/kernel/vserver/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/Makefile 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,18 @@
+#
+# Makefile for the Linux vserver routines.
+vserver-$(CONFIG_VSERVER_MONITOR) += monitor.o
+vserver-$(CONFIG_VSERVER_DEVICE) += device.o
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/monitor.c linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/monitor.c
---- linux-2.6.31.6/kernel/vserver/monitor.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/monitor.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/monitor.c linux-2.6.32-vs2.3.0.36.26/kernel/vserver/monitor.c
+--- linux-2.6.32/kernel/vserver/monitor.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/monitor.c 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,138 @@
+/*
+ * kernel/vserver/monitor.c
+
+#endif /* CONFIG_COMPAT */
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/network.c linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/network.c
---- linux-2.6.31.6/kernel/vserver/network.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/network.c 2009-11-05 03:49:07.000000000 +0100
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/network.c linux-2.6.32-vs2.3.0.36.26/kernel/vserver/network.c
+--- linux-2.6.32/kernel/vserver/network.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/network.c 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,864 @@
+/*
+ * linux/kernel/vserver/network.c
+EXPORT_SYMBOL_GPL(free_nx_info);
+EXPORT_SYMBOL_GPL(unhash_nx_info);
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/proc.c linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/proc.c
---- linux-2.6.31.6/kernel/vserver/proc.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/proc.c 2009-09-10 17:45:54.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/proc.c linux-2.6.32-vs2.3.0.36.26/kernel/vserver/proc.c
+--- linux-2.6.32/kernel/vserver/proc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/proc.c 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,1098 @@
+/*
+ * linux/kernel/vserver/proc.c
+ return buffer - orig;
+}
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/sched.c linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/sched.c
---- linux-2.6.31.6/kernel/vserver/sched.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/sched.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/sched.c linux-2.6.32-vs2.3.0.36.26/kernel/vserver/sched.c
+--- linux-2.6.32/kernel/vserver/sched.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/sched.c 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,414 @@
+/*
+ * linux/kernel/vserver/sched.c
+ return 0;
+}
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/sched_init.h linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/sched_init.h
---- linux-2.6.31.6/kernel/vserver/sched_init.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/sched_init.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/sched_init.h linux-2.6.32-vs2.3.0.36.26/kernel/vserver/sched_init.h
+--- linux-2.6.32/kernel/vserver/sched_init.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/sched_init.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,50 @@
+
+static inline void vx_info_init_sched(struct _vx_sched *sched)
+{
+ return;
+}
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/sched_proc.h linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/sched_proc.h
---- linux-2.6.31.6/kernel/vserver/sched_proc.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/sched_proc.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/sched_proc.h linux-2.6.32-vs2.3.0.36.26/kernel/vserver/sched_proc.h
+--- linux-2.6.32/kernel/vserver/sched_proc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/sched_proc.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,57 @@
+#ifndef _VX_SCHED_PROC_H
+#define _VX_SCHED_PROC_H
+}
+
+#endif /* _VX_SCHED_PROC_H */
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/signal.c linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/signal.c
---- linux-2.6.31.6/kernel/vserver/signal.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/signal.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/signal.c linux-2.6.32-vs2.3.0.36.26/kernel/vserver/signal.c
+--- linux-2.6.32/kernel/vserver/signal.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/signal.c 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,132 @@
+/*
+ * linux/kernel/vserver/signal.c
+ return ret;
+}
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/space.c linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/space.c
---- linux-2.6.31.6/kernel/vserver/space.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/space.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/space.c linux-2.6.32-vs2.3.0.36.26/kernel/vserver/space.c
+--- linux-2.6.32/kernel/vserver/space.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/space.c 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,375 @@
+/*
+ * linux/kernel/vserver/space.c
+ return 0;
+}
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/switch.c linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/switch.c
---- linux-2.6.31.6/kernel/vserver/switch.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/switch.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/switch.c linux-2.6.32-vs2.3.0.36.26/kernel/vserver/switch.c
+--- linux-2.6.32/kernel/vserver/switch.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/switch.c 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,546 @@
+/*
+ * linux/kernel/vserver/switch.c
+}
+
+#endif /* CONFIG_COMPAT */
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/sysctl.c linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/sysctl.c
---- linux-2.6.31.6/kernel/vserver/sysctl.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/sysctl.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/sysctl.c linux-2.6.32-vs2.3.0.36.26/kernel/vserver/sysctl.c
+--- linux-2.6.32/kernel/vserver/sysctl.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/sysctl.c 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,244 @@
+/*
+ * kernel/vserver/sysctl.c
+EXPORT_SYMBOL_GPL(vx_debug_space);
+EXPORT_SYMBOL_GPL(vx_debug_misc);
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/tag.c linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/tag.c
---- linux-2.6.31.6/kernel/vserver/tag.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/tag.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/tag.c linux-2.6.32-vs2.3.0.36.26/kernel/vserver/tag.c
+--- linux-2.6.32/kernel/vserver/tag.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/tag.c 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,63 @@
+/*
+ * linux/kernel/vserver/tag.c
+}
+
+
-diff -NurpP --minimal linux-2.6.31.6/kernel/vserver/vci_config.h linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/vci_config.h
---- linux-2.6.31.6/kernel/vserver/vci_config.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/vci_config.h 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/kernel/vserver/vci_config.h linux-2.6.32-vs2.3.0.36.26/kernel/vserver/vci_config.h
+--- linux-2.6.32/kernel/vserver/vci_config.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/kernel/vserver/vci_config.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,81 @@
+
+/* interface version */
+
-+#define VCI_VERSION 0x00020304
++#define VCI_VERSION 0x00020305
+
+
+enum {
+ 0;
+}
+
-diff -NurpP --minimal linux-2.6.31.6/mm/filemap_xip.c linux-2.6.31.6-vs2.3.0.36.24/mm/filemap_xip.c
---- linux-2.6.31.6/mm/filemap_xip.c 2009-06-11 17:13:27.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/mm/filemap_xip.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/mm/allocpercpu.c linux-2.6.32-vs2.3.0.36.26/mm/allocpercpu.c
+--- linux-2.6.32/mm/allocpercpu.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/mm/allocpercpu.c 2009-12-03 20:04:56.000000000 +0100
+@@ -160,12 +160,14 @@ EXPORT_SYMBOL(__per_cpu_offset);
+
+ void __init setup_per_cpu_areas(void)
+ {
+- unsigned long size, i;
++ unsigned long size, vspc, i;
+ char *ptr;
+ unsigned long nr_possible_cpus = num_possible_cpus();
+
++ vspc = PERCPU_PERCTX * CONFIG_VSERVER_CONTEXTS;
++
+ /* Copy section for each CPU (we discard the original) */
+- size = ALIGN(PERCPU_ENOUGH_ROOM, PAGE_SIZE);
++ size = ALIGN(PERCPU_ENOUGH_ROOM + vspc, PAGE_SIZE);
+ ptr = alloc_bootmem_pages(size * nr_possible_cpus);
+
+ for_each_possible_cpu(i) {
+diff -NurpP --minimal linux-2.6.32/mm/filemap_xip.c linux-2.6.32-vs2.3.0.36.26/mm/filemap_xip.c
+--- linux-2.6.32/mm/filemap_xip.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/mm/filemap_xip.c 2009-12-03 20:04:56.000000000 +0100
@@ -17,6 +17,7 @@
#include <linux/sched.h>
#include <linux/seqlock.h>
#include <asm/tlbflush.h>
#include <asm/io.h>
-diff -NurpP --minimal linux-2.6.31.6/mm/fremap.c linux-2.6.31.6-vs2.3.0.36.24/mm/fremap.c
---- linux-2.6.31.6/mm/fremap.c 2009-03-24 14:22:45.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/mm/fremap.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/mm/fremap.c linux-2.6.32-vs2.3.0.36.26/mm/fremap.c
+--- linux-2.6.32/mm/fremap.c 2009-03-24 14:22:45.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/mm/fremap.c 2009-12-03 20:04:56.000000000 +0100
@@ -16,6 +16,7 @@
#include <linux/module.h>
#include <linux/syscalls.h>
#include <asm/mmu_context.h>
#include <asm/cacheflush.h>
-diff -NurpP --minimal linux-2.6.31.6/mm/hugetlb.c linux-2.6.31.6-vs2.3.0.36.24/mm/hugetlb.c
---- linux-2.6.31.6/mm/hugetlb.c 2009-11-12 12:10:12.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/mm/hugetlb.c 2009-10-05 23:35:52.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/mm/hugetlb.c linux-2.6.32-vs2.3.0.36.26/mm/hugetlb.c
+--- linux-2.6.32/mm/hugetlb.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/mm/hugetlb.c 2009-12-03 20:04:56.000000000 +0100
@@ -24,6 +24,7 @@
#include <asm/io.h>
#include "internal.h"
const unsigned long hugetlb_zero = 0, hugetlb_infinity = ~0UL;
-diff -NurpP --minimal linux-2.6.31.6/mm/memory.c linux-2.6.31.6-vs2.3.0.36.24/mm/memory.c
---- linux-2.6.31.6/mm/memory.c 2009-11-12 12:10:12.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/mm/memory.c 2009-10-05 23:35:52.000000000 +0200
-@@ -55,6 +55,7 @@
+diff -NurpP --minimal linux-2.6.32/mm/memory.c linux-2.6.32-vs2.3.0.36.26/mm/memory.c
+--- linux-2.6.32/mm/memory.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/mm/memory.c 2009-12-03 20:04:56.000000000 +0100
+@@ -56,6 +56,7 @@
#include <linux/kallsyms.h>
#include <linux/swapops.h>
#include <linux/elf.h>
+// #include <linux/vs_memory.h>
+ #include <asm/io.h>
#include <asm/pgalloc.h>
- #include <asm/uaccess.h>
-@@ -613,6 +614,9 @@ static int copy_pte_range(struct mm_stru
+@@ -647,6 +648,9 @@ static int copy_pte_range(struct mm_stru
int progress = 0;
int rss[2];
again:
rss[1] = rss[0] = 0;
dst_pte = pte_alloc_map_lock(dst_mm, dst_pmd, addr, &dst_ptl);
-@@ -2627,6 +2631,8 @@ static int do_anonymous_page(struct mm_s
+@@ -2645,6 +2649,8 @@ static int do_anonymous_page(struct mm_s
/* Allocate our own private page. */
pte_unmap(page_table);
if (unlikely(anon_vma_prepare(vma)))
goto oom;
page = alloc_zeroed_user_highpage_movable(vma, address);
-@@ -2910,6 +2916,7 @@ static inline int handle_pte_fault(struc
+@@ -2936,6 +2942,7 @@ static inline int handle_pte_fault(struc
{
pte_t entry;
spinlock_t *ptl;
entry = *pte;
if (!pte_present(entry)) {
-@@ -2934,9 +2941,12 @@ static inline int handle_pte_fault(struc
+@@ -2960,9 +2967,12 @@ static inline int handle_pte_fault(struc
if (unlikely(!pte_same(*pte, entry)))
goto unlock;
if (flags & FAULT_FLAG_WRITE) {
entry = pte_mkdirty(entry);
}
entry = pte_mkyoung(entry);
-@@ -2954,7 +2964,10 @@ static inline int handle_pte_fault(struc
+@@ -2980,7 +2990,10 @@ static inline int handle_pte_fault(struc
}
unlock:
pte_unmap_unlock(pte, ptl);
}
/*
-diff -NurpP --minimal linux-2.6.31.6/mm/mlock.c linux-2.6.31.6-vs2.3.0.36.24/mm/mlock.c
---- linux-2.6.31.6/mm/mlock.c 2009-11-12 12:10:12.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/mm/mlock.c 2009-10-05 23:35:52.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/mm/mlock.c linux-2.6.32-vs2.3.0.36.26/mm/mlock.c
+--- linux-2.6.32/mm/mlock.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/mm/mlock.c 2009-12-03 20:04:56.000000000 +0100
@@ -18,6 +18,7 @@
#include <linux/rmap.h>
#include <linux/mmzone.h>
#include "internal.h"
-@@ -378,7 +379,7 @@ success:
+@@ -401,7 +402,7 @@ success:
nr_pages = (end - start) >> PAGE_SHIFT;
if (!lock)
nr_pages = -nr_pages;
/*
* vm_flags is protected by the mmap_sem held in write mode.
-@@ -451,7 +452,7 @@ static int do_mlock(unsigned long start,
+@@ -474,7 +475,7 @@ static int do_mlock(unsigned long start,
SYSCALL_DEFINE2(mlock, unsigned long, start, size_t, len)
{
unsigned long lock_limit;
int error = -ENOMEM;
-@@ -464,8 +465,10 @@ SYSCALL_DEFINE2(mlock, unsigned long, st
+@@ -487,8 +488,10 @@ SYSCALL_DEFINE2(mlock, unsigned long, st
len = PAGE_ALIGN(len + (start & ~PAGE_MASK));
start &= PAGE_MASK;
lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
lock_limit >>= PAGE_SHIFT;
-@@ -473,6 +476,7 @@ SYSCALL_DEFINE2(mlock, unsigned long, st
+@@ -496,6 +499,7 @@ SYSCALL_DEFINE2(mlock, unsigned long, st
/* check against resource limits */
if ((locked <= lock_limit) || capable(CAP_IPC_LOCK))
error = do_mlock(start, len, 1);
up_write(¤t->mm->mmap_sem);
return error;
}
-@@ -534,6 +538,8 @@ SYSCALL_DEFINE1(mlockall, int, flags)
+@@ -557,6 +561,8 @@ SYSCALL_DEFINE1(mlockall, int, flags)
lock_limit >>= PAGE_SHIFT;
ret = -ENOMEM;
if (!(flags & MCL_CURRENT) || (current->mm->total_vm <= lock_limit) ||
capable(CAP_IPC_LOCK))
ret = do_mlockall(flags);
-@@ -608,8 +614,10 @@ int account_locked_memory(struct mm_stru
+@@ -631,8 +637,10 @@ int account_locked_memory(struct mm_stru
if (lim < vm)
goto out;
error = 0;
out:
-@@ -623,8 +631,10 @@ void refund_locked_memory(struct mm_stru
+@@ -646,8 +654,10 @@ void refund_locked_memory(struct mm_stru
down_write(&mm->mmap_sem);
up_write(&mm->mmap_sem);
}
-diff -NurpP --minimal linux-2.6.31.6/mm/mmap.c linux-2.6.31.6-vs2.3.0.36.24/mm/mmap.c
---- linux-2.6.31.6/mm/mmap.c 2009-11-12 12:10:12.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/mm/mmap.c 2009-10-05 23:35:52.000000000 +0200
-@@ -1222,7 +1222,8 @@ munmap_back:
+diff -NurpP --minimal linux-2.6.32/mm/mmap.c linux-2.6.32-vs2.3.0.36.26/mm/mmap.c
+--- linux-2.6.32/mm/mmap.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/mm/mmap.c 2009-12-03 20:04:56.000000000 +0100
+@@ -1236,7 +1236,8 @@ munmap_back:
out:
- perf_counter_mmap(vma);
+ perf_event_mmap(vma);
- mm->total_vm += len >> PAGE_SHIFT;
+ // mm->total_vm += len >> PAGE_SHIFT;
vm_stat_account(mm, vm_flags, file, len >> PAGE_SHIFT);
if (vm_flags & VM_LOCKED) {
/*
-@@ -1231,7 +1232,8 @@ out:
+@@ -1245,7 +1246,8 @@ out:
long nr_pages = mlock_vma_pages_range(vma, addr, addr + len);
if (nr_pages < 0)
return nr_pages; /* vma gone! */
} else if ((flags & MAP_POPULATE) && !(flags & MAP_NONBLOCK))
make_pages_present(addr, addr + len);
return addr;
-@@ -1578,9 +1580,9 @@ static int acct_stack_growth(struct vm_a
+@@ -1592,9 +1594,9 @@ static int acct_stack_growth(struct vm_a
return -ENOMEM;
/* Ok, everything looks good - let it rip */
vm_stat_account(mm, vma->vm_flags, vma->vm_file, grow);
return 0;
}
-@@ -1755,7 +1757,8 @@ static void remove_vma_list(struct mm_st
+@@ -1769,7 +1771,8 @@ static void remove_vma_list(struct mm_st
do {
long nrpages = vma_pages(vma);
vm_stat_account(mm, vma->vm_flags, vma->vm_file, -nrpages);
vma = remove_vma(vma);
} while (vma);
-@@ -1927,7 +1930,8 @@ int do_munmap(struct mm_struct *mm, unsi
+@@ -1941,7 +1944,8 @@ int do_munmap(struct mm_struct *mm, unsi
struct vm_area_struct *tmp = vma;
while (tmp && tmp->vm_start < end) {
if (tmp->vm_flags & VM_LOCKED) {
munlock_vma_pages_all(tmp);
}
tmp = tmp->vm_next;
-@@ -2016,6 +2020,8 @@ unsigned long do_brk(unsigned long addr,
+@@ -2030,6 +2034,8 @@ unsigned long do_brk(unsigned long addr,
lock_limit >>= PAGE_SHIFT;
if (locked > lock_limit && !capable(CAP_IPC_LOCK))
return -EAGAIN;
}
/*
-@@ -2042,7 +2048,8 @@ unsigned long do_brk(unsigned long addr,
+@@ -2056,7 +2062,8 @@ unsigned long do_brk(unsigned long addr,
if (mm->map_count > sysctl_max_map_count)
return -ENOMEM;
return -ENOMEM;
/* Can we just expand an old private anonymous mapping? */
-@@ -2068,10 +2075,13 @@ unsigned long do_brk(unsigned long addr,
+@@ -2082,10 +2089,13 @@ unsigned long do_brk(unsigned long addr,
vma->vm_page_prot = vm_get_page_prot(flags);
vma_link(mm, vma, prev, rb_link, rb_parent);
out:
}
return addr;
}
-@@ -2114,6 +2124,11 @@ void exit_mmap(struct mm_struct *mm)
+@@ -2129,6 +2139,11 @@ void exit_mmap(struct mm_struct *mm)
free_pgtables(tlb, vma, FIRST_USER_ADDRESS, 0);
tlb_finish_mmu(tlb, 0, end);
/*
* Walk the list again, actually closing and freeing it,
* with preemption enabled, without holding any MM locks.
-@@ -2153,7 +2168,8 @@ int insert_vm_struct(struct mm_struct *
+@@ -2168,7 +2183,8 @@ int insert_vm_struct(struct mm_struct *
if (__vma && __vma->vm_start < vma->vm_end)
return -ENOMEM;
if ((vma->vm_flags & VM_ACCOUNT) &&
return -ENOMEM;
vma_link(mm, vma, prev, rb_link, rb_parent);
return 0;
-@@ -2229,6 +2245,8 @@ int may_expand_vm(struct mm_struct *mm,
+@@ -2244,6 +2260,8 @@ int may_expand_vm(struct mm_struct *mm,
if (cur + npages > lim)
return 0;
return 1;
}
-@@ -2306,7 +2324,7 @@ int install_special_mapping(struct mm_st
+@@ -2321,7 +2339,7 @@ int install_special_mapping(struct mm_st
return -ENOMEM;
}
- mm->total_vm += len >> PAGE_SHIFT;
+ vx_vmpages_add(mm, len >> PAGE_SHIFT);
- perf_counter_mmap(vma);
+ perf_event_mmap(vma);
-diff -NurpP --minimal linux-2.6.31.6/mm/mremap.c linux-2.6.31.6-vs2.3.0.36.24/mm/mremap.c
---- linux-2.6.31.6/mm/mremap.c 2009-03-24 14:22:45.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/mm/mremap.c 2009-09-10 16:11:43.000000000 +0200
-@@ -19,6 +19,7 @@
+diff -NurpP --minimal linux-2.6.32/mm/mremap.c linux-2.6.32-vs2.3.0.36.26/mm/mremap.c
+--- linux-2.6.32/mm/mremap.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/mm/mremap.c 2009-12-03 20:04:56.000000000 +0100
+@@ -20,6 +20,7 @@
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/mmu_notifier.h>
#include <asm/uaccess.h>
#include <asm/cacheflush.h>
-@@ -220,7 +221,7 @@ static unsigned long move_vma(struct vm_
+@@ -234,7 +235,7 @@ static unsigned long move_vma(struct vm_
* If this were a serious issue, we'd add a flag to do_munmap().
*/
hiwater_vm = mm->hiwater_vm;
vm_stat_account(mm, vma->vm_flags, vma->vm_file, new_len>>PAGE_SHIFT);
if (do_munmap(mm, old_addr, old_len) < 0) {
-@@ -238,7 +239,7 @@ static unsigned long move_vma(struct vm_
+@@ -252,7 +253,7 @@ static unsigned long move_vma(struct vm_
}
if (vm_flags & VM_LOCKED) {
if (new_len > old_len)
mlock_vma_pages_range(new_vma, new_addr + old_len,
new_addr + new_len);
-@@ -349,6 +350,9 @@ unsigned long do_mremap(unsigned long ad
+@@ -363,6 +364,9 @@ unsigned long do_mremap(unsigned long ad
ret = -EAGAIN;
if (locked > lock_limit && !capable(CAP_IPC_LOCK))
goto out;
}
if (!may_expand_vm(mm, (new_len - old_len) >> PAGE_SHIFT)) {
ret = -ENOMEM;
-@@ -377,10 +381,12 @@ unsigned long do_mremap(unsigned long ad
+@@ -391,10 +395,12 @@ unsigned long do_mremap(unsigned long ad
vma_adjust(vma, vma->vm_start,
addr + new_len, vma->vm_pgoff, NULL);
mlock_vma_pages_range(vma, addr + old_len,
addr + new_len);
}
-diff -NurpP --minimal linux-2.6.31.6/mm/nommu.c linux-2.6.31.6-vs2.3.0.36.24/mm/nommu.c
---- linux-2.6.31.6/mm/nommu.c 2009-11-12 12:10:12.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/mm/nommu.c 2009-11-12 12:26:38.000000000 +0100
-@@ -1368,7 +1368,7 @@ unsigned long do_mmap_pgoff(struct file
+diff -NurpP --minimal linux-2.6.32/mm/nommu.c linux-2.6.32-vs2.3.0.36.26/mm/nommu.c
+--- linux-2.6.32/mm/nommu.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/mm/nommu.c 2009-12-03 20:04:56.000000000 +0100
+@@ -1346,7 +1346,7 @@ unsigned long do_mmap_pgoff(struct file
/* okay... we have a mapping; now we have to register it */
result = vma->vm_start;
share:
add_vma_to_mm(current->mm, vma);
-@@ -1628,7 +1628,7 @@ void exit_mmap(struct mm_struct *mm)
+@@ -1606,7 +1606,7 @@ void exit_mmap(struct mm_struct *mm)
kenter("");
while ((vma = mm->mmap)) {
mm->mmap = vma->vm_next;
-diff -NurpP --minimal linux-2.6.31.6/mm/oom_kill.c linux-2.6.31.6-vs2.3.0.36.24/mm/oom_kill.c
---- linux-2.6.31.6/mm/oom_kill.c 2009-06-11 17:13:27.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/mm/oom_kill.c 2009-11-12 12:50:49.000000000 +0100
+diff -NurpP --minimal linux-2.6.32/mm/oom_kill.c linux-2.6.32-vs2.3.0.36.26/mm/oom_kill.c
+--- linux-2.6.32/mm/oom_kill.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/mm/oom_kill.c 2009-12-03 20:04:56.000000000 +0100
@@ -27,6 +27,8 @@
#include <linux/notifier.h>
#include <linux/memcontrol.h>
int sysctl_panic_on_oom;
int sysctl_oom_kill_allocating_task;
-@@ -159,9 +161,21 @@ unsigned long badness(struct task_struct
- points >>= -(p->oomkilladj);
+@@ -186,9 +188,21 @@ unsigned long badness(struct task_struct
+ points >>= -(oom_adj);
}
+ /*
#endif
return points;
}
-@@ -215,8 +229,8 @@ static struct task_struct *select_bad_pr
+@@ -242,8 +256,8 @@ static struct task_struct *select_bad_pr
*/
if (!p->mm)
continue;
continue;
if (mem && !task_in_mem_cgroup(p, mem))
continue;
-@@ -330,8 +344,8 @@ static void __oom_kill_task(struct task_
+@@ -357,8 +371,8 @@ static void __oom_kill_task(struct task_
}
if (verbose)
/*
* We give our sacrificial lamb high priority and access to
-@@ -415,8 +429,8 @@ static int oom_kill_process(struct task_
+@@ -419,8 +433,8 @@ static int oom_kill_process(struct task_
return 0;
}
/* Try to kill a child first */
list_for_each_entry(c, &p->children, sibling) {
-diff -NurpP --minimal linux-2.6.31.6/mm/page_alloc.c linux-2.6.31.6-vs2.3.0.36.24/mm/page_alloc.c
---- linux-2.6.31.6/mm/page_alloc.c 2009-11-12 12:10:12.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/mm/page_alloc.c 2009-10-05 23:35:52.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/mm/page_alloc.c linux-2.6.32-vs2.3.0.36.26/mm/page_alloc.c
+--- linux-2.6.32/mm/page_alloc.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/mm/page_alloc.c 2009-12-03 20:04:56.000000000 +0100
@@ -48,6 +48,8 @@
#include <linux/page_cgroup.h>
#include <linux/debugobjects.h>
#include <linux/kmemleak.h>
+#include <linux/vs_base.h>
+#include <linux/vs_limit.h>
+ #include <trace/events/kmem.h>
#include <asm/tlbflush.h>
- #include <asm/div64.h>
-@@ -2078,6 +2080,9 @@ void si_meminfo(struct sysinfo *val)
+@@ -2130,6 +2132,9 @@ void si_meminfo(struct sysinfo *val)
val->totalhigh = totalhigh_pages;
val->freehigh = nr_free_highpages();
val->mem_unit = PAGE_SIZE;
}
EXPORT_SYMBOL(si_meminfo);
-@@ -2098,6 +2103,9 @@ void si_meminfo_node(struct sysinfo *val
+@@ -2150,6 +2155,9 @@ void si_meminfo_node(struct sysinfo *val
val->freehigh = 0;
#endif
val->mem_unit = PAGE_SIZE;
}
#endif
-diff -NurpP --minimal linux-2.6.31.6/mm/rmap.c linux-2.6.31.6-vs2.3.0.36.24/mm/rmap.c
---- linux-2.6.31.6/mm/rmap.c 2009-09-10 15:26:28.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/mm/rmap.c 2009-09-10 16:11:43.000000000 +0200
-@@ -50,6 +50,7 @@
+diff -NurpP --minimal linux-2.6.32/mm/rmap.c linux-2.6.32-vs2.3.0.36.26/mm/rmap.c
+--- linux-2.6.32/mm/rmap.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/mm/rmap.c 2009-12-03 20:04:56.000000000 +0100
+@@ -55,6 +55,7 @@
#include <linux/memcontrol.h>
#include <linux/mmu_notifier.h>
#include <linux/migrate.h>
#include <asm/tlbflush.h>
-diff -NurpP --minimal linux-2.6.31.6/mm/shmem.c linux-2.6.31.6-vs2.3.0.36.24/mm/shmem.c
---- linux-2.6.31.6/mm/shmem.c 2009-09-10 15:26:28.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/mm/shmem.c 2009-09-10 16:11:43.000000000 +0200
-@@ -1777,7 +1777,7 @@ static int shmem_statfs(struct dentry *d
+diff -NurpP --minimal linux-2.6.32/mm/shmem.c linux-2.6.32-vs2.3.0.36.26/mm/shmem.c
+--- linux-2.6.32/mm/shmem.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/mm/shmem.c 2009-12-03 20:04:56.000000000 +0100
+@@ -1781,7 +1781,7 @@ static int shmem_statfs(struct dentry *d
{
struct shmem_sb_info *sbinfo = SHMEM_SB(dentry->d_sb);
buf->f_bsize = PAGE_CACHE_SIZE;
buf->f_namelen = NAME_MAX;
spin_lock(&sbinfo->stat_lock);
-@@ -2346,7 +2346,7 @@ static int shmem_fill_super(struct super
+@@ -2346,7 +2346,7 @@ int shmem_fill_super(struct super_block
sb->s_maxbytes = SHMEM_MAX_BYTES;
sb->s_blocksize = PAGE_CACHE_SIZE;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_op = &shmem_ops;
sb->s_time_gran = 1;
#ifdef CONFIG_TMPFS_POSIX_ACL
-diff -NurpP --minimal linux-2.6.31.6/mm/slab.c linux-2.6.31.6-vs2.3.0.36.24/mm/slab.c
---- linux-2.6.31.6/mm/slab.c 2009-09-10 15:26:28.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/mm/slab.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/mm/slab.c linux-2.6.32-vs2.3.0.36.26/mm/slab.c
+--- linux-2.6.32/mm/slab.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/mm/slab.c 2009-12-03 20:04:56.000000000 +0100
@@ -431,6 +431,8 @@ static void kmem_list3_init(struct kmem_
#define STATS_INC_FREEMISS(x) do { } while (0)
#endif
kmemcheck_slab_free(cachep, objp, obj_size(cachep));
-diff -NurpP --minimal linux-2.6.31.6/mm/slab_vs.h linux-2.6.31.6-vs2.3.0.36.24/mm/slab_vs.h
---- linux-2.6.31.6/mm/slab_vs.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/mm/slab_vs.h 2009-11-05 04:25:04.000000000 +0100
+diff -NurpP --minimal linux-2.6.32/mm/slab_vs.h linux-2.6.32-vs2.3.0.36.26/mm/slab_vs.h
+--- linux-2.6.32/mm/slab_vs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/mm/slab_vs.h 2009-12-03 20:04:56.000000000 +0100
@@ -0,0 +1,29 @@
+
+#include <linux/vserver/context.h>
+ atomic_sub(cachep->buffer_size, &vxi->cacct.slab[what]);
+}
+
-diff -NurpP --minimal linux-2.6.31.6/mm/swapfile.c linux-2.6.31.6-vs2.3.0.36.24/mm/swapfile.c
---- linux-2.6.31.6/mm/swapfile.c 2009-11-12 12:10:12.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/mm/swapfile.c 2009-11-12 12:26:38.000000000 +0100
+diff -NurpP --minimal linux-2.6.32/mm/swapfile.c linux-2.6.32-vs2.3.0.36.26/mm/swapfile.c
+--- linux-2.6.32/mm/swapfile.c 2009-12-03 20:02:58.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/mm/swapfile.c 2009-12-03 20:04:56.000000000 +0100
@@ -34,6 +34,8 @@
#include <asm/tlbflush.h>
#include <linux/swapops.h>
static DEFINE_SPINLOCK(swap_lock);
static unsigned int nr_swapfiles;
-@@ -1678,6 +1680,8 @@ static void *swap_next(struct seq_file *
+@@ -1680,6 +1682,8 @@ static void *swap_next(struct seq_file *
if (v == SEQ_START_TOKEN)
ptr = swap_info;
else {
ptr = v;
ptr++;
}
-@@ -1705,6 +1709,16 @@ static int swap_show(struct seq_file *sw
+@@ -1707,6 +1711,16 @@ static int swap_show(struct seq_file *sw
if (ptr == SEQ_START_TOKEN) {
seq_puts(swap,"Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n");
return 0;
}
-@@ -2060,6 +2074,8 @@ void si_swapinfo(struct sysinfo *val)
+@@ -2064,6 +2078,8 @@ void si_swapinfo(struct sysinfo *val)
val->freeswap = nr_swap_pages + nr_to_be_unused;
val->totalswap = total_swap_pages + nr_to_be_unused;
spin_unlock(&swap_lock);
}
/*
-diff -NurpP --minimal linux-2.6.31.6/net/core/dev.c linux-2.6.31.6-vs2.3.0.36.24/net/core/dev.c
---- linux-2.6.31.6/net/core/dev.c 2009-11-12 12:10:12.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/core/dev.c 2009-11-08 16:59:44.000000000 +0100
+diff -NurpP --minimal linux-2.6.32/net/core/dev.c linux-2.6.32-vs2.3.0.36.26/net/core/dev.c
+--- linux-2.6.32/net/core/dev.c 2009-12-03 20:02:59.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/core/dev.c 2009-12-03 20:04:56.000000000 +0100
@@ -126,6 +126,7 @@
#include <linux/in.h>
#include <linux/jhash.h>
#include <trace/events/napi.h>
#include "net-sysfs.h"
-@@ -586,7 +587,8 @@ struct net_device *__dev_get_by_name(str
+@@ -591,7 +592,8 @@ struct net_device *__dev_get_by_name(str
hlist_for_each(p, dev_name_hash(net, name)) {
struct net_device *dev
= hlist_entry(p, struct net_device, name_hlist);
return dev;
}
return NULL;
-@@ -635,7 +637,8 @@ struct net_device *__dev_get_by_index(st
+@@ -642,7 +644,8 @@ struct net_device *__dev_get_by_index(st
hlist_for_each(p, dev_index_hash(net, ifindex)) {
struct net_device *dev
= hlist_entry(p, struct net_device, index_hlist);
return dev;
}
return NULL;
-@@ -686,10 +689,12 @@ struct net_device *dev_getbyhwaddr(struc
+@@ -695,10 +698,12 @@ struct net_device *dev_getbyhwaddr(struc
ASSERT_RTNL();
return NULL;
}
-@@ -701,9 +706,11 @@ struct net_device *__dev_getfirstbyhwtyp
+@@ -709,9 +714,11 @@ struct net_device *__dev_getfirstbyhwtyp
struct net_device *dev;
ASSERT_RTNL();
return NULL;
}
-@@ -821,6 +828,8 @@ static int __dev_alloc_name(struct net *
+@@ -830,6 +837,8 @@ static int __dev_alloc_name(struct net *
continue;
if (i < 0 || i >= max_netdevices)
continue;
/* avoid cases where sscanf is not exact inverse of printf */
snprintf(buf, IFNAMSIZ, name, i);
-@@ -2941,6 +2950,8 @@ static int dev_ifconf(struct net *net, c
+@@ -2984,6 +2993,8 @@ static int dev_ifconf(struct net *net, c
total = 0;
for_each_netdev(net, dev) {
for (i = 0; i < NPROTO; i++) {
if (gifconf_list[i]) {
int done;
-@@ -3009,6 +3020,9 @@ static void dev_seq_printf_stats(struct
+@@ -3052,6 +3063,9 @@ static void dev_seq_printf_stats(struct
{
const struct net_device_stats *stats = dev_get_stats(dev);
seq_printf(seq, "%6s:%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu "
"%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
dev->name, stats->rx_bytes, stats->rx_packets,
-@@ -5257,6 +5271,15 @@ int dev_change_net_namespace(struct net_
+@@ -5313,6 +5327,15 @@ int dev_change_net_namespace(struct net_
goto out;
#endif
/* Ensure the device has been registrered */
err = -EINVAL;
if (dev->reg_state != NETREG_REGISTERED)
-@@ -5317,6 +5340,8 @@ int dev_change_net_namespace(struct net_
-
- netdev_unregister_kobject(dev);
-
-+ netdev_unregister_kobject(dev);
-+
- /* Actually switch the network namespace */
- dev_net_set(dev, net);
-
-diff -NurpP --minimal linux-2.6.31.6/net/core/net-sysfs.c linux-2.6.31.6-vs2.3.0.36.24/net/core/net-sysfs.c
---- linux-2.6.31.6/net/core/net-sysfs.c 2009-09-10 15:26:29.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/core/net-sysfs.c 2009-09-10 16:11:43.000000000 +0200
-@@ -513,6 +513,9 @@ int netdev_register_kobject(struct net_d
- if (dev_net(net) != &init_net)
- return 0;
-
-+ if (dev_net(net) != &init_net)
-+ return 0;
-+
- return device_add(dev);
- }
-
-diff -NurpP --minimal linux-2.6.31.6/net/core/rtnetlink.c linux-2.6.31.6-vs2.3.0.36.24/net/core/rtnetlink.c
---- linux-2.6.31.6/net/core/rtnetlink.c 2009-06-11 17:13:29.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/core/rtnetlink.c 2009-11-05 03:50:06.000000000 +0100
-@@ -690,6 +690,8 @@ static int rtnl_dump_ifinfo(struct sk_bu
+diff -NurpP --minimal linux-2.6.32/net/core/rtnetlink.c linux-2.6.32-vs2.3.0.36.26/net/core/rtnetlink.c
+--- linux-2.6.32/net/core/rtnetlink.c 2009-12-03 20:02:59.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/core/rtnetlink.c 2009-12-03 20:04:56.000000000 +0100
+@@ -688,6 +688,8 @@ static int rtnl_dump_ifinfo(struct sk_bu
idx = 0;
for_each_netdev(net, dev) {
if (idx < s_idx)
goto cont;
if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK,
-@@ -1235,6 +1237,9 @@ void rtmsg_ifinfo(int type, struct net_d
+@@ -1222,6 +1224,9 @@ void rtmsg_ifinfo(int type, struct net_d
struct sk_buff *skb;
int err = -ENOBUFS;
skb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL);
if (skb == NULL)
goto errout;
-diff -NurpP --minimal linux-2.6.31.6/net/core/sock.c linux-2.6.31.6-vs2.3.0.36.24/net/core/sock.c
---- linux-2.6.31.6/net/core/sock.c 2009-11-12 12:10:12.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/core/sock.c 2009-11-05 04:25:28.000000000 +0100
+diff -NurpP --minimal linux-2.6.32/net/core/sock.c linux-2.6.32-vs2.3.0.36.26/net/core/sock.c
+--- linux-2.6.32/net/core/sock.c 2009-12-03 20:02:59.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/core/sock.c 2009-12-03 20:04:56.000000000 +0100
@@ -125,6 +125,10 @@
#include <linux/ipsec.h>
#ifdef CONFIG_INET
#include <net/tcp.h>
-@@ -974,6 +978,8 @@ static struct sock *sk_prot_alloc(struct
+@@ -984,6 +988,8 @@ static struct sock *sk_prot_alloc(struct
if (!try_module_get(prot->owner))
goto out_free_sec;
}
return sk;
-@@ -1053,6 +1059,11 @@ static void __sk_free(struct sock *sk)
+@@ -1063,6 +1069,11 @@ static void __sk_free(struct sock *sk)
__func__, atomic_read(&sk->sk_omem_alloc));
put_net(sock_net(sk));
sk_prot_free(sk->sk_prot_creator, sk);
}
-@@ -1100,6 +1111,8 @@ struct sock *sk_clone(const struct sock
+@@ -1110,6 +1121,8 @@ struct sock *sk_clone(const struct sock
/* SANITY */
get_net(sock_net(newsk));
sk_node_init(&newsk->sk_node);
sock_lock_init(newsk);
bh_lock_sock(newsk);
-@@ -1154,6 +1167,12 @@ struct sock *sk_clone(const struct sock
+@@ -1164,6 +1177,12 @@ struct sock *sk_clone(const struct sock
smp_wmb();
atomic_set(&newsk->sk_refcnt, 2);
/*
* Increment the counter in the same struct proto as the master
* sock (sk_refcnt_debug_inc uses newsk->sk_prot->socks, that
-@@ -1872,6 +1891,12 @@ void sock_init_data(struct socket *sock,
+@@ -1882,6 +1901,12 @@ void sock_init_data(struct socket *sock,
sk->sk_stamp = ktime_set(-1L, 0);
/*
* Before updating sk_refcnt, we must commit prior changes to memory
* (Documentation/RCU/rculist_nulls.txt for details)
-diff -NurpP --minimal linux-2.6.31.6/net/ipv4/af_inet.c linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/af_inet.c
---- linux-2.6.31.6/net/ipv4/af_inet.c 2009-09-10 15:26:29.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/af_inet.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/net/ipv4/af_inet.c linux-2.6.32-vs2.3.0.36.26/net/ipv4/af_inet.c
+--- linux-2.6.32/net/ipv4/af_inet.c 2009-12-03 20:02:59.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv4/af_inet.c 2009-12-03 20:04:56.000000000 +0100
@@ -115,6 +115,7 @@
#ifdef CONFIG_IP_MROUTE
#include <linux/mroute.h>
/* The inetsw table contains everything that inet_create needs to
-@@ -324,9 +325,12 @@ lookup_protocol:
+@@ -325,9 +326,12 @@ lookup_protocol:
}
err = -EPERM;
err = -EAFNOSUPPORT;
if (!inet_netns_ok(net, protocol))
goto out_rcu_unlock;
-@@ -444,6 +448,7 @@ int inet_bind(struct socket *sock, struc
+@@ -447,6 +451,7 @@ int inet_bind(struct socket *sock, struc
struct sockaddr_in *addr = (struct sockaddr_in *)uaddr;
struct sock *sk = sock->sk;
struct inet_sock *inet = inet_sk(sk);
unsigned short snum;
int chk_addr_ret;
int err;
-@@ -457,7 +462,11 @@ int inet_bind(struct socket *sock, struc
+@@ -460,7 +465,11 @@ int inet_bind(struct socket *sock, struc
if (addr_len < sizeof(struct sockaddr_in))
goto out;
/* Not specified by any standard per-se, however it breaks too
* many applications when removed. It is unfortunate since
-@@ -469,7 +478,7 @@ int inet_bind(struct socket *sock, struc
+@@ -472,7 +481,7 @@ int inet_bind(struct socket *sock, struc
err = -EADDRNOTAVAIL;
if (!sysctl_ip_nonlocal_bind &&
!(inet->freebind || inet->transparent) &&
chk_addr_ret != RTN_LOCAL &&
chk_addr_ret != RTN_MULTICAST &&
chk_addr_ret != RTN_BROADCAST)
-@@ -494,7 +503,7 @@ int inet_bind(struct socket *sock, struc
+@@ -497,7 +506,7 @@ int inet_bind(struct socket *sock, struc
if (sk->sk_state != TCP_CLOSE || inet->num)
goto out_release_sock;
if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
inet->saddr = 0; /* Use device */
-@@ -687,11 +696,13 @@ int inet_getname(struct socket *sock, st
+@@ -694,11 +703,13 @@ int inet_getname(struct socket *sock, st
peer == 1))
return -ENOTCONN;
sin->sin_port = inet->dport;
sin->sin_port = inet->sport;
sin->sin_addr.s_addr = addr;
}
-diff -NurpP --minimal linux-2.6.31.6/net/ipv4/devinet.c linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/devinet.c
---- linux-2.6.31.6/net/ipv4/devinet.c 2009-09-10 15:26:29.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/devinet.c 2009-11-05 03:50:40.000000000 +0100
+diff -NurpP --minimal linux-2.6.32/net/ipv4/devinet.c linux-2.6.32-vs2.3.0.36.26/net/ipv4/devinet.c
+--- linux-2.6.32/net/ipv4/devinet.c 2009-12-03 20:02:59.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv4/devinet.c 2009-12-03 20:04:56.000000000 +0100
@@ -413,6 +413,7 @@ struct in_device *inetdev_by_index(struc
return in_dev;
}
if (!buf) {
done += sizeof(ifr);
continue;
-@@ -1164,6 +1174,7 @@ static int inet_dump_ifaddr(struct sk_bu
+@@ -1174,6 +1184,7 @@ static int inet_dump_ifaddr(struct sk_bu
struct net_device *dev;
struct in_device *in_dev;
struct in_ifaddr *ifa;
int s_ip_idx, s_idx = cb->args[0];
s_ip_idx = ip_idx = cb->args[1];
-@@ -1178,6 +1189,8 @@ static int inet_dump_ifaddr(struct sk_bu
+@@ -1188,6 +1199,8 @@ static int inet_dump_ifaddr(struct sk_bu
for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;
ifa = ifa->ifa_next, ip_idx++) {
if (ip_idx < s_ip_idx)
continue;
if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
-diff -NurpP --minimal linux-2.6.31.6/net/ipv4/fib_hash.c linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/fib_hash.c
---- linux-2.6.31.6/net/ipv4/fib_hash.c 2009-09-10 15:26:29.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/fib_hash.c 2009-11-05 03:50:54.000000000 +0100
+diff -NurpP --minimal linux-2.6.32/net/ipv4/fib_hash.c linux-2.6.32-vs2.3.0.36.26/net/ipv4/fib_hash.c
+--- linux-2.6.32/net/ipv4/fib_hash.c 2009-09-10 15:26:29.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv4/fib_hash.c 2009-12-03 20:04:56.000000000 +0100
@@ -1021,7 +1021,7 @@ static int fib_seq_show(struct seq_file
prefix = f->fn_key;
mask = FZ_MASK(iter->zone);
seq_printf(seq,
"%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u%n",
fi->fib_dev ? fi->fib_dev->name : "*", prefix,
-diff -NurpP --minimal linux-2.6.31.6/net/ipv4/inet_connection_sock.c linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/inet_connection_sock.c
---- linux-2.6.31.6/net/ipv4/inet_connection_sock.c 2009-06-11 17:13:29.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/inet_connection_sock.c 2009-11-05 04:54:58.000000000 +0100
+diff -NurpP --minimal linux-2.6.32/net/ipv4/inet_connection_sock.c linux-2.6.32-vs2.3.0.36.26/net/ipv4/inet_connection_sock.c
+--- linux-2.6.32/net/ipv4/inet_connection_sock.c 2009-12-03 20:02:59.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv4/inet_connection_sock.c 2009-12-03 20:04:56.000000000 +0100
@@ -49,10 +49,40 @@ void inet_get_local_port_range(int *low,
}
EXPORT_SYMBOL(inet_get_local_port_range);
break;
}
}
-diff -NurpP --minimal linux-2.6.31.6/net/ipv4/inet_diag.c linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/inet_diag.c
---- linux-2.6.31.6/net/ipv4/inet_diag.c 2009-09-10 15:26:29.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/inet_diag.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/net/ipv4/inet_diag.c linux-2.6.32-vs2.3.0.36.26/net/ipv4/inet_diag.c
+--- linux-2.6.32/net/ipv4/inet_diag.c 2009-09-10 15:26:29.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv4/inet_diag.c 2009-12-03 20:04:56.000000000 +0100
@@ -32,6 +32,8 @@
#include <linux/stddef.h>
if (num < s_num)
goto next_dying;
if (r->id.idiag_sport != tw->tw_sport &&
-diff -NurpP --minimal linux-2.6.31.6/net/ipv4/inet_hashtables.c linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/inet_hashtables.c
---- linux-2.6.31.6/net/ipv4/inet_hashtables.c 2009-06-11 17:13:29.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/inet_hashtables.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/net/ipv4/inet_hashtables.c linux-2.6.32-vs2.3.0.36.26/net/ipv4/inet_hashtables.c
+--- linux-2.6.32/net/ipv4/inet_hashtables.c 2009-06-11 17:13:29.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv4/inet_hashtables.c 2009-12-03 20:04:56.000000000 +0100
@@ -21,6 +21,7 @@
#include <net/inet_connection_sock.h>
/*
* if the nulls value we got at the end of this lookup is
* not the expected one, we must restart lookup.
-diff -NurpP --minimal linux-2.6.31.6/net/ipv4/netfilter/nf_nat_helper.c linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/netfilter/nf_nat_helper.c
---- linux-2.6.31.6/net/ipv4/netfilter/nf_nat_helper.c 2009-09-10 15:26:29.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/netfilter/nf_nat_helper.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/net/ipv4/netfilter/nf_nat_helper.c linux-2.6.32-vs2.3.0.36.26/net/ipv4/netfilter/nf_nat_helper.c
+--- linux-2.6.32/net/ipv4/netfilter/nf_nat_helper.c 2009-12-03 20:02:59.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv4/netfilter/nf_nat_helper.c 2009-12-03 20:04:56.000000000 +0100
@@ -19,6 +19,7 @@
#include <net/route.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_ecache.h>
-diff -NurpP --minimal linux-2.6.31.6/net/ipv4/netfilter.c linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/netfilter.c
---- linux-2.6.31.6/net/ipv4/netfilter.c 2009-09-10 15:26:29.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/netfilter.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/net/ipv4/netfilter.c linux-2.6.32-vs2.3.0.36.26/net/ipv4/netfilter.c
+--- linux-2.6.32/net/ipv4/netfilter.c 2009-09-10 15:26:29.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv4/netfilter.c 2009-12-03 20:04:56.000000000 +0100
@@ -4,7 +4,7 @@
#include <linux/netfilter_ipv4.h>
#include <linux/ip.h>
#include <net/xfrm.h>
#include <net/ip.h>
#include <net/netfilter/nf_queue.h>
-diff -NurpP --minimal linux-2.6.31.6/net/ipv4/raw.c linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/raw.c
---- linux-2.6.31.6/net/ipv4/raw.c 2009-09-10 15:26:29.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/raw.c 2009-09-10 17:17:12.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/net/ipv4/raw.c linux-2.6.32-vs2.3.0.36.26/net/ipv4/raw.c
+--- linux-2.6.32/net/ipv4/raw.c 2009-12-03 20:02:59.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv4/raw.c 2009-12-03 20:04:56.000000000 +0100
@@ -117,7 +117,7 @@ static struct sock *__raw_v4_lookup(stru
if (net_eq(sock_net(sk), net) && inet->num == num &&
!(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif))
goto found; /* gotcha */
}
-@@ -372,6 +372,12 @@ static int raw_send_hdrinc(struct sock *
+@@ -383,6 +383,12 @@ static int raw_send_hdrinc(struct sock *
icmp_out_count(net, ((struct icmphdr *)
skb_transport_header(skb))->type);
err = NF_HOOK(PF_INET, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
dst_output);
if (err > 0)
-@@ -383,6 +389,7 @@ out:
-
- error_fault:
- err = -EFAULT;
-+error_free:
- kfree_skb(skb);
- error:
- IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS);
-@@ -551,6 +558,13 @@ static int raw_sendmsg(struct kiocb *ioc
+@@ -563,6 +569,13 @@ static int raw_sendmsg(struct kiocb *ioc
}
security_sk_classify_flow(sk, &fl);
err = ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 1);
}
if (err)
-@@ -620,17 +634,19 @@ static int raw_bind(struct sock *sk, str
+@@ -635,17 +648,19 @@ static int raw_bind(struct sock *sk, str
{
struct inet_sock *inet = inet_sk(sk);
struct sockaddr_in *addr = (struct sockaddr_in *) uaddr;
if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
inet->saddr = 0; /* Use device */
sk_dst_reset(sk);
-@@ -682,7 +698,8 @@ static int raw_recvmsg(struct kiocb *ioc
+@@ -697,7 +712,8 @@ static int raw_recvmsg(struct kiocb *ioc
/* Copy the address. */
if (sin) {
sin->sin_family = AF_INET;
sin->sin_port = 0;
memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
}
-@@ -860,7 +877,8 @@ static struct sock *raw_get_first(struct
+@@ -875,7 +891,8 @@ static struct sock *raw_get_first(struct
struct hlist_node *node;
sk_for_each(sk, node, &state->h->ht[state->bucket])
goto found;
}
sk = NULL;
-@@ -876,7 +894,8 @@ static struct sock *raw_get_next(struct
+@@ -891,7 +908,8 @@ static struct sock *raw_get_next(struct
sk = sk_next(sk);
try_again:
;
if (!sk && ++state->bucket < RAW_HTABLE_SIZE) {
sk = sk_head(&state->h->ht[state->bucket]);
-@@ -935,7 +954,10 @@ static void raw_sock_seq_show(struct seq
+@@ -950,7 +968,10 @@ static void raw_sock_seq_show(struct seq
seq_printf(seq, "%4d: %08X:%04X %08X:%04X"
" %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %d\n",
sk_wmem_alloc_get(sp),
sk_rmem_alloc_get(sp),
0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp),
-diff -NurpP --minimal linux-2.6.31.6/net/ipv4/tcp.c linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/tcp.c
---- linux-2.6.31.6/net/ipv4/tcp.c 2009-09-10 15:26:29.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/tcp.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/net/ipv4/tcp.c linux-2.6.32-vs2.3.0.36.26/net/ipv4/tcp.c
+--- linux-2.6.32/net/ipv4/tcp.c 2009-12-03 20:02:59.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv4/tcp.c 2009-12-03 20:04:56.000000000 +0100
@@ -264,6 +264,7 @@
#include <linux/cache.h>
#include <linux/err.h>
#include <net/icmp.h>
#include <net/tcp.h>
-diff -NurpP --minimal linux-2.6.31.6/net/ipv4/tcp_ipv4.c linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/tcp_ipv4.c
---- linux-2.6.31.6/net/ipv4/tcp_ipv4.c 2009-09-10 15:26:29.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/tcp_ipv4.c 2009-09-10 16:11:43.000000000 +0200
-@@ -1887,6 +1887,12 @@ static void *listening_get_next(struct s
+diff -NurpP --minimal linux-2.6.32/net/ipv4/tcp_ipv4.c linux-2.6.32-vs2.3.0.36.26/net/ipv4/tcp_ipv4.c
+--- linux-2.6.32/net/ipv4/tcp_ipv4.c 2009-12-03 20:03:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv4/tcp_ipv4.c 2009-12-03 20:04:56.000000000 +0100
+@@ -1925,6 +1925,12 @@ static void *listening_get_next(struct s
req = req->dl_next;
while (1) {
while (req) {
if (req->rsk_ops->family == st->family) {
cur = req;
goto out;
-@@ -1911,6 +1917,10 @@ get_req:
+@@ -1949,6 +1955,10 @@ get_req:
}
get_sk:
sk_nulls_for_each_from(sk, node) {
if (sk->sk_family == st->family && net_eq(sock_net(sk), net)) {
cur = sk;
goto out;
-@@ -1974,6 +1984,11 @@ static void *established_get_first(struc
+@@ -2012,6 +2022,11 @@ static void *established_get_first(struc
spin_lock_bh(lock);
sk_nulls_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) {
if (sk->sk_family != st->family ||
!net_eq(sock_net(sk), net)) {
continue;
-@@ -1984,6 +1999,11 @@ static void *established_get_first(struc
+@@ -2022,6 +2037,11 @@ static void *established_get_first(struc
st->state = TCP_SEQ_STATE_TIME_WAIT;
inet_twsk_for_each(tw, node,
&tcp_hashinfo.ehash[st->bucket].twchain) {
if (tw->tw_family != st->family ||
!net_eq(twsk_net(tw), net)) {
continue;
-@@ -2012,7 +2032,9 @@ static void *established_get_next(struct
+@@ -2050,7 +2070,9 @@ static void *established_get_next(struct
tw = cur;
tw = tw_next(tw);
get_tw:
tw = tw_next(tw);
}
if (tw) {
-@@ -2035,6 +2057,11 @@ get_tw:
+@@ -2073,6 +2095,11 @@ get_tw:
sk = sk_nulls_next(sk);
sk_nulls_for_each_from(sk, node) {
if (sk->sk_family == st->family && net_eq(sock_net(sk), net))
goto found;
}
-@@ -2186,9 +2213,9 @@ static void get_openreq4(struct sock *sk
+@@ -2224,9 +2251,9 @@ static void get_openreq4(struct sock *sk
seq_printf(f, "%4d: %08X:%04X %08X:%04X"
" %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %p%n",
i,
ntohs(ireq->rmt_port),
TCP_SYN_RECV,
0, 0, /* could print option size, but that is af dependent. */
-@@ -2231,7 +2258,10 @@ static void get_tcp4_sock(struct sock *s
+@@ -2269,7 +2296,10 @@ static void get_tcp4_sock(struct sock *s
seq_printf(f, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX "
"%08X %5d %8d %lu %d %p %lu %lu %u %u %d%n",
tp->write_seq - tp->snd_una,
sk->sk_state == TCP_LISTEN ? sk->sk_ack_backlog :
(tp->rcv_nxt - tp->copied_seq),
-@@ -2267,7 +2297,10 @@ static void get_timewait4_sock(struct in
+@@ -2305,7 +2335,10 @@ static void get_timewait4_sock(struct in
seq_printf(f, "%4d: %08X:%04X %08X:%04X"
" %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p%n",
3, jiffies_to_clock_t(ttd), 0, 0, 0, 0,
atomic_read(&tw->tw_refcnt), tw, len);
}
-diff -NurpP --minimal linux-2.6.31.6/net/ipv4/tcp_minisocks.c linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/tcp_minisocks.c
---- linux-2.6.31.6/net/ipv4/tcp_minisocks.c 2009-11-12 12:10:12.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/tcp_minisocks.c 2009-10-15 03:49:19.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/net/ipv4/tcp_minisocks.c linux-2.6.32-vs2.3.0.36.26/net/ipv4/tcp_minisocks.c
+--- linux-2.6.32/net/ipv4/tcp_minisocks.c 2009-12-03 20:03:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv4/tcp_minisocks.c 2009-12-03 20:04:56.000000000 +0100
@@ -26,6 +26,10 @@
#include <net/inet_common.h>
#include <net/xfrm.h>
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
if (tw->tw_family == PF_INET6) {
struct ipv6_pinfo *np = inet6_sk(sk);
-diff -NurpP --minimal linux-2.6.31.6/net/ipv4/udp.c linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/udp.c
---- linux-2.6.31.6/net/ipv4/udp.c 2009-09-10 15:26:30.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv4/udp.c 2009-11-05 04:54:58.000000000 +0100
-@@ -222,14 +222,7 @@ fail:
- return error;
+diff -NurpP --minimal linux-2.6.32/net/ipv4/udp.c linux-2.6.32-vs2.3.0.36.26/net/ipv4/udp.c
+--- linux-2.6.32/net/ipv4/udp.c 2009-12-03 20:03:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv4/udp.c 2009-12-03 20:04:56.000000000 +0100
+@@ -224,14 +224,7 @@ fail:
}
+ EXPORT_SYMBOL(udp_lib_get_port);
-static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
-{
- struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2);
-
-- return ( !ipv6_only_sock(sk2) &&
-- (!inet1->rcv_saddr || !inet2->rcv_saddr ||
-- inet1->rcv_saddr == inet2->rcv_saddr ));
+- return (!ipv6_only_sock(sk2) &&
+- (!inet1->rcv_saddr || !inet2->rcv_saddr ||
+- inet1->rcv_saddr == inet2->rcv_saddr));
-}
+extern int ipv4_rcv_saddr_equal(const struct sock *, const struct sock *);
int udp_v4_get_port(struct sock *sk, unsigned short snum)
{
-@@ -251,6 +244,11 @@ static inline int compute_score(struct s
+@@ -253,6 +246,11 @@ static inline int compute_score(struct s
if (inet->rcv_saddr != daddr)
return -1;
score += 2;
}
if (inet->daddr) {
if (inet->daddr != saddr)
-@@ -271,6 +269,7 @@ static inline int compute_score(struct s
+@@ -273,6 +271,7 @@ static inline int compute_score(struct s
return score;
}
/* UDP is nearly always wildcards out the wazoo, it makes no sense to try
* harder than this. -DaveM
*/
-@@ -292,6 +291,11 @@ begin:
+@@ -294,6 +293,11 @@ begin:
sk_nulls_for_each_rcu(sk, node, &hslot->head) {
score = compute_score(sk, net, saddr, hnum, sport,
daddr, dport, dif);
if (score > badness) {
result = sk;
badness = score;
-@@ -305,6 +309,7 @@ begin:
+@@ -307,6 +311,7 @@ begin:
if (get_nulls_value(node) != hash)
goto begin;
if (result) {
if (unlikely(!atomic_inc_not_zero(&result->sk_refcnt)))
result = NULL;
-@@ -314,6 +319,7 @@ begin:
+@@ -316,6 +321,7 @@ begin:
goto begin;
}
}
rcu_read_unlock();
return result;
}
-@@ -356,7 +362,7 @@ static inline struct sock *udp_v4_mcast_
+@@ -358,7 +364,7 @@ static inline struct sock *udp_v4_mcast_
s->sk_hash != hnum ||
(inet->daddr && inet->daddr != rmt_addr) ||
(inet->dport != rmt_port && inet->dport) ||
ipv6_only_sock(s) ||
(s->sk_bound_dev_if && s->sk_bound_dev_if != dif))
continue;
-@@ -698,8 +704,13 @@ int udp_sendmsg(struct kiocb *iocb, stru
+@@ -707,8 +713,13 @@ int udp_sendmsg(struct kiocb *iocb, stru
{ .sport = inet->sport,
.dport = dport } } };
struct net *net = sock_net(sk);
err = ip_route_output_flow(net, &rt, &fl, sk, 1);
if (err) {
if (err == -ENETUNREACH)
-@@ -945,7 +956,8 @@ try_again:
- {
+@@ -988,7 +999,8 @@ try_again:
+ if (sin) {
sin->sin_family = AF_INET;
sin->sin_port = udp_hdr(skb)->source;
- sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
}
if (inet->cmsg_flags)
-@@ -1599,6 +1611,8 @@ static struct sock *udp_get_first(struct
+@@ -1627,6 +1639,8 @@ static struct sock *udp_get_first(struct
sk_nulls_for_each(sk, node, &hslot->head) {
if (!net_eq(sock_net(sk), net))
continue;
if (sk->sk_family == state->family)
goto found;
}
-@@ -1616,7 +1630,9 @@ static struct sock *udp_get_next(struct
+@@ -1644,7 +1658,9 @@ static struct sock *udp_get_next(struct
do {
sk = sk_nulls_next(sk);
if (!sk) {
if (state->bucket < UDP_HTABLE_SIZE)
-@@ -1721,7 +1737,10 @@ static void udp4_format_sock(struct sock
+@@ -1751,7 +1767,10 @@ static void udp4_format_sock(struct sock
seq_printf(f, "%4d: %08X:%04X %08X:%04X"
" %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %d%n",
sk_wmem_alloc_get(sp),
sk_rmem_alloc_get(sp),
0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp),
-diff -NurpP --minimal linux-2.6.31.6/net/ipv6/addrconf.c linux-2.6.31.6-vs2.3.0.36.24/net/ipv6/addrconf.c
---- linux-2.6.31.6/net/ipv6/addrconf.c 2009-09-10 15:26:30.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv6/addrconf.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/net/ipv6/addrconf.c linux-2.6.32-vs2.3.0.36.26/net/ipv6/addrconf.c
+--- linux-2.6.32/net/ipv6/addrconf.c 2009-12-03 20:03:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv6/addrconf.c 2009-12-03 20:04:56.000000000 +0100
@@ -86,6 +86,8 @@
#include <linux/proc_fs.h>
/* Set to 3 to get tracing... */
#define ACONF_DEBUG 2
-@@ -1117,7 +1119,7 @@ out:
+@@ -1119,7 +1121,7 @@ out:
int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev,
const struct in6_addr *daddr, unsigned int prefs,
{
struct ipv6_saddr_score scores[2],
*score = &scores[0], *hiscore = &scores[1];
-@@ -1190,6 +1192,8 @@ int ipv6_dev_get_saddr(struct net *net,
+@@ -1192,6 +1194,8 @@ int ipv6_dev_get_saddr(struct net *net,
dev->name);
continue;
}
score->rule = -1;
bitmap_zero(score->scorebits, IPV6_SADDR_RULE_MAX);
-@@ -2979,7 +2983,10 @@ static void if6_seq_stop(struct seq_file
+@@ -3000,7 +3004,10 @@ static void if6_seq_stop(struct seq_file
static int if6_seq_show(struct seq_file *seq, void *v)
{
struct inet6_ifaddr *ifp = (struct inet6_ifaddr *)v;
&ifp->addr,
ifp->idev->dev->ifindex,
ifp->prefix_len,
-@@ -3476,6 +3483,12 @@ static int inet6_dump_addr(struct sk_buf
+@@ -3497,6 +3504,12 @@ static int inet6_dump_addr(struct sk_buf
struct ifmcaddr6 *ifmca;
struct ifacaddr6 *ifaca;
struct net *net = sock_net(skb->sk);
s_idx = cb->args[0];
s_ip_idx = ip_idx = cb->args[1];
-@@ -3497,6 +3510,8 @@ static int inet6_dump_addr(struct sk_buf
+@@ -3518,6 +3531,8 @@ static int inet6_dump_addr(struct sk_buf
ifa = ifa->if_next, ip_idx++) {
if (ip_idx < s_ip_idx)
continue;
err = inet6_fill_ifaddr(skb, ifa,
NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq,
-@@ -3510,6 +3525,8 @@ static int inet6_dump_addr(struct sk_buf
+@@ -3531,6 +3546,8 @@ static int inet6_dump_addr(struct sk_buf
ifmca = ifmca->next, ip_idx++) {
if (ip_idx < s_ip_idx)
continue;
err = inet6_fill_ifmcaddr(skb, ifmca,
NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq,
-@@ -3523,6 +3540,8 @@ static int inet6_dump_addr(struct sk_buf
+@@ -3544,6 +3561,8 @@ static int inet6_dump_addr(struct sk_buf
ifaca = ifaca->aca_next, ip_idx++) {
if (ip_idx < s_ip_idx)
continue;
err = inet6_fill_ifacaddr(skb, ifaca,
NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq,
-@@ -3809,12 +3828,19 @@ static int inet6_dump_ifinfo(struct sk_b
+@@ -3830,12 +3849,19 @@ static int inet6_dump_ifinfo(struct sk_b
int s_idx = cb->args[0];
struct net_device *dev;
struct inet6_dev *idev;
if ((idev = in6_dev_get(dev)) == NULL)
goto cont;
err = inet6_fill_ifinfo(skb, idev, NETLINK_CB(cb->skb).pid,
-diff -NurpP --minimal linux-2.6.31.6/net/ipv6/af_inet6.c linux-2.6.31.6-vs2.3.0.36.24/net/ipv6/af_inet6.c
---- linux-2.6.31.6/net/ipv6/af_inet6.c 2009-09-10 15:26:30.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv6/af_inet6.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/net/ipv6/af_inet6.c linux-2.6.32-vs2.3.0.36.26/net/ipv6/af_inet6.c
+--- linux-2.6.32/net/ipv6/af_inet6.c 2009-12-03 20:03:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv6/af_inet6.c 2009-12-03 20:04:56.000000000 +0100
@@ -41,6 +41,8 @@
#include <linux/netdevice.h>
#include <linux/icmpv6.h>
if (ipv6_addr_any(&np->rcv_saddr))
ipv6_addr_copy(&sin->sin6_addr, &np->saddr);
else
-diff -NurpP --minimal linux-2.6.31.6/net/ipv6/fib6_rules.c linux-2.6.31.6-vs2.3.0.36.24/net/ipv6/fib6_rules.c
---- linux-2.6.31.6/net/ipv6/fib6_rules.c 2009-09-10 15:26:30.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv6/fib6_rules.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/net/ipv6/fib6_rules.c linux-2.6.32-vs2.3.0.36.26/net/ipv6/fib6_rules.c
+--- linux-2.6.32/net/ipv6/fib6_rules.c 2009-09-10 15:26:30.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv6/fib6_rules.c 2009-12-03 20:04:56.000000000 +0100
@@ -96,7 +96,7 @@ static int fib6_rule_action(struct fib_r
if (ipv6_dev_get_saddr(net,
ip6_dst_idev(&rt->u.dst)->dev,
goto again;
if (!ipv6_prefix_equal(&saddr, &r->src.addr,
r->src.plen))
-diff -NurpP --minimal linux-2.6.31.6/net/ipv6/inet6_hashtables.c linux-2.6.31.6-vs2.3.0.36.24/net/ipv6/inet6_hashtables.c
---- linux-2.6.31.6/net/ipv6/inet6_hashtables.c 2009-03-24 14:22:46.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv6/inet6_hashtables.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/net/ipv6/inet6_hashtables.c linux-2.6.32-vs2.3.0.36.26/net/ipv6/inet6_hashtables.c
+--- linux-2.6.32/net/ipv6/inet6_hashtables.c 2009-03-24 14:22:46.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv6/inet6_hashtables.c 2009-12-03 20:04:56.000000000 +0100
@@ -16,6 +16,7 @@
#include <linux/module.h>
}
if (sk->sk_bound_dev_if) {
if (sk->sk_bound_dev_if != dif)
-diff -NurpP --minimal linux-2.6.31.6/net/ipv6/ip6_output.c linux-2.6.31.6-vs2.3.0.36.24/net/ipv6/ip6_output.c
---- linux-2.6.31.6/net/ipv6/ip6_output.c 2009-09-10 15:26:30.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv6/ip6_output.c 2009-09-10 16:11:43.000000000 +0200
-@@ -951,7 +951,7 @@ static int ip6_dst_lookup_tail(struct so
+diff -NurpP --minimal linux-2.6.32/net/ipv6/ip6_output.c linux-2.6.32-vs2.3.0.36.26/net/ipv6/ip6_output.c
+--- linux-2.6.32/net/ipv6/ip6_output.c 2009-12-03 20:03:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv6/ip6_output.c 2009-12-03 20:04:56.000000000 +0100
+@@ -934,7 +934,7 @@ static int ip6_dst_lookup_tail(struct so
err = ipv6_dev_get_saddr(net, ip6_dst_idev(*dst)->dev,
&fl->fl6_dst,
sk ? inet6_sk(sk)->srcprefs : 0,
if (err)
goto out_err_release;
}
-diff -NurpP --minimal linux-2.6.31.6/net/ipv6/Kconfig linux-2.6.31.6-vs2.3.0.36.24/net/ipv6/Kconfig
---- linux-2.6.31.6/net/ipv6/Kconfig 2009-09-10 15:26:30.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv6/Kconfig 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/net/ipv6/Kconfig linux-2.6.32-vs2.3.0.36.26/net/ipv6/Kconfig
+--- linux-2.6.32/net/ipv6/Kconfig 2009-09-10 15:26:30.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv6/Kconfig 2009-12-03 20:04:56.000000000 +0100
@@ -4,8 +4,8 @@
# IPv6 as module will cause a CRASH if you try to unload it
---help---
This is complemental support for the IP version 6.
You will still be able to do traditional IPv4 networking as well.
-diff -NurpP --minimal linux-2.6.31.6/net/ipv6/ndisc.c linux-2.6.31.6-vs2.3.0.36.24/net/ipv6/ndisc.c
---- linux-2.6.31.6/net/ipv6/ndisc.c 2009-09-10 15:26:30.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv6/ndisc.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/net/ipv6/ndisc.c linux-2.6.32-vs2.3.0.36.26/net/ipv6/ndisc.c
+--- linux-2.6.32/net/ipv6/ndisc.c 2009-12-03 20:03:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv6/ndisc.c 2009-12-03 20:04:56.000000000 +0100
@@ -589,7 +589,7 @@ static void ndisc_send_na(struct net_dev
} else {
if (ipv6_dev_get_saddr(dev_net(dev), dev, daddr,
return;
src_addr = &tmpaddr;
}
-diff -NurpP --minimal linux-2.6.31.6/net/ipv6/raw.c linux-2.6.31.6-vs2.3.0.36.24/net/ipv6/raw.c
---- linux-2.6.31.6/net/ipv6/raw.c 2009-09-10 15:26:30.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv6/raw.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/net/ipv6/raw.c linux-2.6.32-vs2.3.0.36.26/net/ipv6/raw.c
+--- linux-2.6.32/net/ipv6/raw.c 2009-12-03 20:03:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv6/raw.c 2009-12-03 20:04:56.000000000 +0100
@@ -29,6 +29,7 @@
#include <linux/icmpv6.h>
#include <linux/netfilter.h>
/* ipv4 addr of the socket is invalid. Only the
* unspecified and mapped address have a v4 equivalent.
*/
-diff -NurpP --minimal linux-2.6.31.6/net/ipv6/route.c linux-2.6.31.6-vs2.3.0.36.24/net/ipv6/route.c
---- linux-2.6.31.6/net/ipv6/route.c 2009-09-10 15:26:30.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv6/route.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/net/ipv6/route.c linux-2.6.32-vs2.3.0.36.26/net/ipv6/route.c
+--- linux-2.6.32/net/ipv6/route.c 2009-12-03 20:03:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv6/route.c 2009-12-03 20:04:56.000000000 +0100
@@ -2257,7 +2257,8 @@ static int rt6_fill_node(struct net *net
struct inet6_dev *idev = ip6_dst_idev(&rt->u.dst);
struct in6_addr saddr_buf;
NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
}
-diff -NurpP --minimal linux-2.6.31.6/net/ipv6/tcp_ipv6.c linux-2.6.31.6-vs2.3.0.36.24/net/ipv6/tcp_ipv6.c
---- linux-2.6.31.6/net/ipv6/tcp_ipv6.c 2009-09-10 15:26:30.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv6/tcp_ipv6.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/net/ipv6/tcp_ipv6.c linux-2.6.32-vs2.3.0.36.26/net/ipv6/tcp_ipv6.c
+--- linux-2.6.32/net/ipv6/tcp_ipv6.c 2009-12-03 20:03:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv6/tcp_ipv6.c 2009-12-03 20:04:56.000000000 +0100
@@ -68,6 +68,7 @@
#include <linux/crypto.h>
addr_type = ipv6_addr_type(&usin->sin6_addr);
-diff -NurpP --minimal linux-2.6.31.6/net/ipv6/udp.c linux-2.6.31.6-vs2.3.0.36.24/net/ipv6/udp.c
---- linux-2.6.31.6/net/ipv6/udp.c 2009-09-10 15:26:30.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv6/udp.c 2009-11-05 05:04:49.000000000 +0100
+diff -NurpP --minimal linux-2.6.32/net/ipv6/udp.c linux-2.6.32-vs2.3.0.36.26/net/ipv6/udp.c
+--- linux-2.6.32/net/ipv6/udp.c 2009-12-03 20:03:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv6/udp.c 2009-12-03 20:04:56.000000000 +0100
@@ -47,6 +47,7 @@
#include <linux/proc_fs.h>
}
if (!ipv6_addr_any(&np->daddr)) {
if (!ipv6_addr_equal(&np->daddr, saddr))
-diff -NurpP --minimal linux-2.6.31.6/net/ipv6/xfrm6_policy.c linux-2.6.31.6-vs2.3.0.36.24/net/ipv6/xfrm6_policy.c
---- linux-2.6.31.6/net/ipv6/xfrm6_policy.c 2009-09-10 15:26:30.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/ipv6/xfrm6_policy.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/net/ipv6/xfrm6_policy.c linux-2.6.32-vs2.3.0.36.26/net/ipv6/xfrm6_policy.c
+--- linux-2.6.32/net/ipv6/xfrm6_policy.c 2009-12-03 20:03:00.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/ipv6/xfrm6_policy.c 2009-12-03 20:04:56.000000000 +0100
@@ -63,7 +63,7 @@ static int xfrm6_get_saddr(struct net *n
dev = ip6_dst_idev(dst)->dev;
ipv6_dev_get_saddr(dev_net(dev), dev,
dst_release(dst);
return 0;
}
-diff -NurpP --minimal linux-2.6.31.6/net/netlink/af_netlink.c linux-2.6.31.6-vs2.3.0.36.24/net/netlink/af_netlink.c
---- linux-2.6.31.6/net/netlink/af_netlink.c 2009-09-10 15:26:30.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/netlink/af_netlink.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/net/netlink/af_netlink.c linux-2.6.32-vs2.3.0.36.26/net/netlink/af_netlink.c
+--- linux-2.6.32/net/netlink/af_netlink.c 2009-12-03 20:03:01.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/netlink/af_netlink.c 2009-12-03 20:04:56.000000000 +0100
@@ -55,6 +55,9 @@
#include <linux/types.h>
#include <linux/audit.h>
#include <net/net_namespace.h>
#include <net/sock.h>
-@@ -1831,6 +1834,8 @@ static struct sock *netlink_seq_socket_i
+@@ -1899,6 +1902,8 @@ static struct sock *netlink_seq_socket_i
sk_for_each(s, node, &hash->table[j]) {
if (sock_net(s) != seq_file_net(seq))
continue;
if (off == pos) {
iter->link = i;
iter->hash_idx = j;
-@@ -1865,7 +1870,8 @@ static void *netlink_seq_next(struct seq
+@@ -1933,7 +1938,8 @@ static void *netlink_seq_next(struct seq
s = v;
do {
s = sk_next(s);
if (s)
return s;
-@@ -1877,7 +1883,8 @@ static void *netlink_seq_next(struct seq
+@@ -1945,7 +1951,8 @@ static void *netlink_seq_next(struct seq
for (; j <= hash->mask; j++) {
s = sk_head(&hash->table[j]);
s = sk_next(s);
if (s) {
iter->link = i;
-diff -NurpP --minimal linux-2.6.31.6/net/sctp/ipv6.c linux-2.6.31.6-vs2.3.0.36.24/net/sctp/ipv6.c
---- linux-2.6.31.6/net/sctp/ipv6.c 2009-09-10 15:26:31.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/sctp/ipv6.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/net/sctp/ipv6.c linux-2.6.32-vs2.3.0.36.26/net/sctp/ipv6.c
+--- linux-2.6.32/net/sctp/ipv6.c 2009-12-03 20:03:01.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/sctp/ipv6.c 2009-12-03 20:04:56.000000000 +0100
@@ -316,7 +316,8 @@ static void sctp_v6_get_saddr(struct sct
dst ? ip6_dst_idev(dst)->dev : NULL,
&daddr->v6.sin6_addr,
SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: %pI6\n",
&saddr->v6.sin6_addr);
return;
-diff -NurpP --minimal linux-2.6.31.6/net/socket.c linux-2.6.31.6-vs2.3.0.36.24/net/socket.c
---- linux-2.6.31.6/net/socket.c 2009-09-10 15:26:31.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/socket.c 2009-09-10 16:11:43.000000000 +0200
-@@ -95,6 +95,10 @@
+diff -NurpP --minimal linux-2.6.32/net/socket.c linux-2.6.32-vs2.3.0.36.26/net/socket.c
+--- linux-2.6.32/net/socket.c 2009-12-03 20:03:01.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/socket.c 2009-12-03 20:04:56.000000000 +0100
+@@ -96,6 +96,10 @@
#include <net/sock.h>
#include <linux/netfilter.h>
err = sock1->ops->socketpair(sock1, sock2);
if (err < 0)
-diff -NurpP --minimal linux-2.6.31.6/net/sunrpc/auth.c linux-2.6.31.6-vs2.3.0.36.24/net/sunrpc/auth.c
---- linux-2.6.31.6/net/sunrpc/auth.c 2009-03-24 14:22:48.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/sunrpc/auth.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/net/sunrpc/auth.c linux-2.6.32-vs2.3.0.36.26/net/sunrpc/auth.c
+--- linux-2.6.32/net/sunrpc/auth.c 2009-12-03 20:03:01.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/sunrpc/auth.c 2009-12-03 20:04:56.000000000 +0100
@@ -14,6 +14,7 @@
#include <linux/hash.h>
#include <linux/sunrpc/clnt.h>
};
struct rpc_cred *ret;
-diff -NurpP --minimal linux-2.6.31.6/net/sunrpc/auth_unix.c linux-2.6.31.6-vs2.3.0.36.24/net/sunrpc/auth_unix.c
---- linux-2.6.31.6/net/sunrpc/auth_unix.c 2008-12-25 00:26:37.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/sunrpc/auth_unix.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/net/sunrpc/auth_unix.c linux-2.6.32-vs2.3.0.36.26/net/sunrpc/auth_unix.c
+--- linux-2.6.32/net/sunrpc/auth_unix.c 2008-12-25 00:26:37.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/sunrpc/auth_unix.c 2009-12-03 20:04:56.000000000 +0100
@@ -11,12 +11,14 @@
#include <linux/module.h>
#include <linux/sunrpc/clnt.h>
hold = p++;
for (i = 0; i < 16 && cred->uc_gids[i] != (gid_t) NOGROUP; i++)
*p++ = htonl((u32) cred->uc_gids[i]);
-diff -NurpP --minimal linux-2.6.31.6/net/sunrpc/clnt.c linux-2.6.31.6-vs2.3.0.36.24/net/sunrpc/clnt.c
---- linux-2.6.31.6/net/sunrpc/clnt.c 2009-09-10 15:26:31.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/sunrpc/clnt.c 2009-09-10 16:11:43.000000000 +0200
-@@ -31,6 +31,7 @@
+diff -NurpP --minimal linux-2.6.32/net/sunrpc/clnt.c linux-2.6.32-vs2.3.0.36.26/net/sunrpc/clnt.c
+--- linux-2.6.32/net/sunrpc/clnt.c 2009-12-03 20:03:01.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/sunrpc/clnt.c 2009-12-03 20:04:56.000000000 +0100
+@@ -33,6 +33,7 @@
#include <linux/utsname.h>
#include <linux/workqueue.h>
#include <linux/in6.h>
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/rpc_pipe_fs.h>
-@@ -339,6 +340,9 @@ struct rpc_clnt *rpc_create(struct rpc_c
+@@ -358,6 +359,9 @@ struct rpc_clnt *rpc_create(struct rpc_c
if (!(args->flags & RPC_CLNT_CREATE_QUIET))
clnt->cl_chatty = 1;
return clnt;
}
EXPORT_SYMBOL_GPL(rpc_create);
-diff -NurpP --minimal linux-2.6.31.6/net/unix/af_unix.c linux-2.6.31.6-vs2.3.0.36.24/net/unix/af_unix.c
---- linux-2.6.31.6/net/unix/af_unix.c 2009-11-12 12:10:12.000000000 +0100
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/unix/af_unix.c 2009-11-12 12:26:38.000000000 +0100
+diff -NurpP --minimal linux-2.6.32/net/unix/af_unix.c linux-2.6.32-vs2.3.0.36.26/net/unix/af_unix.c
+--- linux-2.6.32/net/unix/af_unix.c 2009-12-03 20:03:01.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/unix/af_unix.c 2009-12-03 20:04:56.000000000 +0100
@@ -114,6 +114,8 @@
#include <linux/mount.h>
#include <net/checksum.h>
sk = next_unix_socket(&iter->i, sk);
return sk;
}
-diff -NurpP --minimal linux-2.6.31.6/net/x25/af_x25.c linux-2.6.31.6-vs2.3.0.36.24/net/x25/af_x25.c
---- linux-2.6.31.6/net/x25/af_x25.c 2009-09-10 15:26:31.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/net/x25/af_x25.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/net/x25/af_x25.c linux-2.6.32-vs2.3.0.36.26/net/x25/af_x25.c
+--- linux-2.6.32/net/x25/af_x25.c 2009-12-03 20:03:01.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/net/x25/af_x25.c 2009-12-03 20:04:56.000000000 +0100
@@ -519,7 +519,10 @@ static int x25_create(struct net *net, s
x25 = x25_sk(sk);
x25_init_timers(sk);
-diff -NurpP --minimal linux-2.6.31.6/scripts/checksyscalls.sh linux-2.6.31.6-vs2.3.0.36.24/scripts/checksyscalls.sh
---- linux-2.6.31.6/scripts/checksyscalls.sh 2009-09-10 15:26:31.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/scripts/checksyscalls.sh 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/scripts/checksyscalls.sh linux-2.6.32-vs2.3.0.36.26/scripts/checksyscalls.sh
+--- linux-2.6.32/scripts/checksyscalls.sh 2009-09-10 15:26:31.000000000 +0200
++++ linux-2.6.32-vs2.3.0.36.26/scripts/checksyscalls.sh 2009-12-03 20:04:56.000000000 +0100
@@ -194,7 +194,6 @@ cat << EOF
#define __IGNORE_afs_syscall
#define __IGNORE_getpmsg
EOF
}
-diff -NurpP --minimal linux-2.6.31.6/security/commoncap.c linux-2.6.31.6-vs2.3.0.36.24/security/commoncap.c
---- linux-2.6.31.6/security/commoncap.c 2009-09-10 15:26:32.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/security/commoncap.c 2009-09-10 16:32:54.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/security/commoncap.c linux-2.6.32-vs2.3.0.36.26/security/commoncap.c
+--- linux-2.6.32/security/commoncap.c 2009-12-03 20:03:02.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/security/commoncap.c 2009-12-03 20:04:56.000000000 +0100
@@ -27,6 +27,7 @@
#include <linux/sched.h>
#include <linux/prctl.h>
return ret;
}
+
-diff -NurpP --minimal linux-2.6.31.6/security/selinux/hooks.c linux-2.6.31.6-vs2.3.0.36.24/security/selinux/hooks.c
---- linux-2.6.31.6/security/selinux/hooks.c 2009-09-10 15:26:32.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/security/selinux/hooks.c 2009-09-10 16:11:43.000000000 +0200
+diff -NurpP --minimal linux-2.6.32/security/selinux/hooks.c linux-2.6.32-vs2.3.0.36.26/security/selinux/hooks.c
+--- linux-2.6.32/security/selinux/hooks.c 2009-12-03 20:03:02.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/security/selinux/hooks.c 2009-12-03 20:04:56.000000000 +0100
@@ -64,7 +64,6 @@
#include <linux/dccp.h>
#include <linux/quota.h>
#include <linux/parser.h>
#include <linux/nfs_mount.h>
#include <net/ipv6.h>
-diff -NurpP --minimal linux-2.6.31.6/security/selinux/include/av_permissions.h linux-2.6.31.6-vs2.3.0.36.24/security/selinux/include/av_permissions.h
---- linux-2.6.31.6/security/selinux/include/av_permissions.h 2009-06-11 17:13:33.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/security/selinux/include/av_permissions.h 2009-09-29 17:20:23.000000000 +0200
-@@ -542,6 +542,7 @@
+diff -NurpP --minimal linux-2.6.32/security/selinux/include/av_permissions.h linux-2.6.32-vs2.3.0.36.26/security/selinux/include/av_permissions.h
+--- linux-2.6.32/security/selinux/include/av_permissions.h 2009-12-03 20:03:02.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/security/selinux/include/av_permissions.h 2009-12-03 20:04:56.000000000 +0100
+@@ -565,6 +565,7 @@
#define CAPABILITY__SETFCAP 0x80000000UL
#define CAPABILITY2__MAC_OVERRIDE 0x00000001UL
#define CAPABILITY2__MAC_ADMIN 0x00000002UL
#define NETLINK_ROUTE_SOCKET__IOCTL 0x00000001UL
#define NETLINK_ROUTE_SOCKET__READ 0x00000002UL
#define NETLINK_ROUTE_SOCKET__WRITE 0x00000004UL
-diff -NurpP --minimal linux-2.6.31.6/security/selinux/include/av_perm_to_string.h linux-2.6.31.6-vs2.3.0.36.24/security/selinux/include/av_perm_to_string.h
---- linux-2.6.31.6/security/selinux/include/av_perm_to_string.h 2009-06-11 17:13:33.000000000 +0200
-+++ linux-2.6.31.6-vs2.3.0.36.24/security/selinux/include/av_perm_to_string.h 2009-09-29 17:20:23.000000000 +0200
-@@ -141,6 +141,7 @@
+diff -NurpP --minimal linux-2.6.32/security/selinux/include/av_perm_to_string.h linux-2.6.32-vs2.3.0.36.26/security/selinux/include/av_perm_to_string.h
+--- linux-2.6.32/security/selinux/include/av_perm_to_string.h 2009-12-03 20:03:02.000000000 +0100
++++ linux-2.6.32-vs2.3.0.36.26/security/selinux/include/av_perm_to_string.h 2009-12-03 20:04:56.000000000 +0100
+@@ -142,6 +142,7 @@
S_(SECCLASS_CAPABILITY, CAPABILITY__SETFCAP, "setfcap")
S_(SECCLASS_CAPABILITY2, CAPABILITY2__MAC_OVERRIDE, "mac_override")
S_(SECCLASS_CAPABILITY2, CAPABILITY2__MAC_ADMIN, "mac_admin")