summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'vserver-sources/2.2.0.7/1013_linux-2.6.22.19.patch')
-rw-r--r--vserver-sources/2.2.0.7/1013_linux-2.6.22.19.patch1031
1 files changed, 1031 insertions, 0 deletions
diff --git a/vserver-sources/2.2.0.7/1013_linux-2.6.22.19.patch b/vserver-sources/2.2.0.7/1013_linux-2.6.22.19.patch
new file mode 100644
index 0000000..edd7db3
--- /dev/null
+++ b/vserver-sources/2.2.0.7/1013_linux-2.6.22.19.patch
@@ -0,0 +1,1031 @@
+diff -NurpP linux-2.6.22.18/arch/i386/kernel/entry.S linux-2.6.22.19/arch/i386/kernel/entry.S
+--- linux-2.6.22.18/arch/i386/kernel/entry.S 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/arch/i386/kernel/entry.S 2008-02-26 00:59:40.000000000 +0100
+@@ -409,8 +409,6 @@ restore_nocheck_notrace:
+ 1: INTERRUPT_RETURN
+ .section .fixup,"ax"
+ iret_exc:
+- TRACE_IRQS_ON
+- ENABLE_INTERRUPTS(CLBR_NONE)
+ pushl $0 # no error code
+ pushl $do_iret_error
+ jmp error_code
+diff -NurpP linux-2.6.22.18/arch/i386/kernel/ptrace.c linux-2.6.22.19/arch/i386/kernel/ptrace.c
+--- linux-2.6.22.18/arch/i386/kernel/ptrace.c 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/arch/i386/kernel/ptrace.c 2008-02-26 00:59:40.000000000 +0100
+@@ -164,14 +164,22 @@ static unsigned long convert_eip_to_line
+ u32 *desc;
+ unsigned long base;
+
+- down(&child->mm->context.sem);
+- desc = child->mm->context.ldt + (seg & ~7);
+- base = (desc[0] >> 16) | ((desc[1] & 0xff) << 16) | (desc[1] & 0xff000000);
++ seg &= ~7UL;
+
+- /* 16-bit code segment? */
+- if (!((desc[1] >> 22) & 1))
+- addr &= 0xffff;
+- addr += base;
++ down(&child->mm->context.sem);
++ if (unlikely((seg >> 3) >= child->mm->context.size))
++ addr = -1L; /* bogus selector, access would fault */
++ else {
++ desc = child->mm->context.ldt + seg;
++ base = ((desc[0] >> 16) |
++ ((desc[1] & 0xff) << 16) |
++ (desc[1] & 0xff000000));
++
++ /* 16-bit code segment? */
++ if (!((desc[1] >> 22) & 1))
++ addr &= 0xffff;
++ addr += base;
++ }
+ up(&child->mm->context.sem);
+ }
+ return addr;
+diff -NurpP linux-2.6.22.18/arch/i386/kernel/traps.c linux-2.6.22.19/arch/i386/kernel/traps.c
+--- linux-2.6.22.18/arch/i386/kernel/traps.c 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/arch/i386/kernel/traps.c 2008-02-26 00:59:40.000000000 +0100
+@@ -517,10 +517,12 @@ fastcall void do_##name(struct pt_regs *
+ do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \
+ }
+
+-#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
++#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr, irq) \
+ fastcall void do_##name(struct pt_regs * regs, long error_code) \
+ { \
+ siginfo_t info; \
++ if (irq) \
++ local_irq_enable(); \
+ info.si_signo = signr; \
+ info.si_errno = 0; \
+ info.si_code = sicode; \
+@@ -560,13 +562,13 @@ DO_VM86_ERROR( 3, SIGTRAP, "int3", int3)
+ #endif
+ DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow)
+ DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds)
+-DO_ERROR_INFO( 6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->eip)
++DO_ERROR_INFO( 6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->eip, 0)
+ DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun)
+ DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
+ DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
+ DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
+-DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
+-DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0)
++DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0, 0)
++DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0, 1)
+
+ fastcall void __kprobes do_general_protection(struct pt_regs * regs,
+ long error_code)
+diff -NurpP linux-2.6.22.18/arch/x86_64/kernel/ptrace.c linux-2.6.22.19/arch/x86_64/kernel/ptrace.c
+--- linux-2.6.22.18/arch/x86_64/kernel/ptrace.c 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/arch/x86_64/kernel/ptrace.c 2008-02-26 00:59:40.000000000 +0100
+@@ -102,16 +102,25 @@ unsigned long convert_rip_to_linear(stru
+ u32 *desc;
+ unsigned long base;
+
+- down(&child->mm->context.sem);
+- desc = child->mm->context.ldt + (seg & ~7);
+- base = (desc[0] >> 16) | ((desc[1] & 0xff) << 16) | (desc[1] & 0xff000000);
++ seg &= ~7UL;
+
+- /* 16-bit code segment? */
+- if (!((desc[1] >> 22) & 1))
+- addr &= 0xffff;
+- addr += base;
++ down(&child->mm->context.sem);
++ if (unlikely((seg >> 3) >= child->mm->context.size))
++ addr = -1L; /* bogus selector, access would fault */
++ else {
++ desc = child->mm->context.ldt + seg;
++ base = ((desc[0] >> 16) |
++ ((desc[1] & 0xff) << 16) |
++ (desc[1] & 0xff000000));
++
++ /* 16-bit code segment? */
++ if (!((desc[1] >> 22) & 1))
++ addr &= 0xffff;
++ addr += base;
++ }
+ up(&child->mm->context.sem);
+ }
++
+ return addr;
+ }
+
+diff -NurpP linux-2.6.22.18/drivers/ata/sata_promise.c linux-2.6.22.19/drivers/ata/sata_promise.c
+--- linux-2.6.22.18/drivers/ata/sata_promise.c 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/drivers/ata/sata_promise.c 2008-02-26 00:59:40.000000000 +0100
+@@ -51,6 +51,7 @@
+ enum {
+ PDC_MAX_PORTS = 4,
+ PDC_MMIO_BAR = 3,
++ PDC_MAX_PRD = LIBATA_MAX_PRD - 1, /* -1 for ASIC PRD bug workaround */
+
+ /* register offsets */
+ PDC_FEATURE = 0x04, /* Feature/Error reg (per port) */
+@@ -157,7 +158,7 @@ static struct scsi_host_template pdc_ata
+ .queuecommand = ata_scsi_queuecmd,
+ .can_queue = ATA_DEF_QUEUE,
+ .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
++ .sg_tablesize = PDC_MAX_PRD,
+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+ .emulated = ATA_SHT_EMULATED,
+ .use_clustering = ATA_SHT_USE_CLUSTERING,
+@@ -330,8 +331,8 @@ static const struct pci_device_id pdc_at
+
+ { PCI_VDEVICE(PROMISE, 0x3318), board_20319 },
+ { PCI_VDEVICE(PROMISE, 0x3319), board_20319 },
+- { PCI_VDEVICE(PROMISE, 0x3515), board_20319 },
+- { PCI_VDEVICE(PROMISE, 0x3519), board_20319 },
++ { PCI_VDEVICE(PROMISE, 0x3515), board_40518 },
++ { PCI_VDEVICE(PROMISE, 0x3519), board_40518 },
+ { PCI_VDEVICE(PROMISE, 0x3d17), board_40518 },
+ { PCI_VDEVICE(PROMISE, 0x3d18), board_40518 },
+
+@@ -531,6 +532,84 @@ static void pdc_atapi_pkt(struct ata_que
+ memcpy(buf+31, cdb, cdb_len);
+ }
+
++/**
++ * pdc_fill_sg - Fill PCI IDE PRD table
++ * @qc: Metadata associated with taskfile to be transferred
++ *
++ * Fill PCI IDE PRD (scatter-gather) table with segments
++ * associated with the current disk command.
++ * Make sure hardware does not choke on it.
++ *
++ * LOCKING:
++ * spin_lock_irqsave(host lock)
++ *
++ */
++static void pdc_fill_sg(struct ata_queued_cmd *qc)
++{
++ struct ata_port *ap = qc->ap;
++ struct scatterlist *sg;
++ unsigned int idx;
++ const u32 SG_COUNT_ASIC_BUG = 41*4;
++
++ if (!(qc->flags & ATA_QCFLAG_DMAMAP))
++ return;
++
++ WARN_ON(qc->__sg == NULL);
++ WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
++
++ idx = 0;
++ ata_for_each_sg(sg, qc) {
++ u32 addr, offset;
++ u32 sg_len, len;
++
++ /* determine if physical DMA addr spans 64K boundary.
++ * Note h/w doesn't support 64-bit, so we unconditionally
++ * truncate dma_addr_t to u32.
++ */
++ addr = (u32) sg_dma_address(sg);
++ sg_len = sg_dma_len(sg);
++
++ while (sg_len) {
++ offset = addr & 0xffff;
++ len = sg_len;
++ if ((offset + sg_len) > 0x10000)
++ len = 0x10000 - offset;
++
++ ap->prd[idx].addr = cpu_to_le32(addr);
++ ap->prd[idx].flags_len = cpu_to_le32(len & 0xffff);
++ VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
++
++ idx++;
++ sg_len -= len;
++ addr += len;
++ }
++ }
++
++ if (idx) {
++ u32 len = le32_to_cpu(ap->prd[idx - 1].flags_len);
++
++ if (len > SG_COUNT_ASIC_BUG) {
++ u32 addr;
++
++ VPRINTK("Splitting last PRD.\n");
++
++ addr = le32_to_cpu(ap->prd[idx - 1].addr);
++ ap->prd[idx - 1].flags_len = cpu_to_le32(len - SG_COUNT_ASIC_BUG);
++ VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx - 1, addr, SG_COUNT_ASIC_BUG);
++
++ addr = addr + len - SG_COUNT_ASIC_BUG;
++ len = SG_COUNT_ASIC_BUG;
++ ap->prd[idx].addr = cpu_to_le32(addr);
++ ap->prd[idx].flags_len = cpu_to_le32(len);
++ VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
++
++ idx++;
++ }
++
++ ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
++ }
++}
++
+ static void pdc_qc_prep(struct ata_queued_cmd *qc)
+ {
+ struct pdc_port_priv *pp = qc->ap->private_data;
+@@ -540,7 +619,7 @@ static void pdc_qc_prep(struct ata_queue
+
+ switch (qc->tf.protocol) {
+ case ATA_PROT_DMA:
+- ata_qc_prep(qc);
++ pdc_fill_sg(qc);
+ /* fall through */
+
+ case ATA_PROT_NODATA:
+@@ -556,11 +635,11 @@ static void pdc_qc_prep(struct ata_queue
+ break;
+
+ case ATA_PROT_ATAPI:
+- ata_qc_prep(qc);
++ pdc_fill_sg(qc);
+ break;
+
+ case ATA_PROT_ATAPI_DMA:
+- ata_qc_prep(qc);
++ pdc_fill_sg(qc);
+ /*FALLTHROUGH*/
+ case ATA_PROT_ATAPI_NODATA:
+ pdc_atapi_pkt(qc);
+diff -NurpP linux-2.6.22.18/drivers/block/cciss.c linux-2.6.22.19/drivers/block/cciss.c
+--- linux-2.6.22.18/drivers/block/cciss.c 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/drivers/block/cciss.c 2008-02-26 00:59:40.000000000 +0100
+@@ -3225,12 +3225,15 @@ static int alloc_cciss_hba(void)
+ for (i = 0; i < MAX_CTLR; i++) {
+ if (!hba[i]) {
+ ctlr_info_t *p;
++
+ p = kzalloc(sizeof(ctlr_info_t), GFP_KERNEL);
+ if (!p)
+ goto Enomem;
+ p->gendisk[0] = alloc_disk(1 << NWD_SHIFT);
+- if (!p->gendisk[0])
++ if (!p->gendisk[0]) {
++ kfree(p);
+ goto Enomem;
++ }
+ hba[i] = p;
+ return i;
+ }
+diff -NurpP linux-2.6.22.18/drivers/char/agp/intel-agp.c linux-2.6.22.19/drivers/char/agp/intel-agp.c
+--- linux-2.6.22.18/drivers/char/agp/intel-agp.c 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/drivers/char/agp/intel-agp.c 2008-02-26 00:59:40.000000000 +0100
+@@ -20,7 +20,9 @@
+ #define PCI_DEVICE_ID_INTEL_82965G_IG 0x29A2
+ #define PCI_DEVICE_ID_INTEL_82965GM_HB 0x2A00
+ #define PCI_DEVICE_ID_INTEL_82965GM_IG 0x2A02
++#define PCI_DEVICE_ID_INTEL_82965GME_HB 0x2A10
+ #define PCI_DEVICE_ID_INTEL_82965GME_IG 0x2A12
++#define PCI_DEVICE_ID_INTEL_82945GME_HB 0x27AC
+ #define PCI_DEVICE_ID_INTEL_82945GME_IG 0x27AE
+ #define PCI_DEVICE_ID_INTEL_G33_HB 0x29C0
+ #define PCI_DEVICE_ID_INTEL_G33_IG 0x29C2
+@@ -33,7 +35,8 @@
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_1_HB || \
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \
+- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB)
++ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB || \
++ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GME_HB)
+
+ #define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \
+@@ -527,6 +530,7 @@ static void intel_i830_init_gtt_entries(
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB ||
++ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GME_HB ||
+ IS_I965 || IS_G33)
+ gtt_entries = MB(48) - KB(size);
+ else
+@@ -538,6 +542,7 @@ static void intel_i830_init_gtt_entries(
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB ||
++ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GME_HB ||
+ IS_I965 || IS_G33)
+ gtt_entries = MB(64) - KB(size);
+ else
+@@ -1848,9 +1853,9 @@ static const struct intel_driver_descrip
+ NULL, &intel_915_driver },
+ { PCI_DEVICE_ID_INTEL_82945G_HB, PCI_DEVICE_ID_INTEL_82945G_IG, 0, "945G",
+ NULL, &intel_915_driver },
+- { PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GM_IG, 1, "945GM",
++ { PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GM_IG, 0, "945GM",
+ NULL, &intel_915_driver },
+- { PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GME_IG, 0, "945GME",
++ { PCI_DEVICE_ID_INTEL_82945GME_HB, PCI_DEVICE_ID_INTEL_82945GME_IG, 0, "945GME",
+ NULL, &intel_915_driver },
+ { PCI_DEVICE_ID_INTEL_82946GZ_HB, PCI_DEVICE_ID_INTEL_82946GZ_IG, 0, "946GZ",
+ NULL, &intel_i965_driver },
+@@ -1860,9 +1865,9 @@ static const struct intel_driver_descrip
+ NULL, &intel_i965_driver },
+ { PCI_DEVICE_ID_INTEL_82965G_HB, PCI_DEVICE_ID_INTEL_82965G_IG, 0, "965G",
+ NULL, &intel_i965_driver },
+- { PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GM_IG, 1, "965GM",
++ { PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GM_IG, 0, "965GM",
+ NULL, &intel_i965_driver },
+- { PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GME_IG, 0, "965GME/GLE",
++ { PCI_DEVICE_ID_INTEL_82965GME_HB, PCI_DEVICE_ID_INTEL_82965GME_IG, 0, "965GME/GLE",
+ NULL, &intel_i965_driver },
+ { PCI_DEVICE_ID_INTEL_7505_0, 0, 0, "E7505", &intel_7505_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_7205_0, 0, 0, "E7205", &intel_7505_driver, NULL },
+@@ -2051,11 +2056,13 @@ static struct pci_device_id agp_intel_pc
+ ID(PCI_DEVICE_ID_INTEL_82915GM_HB),
+ ID(PCI_DEVICE_ID_INTEL_82945G_HB),
+ ID(PCI_DEVICE_ID_INTEL_82945GM_HB),
++ ID(PCI_DEVICE_ID_INTEL_82945GME_HB),
+ ID(PCI_DEVICE_ID_INTEL_82946GZ_HB),
+ ID(PCI_DEVICE_ID_INTEL_82965G_1_HB),
+ ID(PCI_DEVICE_ID_INTEL_82965Q_HB),
+ ID(PCI_DEVICE_ID_INTEL_82965G_HB),
+ ID(PCI_DEVICE_ID_INTEL_82965GM_HB),
++ ID(PCI_DEVICE_ID_INTEL_82965GME_HB),
+ ID(PCI_DEVICE_ID_INTEL_G33_HB),
+ ID(PCI_DEVICE_ID_INTEL_Q35_HB),
+ ID(PCI_DEVICE_ID_INTEL_Q33_HB),
+diff -NurpP linux-2.6.22.18/drivers/char/ipmi/ipmi_si_intf.c linux-2.6.22.19/drivers/char/ipmi/ipmi_si_intf.c
+--- linux-2.6.22.18/drivers/char/ipmi/ipmi_si_intf.c 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/drivers/char/ipmi/ipmi_si_intf.c 2008-02-26 00:59:40.000000000 +0100
+@@ -2214,7 +2214,8 @@ static int ipmi_pci_resume(struct pci_de
+
+ static struct pci_device_id ipmi_pci_devices[] = {
+ { PCI_DEVICE(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID) },
+- { PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) }
++ { PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) },
++ { 0, }
+ };
+ MODULE_DEVICE_TABLE(pci, ipmi_pci_devices);
+
+diff -NurpP linux-2.6.22.18/drivers/media/video/usbvision/usbvision-cards.c linux-2.6.22.19/drivers/media/video/usbvision/usbvision-cards.c
+--- linux-2.6.22.18/drivers/media/video/usbvision/usbvision-cards.c 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/drivers/media/video/usbvision/usbvision-cards.c 2008-02-26 00:59:40.000000000 +0100
+@@ -1081,6 +1081,7 @@ struct usb_device_id usbvision_table []
+ { USB_DEVICE(0x2304, 0x0301), .driver_info=PINNA_LINX_VD_IN_CAB_PAL },
+ { USB_DEVICE(0x2304, 0x0419), .driver_info=PINNA_PCTV_BUNGEE_PAL_FM },
+ { USB_DEVICE(0x2400, 0x4200), .driver_info=HPG_WINTV },
++ { }, /* terminate list */
+ };
+
+ MODULE_DEVICE_TABLE (usb, usbvision_table);
+diff -NurpP linux-2.6.22.18/drivers/misc/sony-laptop.c linux-2.6.22.19/drivers/misc/sony-laptop.c
+--- linux-2.6.22.18/drivers/misc/sony-laptop.c 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/drivers/misc/sony-laptop.c 2008-02-26 00:59:40.000000000 +0100
+@@ -2056,8 +2056,6 @@ static int sony_pic_remove(struct acpi_d
+ struct sony_pic_ioport *io, *tmp_io;
+ struct sony_pic_irq *irq, *tmp_irq;
+
+- sonypi_compat_exit();
+-
+ if (sony_pic_disable(device)) {
+ printk(KERN_ERR DRV_PFX "Couldn't disable device.\n");
+ return -ENXIO;
+@@ -2067,6 +2065,8 @@ static int sony_pic_remove(struct acpi_d
+ release_region(spic_dev.cur_ioport->io.minimum,
+ spic_dev.cur_ioport->io.address_length);
+
++ sonypi_compat_exit();
++
+ sony_laptop_remove_input();
+
+ /* pf attrs */
+@@ -2132,6 +2132,9 @@ static int sony_pic_add(struct acpi_devi
+ goto err_free_resources;
+ }
+
++ if (sonypi_compat_init())
++ goto err_remove_input;
++
+ /* request io port */
+ list_for_each_entry(io, &spic_dev.ioports, list) {
+ if (request_region(io->io.minimum, io->io.address_length,
+@@ -2146,7 +2149,7 @@ static int sony_pic_add(struct acpi_devi
+ if (!spic_dev.cur_ioport) {
+ printk(KERN_ERR DRV_PFX "Failed to request_region.\n");
+ result = -ENODEV;
+- goto err_remove_input;
++ goto err_remove_compat;
+ }
+
+ /* request IRQ */
+@@ -2186,9 +2189,6 @@ static int sony_pic_add(struct acpi_devi
+ if (result)
+ goto err_remove_pf;
+
+- if (sonypi_compat_init())
+- goto err_remove_pf;
+-
+ return 0;
+
+ err_remove_pf:
+@@ -2204,6 +2204,9 @@ err_release_region:
+ release_region(spic_dev.cur_ioport->io.minimum,
+ spic_dev.cur_ioport->io.address_length);
+
++err_remove_compat:
++ sonypi_compat_exit();
++
+ err_remove_input:
+ sony_laptop_remove_input();
+
+diff -NurpP linux-2.6.22.18/drivers/mtd/nand/cafe_nand.c linux-2.6.22.19/drivers/mtd/nand/cafe_nand.c
+--- linux-2.6.22.18/drivers/mtd/nand/cafe_nand.c 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/drivers/mtd/nand/cafe_nand.c 2008-02-26 00:59:40.000000000 +0100
+@@ -816,7 +816,8 @@ static void __devexit cafe_nand_remove(s
+ }
+
+ static struct pci_device_id cafe_nand_tbl[] = {
+- { 0x11ab, 0x4100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MEMORY_FLASH << 8, 0xFFFF0 }
++ { 0x11ab, 0x4100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MEMORY_FLASH << 8, 0xFFFF0 },
++ { 0, }
+ };
+
+ MODULE_DEVICE_TABLE(pci, cafe_nand_tbl);
+diff -NurpP linux-2.6.22.18/drivers/net/via-velocity.c linux-2.6.22.19/drivers/net/via-velocity.c
+--- linux-2.6.22.18/drivers/net/via-velocity.c 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/drivers/net/via-velocity.c 2008-02-26 00:59:40.000000000 +0100
+@@ -1075,6 +1075,9 @@ static int velocity_init_rd_ring(struct
+ int ret = -ENOMEM;
+ unsigned int rsize = sizeof(struct velocity_rd_info) *
+ vptr->options.numrx;
++ int mtu = vptr->dev->mtu;
++
++ vptr->rx_buf_sz = (mtu <= ETH_DATA_LEN) ? PKT_BUF_SZ : mtu + 32;
+
+ vptr->rd_info = kmalloc(rsize, GFP_KERNEL);
+ if(vptr->rd_info == NULL)
+@@ -1733,8 +1736,6 @@ static int velocity_open(struct net_devi
+ struct velocity_info *vptr = netdev_priv(dev);
+ int ret;
+
+- vptr->rx_buf_sz = (dev->mtu <= 1504 ? PKT_BUF_SZ : dev->mtu + 32);
+-
+ ret = velocity_init_rings(vptr);
+ if (ret < 0)
+ goto out;
+@@ -1798,6 +1799,11 @@ static int velocity_change_mtu(struct ne
+ return -EINVAL;
+ }
+
++ if (!netif_running(dev)) {
++ dev->mtu = new_mtu;
++ return 0;
++ }
++
+ if (new_mtu != oldmtu) {
+ spin_lock_irqsave(&vptr->lock, flags);
+
+@@ -1808,12 +1814,6 @@ static int velocity_change_mtu(struct ne
+ velocity_free_rd_ring(vptr);
+
+ dev->mtu = new_mtu;
+- if (new_mtu > 8192)
+- vptr->rx_buf_sz = 9 * 1024;
+- else if (new_mtu > 4096)
+- vptr->rx_buf_sz = 8192;
+- else
+- vptr->rx_buf_sz = 4 * 1024;
+
+ ret = velocity_init_rd_ring(vptr);
+ if (ret < 0)
+diff -NurpP linux-2.6.22.18/drivers/pci/hotplug/fakephp.c linux-2.6.22.19/drivers/pci/hotplug/fakephp.c
+--- linux-2.6.22.18/drivers/pci/hotplug/fakephp.c 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/drivers/pci/hotplug/fakephp.c 2008-02-26 00:59:40.000000000 +0100
+@@ -39,6 +39,7 @@
+ #include <linux/init.h>
+ #include <linux/string.h>
+ #include <linux/slab.h>
++#include <linux/workqueue.h>
+ #include "../pci.h"
+
+ #if !defined(MODULE)
+@@ -63,10 +64,16 @@ struct dummy_slot {
+ struct list_head node;
+ struct hotplug_slot *slot;
+ struct pci_dev *dev;
++ struct work_struct remove_work;
++ unsigned long removed;
+ };
+
+ static int debug;
+ static LIST_HEAD(slot_list);
++static struct workqueue_struct *dummyphp_wq;
++
++static void pci_rescan_worker(struct work_struct *work);
++static DECLARE_WORK(pci_rescan_work, pci_rescan_worker);
+
+ static int enable_slot (struct hotplug_slot *slot);
+ static int disable_slot (struct hotplug_slot *slot);
+@@ -109,7 +116,7 @@ static int add_slot(struct pci_dev *dev)
+ slot->name = &dev->dev.bus_id[0];
+ dbg("slot->name = %s\n", slot->name);
+
+- dslot = kmalloc(sizeof(struct dummy_slot), GFP_KERNEL);
++ dslot = kzalloc(sizeof(struct dummy_slot), GFP_KERNEL);
+ if (!dslot)
+ goto error_info;
+
+@@ -164,6 +171,14 @@ static void remove_slot(struct dummy_slo
+ err("Problem unregistering a slot %s\n", dslot->slot->name);
+ }
+
++/* called from the single-threaded workqueue handler to remove a slot */
++static void remove_slot_worker(struct work_struct *work)
++{
++ struct dummy_slot *dslot =
++ container_of(work, struct dummy_slot, remove_work);
++ remove_slot(dslot);
++}
++
+ /**
+ * Rescan slot.
+ * Tries hard not to re-enable already existing devices
+@@ -267,11 +282,17 @@ static inline void pci_rescan(void) {
+ pci_rescan_buses(&pci_root_buses);
+ }
+
++/* called from the single-threaded workqueue handler to rescan all pci buses */
++static void pci_rescan_worker(struct work_struct *work)
++{
++ pci_rescan();
++}
+
+ static int enable_slot(struct hotplug_slot *hotplug_slot)
+ {
+ /* mis-use enable_slot for rescanning of the pci bus */
+- pci_rescan();
++ cancel_work_sync(&pci_rescan_work);
++ queue_work(dummyphp_wq, &pci_rescan_work);
+ return -ENODEV;
+ }
+
+@@ -306,6 +327,10 @@ static int disable_slot(struct hotplug_s
+ err("Can't remove PCI devices with other PCI devices behind it yet.\n");
+ return -ENODEV;
+ }
++ if (test_and_set_bit(0, &dslot->removed)) {
++ dbg("Slot already scheduled for removal\n");
++ return -ENODEV;
++ }
+ /* search for subfunctions and disable them first */
+ if (!(dslot->dev->devfn & 7)) {
+ for (func = 1; func < 8; func++) {
+@@ -328,8 +353,9 @@ static int disable_slot(struct hotplug_s
+ /* remove the device from the pci core */
+ pci_remove_bus_device(dslot->dev);
+
+- /* blow away this sysfs entry and other parts. */
+- remove_slot(dslot);
++ /* queue work item to blow away this sysfs entry and other parts. */
++ INIT_WORK(&dslot->remove_work, remove_slot_worker);
++ queue_work(dummyphp_wq, &dslot->remove_work);
+
+ return 0;
+ }
+@@ -340,6 +366,7 @@ static void cleanup_slots (void)
+ struct list_head *next;
+ struct dummy_slot *dslot;
+
++ destroy_workqueue(dummyphp_wq);
+ list_for_each_safe (tmp, next, &slot_list) {
+ dslot = list_entry (tmp, struct dummy_slot, node);
+ remove_slot(dslot);
+@@ -351,6 +378,10 @@ static int __init dummyphp_init(void)
+ {
+ info(DRIVER_DESC "\n");
+
++ dummyphp_wq = create_singlethread_workqueue(MY_NAME);
++ if (!dummyphp_wq)
++ return -ENOMEM;
++
+ return pci_scan_buses();
+ }
+
+diff -NurpP linux-2.6.22.18/drivers/scsi/sd.c linux-2.6.22.19/drivers/scsi/sd.c
+--- linux-2.6.22.18/drivers/scsi/sd.c 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/drivers/scsi/sd.c 2008-02-26 00:59:40.000000000 +0100
+@@ -895,6 +895,7 @@ static void sd_rw_intr(struct scsi_cmnd
+ unsigned int xfer_size = SCpnt->request_bufflen;
+ unsigned int good_bytes = result ? 0 : xfer_size;
+ u64 start_lba = SCpnt->request->sector;
++ u64 end_lba = SCpnt->request->sector + (xfer_size / 512);
+ u64 bad_lba;
+ struct scsi_sense_hdr sshdr;
+ int sense_valid = 0;
+@@ -933,26 +934,23 @@ static void sd_rw_intr(struct scsi_cmnd
+ goto out;
+ if (xfer_size <= SCpnt->device->sector_size)
+ goto out;
+- switch (SCpnt->device->sector_size) {
+- case 256:
++ if (SCpnt->device->sector_size < 512) {
++ /* only legitimate sector_size here is 256 */
+ start_lba <<= 1;
+- break;
+- case 512:
+- break;
+- case 1024:
+- start_lba >>= 1;
+- break;
+- case 2048:
+- start_lba >>= 2;
+- break;
+- case 4096:
+- start_lba >>= 3;
+- break;
+- default:
+- /* Print something here with limiting frequency. */
+- goto out;
+- break;
++ end_lba <<= 1;
++ } else {
++ /* be careful ... don't want any overflows */
++ u64 factor = SCpnt->device->sector_size / 512;
++ do_div(start_lba, factor);
++ do_div(end_lba, factor);
+ }
++
++ if (bad_lba < start_lba || bad_lba >= end_lba)
++ /* the bad lba was reported incorrectly, we have
++ * no idea where the error is
++ */
++ goto out;
++
+ /* This computation should always be done in terms of
+ * the resolution of the device's medium.
+ */
+diff -NurpP linux-2.6.22.18/fs/nfs/client.c linux-2.6.22.19/fs/nfs/client.c
+--- linux-2.6.22.18/fs/nfs/client.c 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/fs/nfs/client.c 2008-02-26 00:59:40.000000000 +0100
+@@ -433,9 +433,6 @@ static int nfs_create_rpc_client(struct
+ */
+ static void nfs_destroy_server(struct nfs_server *server)
+ {
+- if (!IS_ERR(server->client_acl))
+- rpc_shutdown_client(server->client_acl);
+-
+ if (!(server->flags & NFS_MOUNT_NONLM))
+ lockd_down(); /* release rpc.lockd */
+ }
+@@ -614,16 +611,6 @@ static int nfs_init_server(struct nfs_se
+ server->namelen = data->namlen;
+ /* Create a client RPC handle for the NFSv3 ACL management interface */
+ nfs_init_server_aclclient(server);
+- if (clp->cl_nfsversion == 3) {
+- if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN)
+- server->namelen = NFS3_MAXNAMLEN;
+- if (!(data->flags & NFS_MOUNT_NORDIRPLUS))
+- server->caps |= NFS_CAP_READDIRPLUS;
+- } else {
+- if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN)
+- server->namelen = NFS2_MAXNAMLEN;
+- }
+-
+ dprintk("<-- nfs_init_server() = 0 [new %p]\n", clp);
+ return 0;
+
+@@ -781,6 +768,9 @@ void nfs_free_server(struct nfs_server *
+
+ if (server->destroy != NULL)
+ server->destroy(server);
++
++ if (!IS_ERR(server->client_acl))
++ rpc_shutdown_client(server->client_acl);
+ if (!IS_ERR(server->client))
+ rpc_shutdown_client(server->client);
+
+@@ -820,6 +810,16 @@ struct nfs_server *nfs_create_server(con
+ error = nfs_probe_fsinfo(server, mntfh, &fattr);
+ if (error < 0)
+ goto error;
++ if (server->nfs_client->rpc_ops->version == 3) {
++ if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN)
++ server->namelen = NFS3_MAXNAMLEN;
++ if (!(data->flags & NFS_MOUNT_NORDIRPLUS))
++ server->caps |= NFS_CAP_READDIRPLUS;
++ } else {
++ if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN)
++ server->namelen = NFS2_MAXNAMLEN;
++ }
++
+ if (!(fattr.valid & NFS_ATTR_FATTR)) {
+ error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr);
+ if (error < 0) {
+@@ -1010,6 +1010,9 @@ struct nfs_server *nfs4_create_server(co
+ if (error < 0)
+ goto error;
+
++ if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
++ server->namelen = NFS4_MAXNAMLEN;
++
+ BUG_ON(!server->nfs_client);
+ BUG_ON(!server->nfs_client->rpc_ops);
+ BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
+@@ -1082,6 +1085,9 @@ struct nfs_server *nfs4_create_referral_
+ if (error < 0)
+ goto error;
+
++ if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
++ server->namelen = NFS4_MAXNAMLEN;
++
+ dprintk("Referral FSID: %llx:%llx\n",
+ (unsigned long long) server->fsid.major,
+ (unsigned long long) server->fsid.minor);
+@@ -1141,6 +1147,9 @@ struct nfs_server *nfs_clone_server(stru
+ if (error < 0)
+ goto out_free_server;
+
++ if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
++ server->namelen = NFS4_MAXNAMLEN;
++
+ dprintk("Cloned FSID: %llx:%llx\n",
+ (unsigned long long) server->fsid.major,
+ (unsigned long long) server->fsid.minor);
+diff -NurpP linux-2.6.22.18/fs/nfs/dir.c linux-2.6.22.19/fs/nfs/dir.c
+--- linux-2.6.22.18/fs/nfs/dir.c 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/fs/nfs/dir.c 2008-02-26 00:59:40.000000000 +0100
+@@ -897,14 +897,13 @@ int nfs_is_exclusive_create(struct inode
+ return (nd->intent.open.flags & O_EXCL) != 0;
+ }
+
+-static inline int nfs_reval_fsid(struct vfsmount *mnt, struct inode *dir,
+- struct nfs_fh *fh, struct nfs_fattr *fattr)
++static inline int nfs_reval_fsid(struct inode *dir, const struct nfs_fattr *fattr)
+ {
+ struct nfs_server *server = NFS_SERVER(dir);
+
+ if (!nfs_fsid_equal(&server->fsid, &fattr->fsid))
+- /* Revalidate fsid on root dir */
+- return __nfs_revalidate_inode(server, mnt->mnt_root->d_inode);
++ /* Revalidate fsid using the parent directory */
++ return __nfs_revalidate_inode(server, dir);
+ return 0;
+ }
+
+@@ -946,7 +945,7 @@ static struct dentry *nfs_lookup(struct
+ res = ERR_PTR(error);
+ goto out_unlock;
+ }
+- error = nfs_reval_fsid(nd->mnt, dir, &fhandle, &fattr);
++ error = nfs_reval_fsid(dir, &fattr);
+ if (error < 0) {
+ res = ERR_PTR(error);
+ goto out_unlock;
+@@ -1163,6 +1162,8 @@ static struct dentry *nfs_readdir_lookup
+ }
+ if (!desc->plus || !(entry->fattr->valid & NFS_ATTR_FATTR))
+ return NULL;
++ if (name.len > NFS_SERVER(dir)->namelen)
++ return NULL;
+ /* Note: caller is already holding the dir->i_mutex! */
+ dentry = d_alloc(parent, &name);
+ if (dentry == NULL)
+diff -NurpP linux-2.6.22.18/fs/nfs/getroot.c linux-2.6.22.19/fs/nfs/getroot.c
+--- linux-2.6.22.18/fs/nfs/getroot.c 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/fs/nfs/getroot.c 2008-02-26 00:59:40.000000000 +0100
+@@ -175,6 +175,9 @@ next_component:
+ path++;
+ name.len = path - (const char *) name.name;
+
++ if (name.len > NFS4_MAXNAMLEN)
++ return -ENAMETOOLONG;
++
+ eat_dot_dir:
+ while (*path == '/')
+ path++;
+diff -NurpP linux-2.6.22.18/fs/nfs/inode.c linux-2.6.22.19/fs/nfs/inode.c
+--- linux-2.6.22.18/fs/nfs/inode.c 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/fs/nfs/inode.c 2008-02-26 00:59:40.000000000 +0100
+@@ -961,8 +961,8 @@ static int nfs_update_inode(struct inode
+ goto out_changed;
+
+ server = NFS_SERVER(inode);
+- /* Update the fsid if and only if this is the root directory */
+- if (inode == inode->i_sb->s_root->d_inode
++ /* Update the fsid? */
++ if (S_ISDIR(inode->i_mode)
+ && !nfs_fsid_equal(&server->fsid, &fattr->fsid))
+ server->fsid = fattr->fsid;
+
+diff -NurpP linux-2.6.22.18/fs/nfs/write.c linux-2.6.22.19/fs/nfs/write.c
+--- linux-2.6.22.18/fs/nfs/write.c 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/fs/nfs/write.c 2008-02-26 00:59:40.000000000 +0100
+@@ -710,6 +710,17 @@ int nfs_flush_incompatible(struct file *
+ }
+
+ /*
++ * If the page cache is marked as unsafe or invalid, then we can't rely on
++ * the PageUptodate() flag. In this case, we will need to turn off
++ * write optimisations that depend on the page contents being correct.
++ */
++static int nfs_write_pageuptodate(struct page *page, struct inode *inode)
++{
++ return PageUptodate(page) &&
++ !(NFS_I(inode)->cache_validity & (NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA));
++}
++
++/*
+ * Update and possibly write a cached page of an NFS file.
+ *
+ * XXX: Keep an eye on generic_file_read to make sure it doesn't do bad
+@@ -730,10 +741,13 @@ int nfs_updatepage(struct file *file, st
+ (long long)(page_offset(page) +offset));
+
+ /* If we're not using byte range locks, and we know the page
+- * is entirely in cache, it may be more efficient to avoid
+- * fragmenting write requests.
++ * is up to date, it may be more efficient to extend the write
++ * to cover the entire page in order to avoid fragmentation
++ * inefficiencies.
+ */
+- if (PageUptodate(page) && inode->i_flock == NULL && !(file->f_mode & O_SYNC)) {
++ if (nfs_write_pageuptodate(page, inode) &&
++ inode->i_flock == NULL &&
++ !(file->f_mode & O_SYNC)) {
+ count = max(count + offset, nfs_page_length(page));
+ offset = 0;
+ }
+diff -NurpP linux-2.6.22.18/fs/nfsd/nfs2acl.c linux-2.6.22.19/fs/nfsd/nfs2acl.c
+--- linux-2.6.22.18/fs/nfsd/nfs2acl.c 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/fs/nfsd/nfs2acl.c 2008-02-26 00:59:40.000000000 +0100
+@@ -41,7 +41,7 @@ static __be32 nfsacld_proc_getacl(struct
+
+ fh = fh_copy(&resp->fh, &argp->fh);
+ if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP)))
+- RETURN_STATUS(nfserr_inval);
++ RETURN_STATUS(nfserr);
+
+ if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
+ RETURN_STATUS(nfserr_inval);
+diff -NurpP linux-2.6.22.18/fs/nfsd/nfs3acl.c linux-2.6.22.19/fs/nfsd/nfs3acl.c
+--- linux-2.6.22.18/fs/nfsd/nfs3acl.c 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/fs/nfsd/nfs3acl.c 2008-02-26 00:59:40.000000000 +0100
+@@ -37,7 +37,7 @@ static __be32 nfsd3_proc_getacl(struct s
+
+ fh = fh_copy(&resp->fh, &argp->fh);
+ if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP)))
+- RETURN_STATUS(nfserr_inval);
++ RETURN_STATUS(nfserr);
+
+ if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
+ RETURN_STATUS(nfserr_inval);
+diff -NurpP linux-2.6.22.18/fs/nfsd/nfs4xdr.c linux-2.6.22.19/fs/nfsd/nfs4xdr.c
+--- linux-2.6.22.18/fs/nfsd/nfs4xdr.c 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/fs/nfsd/nfs4xdr.c 2008-02-26 00:59:40.000000000 +0100
+@@ -1453,7 +1453,8 @@ nfsd4_encode_fattr(struct svc_fh *fhp, s
+ err = vfs_getattr(exp->ex_mnt, dentry, &stat);
+ if (err)
+ goto out_nfserr;
+- if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL)) ||
++ if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL |
++ FATTR4_WORD0_MAXNAME)) ||
+ (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE |
+ FATTR4_WORD1_SPACE_TOTAL))) {
+ err = vfs_statfs(dentry, &statfs);
+@@ -1699,7 +1700,7 @@ out_acl:
+ if (bmval0 & FATTR4_WORD0_MAXNAME) {
+ if ((buflen -= 4) < 0)
+ goto out_resource;
+- WRITE32(~(u32) 0);
++ WRITE32(statfs.f_namelen);
+ }
+ if (bmval0 & FATTR4_WORD0_MAXREAD) {
+ if ((buflen -= 8) < 0)
+diff -NurpP linux-2.6.22.18/include/linux/quicklist.h linux-2.6.22.19/include/linux/quicklist.h
+--- linux-2.6.22.18/include/linux/quicklist.h 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/include/linux/quicklist.h 2008-02-26 00:59:40.000000000 +0100
+@@ -56,14 +56,6 @@ static inline void __quicklist_free(int
+ struct page *page)
+ {
+ struct quicklist *q;
+- int nid = page_to_nid(page);
+-
+- if (unlikely(nid != numa_node_id())) {
+- if (dtor)
+- dtor(p);
+- __free_page(page);
+- return;
+- }
+
+ q = &get_cpu_var(quicklist)[nr];
+ *(void **)p = q->page;
+diff -NurpP linux-2.6.22.18/mm/memory.c linux-2.6.22.19/mm/memory.c
+--- linux-2.6.22.18/mm/memory.c 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/mm/memory.c 2008-02-26 00:59:40.000000000 +0100
+@@ -983,6 +983,8 @@ int get_user_pages(struct task_struct *t
+ int i;
+ unsigned int vm_flags;
+
++ if (len <= 0)
++ return 0;
+ /*
+ * Require read or write permissions.
+ * If 'force' is set, we only require the "MAY" flags.
+diff -NurpP linux-2.6.22.18/mm/quicklist.c linux-2.6.22.19/mm/quicklist.c
+--- linux-2.6.22.18/mm/quicklist.c 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/mm/quicklist.c 2008-02-26 00:59:40.000000000 +0100
+@@ -26,9 +26,17 @@ DEFINE_PER_CPU(struct quicklist, quickli
+ static unsigned long max_pages(unsigned long min_pages)
+ {
+ unsigned long node_free_pages, max;
++ struct zone *zones = NODE_DATA(numa_node_id())->node_zones;
++
++ node_free_pages =
++#ifdef CONFIG_ZONE_DMA
++ zone_page_state(&zones[ZONE_DMA], NR_FREE_PAGES) +
++#endif
++#ifdef CONFIG_ZONE_DMA32
++ zone_page_state(&zones[ZONE_DMA32], NR_FREE_PAGES) +
++#endif
++ zone_page_state(&zones[ZONE_NORMAL], NR_FREE_PAGES);
+
+- node_free_pages = node_page_state(numa_node_id(),
+- NR_FREE_PAGES);
+ max = node_free_pages / FRACTION_OF_NODE_MEM;
+ return max(max, min_pages);
+ }
+diff -NurpP linux-2.6.22.18/net/netfilter/nf_conntrack_proto_tcp.c linux-2.6.22.19/net/netfilter/nf_conntrack_proto_tcp.c
+--- linux-2.6.22.18/net/netfilter/nf_conntrack_proto_tcp.c 2008-02-11 08:31:19.000000000 +0100
++++ linux-2.6.22.19/net/netfilter/nf_conntrack_proto_tcp.c 2008-02-26 00:59:40.000000000 +0100
+@@ -143,7 +143,7 @@ enum tcp_bit_set {
+ * CLOSE_WAIT: ACK seen (after FIN)
+ * LAST_ACK: FIN seen (after FIN)
+ * TIME_WAIT: last ACK seen
+- * CLOSE: closed connection
++ * CLOSE: closed connection (RST)
+ *
+ * LISTEN state is not used.
+ *
+@@ -842,8 +842,21 @@ static int tcp_packet(struct nf_conn *co
+ case TCP_CONNTRACK_SYN_SENT:
+ if (old_state < TCP_CONNTRACK_TIME_WAIT)
+ break;
+- if ((conntrack->proto.tcp.seen[!dir].flags &
+- IP_CT_TCP_FLAG_CLOSE_INIT)
++ /* RFC 1122: "When a connection is closed actively,
++ * it MUST linger in TIME-WAIT state for a time 2xMSL
++ * (Maximum Segment Lifetime). However, it MAY accept
++ * a new SYN from the remote TCP to reopen the connection
++ * directly from TIME-WAIT state, if..."
++ * We ignore the conditions because we are in the
++ * TIME-WAIT state anyway.
++ *
++ * Handle aborted connections: we and the server
++ * think there is an existing connection but the client
++ * aborts it and starts a new one.
++ */
++ if (((conntrack->proto.tcp.seen[dir].flags
++ | conntrack->proto.tcp.seen[!dir].flags)
++ & IP_CT_TCP_FLAG_CLOSE_INIT)
+ || (conntrack->proto.tcp.last_dir == dir
+ && conntrack->proto.tcp.last_index == TCP_RST_SET)) {
+ /* Attempt to reopen a closed/aborted connection.
+@@ -858,16 +871,23 @@ static int tcp_packet(struct nf_conn *co
+ case TCP_CONNTRACK_IGNORE:
+ /* Ignored packets:
+ *
++ * Our connection entry may be out of sync, so ignore
++ * packets which may signal the real connection between
++ * the client and the server.
++ *
+ * a) SYN in ORIGINAL
+ * b) SYN/ACK in REPLY
+ * c) ACK in reply direction after initial SYN in original.
++ *
++ * If the ignored packet is invalid, the receiver will send
++ * a RST we'll catch below.
+ */
+ if (index == TCP_SYNACK_SET
+ && conntrack->proto.tcp.last_index == TCP_SYN_SET
+ && conntrack->proto.tcp.last_dir != dir
+ && ntohl(th->ack_seq) ==
+ conntrack->proto.tcp.last_end) {
+- /* This SYN/ACK acknowledges a SYN that we earlier
++ /* b) This SYN/ACK acknowledges a SYN that we earlier
+ * ignored as invalid. This means that the client and
+ * the server are both in sync, while the firewall is
+ * not. We kill this session and block the SYN/ACK so
+@@ -892,7 +912,7 @@ static int tcp_packet(struct nf_conn *co
+ write_unlock_bh(&tcp_lock);
+ if (LOG_INVALID(IPPROTO_TCP))
+ nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
+- "nf_ct_tcp: invalid packed ignored ");
++ "nf_ct_tcp: invalid packet ignored ");
+ return NF_ACCEPT;
+ case TCP_CONNTRACK_MAX:
+ /* Invalid packet */
+@@ -948,8 +968,7 @@ static int tcp_packet(struct nf_conn *co
+
+ conntrack->proto.tcp.state = new_state;
+ if (old_state != new_state
+- && (new_state == TCP_CONNTRACK_FIN_WAIT
+- || new_state == TCP_CONNTRACK_CLOSE))
++ && new_state == TCP_CONNTRACK_FIN_WAIT)
+ conntrack->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT;
+ timeout = conntrack->proto.tcp.retrans >= nf_ct_tcp_max_retrans
+ && *tcp_timeouts[new_state] > nf_ct_tcp_timeout_max_retrans