From fe9b081b717cd5c3f09590e09f95151d3322a101 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 6 Feb 2005 19:35:09 -0800 Subject: [SPARC64]: Fix off-by-one handling of size in user_fixup.c Noticed by Jurij Smakov Signed-off-by: David S. Miller --- arch/sparc64/lib/user_fixup.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/sparc64/lib/user_fixup.c b/arch/sparc64/lib/user_fixup.c index 58ec56050b9e..0278e34125db 100644 --- a/arch/sparc64/lib/user_fixup.c +++ b/arch/sparc64/lib/user_fixup.c @@ -20,11 +20,12 @@ unsigned long copy_from_user_fixup(void *to, const void __user *from, unsigned l char *dst = to; const char __user *src = from; - while (size--) { + while (size) { if (__get_user(*dst, src)) break; dst++; src++; + size--; } if (size) @@ -38,11 +39,12 @@ unsigned long copy_to_user_fixup(void __user *to, const void *from, unsigned lon char __user *dst = to; const char *src = from; - while (size--) { + while (size) { if (__put_user(*src, dst)) break; dst++; src++; + size--; } return size; @@ -53,7 +55,7 @@ unsigned long copy_in_user_fixup(void __user *to, void __user *from, unsigned lo char __user *dst = to; char __user *src = from; - while (size--) { + while (size) { char tmp; if (__get_user(tmp, src)) @@ -62,6 +64,7 @@ unsigned long copy_in_user_fixup(void __user *to, void __user *from, unsigned lo break; dst++; src++; + size--; } return size; -- cgit v1.2.3 From 84460cf219f33a9bfa682c540224860b972d75a2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 6 Feb 2005 23:29:42 -0800 Subject: [SPARC64]: Update defconfig. Signed-off-by: David S. Miller --- arch/sparc64/defconfig | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index 79917803c92d..5fe6aaabd05f 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.11-rc1 -# Fri Jan 21 20:03:21 2005 +# Linux kernel version: 2.6.11-rc3 +# Mon Feb 7 15:29:00 2005 # CONFIG_64BIT=y CONFIG_MMU=y @@ -845,6 +845,7 @@ CONFIG_BT_HCIUART_H4=y CONFIG_BT_HCIUART_BCSP=y CONFIG_BT_HCIUART_BCSP_TXCRC=y CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m CONFIG_BT_HCIBFUSB=m CONFIG_BT_HCIVHCI=m CONFIG_NETDEVICES=y @@ -1245,7 +1246,12 @@ CONFIG_JFS_SECURITY=y # CONFIG_JFS_DEBUG is not set # CONFIG_JFS_STATISTICS is not set CONFIG_FS_POSIX_ACL=y + +# +# XFS support +# CONFIG_XFS_FS=m +CONFIG_XFS_EXPORT=y # CONFIG_XFS_RT is not set CONFIG_XFS_QUOTA=y CONFIG_XFS_SECURITY=y @@ -1520,6 +1526,11 @@ CONFIG_DVB_ATMEL_AT76C651=m CONFIG_DVB_VES1820=m CONFIG_DVB_TDA10021=m CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terresterial DTV) frontends +# +CONFIG_DVB_NXT2002=m CONFIG_VIDEO_SAA7146=m CONFIG_VIDEO_SAA7146_VV=m CONFIG_VIDEO_VIDEOBUF=m @@ -1527,6 +1538,7 @@ CONFIG_VIDEO_TUNER=m CONFIG_VIDEO_BUF=m CONFIG_VIDEO_BTCX=m CONFIG_VIDEO_IR=m +CONFIG_VIDEO_TVEEPROM=m # # Sound -- cgit v1.2.3 From 7568745304a7618e2fe261ecdac94795ae224ec1 Mon Sep 17 00:00:00 2001 From: John Rose Date: Mon, 7 Feb 2005 00:43:44 -0800 Subject: [PATCH] PCI Hotplug: fix rpaphp firmware dependency Noted by David Woodhouse Here's a fix for the ppc64 crash during boot. This corrects the offending function to use more conventional error codes. I'll follow up with return code cleanups for the entire module, and for RTAS code, since these are probably too big for 2.6.11. Signed-off-by: John Rose Signed-off-by: Linus Torvalds --- drivers/pci/hotplug/rpaphp_core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index 3b20d4be6835..e709bad434f4 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -224,7 +224,7 @@ static int get_children_props(struct device_node *dn, int **drc_indexes, if (!indexes || !names || !types || !domains) { /* Slot does not have dynamically-removable children */ - return 1; + return -EINVAL; } if (drc_indexes) *drc_indexes = indexes; @@ -260,7 +260,7 @@ int rpaphp_get_drc_props(struct device_node *dn, int *drc_index, } rc = get_children_props(dn->parent, &indexes, &names, &types, &domains); - if (rc) { + if (rc < 0) { return 1; } @@ -307,7 +307,7 @@ static int is_php_dn(struct device_node *dn, int **indexes, int **names, int rc; rc = get_children_props(dn, indexes, names, &drc_types, power_domains); - if (rc) { + if (rc >= 0) { if (is_php_type((char *) &drc_types[1])) { *types = drc_types; return 1; @@ -331,7 +331,7 @@ static int is_dr_dn(struct device_node *dn, int **indexes, int **names, rc = get_children_props(dn->parent, indexes, names, types, power_domains); - return (rc == 0); + return (rc >= 0); } static inline int is_vdevice_root(struct device_node *dn) -- cgit v1.2.3 From ece74be24df13c2293f0a3091ec232c466d6ddfb Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 7 Feb 2005 04:27:33 -0800 Subject: [SPARC64]: Mask off stack ptr in compat_alloc_user_space() for 32-bit. Signed-off-by: David S. Miller --- include/asm-sparc64/compat.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/asm-sparc64/compat.h b/include/asm-sparc64/compat.h index e26d7d85c55a..da9c81a6af5a 100644 --- a/include/asm-sparc64/compat.h +++ b/include/asm-sparc64/compat.h @@ -133,6 +133,8 @@ static __inline__ void __user *compat_alloc_user_space(long len) if (!(test_thread_flag(TIF_32BIT))) usp += STACK_BIAS; + else + usp &= 0xffffffffUL; return (void __user *) (usp - len); } -- cgit v1.2.3 From 7b429e1a125a608fd2fa6f9e1036e62beaf10b39 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Feb 2005 05:30:37 -0800 Subject: [PATCH] add MAP_POPULATE/sys_remap_file_pages support to XFS filemap_populate needs to be exported so that filesystems with their own vm_operations (like XFS) can use it. Cc: Nathan Scott Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/xfs/linux-2.6/xfs_file.c | 1 + include/linux/mm.h | 4 +++- mm/filemap.c | 10 ++++------ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index 0e930601a821..7321db1c2fb4 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c @@ -531,6 +531,7 @@ struct file_operations linvfs_dir_operations = { static struct vm_operations_struct linvfs_file_vm_ops = { .nopage = filemap_nopage, + .populate = filemap_populate, #ifdef HAVE_VMOP_MPROTECT .mprotect = linvfs_mprotect, #endif diff --git a/include/linux/mm.h b/include/linux/mm.h index 10d011f464d6..3a8c47c5dc9c 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -756,7 +756,9 @@ extern unsigned long page_unuse(struct page *); extern void truncate_inode_pages(struct address_space *, loff_t); /* generic vm_area_ops exported for stackable file systems */ -struct page *filemap_nopage(struct vm_area_struct *, unsigned long, int *); +extern struct page *filemap_nopage(struct vm_area_struct *, unsigned long, int *); +extern int filemap_populate(struct vm_area_struct *, unsigned long, + unsigned long, pgprot_t, unsigned long, int); /* mm/page-writeback.c */ int write_one_page(struct page *page, int wait); diff --git a/mm/filemap.c b/mm/filemap.c index e82fc19ee094..6d04b97fea14 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1458,12 +1458,9 @@ err: return NULL; } -static int filemap_populate(struct vm_area_struct *vma, - unsigned long addr, - unsigned long len, - pgprot_t prot, - unsigned long pgoff, - int nonblock) +int filemap_populate(struct vm_area_struct *vma, unsigned long addr, + unsigned long len, pgprot_t prot, unsigned long pgoff, + int nonblock) { struct file *file = vma->vm_file; struct address_space *mapping = file->f_mapping; @@ -1523,6 +1520,7 @@ int generic_file_mmap(struct file * file, struct vm_area_struct * vma) vma->vm_ops = &generic_file_vm_ops; return 0; } +EXPORT_SYMBOL(filemap_populate); /* * This is for filesystems which do not implement ->writepage. -- cgit v1.2.3 From 73f54a780c55e358f2b630db9f89be409426e588 Mon Sep 17 00:00:00 2001 From: Alex Yustasov Date: Mon, 7 Feb 2005 05:30:52 -0800 Subject: [PATCH] Add missing configure calls to intel agp resume code. Fix for resume on i850. Maybe for i855GM. Signed-off by: Nigel Cunningham Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/agp/intel-agp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index a3abfb89d7cb..06e791f3b65d 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -1748,12 +1748,16 @@ static int agp_intel_resume(struct pci_dev *pdev) if (bridge->driver == &intel_generic_driver) intel_configure(); + else if (bridge->driver == &intel_850_driver) + intel_850_configure(); else if (bridge->driver == &intel_845_driver) intel_845_configure(); else if (bridge->driver == &intel_830mp_driver) intel_830mp_configure(); else if (bridge->driver == &intel_915_driver) intel_i915_configure(); + else if (bridge->driver == &intel_830_driver) + intel_i830_configure(); return 0; } -- cgit v1.2.3 From 01c8df0425061f81f99107ca63e4f0a981ec7f6a Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Mon, 7 Feb 2005 05:31:08 -0800 Subject: [PATCH] fix wait_task_inactive race When a task is put to sleep, it is dequeued from the runqueue while it is still running. The problem is that one some arches that have non-atomic scheduling, the runqueue lock can be dropped and retaken in schedule() before the task actually schedules off, and wait_task_inactive did not account for this. Signed-off-by: Nick Piggin Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/sched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sched.c b/kernel/sched.c index f708d10e7750..911fbdd9c151 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -867,7 +867,7 @@ void wait_task_inactive(task_t * p) repeat: rq = task_rq_lock(p, &flags); /* Must be off runqueue entirely, not preempted. */ - if (unlikely(p->array)) { + if (unlikely(p->array || task_running(rq, p))) { /* If it's preempted, we yield. It could be a while. */ preempted = !task_running(rq, p); task_rq_unlock(rq, &flags); -- cgit v1.2.3 From 87daf848c912e0e4b0482095ab0709ae049ef2ef Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 7 Feb 2005 05:31:22 -0800 Subject: [PATCH] add design comment to kick_process() Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/sched.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel/sched.c b/kernel/sched.c index 911fbdd9c151..95042b27d30c 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -885,6 +885,12 @@ repeat: * * Cause a process which is running on another CPU to enter * kernel-mode, without any delay. (to get signals handled.) + * + * NOTE: this function doesnt have to take the runqueue lock, + * because all it wants to ensure is that the remote task enters + * the kernel. If the IPI races and the task has been migrated + * to another CPU then no harm is done and the purpose has been + * achieved as well. */ void kick_process(task_t *p) { -- cgit v1.2.3 From 339a8acbcd459559a618908afd431b917bee69bd Mon Sep 17 00:00:00 2001 From: "Paolo \\'Blaisorblade\\' Giarrusso" Date: Mon, 7 Feb 2005 05:31:37 -0800 Subject: [PATCH] uml: kbuild: add further cleaning Descend into arch/um/kernel/skas/util during make clean. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/skas/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile index c340c9cbf19b..867dff072934 100644 --- a/arch/um/kernel/skas/Makefile +++ b/arch/um/kernel/skas/Makefile @@ -11,3 +11,5 @@ USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) $(USER_OBJS) : %.o: %.c $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< + +subdir- := util -- cgit v1.2.3 From fe1fd25ec7decb88af05342ffead7a00b2c73bdf Mon Sep 17 00:00:00 2001 From: "Paolo \\'Blaisorblade\\' Giarrusso" Date: Mon, 7 Feb 2005 05:31:52 -0800 Subject: [PATCH] uml: hostfs: (security) fix chmod +s permission check Frank Fricke reported that hostfs does not verify that a chmod +s, for instance, is done by a sufficiently privileged user, as long as the UML kernel itself can complete the operation on the host. So, for instance, if UML is run as root and under /mnt/host we have a hostfs mount, this works successfully: paolo@zion:~ (0)$ chmod 4755 /mnt/host/bin/bash paolo@zion:~ (0)$ ll /mnt/host/bin/bash -rwsr-xr-x 1 root root 662724 2004-10-20 02:15 /mnt/host/bin/bash* (bash refuses running as setuid, but you could have another shell on the host, as dash or whatever). In general, if UML is run as uid 500 on the host, a hostfs mount is done and under the hostfs mount there is a file with uid 500 on the host, I can freely make it setuid (if it's executable). This is especially bad when UML is run as root (which you should not do), but is a problem in general, since it allows any user to create setuid 500 (in this example) executables on the host filesystem. Finally, while I was looking at the chmod() implementation, I spotted a kludge in the code and explained it with a comment. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Frank 'xraz' Fricke Cc: Alexander Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/hostfs/hostfs.h | 21 +++++++++++++++++++++ fs/hostfs/hostfs_kern.c | 4 ++++ 2 files changed, 25 insertions(+) diff --git a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h index 416761fce324..c1516d013bf6 100644 --- a/fs/hostfs/hostfs.h +++ b/fs/hostfs/hostfs.h @@ -16,9 +16,30 @@ #define HOSTFS_ATTR_CTIME 64 #define HOSTFS_ATTR_ATIME_SET 128 #define HOSTFS_ATTR_MTIME_SET 256 + +/* These two are unused by hostfs. */ #define HOSTFS_ATTR_FORCE 512 /* Not a change, but a change it */ #define HOSTFS_ATTR_ATTR_FLAG 1024 +/* If you are very careful, you'll notice that these two are missing: + * + * #define ATTR_KILL_SUID 2048 + * #define ATTR_KILL_SGID 4096 + * + * and this is because they were added in 2.5 development in this patch: + * + * http://linux.bkbits.net:8080/linux-2.5/ + * cset@3caf4a12k4XgDzK7wyK-TGpSZ9u2Ww?nav=index.html + * |src/.|src/include|src/include/linux|related/include/linux/fs.h + * + * Actually, they are not needed by most ->setattr() methods - they are set by + * callers of notify_change() to notify that the setuid/setgid bits must be + * dropped. + * notify_change() will delete those flags, make sure attr->ia_valid & ATTR_MODE + * is on, and remove the appropriate bits from attr->ia_mode (attr is a + * "struct iattr *"). -BlaisorBlade + */ + struct hostfs_iattr { unsigned int ia_valid; mode_t ia_mode; diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index f9759e012416..144ff70fbd55 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -823,6 +823,10 @@ int hostfs_setattr(struct dentry *dentry, struct iattr *attr) char *name; int err; + err = inode_change_ok(dentry->d_inode, attr); + if (err) + return err; + if(append) attr->ia_valid &= ~ATTR_SIZE; -- cgit v1.2.3 From c835cd920f83ee7a79f6cf98e2e946fd43cda82c Mon Sep 17 00:00:00 2001 From: "Suresh B. Siddha" Date: Mon, 7 Feb 2005 05:32:06 -0800 Subject: [PATCH] x86_64: missing lock prefix in switch_to Add the missing "lock" prefix in switch_to macro. Signed-off-by: Suresh Siddha Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-x86_64/system.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-x86_64/system.h b/include/asm-x86_64/system.h index 05acc62c2b61..c1710933828f 100644 --- a/include/asm-x86_64/system.h +++ b/include/asm-x86_64/system.h @@ -35,7 +35,7 @@ "thread_return:\n\t" \ "movq %%gs:%P[pda_pcurrent],%%rsi\n\t" \ "movq %P[thread_info](%%rsi),%%r8\n\t" \ - "btr %[tif_fork],%P[ti_flags](%%r8)\n\t" \ + LOCK "btr %[tif_fork],%P[ti_flags](%%r8)\n\t" \ "movq %%rax,%%rdi\n\t" \ "jc ret_from_fork\n\t" \ RESTORE_CONTEXT \ -- cgit v1.2.3 From 770b8453bdce523aaccf5845cfe8d3f9a6c9c07e Mon Sep 17 00:00:00 2001 From: Martin Kögler Date: Mon, 7 Feb 2005 05:32:21 -0800 Subject: [PATCH] serial: fix low-latency mode deadlock We presently deadlock in low-latency mode because the receive code holds port.lock while calling into the tty code to perform echoing. The tty code calls back into the driver, which then takes port.lock. Fix that by dropping the lock around the echo call. Acked-by: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/8250.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index d4e7733dbeb8..ec620e33fcf6 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -987,8 +987,11 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) /* The following is not allowed by the tty layer and unsafe. It should be fixed ASAP */ if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { - if(tty->low_latency) + if (tty->low_latency) { + spin_unlock(&up->port.lock); tty_flip_buffer_push(tty); + spin_lock(&up->port.lock); + } /* If this failed then we will throw away the bytes but must do so to clear interrupts */ } @@ -1059,7 +1062,9 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) ignore_char: lsr = serial_inp(up, UART_LSR); } while ((lsr & UART_LSR_DR) && (max_count-- > 0)); + spin_unlock(&up->port.lock); tty_flip_buffer_push(tty); + spin_lock(&up->port.lock); *status = lsr; } -- cgit v1.2.3 From 9a6caf114643022373e2af1b2073b9e19aa483db Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Mon, 7 Feb 2005 05:32:36 -0800 Subject: [PATCH] mips: add unknown page size string This patch had fixed the following warning. arch/mips/lib-32/dump_tlb.c: In function 'dump_tlb': arch/mips/lib-32/dump_tlb.c:69: warning: control may reach end of non-void function 'msk2str' being inlined This patch adds return value, when page size is not match. Signed-off-by: Yoichi Yuasa Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/mips/lib-32/dump_tlb.c | 2 ++ arch/mips/lib-64/dump_tlb.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/arch/mips/lib-32/dump_tlb.c b/arch/mips/lib-32/dump_tlb.c index b92fea6927ea..019ac8f005d7 100644 --- a/arch/mips/lib-32/dump_tlb.c +++ b/arch/mips/lib-32/dump_tlb.c @@ -32,6 +32,8 @@ static inline const char *msk2str(unsigned int mask) case PM_256M: return "256Mb"; #endif } + + return "unknown"; } #define BARRIER() \ diff --git a/arch/mips/lib-64/dump_tlb.c b/arch/mips/lib-64/dump_tlb.c index 2a422948c7dc..42f88e055b4c 100644 --- a/arch/mips/lib-64/dump_tlb.c +++ b/arch/mips/lib-64/dump_tlb.c @@ -32,6 +32,8 @@ static inline const char *msk2str(unsigned int mask) case PM_256M: return "256Mb"; #endif } + + return "unknown"; } #define BARRIER() \ -- cgit v1.2.3 From 26815161adef49875c03f19536c2c176d638c151 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Mon, 7 Feb 2005 05:32:50 -0800 Subject: [PATCH] qlogic nonatomic warning fix The qlogic driver complains about the use of smp_processor_id() in preemptible code. And it's right. But it's just for an affinity optimisation and we can validly quash the warning. Signed-off-by: Andrew Vasquez Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/qla2xxx/qla_os.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 540879308d32..22bdb841c8e4 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -859,7 +859,7 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *)) * In all other cases we'll let an irq pick up our IO and submit it * to the controller to improve affinity. */ - if (smp_processor_id() == ha->last_irq_cpu || was_empty) + if (_smp_processor_id() == ha->last_irq_cpu || was_empty) qla2x00_next(ha); spin_lock_irq(ha->host->host_lock); -- cgit v1.2.3 From a2bfbd426f2a16ef60b5eb59e1064f187d12c6ac Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Mon, 7 Feb 2005 15:46:44 -0800 Subject: [PATCH] md: fix problems with verion-1 superblock code - off-by-one error - missing recalc of checksum Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 071b347b282b..1a8c43bede92 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -935,8 +935,8 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev) max_dev = 0; ITERATE_RDEV(mddev,rdev2,tmp) - if (rdev2->desc_nr > max_dev) - max_dev = rdev2->desc_nr; + if (rdev2->desc_nr+1 > max_dev) + max_dev = rdev2->desc_nr+1; sb->max_dev = cpu_to_le32(max_dev); for (i=0; irecovery_offset = cpu_to_le64(0); /* not supported yet */ + sb->sb_csum = calc_sb_1_csum(sb); } -- cgit v1.2.3 From 061e71516e1c9f5a0b1b0e0c6a1c7b4e3079880f Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Mon, 7 Feb 2005 15:46:57 -0800 Subject: [PATCH] md: prevent oops when drive set faulty in inactive md array. hot_add_disk and hot_remove_disk check mddev->pers before proceeding. set_disk_faulty should too. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/md/md.c b/drivers/md/md.c index 1a8c43bede92..fad83e2711e2 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2441,6 +2441,9 @@ static int set_disk_faulty(mddev_t *mddev, dev_t dev) { mdk_rdev_t *rdev; + if (mddev->pers == NULL) + return -ENODEV; + rdev = find_rdev(mddev, dev); if (!rdev) return -ENODEV; -- cgit v1.2.3 From 31647d19a40d51e90451d8646903094c82407671 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Mon, 7 Feb 2005 15:47:13 -0800 Subject: [PATCH] md: make md work a bit better with devfs - set ->devfs_name - create initial devfs names slightly differently so as not to conflict - re-read partition table when an array is assembled at boot time - not sure why this is needed, but it is. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 9 ++++++--- init/do_mounts_md.c | 10 ++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index fad83e2711e2..8a707510846e 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1473,10 +1473,13 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data) } disk->major = MAJOR(dev); disk->first_minor = unit << shift; - if (partitioned) + if (partitioned) { sprintf(disk->disk_name, "md_d%d", unit); - else + sprintf(disk->devfs_name, "md/d%d", unit); + } else { sprintf(disk->disk_name, "md%d", unit); + sprintf(disk->devfs_name, "md/%d", unit); + } disk->fops = &md_fops; disk->private_data = mddev; disk->queue = mddev->queue; @@ -3659,7 +3662,7 @@ int __init md_init(void) for (minor=0; minor < MAX_MD_DEVS; ++minor) devfs_mk_bdev(MKDEV(mdp_major, minor< Date: Mon, 7 Feb 2005 15:47:26 -0800 Subject: [PATCH] md: fix endless loop when syncing an array that doesn't need any resync. If the resync checkpoint for an array is at the end of the array, It doesn't get set to MAX_SECTOR, so resyncing will be retried. By updating curr_resync early, this problem is fixed. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 8a707510846e..68669ce10268 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3369,10 +3369,12 @@ static void md_do_sync(mddev_t *mddev) init_waitqueue_head(&mddev->recovery_wait); last_check = 0; - if (j) + if (j>2) { printk(KERN_INFO "md: resuming recovery of %s from checkpoint.\n", mdname(mddev)); + mddev->curr_resync = j; + } while (j < max_sectors) { int sectors; @@ -3454,7 +3456,7 @@ static void md_do_sync(mddev_t *mddev) if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) && mddev->curr_resync > 2 && - mddev->curr_resync > mddev->recovery_cp) { + mddev->curr_resync >= mddev->recovery_cp) { if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { printk(KERN_INFO "md: checkpointing recovery of %s.\n", -- cgit v1.2.3 From ba6cf074e858070e0cd5def1b3ece88f79255976 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Mon, 7 Feb 2005 15:47:40 -0800 Subject: [PATCH] md: remove extra loop from copy_data copy_data currently loops over bio's in a list, but the caller also does the same looping, sometimes with extra work. So remove the loop from copy_data. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/raid5.c | 68 ++++++++++++++++++++++++-------------------------- drivers/md/raid6main.c | 61 +++++++++++++++++++++----------------------- 2 files changed, 61 insertions(+), 68 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 783ae7a5b218..caee18691192 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -612,11 +612,10 @@ static sector_t compute_blocknr(struct stripe_head *sh, int i) /* - * Copy data between a page in the stripe cache, and one or more bion - * The page could align with the middle of the bio, or there could be - * several bion, each with several bio_vecs, which cover part of the page - * Multiple bion are linked together on bi_next. There may be extras - * at the end of this list. We ignore them. + * Copy data between a page in the stripe cache, and a bio. + * There are no alignment or size guarantees between the page or the + * bio except that there is some overlap. + * All iovecs in the bio must be considered. */ static void copy_data(int frombio, struct bio *bio, struct page *page, @@ -625,41 +624,38 @@ static void copy_data(int frombio, struct bio *bio, char *pa = page_address(page); struct bio_vec *bvl; int i; + int page_offset; - for (;bio && bio->bi_sector < sector+STRIPE_SECTORS; - bio = r5_next_bio(bio, sector) ) { - int page_offset; - if (bio->bi_sector >= sector) - page_offset = (signed)(bio->bi_sector - sector) * 512; - else - page_offset = (signed)(sector - bio->bi_sector) * -512; - bio_for_each_segment(bvl, bio, i) { - int len = bio_iovec_idx(bio,i)->bv_len; - int clen; - int b_offset = 0; - - if (page_offset < 0) { - b_offset = -page_offset; - page_offset += b_offset; - len -= b_offset; - } + if (bio->bi_sector >= sector) + page_offset = (signed)(bio->bi_sector - sector) * 512; + else + page_offset = (signed)(sector - bio->bi_sector) * -512; + bio_for_each_segment(bvl, bio, i) { + int len = bio_iovec_idx(bio,i)->bv_len; + int clen; + int b_offset = 0; + + if (page_offset < 0) { + b_offset = -page_offset; + page_offset += b_offset; + len -= b_offset; + } - if (len > 0 && page_offset + len > STRIPE_SIZE) - clen = STRIPE_SIZE - page_offset; - else clen = len; + if (len > 0 && page_offset + len > STRIPE_SIZE) + clen = STRIPE_SIZE - page_offset; + else clen = len; - if (clen > 0) { - char *ba = __bio_kmap_atomic(bio, i, KM_USER0); - if (frombio) - memcpy(pa+page_offset, ba+b_offset, clen); - else - memcpy(ba+b_offset, pa+page_offset, clen); - __bio_kunmap_atomic(ba, KM_USER0); - } - if (clen < len) /* hit end of page */ - break; - page_offset += len; + if (clen > 0) { + char *ba = __bio_kmap_atomic(bio, i, KM_USER0); + if (frombio) + memcpy(pa+page_offset, ba+b_offset, clen); + else + memcpy(ba+b_offset, pa+page_offset, clen); + __bio_kunmap_atomic(ba, KM_USER0); } + if (clen < len) /* hit end of page */ + break; + page_offset += len; } } diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c index 8c52254c262f..70012c521c6e 100644 --- a/drivers/md/raid6main.c +++ b/drivers/md/raid6main.c @@ -670,41 +670,38 @@ static void copy_data(int frombio, struct bio *bio, char *pa = page_address(page); struct bio_vec *bvl; int i; + int page_offset; - for (;bio && bio->bi_sector < sector+STRIPE_SECTORS; - bio = r5_next_bio(bio, sector) ) { - int page_offset; - if (bio->bi_sector >= sector) - page_offset = (signed)(bio->bi_sector - sector) * 512; - else - page_offset = (signed)(sector - bio->bi_sector) * -512; - bio_for_each_segment(bvl, bio, i) { - int len = bio_iovec_idx(bio,i)->bv_len; - int clen; - int b_offset = 0; - - if (page_offset < 0) { - b_offset = -page_offset; - page_offset += b_offset; - len -= b_offset; - } + if (bio->bi_sector >= sector) + page_offset = (signed)(bio->bi_sector - sector) * 512; + else + page_offset = (signed)(sector - bio->bi_sector) * -512; + bio_for_each_segment(bvl, bio, i) { + int len = bio_iovec_idx(bio,i)->bv_len; + int clen; + int b_offset = 0; + + if (page_offset < 0) { + b_offset = -page_offset; + page_offset += b_offset; + len -= b_offset; + } - if (len > 0 && page_offset + len > STRIPE_SIZE) - clen = STRIPE_SIZE - page_offset; - else clen = len; - - if (clen > 0) { - char *ba = __bio_kmap_atomic(bio, i, KM_USER0); - if (frombio) - memcpy(pa+page_offset, ba+b_offset, clen); - else - memcpy(ba+b_offset, pa+page_offset, clen); - __bio_kunmap_atomic(ba, KM_USER0); - } - if (clen < len) /* hit end of page */ - break; - page_offset += len; + if (len > 0 && page_offset + len > STRIPE_SIZE) + clen = STRIPE_SIZE - page_offset; + else clen = len; + + if (clen > 0) { + char *ba = __bio_kmap_atomic(bio, i, KM_USER0); + if (frombio) + memcpy(pa+page_offset, ba+b_offset, clen); + else + memcpy(ba+b_offset, pa+page_offset, clen); + __bio_kunmap_atomic(ba, KM_USER0); } + if (clen < len) /* hit end of page */ + break; + page_offset += len; } } -- cgit v1.2.3 From 3624ed47542112ec3449fbd1aa7cb745f7ac6fab Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Mon, 7 Feb 2005 15:47:54 -0800 Subject: [PATCH] raid5 overlapping read hack If we detect an overlap, we set a flag and wait for a wakeup. When requests are handled, if the flag was set, we perform the wakeup. Note that the code currently in -mm is badly broken. With this patch applied, it passes tests the use O_DIRECT to cause lots of overlapping requests. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/raid5.c | 55 +++++++++++++++++++++++++++++++++++++++------- drivers/md/raid6main.c | 51 ++++++++++++++++++++++++++++++++++-------- include/linux/raid/raid5.h | 2 ++ 3 files changed, 91 insertions(+), 17 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index caee18691192..5ee4c2b553e9 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -49,7 +49,7 @@ * This macro is used to determine the 'next' bio in the list, given the sector * of the current stripe+device */ -#define r5_next_bio(bio, sect) ( ( bio->bi_sector + (bio->bi_size>>9) < sect + STRIPE_SECTORS) ? bio->bi_next : NULL) +#define r5_next_bio(bio, sect) ( ( (bio)->bi_sector + ((bio)->bi_size>>9) < sect + STRIPE_SECTORS) ? (bio)->bi_next : NULL) /* * The following can be used to debug the driver */ @@ -232,6 +232,7 @@ static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector) } static void unplug_slaves(mddev_t *mddev); +static void raid5_unplug_device(request_queue_t *q); static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector, int pd_idx, int noblock) @@ -721,6 +722,10 @@ static void compute_parity(struct stripe_head *sh, int method) ptr[count++] = page_address(sh->dev[i].page); chosen = sh->dev[i].towrite; sh->dev[i].towrite = NULL; + + if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) + wake_up(&conf->wait_for_overlap); + if (sh->dev[i].written) BUG(); sh->dev[i].written = chosen; check_xor(); @@ -733,6 +738,10 @@ static void compute_parity(struct stripe_head *sh, int method) if (i!=pd_idx && sh->dev[i].towrite) { chosen = sh->dev[i].towrite; sh->dev[i].towrite = NULL; + + if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) + wake_up(&conf->wait_for_overlap); + if (sh->dev[i].written) BUG(); sh->dev[i].written = chosen; } @@ -789,7 +798,7 @@ static void compute_parity(struct stripe_head *sh, int method) * toread/towrite point to the first in a chain. * The bi_next chain must be in order. */ -static void add_stripe_bio (struct stripe_head *sh, struct bio *bi, int dd_idx, int forwrite) +static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, int forwrite) { struct bio **bip; raid5_conf_t *conf = sh->raid_conf; @@ -806,10 +815,13 @@ static void add_stripe_bio (struct stripe_head *sh, struct bio *bi, int dd_idx, else bip = &sh->dev[dd_idx].toread; while (*bip && (*bip)->bi_sector < bi->bi_sector) { - BUG_ON((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector); + if ((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector) + goto overlap; bip = & (*bip)->bi_next; } -/* FIXME do I need to worry about overlapping bion */ + if (*bip && (*bip)->bi_sector < bi->bi_sector + ((bi->bi_size)>>9)) + goto overlap; + if (*bip && bi->bi_next && (*bip) != bi->bi_next) BUG(); if (*bip) @@ -824,7 +836,7 @@ static void add_stripe_bio (struct stripe_head *sh, struct bio *bi, int dd_idx, (unsigned long long)sh->sector, dd_idx); if (forwrite) { - /* check if page is coverred */ + /* check if page is covered */ sector_t sector = sh->dev[dd_idx].sector; for (bi=sh->dev[dd_idx].towrite; sector < sh->dev[dd_idx].sector + STRIPE_SECTORS && @@ -836,6 +848,13 @@ static void add_stripe_bio (struct stripe_head *sh, struct bio *bi, int dd_idx, if (sector >= sh->dev[dd_idx].sector + STRIPE_SECTORS) set_bit(R5_OVERWRITE, &sh->dev[dd_idx].flags); } + return 1; + + overlap: + set_bit(R5_Overlap, &sh->dev[dd_idx].flags); + spin_unlock_irq(&conf->device_lock); + spin_unlock(&sh->lock); + return 0; } @@ -896,6 +915,8 @@ static void handle_stripe(struct stripe_head *sh) spin_lock_irq(&conf->device_lock); rbi = dev->toread; dev->toread = NULL; + if (test_and_clear_bit(R5_Overlap, &dev->flags)) + wake_up(&conf->wait_for_overlap); spin_unlock_irq(&conf->device_lock); while (rbi && rbi->bi_sector < dev->sector + STRIPE_SECTORS) { copy_data(0, rbi, dev->page, dev->sector); @@ -943,6 +964,9 @@ static void handle_stripe(struct stripe_head *sh) sh->dev[i].towrite = NULL; if (bi) to_write--; + if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) + wake_up(&conf->wait_for_overlap); + while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){ struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector); clear_bit(BIO_UPTODATE, &bi->bi_flags); @@ -971,6 +995,8 @@ static void handle_stripe(struct stripe_head *sh) if (!test_bit(R5_Insync, &sh->dev[i].flags)) { bi = sh->dev[i].toread; sh->dev[i].toread = NULL; + if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) + wake_up(&conf->wait_for_overlap); if (bi) to_read--; while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){ struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector); @@ -1398,6 +1424,7 @@ static int make_request (request_queue_t *q, struct bio * bi) if ( bio_data_dir(bi) == WRITE ) md_write_start(mddev); for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) { + DEFINE_WAIT(w); new_sector = raid5_compute_sector(logical_sector, raid_disks, data_disks, &dd_idx, &pd_idx, conf); @@ -1406,17 +1433,28 @@ static int make_request (request_queue_t *q, struct bio * bi) (unsigned long long)new_sector, (unsigned long long)logical_sector); + retry: + prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE); sh = get_active_stripe(conf, new_sector, pd_idx, (bi->bi_rw&RWA_MASK)); if (sh) { - - add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK)); - + if (!add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK))) { + /* Add failed due to overlap. Flush everything + * and wait a while + */ + raid5_unplug_device(mddev->queue); + release_stripe(sh); + schedule(); + goto retry; + } + finish_wait(&conf->wait_for_overlap, &w); raid5_plug_device(conf); handle_stripe(sh); release_stripe(sh); + } else { /* cannot get stripe for read-ahead, just give-up */ clear_bit(BIO_UPTODATE, &bi->bi_flags); + finish_wait(&conf->wait_for_overlap, &w); break; } @@ -1564,6 +1602,7 @@ static int run (mddev_t *mddev) spin_lock_init(&conf->device_lock); init_waitqueue_head(&conf->wait_for_stripe); + init_waitqueue_head(&conf->wait_for_overlap); INIT_LIST_HEAD(&conf->handle_list); INIT_LIST_HEAD(&conf->delayed_list); INIT_LIST_HEAD(&conf->inactive_list); diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c index 70012c521c6e..0f82d85939e7 100644 --- a/drivers/md/raid6main.c +++ b/drivers/md/raid6main.c @@ -54,7 +54,7 @@ * This macro is used to determine the 'next' bio in the list, given the sector * of the current stripe+device */ -#define r5_next_bio(bio, sect) ( ( bio->bi_sector + (bio->bi_size>>9) < sect + STRIPE_SECTORS) ? bio->bi_next : NULL) +#define r5_next_bio(bio, sect) ( ( (bio)->bi_sector + ((bio)->bi_size>>9) < sect + STRIPE_SECTORS) ? (bio)->bi_next : NULL) /* * The following can be used to debug the driver */ @@ -735,6 +735,10 @@ static void compute_parity(struct stripe_head *sh, int method) if ( i != pd_idx && i != qd_idx && sh->dev[i].towrite ) { chosen = sh->dev[i].towrite; sh->dev[i].towrite = NULL; + + if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) + wake_up(&conf->wait_for_overlap); + if (sh->dev[i].written) BUG(); sh->dev[i].written = chosen; } @@ -897,7 +901,7 @@ static void compute_block_2(struct stripe_head *sh, int dd_idx1, int dd_idx2) * toread/towrite point to the first in a chain. * The bi_next chain must be in order. */ -static void add_stripe_bio (struct stripe_head *sh, struct bio *bi, int dd_idx, int forwrite) +static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, int forwrite) { struct bio **bip; raid6_conf_t *conf = sh->raid_conf; @@ -914,10 +918,13 @@ static void add_stripe_bio (struct stripe_head *sh, struct bio *bi, int dd_idx, else bip = &sh->dev[dd_idx].toread; while (*bip && (*bip)->bi_sector < bi->bi_sector) { - BUG_ON((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector); - bip = & (*bip)->bi_next; + if ((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector) + goto overlap; + bip = &(*bip)->bi_next; } -/* FIXME do I need to worry about overlapping bion */ + if (*bip && (*bip)->bi_sector < bi->bi_sector + ((bi->bi_size)>>9)) + goto overlap; + if (*bip && bi->bi_next && (*bip) != bi->bi_next) BUG(); if (*bip) @@ -932,7 +939,7 @@ static void add_stripe_bio (struct stripe_head *sh, struct bio *bi, int dd_idx, (unsigned long long)sh->sector, dd_idx); if (forwrite) { - /* check if page is coverred */ + /* check if page is covered */ sector_t sector = sh->dev[dd_idx].sector; for (bi=sh->dev[dd_idx].towrite; sector < sh->dev[dd_idx].sector + STRIPE_SECTORS && @@ -944,6 +951,13 @@ static void add_stripe_bio (struct stripe_head *sh, struct bio *bi, int dd_idx, if (sector >= sh->dev[dd_idx].sector + STRIPE_SECTORS) set_bit(R5_OVERWRITE, &sh->dev[dd_idx].flags); } + return 1; + + overlap: + set_bit(R5_Overlap, &sh->dev[dd_idx].flags); + spin_unlock_irq(&conf->device_lock); + spin_unlock(&sh->lock); + return 0; } @@ -1007,6 +1021,8 @@ static void handle_stripe(struct stripe_head *sh) spin_lock_irq(&conf->device_lock); rbi = dev->toread; dev->toread = NULL; + if (test_and_clear_bit(R5_Overlap, &dev->flags)) + wake_up(&conf->wait_for_overlap); spin_unlock_irq(&conf->device_lock); while (rbi && rbi->bi_sector < dev->sector + STRIPE_SECTORS) { copy_data(0, rbi, dev->page, dev->sector); @@ -1056,6 +1072,9 @@ static void handle_stripe(struct stripe_head *sh) sh->dev[i].towrite = NULL; if (bi) to_write--; + if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) + wake_up(&conf->wait_for_overlap); + while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){ struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector); clear_bit(BIO_UPTODATE, &bi->bi_flags); @@ -1084,6 +1103,8 @@ static void handle_stripe(struct stripe_head *sh) if (!test_bit(R5_Insync, &sh->dev[i].flags)) { bi = sh->dev[i].toread; sh->dev[i].toread = NULL; + if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) + wake_up(&conf->wait_for_overlap); if (bi) to_read--; while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){ struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector); @@ -1563,6 +1584,7 @@ static int make_request (request_queue_t *q, struct bio * bi) if ( bio_data_dir(bi) == WRITE ) md_write_start(mddev); for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) { + DEFINE_WAIT(w); new_sector = raid6_compute_sector(logical_sector, raid_disks, data_disks, &dd_idx, &pd_idx, conf); @@ -1571,17 +1593,27 @@ static int make_request (request_queue_t *q, struct bio * bi) (unsigned long long)new_sector, (unsigned long long)logical_sector); + retry: + prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE); sh = get_active_stripe(conf, new_sector, pd_idx, (bi->bi_rw&RWA_MASK)); if (sh) { - - add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK)); - + if (!add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK))) { + /* Add failed due to overlap. Flush everything + * and wait a while + */ + raid6_unplug_device(mddev->queue); + release_stripe(sh); + schedule(); + goto retry; + } + finish_wait(&conf->wait_for_overlap, &w); raid6_plug_device(conf); handle_stripe(sh); release_stripe(sh); } else { /* cannot get stripe for read-ahead, just give-up */ clear_bit(BIO_UPTODATE, &bi->bi_flags); + finish_wait(&conf->wait_for_overlap, &w); break; } @@ -1729,6 +1761,7 @@ static int run (mddev_t *mddev) spin_lock_init(&conf->device_lock); init_waitqueue_head(&conf->wait_for_stripe); + init_waitqueue_head(&conf->wait_for_overlap); INIT_LIST_HEAD(&conf->handle_list); INIT_LIST_HEAD(&conf->delayed_list); INIT_LIST_HEAD(&conf->inactive_list); diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h index baf88d2ad986..d63ddcb4afad 100644 --- a/include/linux/raid/raid5.h +++ b/include/linux/raid/raid5.h @@ -152,6 +152,7 @@ struct stripe_head { #define R5_Wantread 4 /* want to schedule a read */ #define R5_Wantwrite 5 #define R5_Syncio 6 /* this io need to be accounted as resync io */ +#define R5_Overlap 7 /* There is a pending overlapping request on this block */ /* * Write method @@ -219,6 +220,7 @@ struct raid5_private_data { atomic_t active_stripes; struct list_head inactive_list; wait_queue_head_t wait_for_stripe; + wait_queue_head_t wait_for_overlap; int inactive_blocked; /* release of inactive stripes blocked, * waiting for 25% to be free */ -- cgit v1.2.3 From ddfefa1aa85f92359635ad5177417064182ec62f Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Mon, 7 Feb 2005 15:48:07 -0800 Subject: [PATCH] nfsd: Don't try to cache reply to nfsv2 readdir. As readdir returns the reply in a separate page, the cache code cannot find the reply (and it would probably be too big anyway) so flag readdir for NOCACHE Signed-off-by: Olaf Kirch Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfsd/nfsproc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index 70b32eac873c..f3bf5368551c 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c @@ -540,7 +540,7 @@ static struct svc_procedure nfsd_procedures2[18] = { PROC(symlink, symlinkargs, void, none, RC_REPLSTAT, ST), PROC(mkdir, createargs, diropres, fhandle, RC_REPLBUFF, ST+FH+AT), PROC(rmdir, diropargs, void, none, RC_REPLSTAT, ST), - PROC(readdir, readdirargs, readdirres, none, RC_REPLBUFF, 0), + PROC(readdir, readdirargs, readdirres, none, RC_NOCACHE, 0), PROC(statfs, fhandle, statfsres, none, RC_NOCACHE, ST+5), }; -- cgit v1.2.3 From 1a70252c4faab29b740677913634a0e86aa8c12c Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Mon, 7 Feb 2005 15:48:20 -0800 Subject: [PATCH] nfsd: Allow read access over NFS to files with APPEND bit set. Write access cannot safely be allowed as NFS doesn't support append, but read access should be ok. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfsd/vfs.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index f7ad9f759f83..a5a58a1dba0a 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -656,12 +656,15 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, dentry = fhp->fh_dentry; inode = dentry->d_inode; - /* Disallow access to files with the append-only bit set or - * with mandatory locking enabled + /* Disallow write access to files with the append-only bit set + * or any access when mandatory locking enabled */ err = nfserr_perm; - if (IS_APPEND(inode) || IS_ISMNDLK(inode)) + if (IS_APPEND(inode) && (access & MAY_WRITE)) goto out; + if (IS_ISMNDLK(inode)) + goto out; + if (!inode->i_fop) goto out; -- cgit v1.2.3 From ca323f212407364030c58f64bd94b29213599612 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 7 Feb 2005 15:59:56 -0800 Subject: Fix ATM copy-to-user usage. More of the Guninski "copy_to_user() takes a size_t" series. --- net/atm/addr.c | 2 +- net/atm/addr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/atm/addr.c b/net/atm/addr.c index 225f6843c32f..1c8867f7f54a 100644 --- a/net/atm/addr.c +++ b/net/atm/addr.c @@ -108,7 +108,7 @@ int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr) } int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user * buf, - int size) + size_t size) { unsigned long flags; struct atm_dev_addr *this; diff --git a/net/atm/addr.h b/net/atm/addr.h index 2affa3a128ca..3099d21feeaa 100644 --- a/net/atm/addr.h +++ b/net/atm/addr.h @@ -13,6 +13,6 @@ void atm_reset_addr(struct atm_dev *dev); int atm_add_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr); int atm_del_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr); -int atm_get_addr(struct atm_dev *dev,struct sockaddr_atmsvc __user *buf,int size); +int atm_get_addr(struct atm_dev *dev,struct sockaddr_atmsvc __user *buf,size_t size); #endif -- cgit v1.2.3 From d7c43720790d44853eda25249b4c10c1dd78458e Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 7 Feb 2005 16:05:10 -0800 Subject: [PATCH] NOMMU: Improved handling of get_unmapped_area() errors The attached patch does two things: (1) We no longer check the return value of file->f_op->get_unmapped_area() unless we actually called it. We know addr is zero otherwise because we'd've given an error earlier if it wasn't. (2) If -ENOSYS was returned by that operation, then we assume we actually called a driver (such as the framebuffer driver) that might want to invoke the operation in a lower level driver (such as matroxfb) if one exists, and that it found that one didn't. We translate the -ENOSYS error into -ENODEV - the error we would have given if the operation was not supplied in the file ops. Doing this permits us an opportunity for arch_get_unmapped_area() or something else to be called if we want that to happen, particularly in the MMU case. Signed-Off-By: David Howells Signed-Off-By: Linus Torvalds --- mm/nommu.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/mm/nommu.c b/mm/nommu.c index fcca232e4b9e..67ad603e217b 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -567,12 +567,14 @@ unsigned long do_mmap_pgoff(struct file *file, * that it represents a valid section of the address space * - this is the hook for quasi-memory character devices */ - if (file && file->f_op->get_unmapped_area) + if (file && file->f_op->get_unmapped_area) { addr = file->f_op->get_unmapped_area(file, addr, len, pgoff, flags); - - if (IS_ERR((void *) addr)) { - ret = addr; - goto error; + if (IS_ERR((void *) addr)) { + ret = addr; + if (ret == (unsigned long) -ENOSYS) + ret = (unsigned long) -ENODEV; + goto error; + } } /* we're going to need a VMA struct as well */ -- cgit v1.2.3 From e1920b5396747f01100a7126333439015c9a3614 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 7 Feb 2005 16:05:27 -0800 Subject: [PATCH] NOMMU: Documentation of no-MMU mmap The attached patch adds documentation for the behaviour of the no-MMU mmap. Signed-Off-By: David Howells Signed-Off-By: Linus Torvalds --- Documentation/nommu-mmap.txt | 141 +++++++++++++++++++++++++++++++++++++++++++ mm/nommu.c | 4 +- 2 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 Documentation/nommu-mmap.txt diff --git a/Documentation/nommu-mmap.txt b/Documentation/nommu-mmap.txt new file mode 100644 index 000000000000..fcf1c086f0ba --- /dev/null +++ b/Documentation/nommu-mmap.txt @@ -0,0 +1,141 @@ + ============================= + NO-MMU MEMORY MAPPING SUPPORT + ============================= + +The kernel has limited support for memory mapping under no-MMU conditions, such +as are used in uClinux environments. From the userspace point of view, memory +mapping is made use of in conjunction with the mmap() system call, the shmat() +call and the execve() system call. From the kernel's point of view, execve() +mapping is actually performed by the binfmt drivers, which call back into the +mmap() routines to do the actual work. + +Memory mapping behaviour also involves the way fork(), vfork(), clone() and +ptrace() work. Under uClinux there is no fork(), and clone() must be supplied +the CLONE_VM flag. + +The behaviour is similar between the MMU and no-MMU cases, but not identical; +and it's also much more restricted in the latter case: + + (*) Anonymous mapping, MAP_PRIVATE + + In the MMU case: VM regions backed by arbitrary pages; copy-on-write + across fork. + + In the no-MMU case: VM regions backed by arbitrary contiguous runs of + pages. + + (*) Anonymous mapping, MAP_SHARED + + These behave very much like private mappings, except that they're + shared across fork() or clone() without CLONE_VM in the MMU case. Since + the no-MMU case doesn't support these, behaviour is identical to + MAP_PRIVATE there. + + (*) File, MAP_PRIVATE, PROT_READ / PROT_EXEC, !PROT_WRITE + + In the MMU case: VM regions backed by pages read from file; changes to + the underlying file are reflected in the mapping; copied across fork. + + In the no-MMU case: VM regions backed by arbitrary contiguous runs of + pages into which the appropriate bit of the file is read; any remaining + bit of the mapping is cleared; such mappings are shared if possible; + writes to the file do not affect the mapping; writes to the mapping are + visible in other processes (no MMU protection), but should not happen. + + (*) File, MAP_PRIVATE, PROT_READ / PROT_EXEC, PROT_WRITE + + In the MMU case: like the non-PROT_WRITE case, except that the pages in + question get copied before the write actually happens. From that point + on writes to that page in the file no longer get reflected into the + mapping's backing pages. + + In the no-MMU case: works exactly as for the non-PROT_WRITE case. + + (*) Regular file / blockdev, MAP_SHARED, PROT_READ / PROT_EXEC / PROT_WRITE + + In the MMU case: VM regions backed by pages read from file; changes to + pages written back to file; writes to file reflected into pages backing + mapping; shared across fork. + + In the no-MMU case: not supported. + + (*) Memory backed regular file, MAP_SHARED, PROT_READ / PROT_EXEC / PROT_WRITE + + In the MMU case: As for ordinary regular files. + + In the no-MMU case: The filesystem providing the memory-backed file + (such as ramfs or tmpfs) may choose to honour an open, truncate, mmap + sequence by providing a contiguous sequence of pages to map. In that + case, a shared-writable memory mapping will be possible. It will work + as for the MMU case. If the filesystem does not provide any such + support, then the mapping request will be denied. + + (*) Memory backed chardev, MAP_SHARED, PROT_READ / PROT_EXEC / PROT_WRITE + + In the MMU case: As for ordinary regular files. + + In the no-MMU case: The character device driver may choose to honour + the mmap() by providing direct access to the underlying device if it + provides memory or quasi-memory that can be accessed directly. Examples + of such are frame buffers and flash devices. If the driver does not + provide any such support, then the mapping request will be denied. + + +============================ +FURTHER NOTES ON NO-MMU MMAP +============================ + + (*) A request for a private mapping of less than a page in size may not return + a page-aligned buffer. This is because the kernel calls kmalloc() to + allocate the buffer, not get_free_page(). + + (*) A list of all the mappings on the system is visible through /proc/maps in + no-MMU mode. + + (*) Supplying MAP_FIXED or a requesting a particular mapping address will + result in an error. + + (*) Files mapped privately must have a read method provided by the driver or + filesystem so that the contents can be read into the memory allocated. An + error will result if they don't. This is most likely to be encountered + with character device files, pipes, fifos and sockets. + + +============================================ +PROVIDING SHAREABLE CHARACTER DEVICE SUPPORT +============================================ + +To provide shareable character device support, a driver must provide a +file->f_op->get_unmapped_area() operation. The mmap() routines will call this +to get a proposed address for the mapping. This may return an error if it +doesn't wish to honour the mapping because it's too long, at a weird offset, +under some unsupported combination of flags or whatever. + +The vm_ops->close() routine will be invoked when the last mapping on a chardev +is removed. An existing mapping will be shared, partially or not, if possible +without notifying the driver. + +It is permitted also for the file->f_op->get_unmapped_area() operation to +return -ENOSYS. This will be taken to mean that this operation just doesn't +want to handle it, despite the fact it's got an operation. For instance, it +might try directing the call to a secondary driver which turns out not to +implement it. Such is the case for the framebuffer driver which attempts to +direct the call to the device-specific driver. + + +============================================== +PROVIDING SHAREABLE MEMORY-BACKED FILE SUPPORT +============================================== + +Provision of shared mappings on memory backed files is similar to the provision +of support for shared mapped character devices. The main difference is that the +filesystem providing the service will probably allocate a contiguous collection +of pages and permit mappings to be made on that. + +It is recommended that a truncate operation applied to such a file that +increases the file size, if that file is empty, be taken as a request to gather +enough pages to honour a mapping. This is required to support POSIX shared +memory. + +Memory backed devices are indicated by the mapping's backing device info having +the memory_backed flag set. diff --git a/mm/nommu.c b/mm/nommu.c index 67ad603e217b..8e70b95a8d9f 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -4,7 +4,9 @@ * Replacement code for mm functions to support CPU's that don't * have any form of memory management unit (thus no virtual memory). * - * Copyright (c) 2004 David Howells + * See Documentation/nommu-mmap.txt + * + * Copyright (c) 2004-2005 David Howells * Copyright (c) 2000-2003 David McCullough * Copyright (c) 2000-2001 D Jeff Dionne * Copyright (c) 2002 Greg Ungerer -- cgit v1.2.3 From 149d5cefb81c6a758e7197343063f22a7bd63b5b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 9 Feb 2005 17:26:24 +1100 Subject: Invalid bound check of driver defined ioctls in drm_ioctl Bug fd.o 2489 Reporter: Aapo Tahkola Signed-off-by: Dave Airlie --- drivers/char/drm/drm_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c index d216c28fb669..5845d986e6ec 100644 --- a/drivers/char/drm/drm_drv.c +++ b/drivers/char/drm/drm_drv.c @@ -516,7 +516,7 @@ int drm_ioctl( struct inode *inode, struct file *filp, if (nr < DRIVER_IOCTL_COUNT) ioctl = &drm_ioctls[nr]; - else if ((nr >= DRM_COMMAND_BASE) || (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) + else if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE]; else goto err_i1; -- cgit v1.2.3 From 4b5d23815ebcaaf030d98fec673f42b7736a02bc Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 9 Feb 2005 18:57:43 +1100 Subject: drm: fix race condition in radeon driver Close a race which could allow for privilege escalation by users with DRI privileges on Radeon hardware. Essentially, a malicious program could submit a packet containing an offset (possibly in main memory) to be rendered from/to, while a separate thread switched that offset in userspace rapidly between a valid value and an invalid one. radeon_check_and_fixup_offset() would pull the offset in from user space, check it, and spit it back out to user space to be copied in later by the emit code. It would sometimes catch the bad value, but sometimes the malicious program could modify it after the check and get an invalid offset rendered from/to. Fix this by allocating a temporary buffer and copying the data in at once. While here, make the cliprects stuff not do the VERIFYAREA_READ and COPY_FROM_USER_UNCHECKED gymnastics, avoiding a lock order reversal on FreeBSD. Performance impact is negligible -- no difference on r200 to ~1% improvement on rv200 in quake3 tests (P4 1Ghz, demofour at 1024x768, n=4 or 5) From: Eric Anholt Signed-off-by: Dave Airlie --- drivers/char/drm/drm_os_linux.h | 3 - drivers/char/drm/radeon_drv.h | 28 ++++---- drivers/char/drm/radeon_state.c | 155 ++++++++++++++++++---------------------- 3 files changed, 83 insertions(+), 103 deletions(-) diff --git a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h index 9870cc3283b1..3247e14b564f 100644 --- a/drivers/char/drm/drm_os_linux.h +++ b/drivers/char/drm/drm_os_linux.h @@ -96,9 +96,6 @@ static __inline__ int mtrr_del (int reg, unsigned long base, __copy_to_user(arg1, arg2, arg3) #define DRM_GET_USER_UNCHECKED(val, uaddr) \ __get_user(val, uaddr) -#define DRM_PUT_USER_UNCHECKED(uaddr, val) \ - __put_user(val, uaddr) - #define DRM_GET_PRIV_WITH_RETURN(_priv, _filp) _priv = _filp->private_data diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index 4fdcc2836f69..ce4ea6969ea5 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h @@ -1027,25 +1027,27 @@ do { \ } while (0) -#define OUT_RING_USER_TABLE( tab, sz ) do { \ +#define OUT_RING_TABLE( tab, sz ) do { \ int _size = (sz); \ - int __user *_tab = (tab); \ + int *_tab = (int *)(tab); \ \ if (write + _size > mask) { \ - int i = (mask+1) - write; \ - if (DRM_COPY_FROM_USER_UNCHECKED( (int *)(ring+write), \ - _tab, i*4 )) \ - return DRM_ERR(EFAULT); \ + int _i = (mask+1) - write; \ + _size -= _i; \ + while (_i > 0 ) { \ + *(int *)(ring + write) = *_tab++; \ + write++; \ + _i--; \ + } \ write = 0; \ - _size -= i; \ - _tab += i; \ + _tab += _i; \ } \ \ - if (_size && DRM_COPY_FROM_USER_UNCHECKED( (int *)(ring+write), \ - _tab, _size*4 )) \ - return DRM_ERR(EFAULT); \ - \ - write += _size; \ + while (_size > 0) { \ + *(ring + write) = *_tab++; \ + write++; \ + _size--; \ + } \ write &= mask; \ } while (0) diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c index 6a0f129f7bc9..b8d38e106708 100644 --- a/drivers/char/drm/radeon_state.c +++ b/drivers/char/drm/radeon_state.c @@ -93,21 +93,6 @@ static __inline__ int radeon_check_and_fixup_offset( drm_radeon_private_t *dev_p return 0; } -static __inline__ int radeon_check_and_fixup_offset_user( drm_radeon_private_t *dev_priv, - drm_file_t *filp_priv, - u32 __user *offset ) { - u32 off; - - DRM_GET_USER_UNCHECKED( off, offset ); - - if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &off ) ) - return DRM_ERR( EINVAL ); - - DRM_PUT_USER_UNCHECKED( offset, off ); - - return 0; -} - static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_priv, drm_file_t *filp_priv, int id, @@ -115,18 +100,18 @@ static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_ switch ( id ) { case RADEON_EMIT_PP_MISC: - if ( radeon_check_and_fixup_offset_user( dev_priv, filp_priv, - &data[( RADEON_RB3D_DEPTHOFFSET - - RADEON_PP_MISC ) / 4] ) ) { + if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, + &data[( RADEON_RB3D_DEPTHOFFSET + - RADEON_PP_MISC ) / 4] ) ) { DRM_ERROR( "Invalid depth buffer offset\n" ); return DRM_ERR( EINVAL ); } break; case RADEON_EMIT_PP_CNTL: - if ( radeon_check_and_fixup_offset_user( dev_priv, filp_priv, - &data[( RADEON_RB3D_COLOROFFSET - - RADEON_PP_CNTL ) / 4] ) ) { + if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, + &data[( RADEON_RB3D_COLOROFFSET + - RADEON_PP_CNTL ) / 4] ) ) { DRM_ERROR( "Invalid colour buffer offset\n" ); return DRM_ERR( EINVAL ); } @@ -138,8 +123,8 @@ static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_ case R200_EMIT_PP_TXOFFSET_3: case R200_EMIT_PP_TXOFFSET_4: case R200_EMIT_PP_TXOFFSET_5: - if ( radeon_check_and_fixup_offset_user( dev_priv, filp_priv, - &data[0] ) ) { + if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, + &data[0] ) ) { DRM_ERROR( "Invalid R200 texture offset\n" ); return DRM_ERR( EINVAL ); } @@ -148,9 +133,9 @@ static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_ case RADEON_EMIT_PP_TXFILTER_0: case RADEON_EMIT_PP_TXFILTER_1: case RADEON_EMIT_PP_TXFILTER_2: - if ( radeon_check_and_fixup_offset_user( dev_priv, filp_priv, - &data[( RADEON_PP_TXOFFSET_0 - - RADEON_PP_TXFILTER_0 ) / 4] ) ) { + if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, + &data[( RADEON_PP_TXOFFSET_0 + - RADEON_PP_TXFILTER_0 ) / 4] ) ) { DRM_ERROR( "Invalid R100 texture offset\n" ); return DRM_ERR( EINVAL ); } @@ -164,9 +149,8 @@ static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_ case R200_EMIT_PP_CUBIC_OFFSETS_5: { int i; for ( i = 0; i < 5; i++ ) { - if ( radeon_check_and_fixup_offset_user( dev_priv, - filp_priv, - &data[i] ) ) { + if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, + &data[i] ) ) { DRM_ERROR( "Invalid R200 cubic texture offset\n" ); return DRM_ERR( EINVAL ); } @@ -250,17 +234,11 @@ static __inline__ int radeon_check_and_fixup_packet3( drm_radeon_private_t *dev_ drm_file_t *filp_priv, drm_radeon_cmd_buffer_t *cmdbuf, unsigned int *cmdsz ) { - u32 tmp[4]; - u32 __user *cmd = (u32 __user *)cmdbuf->buf; - - if ( DRM_COPY_FROM_USER_UNCHECKED( tmp, cmd, sizeof( tmp ) ) ) { - DRM_ERROR( "Failed to copy data from user space\n" ); - return DRM_ERR( EFAULT ); - } + u32 *cmd = (u32 *) cmdbuf->buf; - *cmdsz = 2 + ( ( tmp[0] & RADEON_CP_PACKET_COUNT_MASK ) >> 16 ); + *cmdsz = 2 + ( ( cmd[0] & RADEON_CP_PACKET_COUNT_MASK ) >> 16 ); - if ( ( tmp[0] & 0xc0000000 ) != RADEON_CP_PACKET3 ) { + if ( ( cmd[0] & 0xc0000000 ) != RADEON_CP_PACKET3 ) { DRM_ERROR( "Not a type 3 packet\n" ); return DRM_ERR( EINVAL ); } @@ -271,32 +249,27 @@ static __inline__ int radeon_check_and_fixup_packet3( drm_radeon_private_t *dev_ } /* Check client state and fix it up if necessary */ - if ( tmp[0] & 0x8000 ) { /* MSB of opcode: next DWORD GUI_CNTL */ + if ( cmd[0] & 0x8000 ) { /* MSB of opcode: next DWORD GUI_CNTL */ u32 offset; - if ( tmp[1] & ( RADEON_GMC_SRC_PITCH_OFFSET_CNTL + if ( cmd[1] & ( RADEON_GMC_SRC_PITCH_OFFSET_CNTL | RADEON_GMC_DST_PITCH_OFFSET_CNTL ) ) { - offset = tmp[2] << 10; + offset = cmd[2] << 10; if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &offset ) ) { DRM_ERROR( "Invalid first packet offset\n" ); return DRM_ERR( EINVAL ); } - tmp[2] = ( tmp[2] & 0xffc00000 ) | offset >> 10; + cmd[2] = ( cmd[2] & 0xffc00000 ) | offset >> 10; } - if ( ( tmp[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL ) && - ( tmp[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL ) ) { - offset = tmp[3] << 10; + if ( ( cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL ) && + ( cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL ) ) { + offset = cmd[3] << 10; if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &offset ) ) { DRM_ERROR( "Invalid second packet offset\n" ); return DRM_ERR( EINVAL ); } - tmp[3] = ( tmp[3] & 0xffc00000 ) | offset >> 10; - } - - if ( DRM_COPY_TO_USER_UNCHECKED( cmd, tmp, sizeof( tmp ) ) ) { - DRM_ERROR( "Failed to copy data to user space\n" ); - return DRM_ERR( EFAULT ); + cmd[3] = ( cmd[3] & 0xffc00000 ) | offset >> 10; } } @@ -2473,7 +2446,7 @@ static int radeon_emit_packets( { int id = (int)header.packet.packet_id; int sz, reg; - int __user *data = (int __user *)cmdbuf->buf; + int *data = (int *)cmdbuf->buf; RING_LOCALS; if (id >= RADEON_MAX_STATE_PACKETS) @@ -2494,7 +2467,7 @@ static int radeon_emit_packets( BEGIN_RING(sz+1); OUT_RING( CP_PACKET0( reg, (sz-1) ) ); - OUT_RING_USER_TABLE( data, sz ); + OUT_RING_TABLE( data, sz ); ADVANCE_RING(); cmdbuf->buf += sz * sizeof(int); @@ -2508,7 +2481,6 @@ static __inline__ int radeon_emit_scalars( drm_radeon_cmd_buffer_t *cmdbuf ) { int sz = header.scalars.count; - int __user *data = (int __user *)cmdbuf->buf; int start = header.scalars.offset; int stride = header.scalars.stride; RING_LOCALS; @@ -2517,7 +2489,7 @@ static __inline__ int radeon_emit_scalars( OUT_RING( CP_PACKET0( RADEON_SE_TCL_SCALAR_INDX_REG, 0 ) ); OUT_RING( start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT)); OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_SCALAR_DATA_REG, sz-1 ) ); - OUT_RING_USER_TABLE( data, sz ); + OUT_RING_TABLE( cmdbuf->buf, sz ); ADVANCE_RING(); cmdbuf->buf += sz * sizeof(int); cmdbuf->bufsz -= sz * sizeof(int); @@ -2532,7 +2504,6 @@ static __inline__ int radeon_emit_scalars2( drm_radeon_cmd_buffer_t *cmdbuf ) { int sz = header.scalars.count; - int __user *data = (int __user *)cmdbuf->buf; int start = ((unsigned int)header.scalars.offset) + 0x100; int stride = header.scalars.stride; RING_LOCALS; @@ -2541,7 +2512,7 @@ static __inline__ int radeon_emit_scalars2( OUT_RING( CP_PACKET0( RADEON_SE_TCL_SCALAR_INDX_REG, 0 ) ); OUT_RING( start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT)); OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_SCALAR_DATA_REG, sz-1 ) ); - OUT_RING_USER_TABLE( data, sz ); + OUT_RING_TABLE( cmdbuf->buf, sz ); ADVANCE_RING(); cmdbuf->buf += sz * sizeof(int); cmdbuf->bufsz -= sz * sizeof(int); @@ -2554,7 +2525,6 @@ static __inline__ int radeon_emit_vectors( drm_radeon_cmd_buffer_t *cmdbuf ) { int sz = header.vectors.count; - int __user *data = (int __user *)cmdbuf->buf; int start = header.vectors.offset; int stride = header.vectors.stride; RING_LOCALS; @@ -2563,7 +2533,7 @@ static __inline__ int radeon_emit_vectors( OUT_RING( CP_PACKET0( RADEON_SE_TCL_VECTOR_INDX_REG, 0 ) ); OUT_RING( start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT)); OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_VECTOR_DATA_REG, (sz-1) ) ); - OUT_RING_USER_TABLE( data, sz ); + OUT_RING_TABLE( cmdbuf->buf, sz ); ADVANCE_RING(); cmdbuf->buf += sz * sizeof(int); @@ -2578,7 +2548,6 @@ static int radeon_emit_packet3( drm_device_t *dev, { drm_radeon_private_t *dev_priv = dev->dev_private; unsigned int cmdsz; - int __user *cmd = (int __user *)cmdbuf->buf; int ret; RING_LOCALS; @@ -2591,7 +2560,7 @@ static int radeon_emit_packet3( drm_device_t *dev, } BEGIN_RING( cmdsz ); - OUT_RING_USER_TABLE( cmd, cmdsz ); + OUT_RING_TABLE( cmdbuf->buf, cmdsz ); ADVANCE_RING(); cmdbuf->buf += cmdsz * 4; @@ -2608,7 +2577,6 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev, drm_radeon_private_t *dev_priv = dev->dev_private; drm_clip_rect_t box; unsigned int cmdsz; - int __user *cmd = (int __user *)cmdbuf->buf; int ret; drm_clip_rect_t __user *boxes = cmdbuf->boxes; int i = 0; @@ -2627,7 +2595,7 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev, do { if ( i < cmdbuf->nbox ) { - if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) )) + if (DRM_COPY_FROM_USER( &box, &boxes[i], sizeof(box) )) return DRM_ERR(EFAULT); /* FIXME The second and subsequent times round * this loop, send a WAIT_UNTIL_3D_IDLE before @@ -2650,7 +2618,7 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev, } BEGIN_RING( cmdsz ); - OUT_RING_USER_TABLE( cmd, cmdsz ); + OUT_RING_TABLE( cmdbuf->buf, cmdsz ); ADVANCE_RING(); } while ( ++i < cmdbuf->nbox ); @@ -2703,7 +2671,8 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS ) int idx; drm_radeon_cmd_buffer_t cmdbuf; drm_radeon_cmd_header_t header; - int orig_nbox; + int orig_nbox, orig_bufsz; + char *kbuf=NULL; LOCK_TEST_WITH_RETURN( dev, filp ); @@ -2720,24 +2689,29 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS ) RING_SPACE_TEST_WITH_RETURN( dev_priv ); VB_AGE_TEST_WITH_RETURN( dev_priv ); + if (cmdbuf.bufsz > 64*1024 || cmdbuf.bufsz<0) { + return DRM_ERR(EINVAL); + } - if (DRM_VERIFYAREA_READ( cmdbuf.buf, cmdbuf.bufsz )) - return DRM_ERR(EFAULT); - - if (cmdbuf.nbox && - DRM_VERIFYAREA_READ(cmdbuf.boxes, - cmdbuf.nbox * sizeof(drm_clip_rect_t))) - return DRM_ERR(EFAULT); + /* Allocate an in-kernel area and copy in the cmdbuf. Do this to avoid + * races between checking values and using those values in other code, + * and simply to avoid a lot of function calls to copy in data. + */ + orig_bufsz = cmdbuf.bufsz; + if (orig_bufsz != 0) { + kbuf = drm_alloc(cmdbuf.bufsz, DRM_MEM_DRIVER); + if (kbuf == NULL) + return DRM_ERR(ENOMEM); + if (DRM_COPY_FROM_USER(kbuf, cmdbuf.buf, cmdbuf.bufsz)) + return DRM_ERR(EFAULT); + cmdbuf.buf = kbuf; + } orig_nbox = cmdbuf.nbox; while ( cmdbuf.bufsz >= sizeof(header) ) { - - if (DRM_GET_USER_UNCHECKED( header.i, (int __user *)cmdbuf.buf )) { - DRM_ERROR("__get_user %p\n", cmdbuf.buf); - return DRM_ERR(EFAULT); - } + header.i = *(int *)cmdbuf.buf; cmdbuf.buf += sizeof(header); cmdbuf.bufsz -= sizeof(header); @@ -2746,7 +2720,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS ) DRM_DEBUG("RADEON_CMD_PACKET\n"); if (radeon_emit_packets( dev_priv, filp_priv, header, &cmdbuf )) { DRM_ERROR("radeon_emit_packets failed\n"); - return DRM_ERR(EINVAL); + goto err; } break; @@ -2754,7 +2728,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS ) DRM_DEBUG("RADEON_CMD_SCALARS\n"); if (radeon_emit_scalars( dev_priv, header, &cmdbuf )) { DRM_ERROR("radeon_emit_scalars failed\n"); - return DRM_ERR(EINVAL); + goto err; } break; @@ -2762,7 +2736,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS ) DRM_DEBUG("RADEON_CMD_VECTORS\n"); if (radeon_emit_vectors( dev_priv, header, &cmdbuf )) { DRM_ERROR("radeon_emit_vectors failed\n"); - return DRM_ERR(EINVAL); + goto err; } break; @@ -2772,14 +2746,14 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS ) if ( idx < 0 || idx >= dma->buf_count ) { DRM_ERROR( "buffer index %d (of %d max)\n", idx, dma->buf_count - 1 ); - return DRM_ERR(EINVAL); + goto err; } buf = dma->buflist[idx]; if ( buf->filp != filp || buf->pending ) { DRM_ERROR( "bad buffer %p %p %d\n", buf->filp, filp, buf->pending); - return DRM_ERR(EINVAL); + goto err; } radeon_cp_discard_buffer( dev, buf ); @@ -2789,7 +2763,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS ) DRM_DEBUG("RADEON_CMD_PACKET3\n"); if (radeon_emit_packet3( dev, filp_priv, &cmdbuf )) { DRM_ERROR("radeon_emit_packet3 failed\n"); - return DRM_ERR(EINVAL); + goto err; } break; @@ -2797,7 +2771,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS ) DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n"); if (radeon_emit_packet3_cliprect( dev, filp_priv, &cmdbuf, orig_nbox )) { DRM_ERROR("radeon_emit_packet3_clip failed\n"); - return DRM_ERR(EINVAL); + goto err; } break; @@ -2805,7 +2779,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS ) DRM_DEBUG("RADEON_CMD_SCALARS2\n"); if (radeon_emit_scalars2( dev_priv, header, &cmdbuf )) { DRM_ERROR("radeon_emit_scalars2 failed\n"); - return DRM_ERR(EINVAL); + goto err; } break; @@ -2813,21 +2787,28 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS ) DRM_DEBUG("RADEON_CMD_WAIT\n"); if (radeon_emit_wait( dev, header.wait.flags )) { DRM_ERROR("radeon_emit_wait failed\n"); - return DRM_ERR(EINVAL); + goto err; } break; default: DRM_ERROR("bad cmd_type %d at %p\n", header.header.cmd_type, cmdbuf.buf - sizeof(header)); - return DRM_ERR(EINVAL); + goto err; } } + if (orig_bufsz != 0) + drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER); DRM_DEBUG("DONE\n"); COMMIT_RING(); return 0; + +err: + if (orig_bufsz != 0) + drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER); + return DRM_ERR(EINVAL); } -- cgit v1.2.3 From 7eac2191d255d5eb5c38150962f2868f5d41ccf5 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 8 Feb 2005 22:10:09 +0000 Subject: [ARM PATCH] 2457/1: fix two typos in arch/arm/mm/tlb*.S Patch from Lennert Buytenhek Fix two typos in arch/arm/mm/tlb*.S Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- arch/arm/mm/tlb-v4.S | 2 +- arch/arm/mm/tlb-v4wb.S | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mm/tlb-v4.S b/arch/arm/mm/tlb-v4.S index 0c7329f9c38a..db82ee468248 100644 --- a/arch/arm/mm/tlb-v4.S +++ b/arch/arm/mm/tlb-v4.S @@ -44,7 +44,7 @@ ENTRY(v4_flush_user_tlb_range) mov pc, lr /* - * v4_flush_kerm_tlb_range(start, end) + * v4_flush_kern_tlb_range(start, end) * * Invalidate a range of TLB entries in the specified kernel * address range. diff --git a/arch/arm/mm/tlb-v4wb.S b/arch/arm/mm/tlb-v4wb.S index 15dc83d10397..7908d5f1f130 100644 --- a/arch/arm/mm/tlb-v4wb.S +++ b/arch/arm/mm/tlb-v4wb.S @@ -47,7 +47,7 @@ ENTRY(v4wb_flush_user_tlb_range) mov pc, lr /* - * v4_flush_kerm_tlb_range(start, end) + * v4_flush_kern_tlb_range(start, end) * * Invalidate a range of TLB entries in the specified kernel * address range. -- cgit v1.2.3 From 31c0355276f3840de2ebc06df4f770b7d52a7d0b Mon Sep 17 00:00:00 2001 From: Grant Grundler Date: Mon, 7 Feb 2005 23:57:45 -0800 Subject: [TG3]: Clean up grc_local_ctrl usage. Make the code more readable by only flipping the specific bits that need to change each register write. Signed-off-by: Grant Grundler (grundler@parisc-linux.org) Signed-off-by: David S. Miller --- drivers/net/tg3.c | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 0a09d933a770..74ed0863ca97 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -893,7 +893,7 @@ static void tg3_frob_aux_power(struct tg3 *tp) GRC_LCLCTRL_GPIO_OUTPUT1)); udelay(100); } else { - int no_gpio2; + u32 no_gpio2; u32 grc_local_ctrl; if (tp_peer != tp && @@ -901,8 +901,8 @@ static void tg3_frob_aux_power(struct tg3 *tp) return; /* On 5753 and variants, GPIO2 cannot be used. */ - no_gpio2 = (tp->nic_sram_data_cfg & - NIC_SRAM_DATA_CFG_NO_GPIO2) != 0; + no_gpio2 = tp->nic_sram_data_cfg & + NIC_SRAM_DATA_CFG_NO_GPIO2; grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE1 | @@ -914,29 +914,17 @@ static void tg3_frob_aux_power(struct tg3 *tp) GRC_LCLCTRL_GPIO_OUTPUT2); } tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | - grc_local_ctrl); + grc_local_ctrl); udelay(100); - grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 | - GRC_LCLCTRL_GPIO_OE1 | - GRC_LCLCTRL_GPIO_OE2 | - GRC_LCLCTRL_GPIO_OUTPUT0 | - GRC_LCLCTRL_GPIO_OUTPUT1 | - GRC_LCLCTRL_GPIO_OUTPUT2; - if (no_gpio2) { - grc_local_ctrl &= ~(GRC_LCLCTRL_GPIO_OE2 | - GRC_LCLCTRL_GPIO_OUTPUT2); - } + grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT0; + tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | - grc_local_ctrl); + grc_local_ctrl); udelay(100); - grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 | - GRC_LCLCTRL_GPIO_OE1 | - GRC_LCLCTRL_GPIO_OE2 | - GRC_LCLCTRL_GPIO_OUTPUT0 | - GRC_LCLCTRL_GPIO_OUTPUT1; if (!no_gpio2) { + grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT2; tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | grc_local_ctrl); udelay(100); -- cgit v1.2.3 From 6c25c2655a163004a4b9f52b27cb433ffc5b76ab Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 7 Feb 2005 23:59:00 -0800 Subject: [TG3]: Update driver version and reldate. Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 74ed0863ca97..789b9086b717 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -60,8 +60,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.20" -#define DRV_MODULE_RELDATE "February 2, 2005" +#define DRV_MODULE_VERSION "3.21" +#define DRV_MODULE_RELDATE "February 8, 2005" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 -- cgit v1.2.3 From fc86dddb3b4ddc3594bba99c92707428acb6534f Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 8 Feb 2005 00:18:48 -0800 Subject: [XFRM]: Kill xfrm_export.c This patch removes xfrm_export.c and moves the EXPORT_SYMBOL{,_GPL}'s to the files where the actual functions are. Signed-off-by: Adrian Bunk Signed-off-by: David S. Miller --- net/xfrm/Makefile | 3 +-- net/xfrm/xfrm_algo.c | 12 ++++++++++ net/xfrm/xfrm_export.c | 62 -------------------------------------------------- net/xfrm/xfrm_input.c | 4 ++++ net/xfrm/xfrm_policy.c | 20 +++++++++++++++- net/xfrm/xfrm_state.c | 29 +++++++++++++++++++++-- 6 files changed, 63 insertions(+), 67 deletions(-) delete mode 100644 net/xfrm/xfrm_export.c diff --git a/net/xfrm/Makefile b/net/xfrm/Makefile index 12bf0f88616c..693aac1aa833 100644 --- a/net/xfrm/Makefile +++ b/net/xfrm/Makefile @@ -2,7 +2,6 @@ # Makefile for the XFRM subsystem. # -obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_input.o xfrm_algo.o \ - xfrm_export.o +obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_input.o xfrm_algo.o obj-$(CONFIG_XFRM_USER) += xfrm_user.o diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c index 74e995aed022..080aae243ce0 100644 --- a/net/xfrm/xfrm_algo.c +++ b/net/xfrm/xfrm_algo.c @@ -316,6 +316,7 @@ struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id) } return NULL; } +EXPORT_SYMBOL_GPL(xfrm_aalg_get_byid); struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id) { @@ -331,6 +332,7 @@ struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id) } return NULL; } +EXPORT_SYMBOL_GPL(xfrm_ealg_get_byid); struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id) { @@ -346,6 +348,7 @@ struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id) } return NULL; } +EXPORT_SYMBOL_GPL(xfrm_calg_get_byid); static struct xfrm_algo_desc *xfrm_get_byname(struct xfrm_algo_desc *list, int entries, char *name, @@ -380,16 +383,19 @@ struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name, int probe) { return xfrm_get_byname(aalg_list, aalg_entries(), name, probe); } +EXPORT_SYMBOL_GPL(xfrm_aalg_get_byname); struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name, int probe) { return xfrm_get_byname(ealg_list, ealg_entries(), name, probe); } +EXPORT_SYMBOL_GPL(xfrm_ealg_get_byname); struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe) { return xfrm_get_byname(calg_list, calg_entries(), name, probe); } +EXPORT_SYMBOL_GPL(xfrm_calg_get_byname); struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx) { @@ -398,6 +404,7 @@ struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx) return &aalg_list[idx]; } +EXPORT_SYMBOL_GPL(xfrm_aalg_get_byidx); struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx) { @@ -406,6 +413,7 @@ struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx) return &ealg_list[idx]; } +EXPORT_SYMBOL_GPL(xfrm_ealg_get_byidx); /* * Probe for the availability of crypto algorithms, and set the available @@ -438,6 +446,7 @@ void xfrm_probe_algs(void) } #endif } +EXPORT_SYMBOL_GPL(xfrm_probe_algs); int xfrm_count_auth_supported(void) { @@ -448,6 +457,7 @@ int xfrm_count_auth_supported(void) n++; return n; } +EXPORT_SYMBOL_GPL(xfrm_count_auth_supported); int xfrm_count_enc_supported(void) { @@ -458,6 +468,7 @@ int xfrm_count_enc_supported(void) n++; return n; } +EXPORT_SYMBOL_GPL(xfrm_count_enc_supported); /* Move to common area: it is shared with AH. */ @@ -532,6 +543,7 @@ void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm, if (len) BUG(); } +EXPORT_SYMBOL_GPL(skb_icv_walk); #if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE) diff --git a/net/xfrm/xfrm_export.c b/net/xfrm/xfrm_export.c deleted file mode 100644 index 7ca0e889e54a..000000000000 --- a/net/xfrm/xfrm_export.c +++ /dev/null @@ -1,62 +0,0 @@ -#include -#include - -EXPORT_SYMBOL(xfrm_user_policy); -EXPORT_SYMBOL(km_waitq); -EXPORT_SYMBOL(km_new_mapping); -EXPORT_SYMBOL(xfrm_cfg_sem); -EXPORT_SYMBOL(xfrm_policy_alloc); -EXPORT_SYMBOL(__xfrm_policy_destroy); -EXPORT_SYMBOL(xfrm_lookup); -EXPORT_SYMBOL(__xfrm_policy_check); -EXPORT_SYMBOL(__xfrm_route_forward); -EXPORT_SYMBOL(xfrm_state_alloc); -EXPORT_SYMBOL(__xfrm_state_destroy); -EXPORT_SYMBOL(xfrm_state_insert); -EXPORT_SYMBOL(xfrm_state_add); -EXPORT_SYMBOL(xfrm_state_update); -EXPORT_SYMBOL(xfrm_state_check_expire); -EXPORT_SYMBOL(xfrm_state_check); -EXPORT_SYMBOL(xfrm_state_lookup); -EXPORT_SYMBOL(xfrm_state_register_afinfo); -EXPORT_SYMBOL(xfrm_state_unregister_afinfo); -EXPORT_SYMBOL(xfrm_state_delete_tunnel); -EXPORT_SYMBOL(xfrm_replay_check); -EXPORT_SYMBOL(xfrm_replay_advance); -EXPORT_SYMBOL(__secpath_destroy); -EXPORT_SYMBOL(secpath_dup); -EXPORT_SYMBOL(xfrm_get_acqseq); -EXPORT_SYMBOL(xfrm_parse_spi); -EXPORT_SYMBOL(xfrm_register_type); -EXPORT_SYMBOL(xfrm_unregister_type); -EXPORT_SYMBOL(xfrm_get_type); -EXPORT_SYMBOL(xfrm_register_km); -EXPORT_SYMBOL(xfrm_unregister_km); -EXPORT_SYMBOL(xfrm_state_delete); -EXPORT_SYMBOL(xfrm_state_walk); -EXPORT_SYMBOL(xfrm_find_acq_byseq); -EXPORT_SYMBOL(xfrm_find_acq); -EXPORT_SYMBOL(xfrm_alloc_spi); -EXPORT_SYMBOL(xfrm_state_flush); -EXPORT_SYMBOL(xfrm_policy_bysel); -EXPORT_SYMBOL(xfrm_policy_insert); -EXPORT_SYMBOL(xfrm_policy_walk); -EXPORT_SYMBOL(xfrm_policy_flush); -EXPORT_SYMBOL(xfrm_policy_byid); -EXPORT_SYMBOL(xfrm_policy_list); -EXPORT_SYMBOL(xfrm_dst_lookup); -EXPORT_SYMBOL(xfrm_policy_register_afinfo); -EXPORT_SYMBOL(xfrm_policy_unregister_afinfo); - -EXPORT_SYMBOL_GPL(xfrm_probe_algs); -EXPORT_SYMBOL_GPL(xfrm_count_auth_supported); -EXPORT_SYMBOL_GPL(xfrm_count_enc_supported); -EXPORT_SYMBOL_GPL(xfrm_aalg_get_byidx); -EXPORT_SYMBOL_GPL(xfrm_ealg_get_byidx); -EXPORT_SYMBOL_GPL(xfrm_aalg_get_byid); -EXPORT_SYMBOL_GPL(xfrm_ealg_get_byid); -EXPORT_SYMBOL_GPL(xfrm_calg_get_byid); -EXPORT_SYMBOL_GPL(xfrm_aalg_get_byname); -EXPORT_SYMBOL_GPL(xfrm_ealg_get_byname); -EXPORT_SYMBOL_GPL(xfrm_calg_get_byname); -EXPORT_SYMBOL_GPL(skb_icv_walk); diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index abe2e674cabd..c58a6f05a0b6 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -8,6 +8,7 @@ */ #include +#include #include #include @@ -20,6 +21,7 @@ void __secpath_destroy(struct sec_path *sp) xfrm_state_put(sp->x[i].xvec); kmem_cache_free(secpath_cachep, sp); } +EXPORT_SYMBOL(__secpath_destroy); struct sec_path *secpath_dup(struct sec_path *src) { @@ -40,6 +42,7 @@ struct sec_path *secpath_dup(struct sec_path *src) atomic_set(&sp->refcnt, 1); return sp; } +EXPORT_SYMBOL(secpath_dup); /* Fetch spi and seq from ipsec header */ @@ -73,6 +76,7 @@ int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq) *seq = *(u32*)(skb->h.raw + offset_seq); return 0; } +EXPORT_SYMBOL(xfrm_parse_spi); void __init xfrm_input_init(void) { diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 3ec936879f38..8d34ed106443 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -21,14 +21,17 @@ #include #include #include +#include #include #include DECLARE_MUTEX(xfrm_cfg_sem); +EXPORT_SYMBOL(xfrm_cfg_sem); static DEFINE_RWLOCK(xfrm_policy_lock); struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2]; +EXPORT_SYMBOL(xfrm_policy_list); static DEFINE_RWLOCK(xfrm_policy_afinfo_lock); static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO]; @@ -62,6 +65,7 @@ int xfrm_register_type(struct xfrm_type *type, unsigned short family) xfrm_policy_put_afinfo(afinfo); return err; } +EXPORT_SYMBOL(xfrm_register_type); int xfrm_unregister_type(struct xfrm_type *type, unsigned short family) { @@ -82,6 +86,7 @@ int xfrm_unregister_type(struct xfrm_type *type, unsigned short family) xfrm_policy_put_afinfo(afinfo); return err; } +EXPORT_SYMBOL(xfrm_unregister_type); struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family) { @@ -112,6 +117,7 @@ retry: xfrm_policy_put_afinfo(afinfo); return type; } +EXPORT_SYMBOL(xfrm_get_type); int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsigned short family) @@ -129,6 +135,7 @@ int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, xfrm_policy_put_afinfo(afinfo); return err; } +EXPORT_SYMBOL(xfrm_dst_lookup); void xfrm_put_type(struct xfrm_type *type) { @@ -234,6 +241,7 @@ struct xfrm_policy *xfrm_policy_alloc(int gfp) } return policy; } +EXPORT_SYMBOL(xfrm_policy_alloc); /* Destroy xfrm_policy: descendant resources must be released to this moment. */ @@ -250,6 +258,7 @@ void __xfrm_policy_destroy(struct xfrm_policy *policy) kfree(policy); } +EXPORT_SYMBOL(__xfrm_policy_destroy); static void xfrm_policy_gc_kill(struct xfrm_policy *policy) { @@ -373,6 +382,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) } return 0; } +EXPORT_SYMBOL(xfrm_policy_insert); struct xfrm_policy *xfrm_policy_bysel(int dir, struct xfrm_selector *sel, int delete) @@ -396,6 +406,7 @@ struct xfrm_policy *xfrm_policy_bysel(int dir, struct xfrm_selector *sel, } return pol; } +EXPORT_SYMBOL(xfrm_policy_bysel); struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete) { @@ -418,6 +429,7 @@ struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete) } return pol; } +EXPORT_SYMBOL(xfrm_policy_byid); void xfrm_policy_flush(void) { @@ -438,6 +450,7 @@ void xfrm_policy_flush(void) atomic_inc(&flow_cache_genid); write_unlock_bh(&xfrm_policy_lock); } +EXPORT_SYMBOL(xfrm_policy_flush); int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*), void *data) @@ -470,7 +483,7 @@ out: read_unlock_bh(&xfrm_policy_lock); return error; } - +EXPORT_SYMBOL(xfrm_policy_walk); /* Find policy to apply to this flow. */ @@ -845,6 +858,7 @@ error: *dst_p = NULL; return err; } +EXPORT_SYMBOL(xfrm_lookup); /* When skb is transformed back to its "native" form, we have to * check policy restrictions. At the moment we make this in maximally @@ -981,6 +995,7 @@ reject: xfrm_pol_put(pol); return 0; } +EXPORT_SYMBOL(__xfrm_policy_check); int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) { @@ -991,6 +1006,7 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) return xfrm_lookup(&skb->dst, &fl, NULL, 0) == 0; } +EXPORT_SYMBOL(__xfrm_route_forward); /* Optimize later using cookies and generation ids. */ @@ -1163,6 +1179,7 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) write_unlock(&xfrm_policy_afinfo_lock); return err; } +EXPORT_SYMBOL(xfrm_policy_register_afinfo); int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo) { @@ -1190,6 +1207,7 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo) write_unlock(&xfrm_policy_afinfo_lock); return err; } +EXPORT_SYMBOL(xfrm_policy_unregister_afinfo); static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family) { diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 5c9a57d6c09a..e43aa8c27483 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -17,6 +17,7 @@ #include #include #include +#include #include /* Each xfrm_state may be linked to two tables: @@ -38,6 +39,7 @@ static struct list_head xfrm_state_bydst[XFRM_DST_HSIZE]; static struct list_head xfrm_state_byspi[XFRM_DST_HSIZE]; DECLARE_WAIT_QUEUE_HEAD(km_waitq); +EXPORT_SYMBOL(km_waitq); static DEFINE_RWLOCK(xfrm_state_afinfo_lock); static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO]; @@ -193,6 +195,7 @@ struct xfrm_state *xfrm_state_alloc(void) } return x; } +EXPORT_SYMBOL(xfrm_state_alloc); void __xfrm_state_destroy(struct xfrm_state *x) { @@ -203,6 +206,7 @@ void __xfrm_state_destroy(struct xfrm_state *x) spin_unlock_bh(&xfrm_state_gc_lock); schedule_work(&xfrm_state_gc_work); } +EXPORT_SYMBOL(__xfrm_state_destroy); static void __xfrm_state_delete(struct xfrm_state *x) { @@ -241,6 +245,7 @@ void xfrm_state_delete(struct xfrm_state *x) __xfrm_state_delete(x); spin_unlock_bh(&x->lock); } +EXPORT_SYMBOL(xfrm_state_delete); void xfrm_state_flush(u8 proto) { @@ -267,6 +272,7 @@ restart: spin_unlock_bh(&xfrm_state_lock); wake_up(&km_waitq); } +EXPORT_SYMBOL(xfrm_state_flush); static int xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl, @@ -392,6 +398,7 @@ void xfrm_state_insert(struct xfrm_state *x) __xfrm_state_insert(x); spin_unlock_bh(&xfrm_state_lock); } +EXPORT_SYMBOL(xfrm_state_insert); static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq); @@ -444,6 +451,7 @@ out: return err; } +EXPORT_SYMBOL(xfrm_state_add); int xfrm_state_update(struct xfrm_state *x) { @@ -508,6 +516,7 @@ out: return err; } +EXPORT_SYMBOL(xfrm_state_update); int xfrm_state_check_expire(struct xfrm_state *x) { @@ -531,6 +540,7 @@ int xfrm_state_check_expire(struct xfrm_state *x) km_state_expired(x, 0); return 0; } +EXPORT_SYMBOL(xfrm_state_check_expire); static int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb) { @@ -553,6 +563,7 @@ int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb) err: return err; } +EXPORT_SYMBOL(xfrm_state_check); struct xfrm_state * xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, @@ -569,6 +580,7 @@ xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, xfrm_state_put_afinfo(afinfo); return x; } +EXPORT_SYMBOL(xfrm_state_lookup); struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto, @@ -586,6 +598,7 @@ xfrm_find_acq(u8 mode, u32 reqid, u8 proto, xfrm_state_put_afinfo(afinfo); return x; } +EXPORT_SYMBOL(xfrm_find_acq); /* Silly enough, but I'm lazy to build resolution list */ @@ -614,7 +627,8 @@ struct xfrm_state *xfrm_find_acq_byseq(u32 seq) spin_unlock_bh(&xfrm_state_lock); return x; } - +EXPORT_SYMBOL(xfrm_find_acq_byseq); + u32 xfrm_get_acqseq(void) { u32 res; @@ -626,6 +640,7 @@ u32 xfrm_get_acqseq(void) spin_unlock_bh(&acqseq_lock); return res; } +EXPORT_SYMBOL(xfrm_get_acqseq); void xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi) @@ -666,6 +681,7 @@ xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi) wake_up(&km_waitq); } } +EXPORT_SYMBOL(xfrm_alloc_spi); int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*), void *data) @@ -700,7 +716,7 @@ out: spin_unlock_bh(&xfrm_state_lock); return err; } - +EXPORT_SYMBOL(xfrm_state_walk); int xfrm_replay_check(struct xfrm_state *x, u32 seq) { @@ -726,6 +742,7 @@ int xfrm_replay_check(struct xfrm_state *x, u32 seq) } return 0; } +EXPORT_SYMBOL(xfrm_replay_check); void xfrm_replay_advance(struct xfrm_state *x, u32 seq) { @@ -745,6 +762,7 @@ void xfrm_replay_advance(struct xfrm_state *x, u32 seq) x->replay.bitmap |= (1U << diff); } } +EXPORT_SYMBOL(xfrm_replay_advance); static struct list_head xfrm_km_list = LIST_HEAD_INIT(xfrm_km_list); static DEFINE_RWLOCK(xfrm_km_lock); @@ -797,6 +815,7 @@ int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport) read_unlock(&xfrm_km_lock); return err; } +EXPORT_SYMBOL(km_new_mapping); void km_policy_expired(struct xfrm_policy *pol, int dir, int hard) { @@ -850,6 +869,7 @@ out: kfree(data); return err; } +EXPORT_SYMBOL(xfrm_user_policy); int xfrm_register_km(struct xfrm_mgr *km) { @@ -858,6 +878,7 @@ int xfrm_register_km(struct xfrm_mgr *km) write_unlock_bh(&xfrm_km_lock); return 0; } +EXPORT_SYMBOL(xfrm_register_km); int xfrm_unregister_km(struct xfrm_mgr *km) { @@ -866,6 +887,7 @@ int xfrm_unregister_km(struct xfrm_mgr *km) write_unlock_bh(&xfrm_km_lock); return 0; } +EXPORT_SYMBOL(xfrm_unregister_km); int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo) { @@ -885,6 +907,7 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo) write_unlock(&xfrm_state_afinfo_lock); return err; } +EXPORT_SYMBOL(xfrm_state_register_afinfo); int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo) { @@ -906,6 +929,7 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo) write_unlock(&xfrm_state_afinfo_lock); return err; } +EXPORT_SYMBOL(xfrm_state_unregister_afinfo); static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family) { @@ -940,6 +964,7 @@ void xfrm_state_delete_tunnel(struct xfrm_state *x) x->tunnel = NULL; } } +EXPORT_SYMBOL(xfrm_state_delete_tunnel); void __init xfrm_state_init(void) { -- cgit v1.2.3 From 3b3ed7823cd33cc1ebdee3f8c47e6e7169e7fb6c Mon Sep 17 00:00:00 2001 From: Nishanth Aravamudan Date: Tue, 8 Feb 2005 00:20:23 -0800 Subject: [NET]: Replace schedule_timeout() with msleep() in netdev_wait_allrefs() Description: Use msleep() instead of schedule_timeout() to guarantee the task delays as expected. The current code uses TASK_INTERRUPTIBLE, but does not respond to signals, so msleep() should be ok. Signed-off-by: Nishanth Aravamudan Signed-off-by: David S. Miller --- net/core/dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 4dc01e26f158..5d4abaa85351 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -108,6 +108,7 @@ #include #include #include +#include #ifdef CONFIG_NET_RADIO #include /* Note : will define WIRELESS_EXT */ #include @@ -2899,8 +2900,7 @@ static void netdev_wait_allrefs(struct net_device *dev) rebroadcast_time = jiffies; } - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ / 4); + msleep(250); if (time_after(jiffies, warning_time + 10 * HZ)) { printk(KERN_EMERG "unregister_netdevice: " -- cgit v1.2.3 From f8afb60c7537130448cc479d6d8dc9bf4ee06027 Mon Sep 17 00:00:00 2001 From: Nishanth Aravamudan Date: Tue, 8 Feb 2005 04:04:08 -0800 Subject: [IPVS]: Replace schedule_timeout() with ssleep() Description: Use ssleep() instead of schedule_timeout() to guarantee the task delays as expected. The first two replacements use TASK_INTERRUPTIBLE but do not check for signals, so ssleep() should be appropriate. Signed-off-by: Nishanth Aravamudan Signed-off-by: David S. Miller --- net/ipv4/ipvs/ip_vs_sync.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c index da30bebbddc8..25c479550a32 100644 --- a/net/ipv4/ipvs/ip_vs_sync.c +++ b/net/ipv4/ipvs/ip_vs_sync.c @@ -23,7 +23,7 @@ #include #include #include - +#include #include #include #include /* for ip_mc_join_group */ @@ -647,8 +647,7 @@ static void sync_master_loop(void) if (stop_master_sync) break; - __set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); + ssleep(1); } /* clean up the sync_buff queue */ @@ -705,8 +704,7 @@ static void sync_backup_loop(void) if (stop_backup_sync) break; - __set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); + ssleep(1); } /* release the sending multicast socket */ @@ -818,8 +816,7 @@ static int fork_sync_thread(void *startup) if ((pid = kernel_thread(sync_thread, startup, 0)) < 0) { IP_VS_ERR("could not create sync_thread due to %d... " "retrying.\n", pid); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(HZ); + ssleep(1); goto repeat; } @@ -853,8 +850,7 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid) if ((pid = kernel_thread(fork_sync_thread, &startup, 0)) < 0) { IP_VS_ERR("could not create fork_sync_thread due to %d... " "retrying.\n", pid); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(HZ); + ssleep(1); goto repeat; } -- cgit v1.2.3 From aff4b2884d29bc0acb66d70f6a8e240cf843d5bc Mon Sep 17 00:00:00 2001 From: Nishanth Aravamudan Date: Tue, 8 Feb 2005 04:05:07 -0800 Subject: [IPV4]: ipconfig: Replace schedule_timeout() with msleep() Description: Use msleep() instead of schedule_timeout() to guarantee the task delays as expected. Change the units of the two constants to be msecs and secs respectively. Signed-off-by: Nishanth Aravamudan Signed-off-by: David S. Miller --- net/ipv4/ipconfig.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index c542f2dab253..f2509034ce72 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -84,8 +85,8 @@ #endif /* Define the friendly delay before and after opening net devices */ -#define CONF_PRE_OPEN (HZ/2) /* Before opening: 1/2 second */ -#define CONF_POST_OPEN (1*HZ) /* After opening: 1 second */ +#define CONF_PRE_OPEN 500 /* Before opening: 1/2 second */ +#define CONF_POST_OPEN 1 /* After opening: 1 second */ /* Define the timeout for waiting for a DHCP/BOOTP/RARP reply */ #define CONF_OPEN_RETRIES 2 /* (Re)open devices twice */ @@ -1259,16 +1260,14 @@ static int __init ip_auto_config(void) try_try_again: #endif /* Give hardware a chance to settle */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(CONF_PRE_OPEN); + msleep(CONF_PRE_OPEN); /* Setup all network devices */ if (ic_open_devs() < 0) return -1; /* Give drivers a chance to settle */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(CONF_POST_OPEN); + ssleep(CONF_POST_OPEN); /* * If the config information is insufficient (e.g., our IP address or -- cgit v1.2.3 From b9870469ad7564a4b3608c3c0cf3181bcd030b66 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 8 Feb 2005 04:22:16 -0800 Subject: [TCP]: Fix calculation for collapsed skb size Noticed by Denis V. Lunev and based upon original patch by Alexey Kuznetsov Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index bfcd43832cb0..9865091954f3 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3760,8 +3760,7 @@ tcp_collapse(struct sock *sk, struct sk_buff *head, while (before(start, end)) { struct sk_buff *nskb; int header = skb_headroom(skb); - int copy = (PAGE_SIZE - sizeof(struct sk_buff) - - sizeof(struct skb_shared_info) - header - 31)&~15; + int copy = SKB_MAX_ORDER(header, 0); /* Too big header? This can happen with IPv6. */ if (copy < 0) -- cgit v1.2.3 From fcf28f99680a1f4d76384e4868ecd9b3d591460c Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 8 Feb 2005 04:24:20 -0800 Subject: [PKT_SCHED]: Fix u32 double listing. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/sched/cls_u32.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 8b870402bc96..821d3b9c5c55 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -91,6 +91,7 @@ struct tc_u_hnode { struct tc_u_hnode *next; u32 handle; + u32 prio; struct tc_u_common *tp_c; int refcnt; unsigned divisor; @@ -323,6 +324,7 @@ static int u32_init(struct tcf_proto *tp) root_ht->divisor = 0; root_ht->refcnt++; root_ht->handle = tp_c ? gen_new_htid(tp_c) : 0x80000000; + root_ht->prio = tp->prio; if (tp_c == NULL) { tp_c = kmalloc(sizeof(*tp_c), GFP_KERNEL); @@ -587,6 +589,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle, ht->refcnt = 0; ht->divisor = divisor; ht->handle = handle; + ht->prio = tp->prio; ht->next = tp_c->hlist; tp_c->hlist = ht; *arg = (unsigned long)ht; @@ -703,6 +706,8 @@ static void u32_walk(struct tcf_proto *tp, struct tcf_walker *arg) return; for (ht = tp_c->hlist; ht; ht = ht->next) { + if (ht->prio != tp->prio) + continue; if (arg->count >= arg->skip) { if (arg->fn(tp, (unsigned long)ht, arg) < 0) { arg->stop = 1; -- cgit v1.2.3 From 76dd2a8f9e46dcc70d0c1ca3728bce9bbac86c64 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 8 Feb 2005 15:35:29 -0800 Subject: [PATCH] Fix oops in alloc_zeroed_user_highpage() when page is NULL The generic and IA-64 versions of alloc_zeroed_user_highpage() don't check the return value from alloc_page_vma(). This can lead to an oops if we're OOM. This fixes my oops on PPC64, but I haven't got an IA-64 machine/compiler handy. Signed-off-by: Michael Ellerman Signed-off-by: Linus Torvalds --- include/asm-ia64/page.h | 3 ++- include/linux/highmem.h | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h index 1991944ddfd9..24770c011fd8 100644 --- a/include/asm-ia64/page.h +++ b/include/asm-ia64/page.h @@ -79,7 +79,8 @@ do { \ #define alloc_zeroed_user_highpage(vma, vaddr) \ ({ \ struct page *page = alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr); \ - flush_dcache_page(page); \ + if (page) \ + flush_dcache_page(page); \ page; \ }) diff --git a/include/linux/highmem.h b/include/linux/highmem.h index 11d84c93af71..2a7e6c65c882 100644 --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -48,7 +48,9 @@ alloc_zeroed_user_highpage(struct vm_area_struct *vma, unsigned long vaddr) { struct page *page = alloc_page_vma(GFP_HIGHUSER, vma, vaddr); - clear_user_highpage(page, vaddr); + if (page) + clear_user_highpage(page, vaddr); + return page; } #endif -- cgit v1.2.3