From f8ad23a401d41f90cb377035d206b41de0699a0b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 6 Dec 2005 05:44:18 -0500 Subject: [PATCH] fix iomem annotations in sparc32 pcic code Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- include/asm-sparc/pcic.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/asm-sparc/pcic.h b/include/asm-sparc/pcic.h index 301ae8022dd..dedea14d87c 100644 --- a/include/asm-sparc/pcic.h +++ b/include/asm-sparc/pcic.h @@ -16,10 +16,10 @@ #include struct linux_pcic { - void * __iomem pcic_regs; + void __iomem *pcic_regs; unsigned long pcic_io; - void * __iomem pcic_config_space_addr; - void * __iomem pcic_config_space_data; + void __iomem *pcic_config_space_addr; + void __iomem *pcic_config_space_data; struct resource pcic_res_regs; struct resource pcic_res_io; struct resource pcic_res_cfg_addr; -- cgit v1.2.3-70-g09d2 From a32972965e23471f0762a1136f80990ebf72406a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 6 Dec 2005 05:56:39 -0500 Subject: [PATCH] sun4c_memerr_reg __iomem annotations Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- arch/sparc/mm/sun4c.c | 2 +- include/asm-sparc/memreg.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index 1d560390e28..731f19603ca 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c @@ -497,7 +497,7 @@ static void __init sun4c_probe_mmu(void) patch_kernel_fault_handler(); } -volatile unsigned long *sun4c_memerr_reg = NULL; +volatile unsigned long __iomem *sun4c_memerr_reg = NULL; void __init sun4c_probe_memerr_reg(void) { diff --git a/include/asm-sparc/memreg.h b/include/asm-sparc/memreg.h index c0498d3baf9..5fb95c828da 100644 --- a/include/asm-sparc/memreg.h +++ b/include/asm-sparc/memreg.h @@ -36,7 +36,7 @@ /* Memory parity error register with associated bit constants. */ #ifndef __ASSEMBLY__ -extern __volatile__ unsigned long *sun4c_memerr_reg; +extern __volatile__ unsigned long __iomem *sun4c_memerr_reg; #endif #define SUN4C_MPE_ERROR 0x80 /* Parity error detected. (ro) */ -- cgit v1.2.3-70-g09d2 From f5899b5d4fa806403f547dc41312d017d94ec273 Mon Sep 17 00:00:00 2001 From: John Hawkes Date: Fri, 16 Dec 2005 10:00:24 -0800 Subject: [IA64] disable preemption in udelay() The udelay() inline for ia64 uses the ITC. If CONFIG_PREEMPT is enabled and the platform has unsynchronized ITCs and the calling task migrates to another CPU while doing the udelay loop, then the effective delay may be too short or very, very long. This patch disables preemption around 100 usec chunks of the overall desired udelay time. This minimizes preemption-holdoffs. udelay() is now too big to be inline, move it out of line and export it. Signed-off-by: John Hawkes Signed-off-by: Tony Luck --- arch/ia64/kernel/time.c | 29 +++++++++++++++++++++++++++++ include/asm-ia64/delay.h | 10 +--------- 2 files changed, 30 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index 5b7e736f3b4..028a2b95936 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c @@ -249,3 +249,32 @@ time_init (void) */ set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); } + +#define SMALLUSECS 100 + +void +udelay (unsigned long usecs) +{ + unsigned long start; + unsigned long cycles; + unsigned long smallusecs; + + /* + * Execute the non-preemptible delay loop (because the ITC might + * not be synchronized between CPUS) in relatively short time + * chunks, allowing preemption between the chunks. + */ + while (usecs > 0) { + smallusecs = (usecs > SMALLUSECS) ? SMALLUSECS : usecs; + preempt_disable(); + cycles = smallusecs*local_cpu_data->cyc_per_usec; + start = ia64_get_itc(); + + while (ia64_get_itc() - start < cycles) + cpu_relax(); + + preempt_enable(); + usecs -= smallusecs; + } +} +EXPORT_SYMBOL(udelay); diff --git a/include/asm-ia64/delay.h b/include/asm-ia64/delay.h index 57182d6f2b9..bba70207639 100644 --- a/include/asm-ia64/delay.h +++ b/include/asm-ia64/delay.h @@ -84,14 +84,6 @@ __delay (unsigned long loops) ia64_delay_loop (loops - 1); } -static __inline__ void -udelay (unsigned long usecs) -{ - unsigned long start = ia64_get_itc(); - unsigned long cycles = usecs*local_cpu_data->cyc_per_usec; - - while (ia64_get_itc() - start < cycles) - cpu_relax(); -} +extern void udelay (unsigned long usecs); #endif /* _ASM_IA64_DELAY_H */ -- cgit v1.2.3-70-g09d2 From 4d7672b46244abffea1953e55688c0ea143dd617 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 16 Dec 2005 10:21:23 -0800 Subject: Make sure we copy pages inserted with "vm_insert_page()" on fork The logic that decides that a fork() might be able to avoid copying a VM area when it can be re-created by page faults didn't know about the new vm_insert_page() case. Also make some things a bit more anal wrt VM_PFNMAP. Pointed out by Hugh Dickins Signed-off-by: Linus Torvalds --- include/linux/mm.h | 1 + mm/memory.c | 3 ++- mm/mmap.c | 2 +- mm/mremap.c | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/linux/mm.h b/include/linux/mm.h index e5677f45674..a06a84d347f 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -163,6 +163,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_INSERTPAGE 0x02000000 /* The vma has had "vm_insert_page()" done on it */ #ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */ #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS diff --git a/mm/memory.c b/mm/memory.c index d22f78c8a38..d8dde07a365 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -574,7 +574,7 @@ int copy_page_range(struct mm_struct *dst_mm, struct mm_struct *src_mm, * readonly mappings. The tradeoff is that copy_page_range is more * efficient than faulting. */ - if (!(vma->vm_flags & (VM_HUGETLB|VM_NONLINEAR|VM_PFNMAP))) { + if (!(vma->vm_flags & (VM_HUGETLB|VM_NONLINEAR|VM_PFNMAP|VM_INSERTPAGE))) { if (!vma->anon_vma) return 0; } @@ -1228,6 +1228,7 @@ int vm_insert_page(struct vm_area_struct *vma, unsigned long addr, struct page * return -EFAULT; if (!page_count(page)) return -EINVAL; + vma->vm_flags |= VM_INSERTPAGE; return insert_page(vma->vm_mm, addr, page, vma->vm_page_prot); } EXPORT_SYMBOL(vm_insert_page); diff --git a/mm/mmap.c b/mm/mmap.c index 11ca5927d5f..64ba4dbcb7d 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -611,7 +611,7 @@ again: remove_next = 1 + (end > next->vm_end); * If the vma has a ->close operation then the driver probably needs to release * per-vma resources, so we don't attempt to merge those. */ -#define VM_SPECIAL (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED) +#define VM_SPECIAL (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED | VM_PFNMAP) static inline int is_mergeable_vma(struct vm_area_struct *vma, struct file *file, unsigned long vm_flags) diff --git a/mm/mremap.c b/mm/mremap.c index b535438c363..ddaeee9a0b6 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -323,7 +323,7 @@ unsigned long do_mremap(unsigned long addr, /* We can't remap across vm area boundaries */ if (old_len > vma->vm_end - addr) goto out; - if (vma->vm_flags & VM_DONTEXPAND) { + if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP)) { if (new_len > old_len) goto out; } -- cgit v1.2.3-70-g09d2 From dc86e88c2bb8a7603ee175fbb6a9e92cf3293dd8 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Mon, 12 Dec 2005 09:34:32 -0800 Subject: [IA64] Add __read_mostly support for IA64 sparc64, i386 and x86_64 have support for a special data section dedicated to rarely updated data that is frequently read. The section was created to avoid false sharing of those rarely read data with frequently written kernel data. This patch creates such a data section for ia64 and will group rarely written data into this section. Signed-off-by: Christoph Lameter Signed-off-by: Tony Luck --- arch/ia64/kernel/vmlinux.lds.S | 3 +++ include/linux/cache.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S index 30d8564e960..73af6267d2e 100644 --- a/arch/ia64/kernel/vmlinux.lds.S +++ b/arch/ia64/kernel/vmlinux.lds.S @@ -177,6 +177,9 @@ SECTIONS } . = ALIGN(PAGE_SIZE); /* make sure the gate page doesn't expose kernel data */ + .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) + { *(.data.read_mostly) } + .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) { *(.data.cacheline_aligned) } diff --git a/include/linux/cache.h b/include/linux/cache.h index f6b5a46c5f8..0b7ecf3af78 100644 --- a/include/linux/cache.h +++ b/include/linux/cache.h @@ -13,7 +13,7 @@ #define SMP_CACHE_BYTES L1_CACHE_BYTES #endif -#if defined(CONFIG_X86) || defined(CONFIG_SPARC64) +#if defined(CONFIG_X86) || defined(CONFIG_SPARC64) || defined(CONFIG_IA64) #define __read_mostly __attribute__((__section__(".data.read_mostly"))) #else #define __read_mostly -- cgit v1.2.3-70-g09d2 From 7c3dbbe982ac85837f1da150ea9539a9e9a12557 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 16 Dec 2005 22:35:23 +0000 Subject: [PATCH] ppc: ppc4xx_dma DMA_MODE_{READ,WRITE} fix DMA_MODE_{READ,WRITE} are declared in asm-powerpc/dma.h and their declarations there match the definitions. Old declarations in ppc4xx_dma.h are not right anymore (wrong type, to start with). Killed them, added include of asm/dma.h where needed. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- arch/ppc/syslib/ppc4xx_dma.c | 1 + include/asm-ppc/ppc4xx_dma.h | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'include') diff --git a/arch/ppc/syslib/ppc4xx_dma.c b/arch/ppc/syslib/ppc4xx_dma.c index f15e64285f9..05ccd598dd4 100644 --- a/arch/ppc/syslib/ppc4xx_dma.c +++ b/arch/ppc/syslib/ppc4xx_dma.c @@ -30,6 +30,7 @@ #include #include +#include #include ppc_dma_ch_t dma_channels[MAX_PPC4xx_DMA_CHANNELS]; diff --git a/include/asm-ppc/ppc4xx_dma.h b/include/asm-ppc/ppc4xx_dma.h index a415001165f..46a086fff81 100644 --- a/include/asm-ppc/ppc4xx_dma.h +++ b/include/asm-ppc/ppc4xx_dma.h @@ -33,9 +33,6 @@ #define MAX_PPC4xx_DMA_CHANNELS 4 -/* in arch/ppc/kernel/setup.c -- Cort */ -extern unsigned long DMA_MODE_WRITE, DMA_MODE_READ; - /* * Function return status codes * These values are used to indicate whether or not the function -- cgit v1.2.3-70-g09d2 From 37b1cc3910f7976369fc0ed55068a686e92555e6 Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Fri, 16 Dec 2005 11:17:29 +0900 Subject: [PATCH] mtd onenand driver: check correct manufacturer This (and the three subsequent patches) is working well on OMAP H4 with 2.6.15-rc4 kernel and passes the LTP fs test. Signed-off-by: Linus Torvalds --- drivers/mtd/onenand/onenand_base.c | 16 ++++++++++------ include/linux/mtd/onenand.h | 1 - 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index f67d5d6eb9a..33d6f5c2e05 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -1346,7 +1346,6 @@ static void onenand_print_device_info(int device) static const struct onenand_manufacturers onenand_manuf_ids[] = { {ONENAND_MFR_SAMSUNG, "Samsung"}, - {ONENAND_MFR_UNKNOWN, "Unknown"} }; /** @@ -1357,17 +1356,22 @@ static const struct onenand_manufacturers onenand_manuf_ids[] = { */ static int onenand_check_maf(int manuf) { + int size = ARRAY_SIZE(onenand_manuf_ids); + char *name; int i; - for (i = 0; onenand_manuf_ids[i].id; i++) { + for (i = 0; i < size; i++) if (manuf == onenand_manuf_ids[i].id) break; - } - printk(KERN_DEBUG "OneNAND Manufacturer: %s (0x%0x)\n", - onenand_manuf_ids[i].name, manuf); + if (i < size) + name = onenand_manuf_ids[i].name; + else + name = "Unknown"; + + printk(KERN_DEBUG "OneNAND Manufacturer: %s (0x%0x)\n", name, manuf); - return (i != ONENAND_MFR_UNKNOWN); + return (i == size); } /** diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index f1fd4215686..53423d3b43b 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -140,7 +140,6 @@ struct onenand_chip { * OneNAND Flash Manufacturer ID Codes */ #define ONENAND_MFR_SAMSUNG 0xec -#define ONENAND_MFR_UNKNOWN 0x00 /** * struct nand_manufacturers - NAND Flash Manufacturer ID Structure -- cgit v1.2.3-70-g09d2 From 532a37cf8d05dd1aa5631be836036204b0d2b4a1 Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Fri, 16 Dec 2005 11:17:29 +0900 Subject: [PATCH] mtd onenand driver: reduce stack usage Signed-off-by: Linus Torvalds --- drivers/mtd/onenand/onenand_base.c | 27 ++++++++++++++++++++++++--- drivers/mtd/onenand/onenand_bbt.c | 4 ++-- include/linux/mtd/onenand.h | 4 ++-- 3 files changed, 28 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index d57afbaaedc..a53a73fc2a5 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -940,7 +940,7 @@ static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, u_char *eccbuf, struct nand_oobinfo *oobsel) { struct onenand_chip *this = mtd->priv; - unsigned char buffer[MAX_ONENAND_PAGESIZE], *pbuf; + unsigned char *pbuf; size_t total_len, len; int i, written = 0; int ret = 0; @@ -975,7 +975,7 @@ static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, /* Loop until all keve's data has been written */ len = 0; while (count) { - pbuf = buffer; + pbuf = this->page_buf; /* * If the given tuple is >= pagesize then * write it out from the iov @@ -995,7 +995,7 @@ static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, int cnt = 0, thislen; while (cnt < mtd->oobblock) { thislen = min_t(int, mtd->oobblock - cnt, vecs->iov_len - len); - memcpy(buffer + cnt, vecs->iov_base + len, thislen); + memcpy(this->page_buf + cnt, vecs->iov_base + len, thislen); cnt += thislen; len += thislen; @@ -1519,6 +1519,18 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) this->read_bufferram = onenand_sync_read_bufferram; } + /* Allocate buffers, if necessary */ + if (!this->page_buf) { + size_t len; + len = mtd->oobblock + mtd->oobsize; + this->page_buf = kmalloc(len, GFP_KERNEL); + if (!this->page_buf) { + printk(KERN_ERR "onenand_scan(): Can't allocate page_buf\n"); + return -ENOMEM; + } + this->options |= ONENAND_PAGEBUF_ALLOC; + } + this->state = FL_READY; init_waitqueue_head(&this->wq); spin_lock_init(&this->chip_lock); @@ -1580,12 +1592,21 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) */ void onenand_release(struct mtd_info *mtd) { + struct onenand_chip *this = mtd->priv; + #ifdef CONFIG_MTD_PARTITIONS /* Deregister partitions */ del_mtd_partitions (mtd); #endif /* Deregister the device */ del_mtd_device (mtd); + + /* Free bad block table memory, if allocated */ + if (this->bbm) + kfree(this->bbm); + /* Buffer allocated by onenand_scan */ + if (this->options & ONENAND_PAGEBUF_ALLOC) + kfree(this->page_buf); } EXPORT_SYMBOL_GPL(onenand_scan); diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c index f40190f499e..4510d3361ea 100644 --- a/drivers/mtd/onenand/onenand_bbt.c +++ b/drivers/mtd/onenand/onenand_bbt.c @@ -118,10 +118,10 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr */ static inline int onenand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd) { - unsigned char data_buf[MAX_ONENAND_PAGESIZE]; + struct onenand_chip *this = mtd->priv; bd->options &= ~NAND_BBT_SCANEMPTY; - return create_bbt(mtd, data_buf, bd, -1); + return create_bbt(mtd, this->page_buf, bd, -1); } /** diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index 53423d3b43b..7419b5fab13 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -17,7 +17,6 @@ #include #define MAX_BUFFERRAM 2 -#define MAX_ONENAND_PAGESIZE (2048 + 64) /* Scan and identify a OneNAND device */ extern int onenand_scan(struct mtd_info *mtd, int max_chips); @@ -110,6 +109,7 @@ struct onenand_chip { spinlock_t chip_lock; wait_queue_head_t wq; onenand_state_t state; + unsigned char *page_buf; struct nand_oobinfo *autooob; @@ -134,7 +134,7 @@ struct onenand_chip { * Options bits */ #define ONENAND_CONT_LOCK (0x0001) - +#define ONENAND_PAGEBUF_ALLOC (0x1000) /* * OneNAND Flash Manufacturer ID Codes -- cgit v1.2.3-70-g09d2 From 6b80ebedbee87c5b2213fc3635bf0bd7450bce30 Mon Sep 17 00:00:00 2001 From: Kristian Slavov Date: Mon, 19 Dec 2005 13:54:44 -0800 Subject: [RTNETLINK]: Fix RTNLGRP definitions in rtnetlink.h I reported a problem and gave hints to the solution, but nobody seemed to react. So I prepared a patch against 2.6.14.4. Tested on 2.6.14.4 with "ip monitor addr" and with the program attached, while adding and removing IPv6 address. Both programs didn't receive any messages. Tested 2.6.14.4 + this patch, and both programs received add and remove messages. Signed-off-by: Kristian Slavov Acked-by: Jamal Hadi salim ACKed-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/rtnetlink.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index c231e9a08f0..d50482ba27f 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -866,6 +866,7 @@ enum rtnetlink_groups { #define RTNLGRP_IPV4_MROUTE RTNLGRP_IPV4_MROUTE RTNLGRP_IPV4_ROUTE, #define RTNLGRP_IPV4_ROUTE RTNLGRP_IPV4_ROUTE + RTNLGRP_NOP1, RTNLGRP_IPV6_IFADDR, #define RTNLGRP_IPV6_IFADDR RTNLGRP_IPV6_IFADDR RTNLGRP_IPV6_MROUTE, @@ -876,8 +877,11 @@ enum rtnetlink_groups { #define RTNLGRP_IPV6_IFINFO RTNLGRP_IPV6_IFINFO RTNLGRP_DECnet_IFADDR, #define RTNLGRP_DECnet_IFADDR RTNLGRP_DECnet_IFADDR + RTNLGRP_NOP2, RTNLGRP_DECnet_ROUTE, #define RTNLGRP_DECnet_ROUTE RTNLGRP_DECnet_ROUTE + RTNLGRP_NOP3, + RTNLGRP_NOP4, RTNLGRP_IPV6_PREFIX, #define RTNLGRP_IPV6_PREFIX RTNLGRP_IPV6_PREFIX __RTNLGRP_MAX -- cgit v1.2.3-70-g09d2 From 399c180ac5f0cb66ef9479358e0b8b6bafcbeafe Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 19 Dec 2005 14:23:23 -0800 Subject: [IPSEC]: Perform SA switchover immediately. When we insert a new xfrm_state which potentially subsumes an existing one, make sure all cached bundles are flushed so that the new SA is used immediately. Signed-off-by: David S. Miller --- include/net/xfrm.h | 1 + net/xfrm/xfrm_policy.c | 19 ++++++++++++++----- net/xfrm/xfrm_state.c | 5 +++++ 3 files changed, 20 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 5beae1ccd57..1cdb8791213 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -890,6 +890,7 @@ struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto, extern void xfrm_policy_flush(void); extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol); extern int xfrm_flush_bundles(void); +extern void xfrm_flush_all_bundles(void); extern int xfrm_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl, int family); extern void xfrm_init_pmtu(struct dst_entry *dst); diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 0db9e57013f..54a4be6a7d2 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1014,13 +1014,12 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) } EXPORT_SYMBOL(__xfrm_route_forward); -/* Optimize later using cookies and generation ids. */ - static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie) { - if (!stale_bundle(dst)) - return dst; - + /* If it is marked obsolete, which is how we even get here, + * then we have purged it from the policy bundle list and we + * did that for a good reason. + */ return NULL; } @@ -1104,6 +1103,16 @@ int xfrm_flush_bundles(void) return 0; } +static int always_true(struct dst_entry *dst) +{ + return 1; +} + +void xfrm_flush_all_bundles(void) +{ + xfrm_prune_bundles(always_true); +} + void xfrm_init_pmtu(struct dst_entry *dst) { do { diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 7cf48aa6c95..479effc9766 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -431,6 +431,8 @@ void xfrm_state_insert(struct xfrm_state *x) spin_lock_bh(&xfrm_state_lock); __xfrm_state_insert(x); spin_unlock_bh(&xfrm_state_lock); + + xfrm_flush_all_bundles(); } EXPORT_SYMBOL(xfrm_state_insert); @@ -478,6 +480,9 @@ out: spin_unlock_bh(&xfrm_state_lock); xfrm_state_put_afinfo(afinfo); + if (!err) + xfrm_flush_all_bundles(); + if (x1) { xfrm_state_delete(x1); xfrm_state_put(x1); -- cgit v1.2.3-70-g09d2 From 29884df0d89c1df0dec3449405bc41569bb44800 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 13 Dec 2005 16:13:54 -0500 Subject: NFS: Fix another O_DIRECT race Ensure we call unmap_mapping_range() and sync dirty pages to disk before doing an NFS direct write. Signed-off-by: Trond Myklebust --- fs/nfs/direct.c | 24 ++++++------------------ fs/nfs/file.c | 23 ++++------------------- fs/nfs/inode.c | 28 +++++++++++++++++++++++----- include/linux/nfs_fs.h | 1 + 4 files changed, 34 insertions(+), 42 deletions(-) (limited to 'include') diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index b497c71384e..07922881760 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -678,15 +678,9 @@ nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t if (!count) goto out; - if (mapping->nrpages) { - retval = filemap_fdatawrite(mapping); - if (retval == 0) - retval = nfs_wb_all(inode); - if (retval == 0) - retval = filemap_fdatawait(mapping); - if (retval) - goto out; - } + retval = nfs_sync_mapping(mapping); + if (retval) + goto out; retval = nfs_direct_read(inode, ctx, &iov, pos, 1); if (retval > 0) @@ -764,15 +758,9 @@ nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count, if (!count) goto out; - if (mapping->nrpages) { - retval = filemap_fdatawrite(mapping); - if (retval == 0) - retval = nfs_wb_all(inode); - if (retval == 0) - retval = filemap_fdatawait(mapping); - if (retval) - goto out; - } + retval = nfs_sync_mapping(mapping); + if (retval) + goto out; retval = nfs_direct_write(inode, ctx, &iov, pos, 1); if (mapping->nrpages) diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 57d3e77d97e..eb5cd4c3bbf 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -433,11 +433,7 @@ static int do_unlk(struct file *filp, int cmd, struct file_lock *fl) * Flush all pending writes before doing anything * with locks.. */ - filemap_fdatawrite(filp->f_mapping); - down(&inode->i_sem); - nfs_wb_all(inode); - up(&inode->i_sem); - filemap_fdatawait(filp->f_mapping); + nfs_sync_mapping(filp->f_mapping); /* NOTE: special case * If we're signalled while cleaning up locks on process exit, we @@ -465,15 +461,8 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl) * Flush all pending writes before doing anything * with locks.. */ - status = filemap_fdatawrite(filp->f_mapping); - if (status == 0) { - down(&inode->i_sem); - status = nfs_wb_all(inode); - up(&inode->i_sem); - if (status == 0) - status = filemap_fdatawait(filp->f_mapping); - } - if (status < 0) + status = nfs_sync_mapping(filp->f_mapping); + if (status != 0) goto out; lock_kernel(); @@ -497,11 +486,7 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl) * Make sure we clear the cache whenever we try to get the lock. * This makes locking act as a cache coherency point. */ - filemap_fdatawrite(filp->f_mapping); - down(&inode->i_sem); - nfs_wb_all(inode); /* we may have slept */ - up(&inode->i_sem); - filemap_fdatawait(filp->f_mapping); + nfs_sync_mapping(filp->f_mapping); nfs_zap_caches(inode); out: rpc_clnt_sigunmask(NFS_CLIENT(inode), &oldset); diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index afd75d0463f..432f41cd75e 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -640,6 +640,27 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) return 0; } +/** + * nfs_sync_mapping - helper to flush all mmapped dirty data to disk + */ +int nfs_sync_mapping(struct address_space *mapping) +{ + int ret; + + if (mapping->nrpages == 0) + return 0; + unmap_mapping_range(mapping, 0, 0, 0); + ret = filemap_fdatawrite(mapping); + if (ret != 0) + goto out; + ret = filemap_fdatawait(mapping); + if (ret != 0) + goto out; + ret = nfs_wb_all(mapping->host); +out: + return ret; +} + /* * Invalidate the local caches */ @@ -1179,11 +1200,8 @@ void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) struct nfs_inode *nfsi = NFS_I(inode); if (nfsi->cache_validity & NFS_INO_INVALID_DATA) { - if (S_ISREG(inode->i_mode)) { - if (filemap_fdatawrite(mapping) == 0) - filemap_fdatawait(mapping); - nfs_wb_all(inode); - } + if (S_ISREG(inode->i_mode)) + nfs_sync_mapping(mapping); invalidate_inode_pages2(mapping); spin_lock(&inode->i_lock); diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 12787a9b025..2516adeccec 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -291,6 +291,7 @@ static inline int nfs_verify_change_attribute(struct inode *inode, unsigned long /* * linux/fs/nfs/inode.c */ +extern int nfs_sync_mapping(struct address_space *mapping); extern void nfs_zap_caches(struct inode *); extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *, struct nfs_fattr *); -- cgit v1.2.3-70-g09d2 From fd30fc3256824f03c2ff9317269d66f72f7042ca Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Tue, 20 Dec 2005 13:10:22 -0600 Subject: [PATCH] relayfs: remove warning printk() in relay_switch_subbuf() There's currently a diagnostic printk in relay_switch_subbuf() meant as a warning if you accidentally try to log an event larger than the sub-buffer size. The problem is if this happens while logging from somewhere it's not safe to be doing printks, such as in the scheduler, you can end up with a deadlock. This patch removes the warning from relay_switch_subbuf() and instead prints some diagnostic info when the channel is closed. Thanks to Mathieu Desnoyers for pointing out the problem and suggesting a fix. Signed-off-by: Tom Zanussi Signed-off-by: Linus Torvalds --- fs/relayfs/relay.c | 8 ++++++-- include/linux/relayfs_fs.h | 5 +++-- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/fs/relayfs/relay.c b/fs/relayfs/relay.c index 16446a15c96..2a6f7f12b7f 100644 --- a/fs/relayfs/relay.c +++ b/fs/relayfs/relay.c @@ -333,8 +333,7 @@ size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length) return length; toobig: - printk(KERN_WARNING "relayfs: event too large (%Zd)\n", length); - WARN_ON(1); + buf->chan->last_toobig = length; return 0; } @@ -399,6 +398,11 @@ void relay_close(struct rchan *chan) relay_close_buf(chan->buf[i]); } + if (chan->last_toobig) + printk(KERN_WARNING "relayfs: one or more items not logged " + "[item size (%Zd) > sub-buffer size (%Zd)]\n", + chan->last_toobig, chan->subbuf_size); + kref_put(&chan->kref, relay_destroy_channel); } diff --git a/include/linux/relayfs_fs.h b/include/linux/relayfs_fs.h index cfafc3e76bc..fb7e8073732 100644 --- a/include/linux/relayfs_fs.h +++ b/include/linux/relayfs_fs.h @@ -20,9 +20,9 @@ #include /* - * Tracks changes to rchan_buf struct + * Tracks changes to rchan/rchan_buf structs */ -#define RELAYFS_CHANNEL_VERSION 5 +#define RELAYFS_CHANNEL_VERSION 6 /* * Per-cpu relay channel buffer @@ -60,6 +60,7 @@ struct rchan struct rchan_callbacks *cb; /* client callbacks */ struct kref kref; /* channel refcount */ void *private_data; /* for user-defined data */ + size_t last_toobig; /* tried to log event > subbuf size */ struct rchan_buf *buf[NR_CPUS]; /* per-cpu channel buffers */ }; -- cgit v1.2.3-70-g09d2