From 96fcef0a0cf876713d6acc94751fa674edc66e16 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 4 Oct 2003 21:01:16 -0700 Subject: [PATCH] boot-time selectable log buffer size From: Andrea Arcangeli Allow the printk log buffer size to be selected with a __setup parameter, `log_buf_len=N', where N must be a power-of-two. The default, initial statically allocated buffer size is still determined via kernel config. --- Documentation/kernel-parameters.txt | 4 ++ kernel/printk.c | 84 ++++++++++++++++++++++++++++--------- 2 files changed, 69 insertions(+), 19 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 3a66d54c51e0..5c763cec6821 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -460,6 +460,10 @@ running once the system is up. logibm_irq= [HW,MOUSE] Logitech Bus Mouse Driver Format: + log_buf_len=n Sets the size of the printk ring buffer, in bytes. + Format is n, nk, nM. n must be a power of two. The + default is set in kernel config. + lp=0 [LP] Specify parallel ports to use, e.g, lp=port[,port...] lp=none,parport0 (lp0 not configured, lp1 uses lp=reset first parallel port). 'lp=0' disables the diff --git a/kernel/printk.c b/kernel/printk.c index 830b690f9692..caaa3e557ef6 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -29,11 +29,11 @@ #include #include #include +#include #include -#define LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT) -#define LOG_BUF_MASK (LOG_BUF_LEN-1) +#define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT) /* printk's without a loglevel use this.. */ #define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */ @@ -68,17 +68,21 @@ struct console *console_drivers; */ static spinlock_t logbuf_lock = SPIN_LOCK_UNLOCKED; -static char log_buf[LOG_BUF_LEN]; +static char __log_buf[__LOG_BUF_LEN]; +static char *log_buf = __log_buf; +static int log_buf_len = __LOG_BUF_LEN; + +#define LOG_BUF_MASK (log_buf_len-1) #define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK]) /* - * The indices into log_buf are not constrained to LOG_BUF_LEN - they + * The indices into log_buf are not constrained to log_buf_len - they * must be masked before subscripting */ -static unsigned long log_start; /* Index into log_buf: next char to be read by syslog() */ -static unsigned long con_start; /* Index into log_buf: next char to be sent to consoles */ -static unsigned long log_end; /* Index into log_buf: most-recently-written-char + 1 */ -static unsigned long logged_chars; /* Number of chars produced since last read+clear operation */ +static unsigned long log_start; /* Index into log_buf: next char to be read by syslog() */ +static unsigned long con_start; /* Index into log_buf: next char to be sent to consoles */ +static unsigned long log_end; /* Index into log_buf: most-recently-written-char + 1 */ +static unsigned long logged_chars; /* Number of chars produced since last read+clear operation */ struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES]; static int preferred_console = -1; @@ -141,6 +145,45 @@ static int __init console_setup(char *str) __setup("console=", console_setup); +static int __init log_buf_len_setup(char *str) +{ + unsigned long size = memparse(str, &str); + + if (size > log_buf_len) { + unsigned long start, dest_idx, offset; + char * new_log_buf; + + new_log_buf = alloc_bootmem(size); + if (!new_log_buf) { + printk("log_buf_len: allocation failed\n"); + goto out; + } + + spin_lock_irq(&logbuf_lock); + log_buf_len = size; + log_buf = new_log_buf; + + offset = start = min(con_start, log_start); + dest_idx = 0; + while (start != log_end) { + log_buf[dest_idx] = __log_buf[start & (__LOG_BUF_LEN - 1)]; + start++; + dest_idx++; + } + log_start -= offset; + con_start -= offset; + log_end -= offset; + spin_unlock_irq(&logbuf_lock); + + printk("log_buf_len: %d\n", log_buf_len); + } +out: + + return 1; +} + +__setup("log_buf_len=", log_buf_len_setup); + /* * Commands to do_syslog: * @@ -213,8 +256,8 @@ int do_syslog(int type, char __user * buf, int len) if (error) goto out; count = len; - if (count > LOG_BUF_LEN) - count = LOG_BUF_LEN; + if (count > log_buf_len) + count = log_buf_len; spin_lock_irq(&logbuf_lock); if (count > logged_chars) count = logged_chars; @@ -229,7 +272,7 @@ int do_syslog(int type, char __user * buf, int len) */ for(i = 0; i < count && !error; i++) { j = limit-1-i; - if (j+LOG_BUF_LEN < log_end) + if (j + log_buf_len < log_end) break; c = LOG_BUF(j); spin_unlock_irq(&logbuf_lock); @@ -302,12 +345,15 @@ static void __call_console_drivers(unsigned long start, unsigned long end) /* * Write out chars from start to end - 1 inclusive */ -static void _call_console_drivers(unsigned long start, unsigned long end, int msg_log_level) +static void _call_console_drivers(unsigned long start, + unsigned long end, int msg_log_level) { - if (msg_log_level < console_loglevel && console_drivers && start != end) { + if (msg_log_level < console_loglevel && + console_drivers && start != end) { if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) { /* wrapped write */ - __call_console_drivers(start & LOG_BUF_MASK, LOG_BUF_LEN); + __call_console_drivers(start & LOG_BUF_MASK, + log_buf_len); __call_console_drivers(0, end & LOG_BUF_MASK); } else { __call_console_drivers(start, end); @@ -370,11 +416,11 @@ static void emit_log_char(char c) { LOG_BUF(log_end) = c; log_end++; - if (log_end - log_start > LOG_BUF_LEN) - log_start = log_end - LOG_BUF_LEN; - if (log_end - con_start > LOG_BUF_LEN) - con_start = log_end - LOG_BUF_LEN; - if (logged_chars < LOG_BUF_LEN) + if (log_end - log_start > log_buf_len) + log_start = log_end - log_buf_len; + if (log_end - con_start > log_buf_len) + con_start = log_end - log_buf_len; + if (logged_chars < log_buf_len) logged_chars++; } -- cgit v1.2.3 From c72da22fc150508340eea30c261d645bdac11b59 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 4 Oct 2003 21:01:50 -0700 Subject: [PATCH] Clean up MAX_NR_NODES/NUMNODES/etc. [1/5] From: Matthew Dobson This starts a series of cleanups against the way in which the various architectures specify the number of nodes and memory zones. We end up supporting up to 1024 memory zones on ia64, which is a recent requirement. Has been tested on ia32, ia64 (UMA), ppa64 (UMA) and NUMAQ. Make sure MAX_NUMNODES is defined in one and only one place. Remove superfluous definitions. Instead of defining MAX_NUMNODES in asm/numnodes.h, we define NODES_SHIFT there. Then in linux/mmzone.h we turn that NODES_SHIFT value into MAX_NUMNODES. --- include/asm-alpha/numnodes.h | 3 ++- include/asm-i386/numaq.h | 1 - include/asm-i386/numnodes.h | 14 +++++++++----- include/asm-i386/srat.h | 1 - include/asm-ppc64/numnodes.h | 3 ++- include/asm-x86_64/mmzone.h | 1 - include/asm-x86_64/numnodes.h | 7 ++----- include/linux/mmzone.h | 5 +++-- mm/slab.c | 2 +- 9 files changed, 19 insertions(+), 18 deletions(-) diff --git a/include/asm-alpha/numnodes.h b/include/asm-alpha/numnodes.h index 3c370ca3aaa6..cd425827e4f3 100644 --- a/include/asm-alpha/numnodes.h +++ b/include/asm-alpha/numnodes.h @@ -1,6 +1,7 @@ #ifndef _ASM_MAX_NUMNODES_H #define _ASM_MAX_NUMNODES_H -#define MAX_NUMNODES 128 /* Marvel */ +/* Max 128 Nodes - Marvel */ +#define NODES_SHIFT 7 #endif /* _ASM_MAX_NUMNODES_H */ diff --git a/include/asm-i386/numaq.h b/include/asm-i386/numaq.h index 13eb04501378..38f710dc37f2 100644 --- a/include/asm-i386/numaq.h +++ b/include/asm-i386/numaq.h @@ -28,7 +28,6 @@ #ifdef CONFIG_X86_NUMAQ -#define MAX_NUMNODES 16 extern int get_memcfg_numaq(void); /* diff --git a/include/asm-i386/numnodes.h b/include/asm-i386/numnodes.h index d77cbdcda572..a61f38c8176f 100644 --- a/include/asm-i386/numnodes.h +++ b/include/asm-i386/numnodes.h @@ -4,11 +4,15 @@ #include #ifdef CONFIG_X86_NUMAQ -#include -#elif CONFIG_ACPI_SRAT -#include -#else -#define MAX_NUMNODES 1 + +/* Max 16 Nodes */ +#define NODES_SHIFT 4 + +#elif defined(CONFIG_ACPI_SRAT) + +/* Max 8 Nodes */ +#define NODES_SHIFT 3 + #endif /* CONFIG_X86_NUMAQ */ #endif /* _ASM_MAX_NUMNODES_H */ diff --git a/include/asm-i386/srat.h b/include/asm-i386/srat.h index 13563f45870e..165ab4bdc02b 100644 --- a/include/asm-i386/srat.h +++ b/include/asm-i386/srat.h @@ -31,7 +31,6 @@ #error CONFIG_ACPI_SRAT not defined, and srat.h header has been included #endif -#define MAX_NUMNODES 8 extern int get_memcfg_from_srat(void); extern unsigned long *get_zholes_size(int); diff --git a/include/asm-ppc64/numnodes.h b/include/asm-ppc64/numnodes.h index 7c85cfe9ecdd..75ae0b906708 100644 --- a/include/asm-ppc64/numnodes.h +++ b/include/asm-ppc64/numnodes.h @@ -1,6 +1,7 @@ #ifndef _ASM_MAX_NUMNODES_H #define _ASM_MAX_NUMNODES_H -#define MAX_NUMNODES 16 +/* Max 16 Nodes */ +#define NODES_SHIFT 4 #endif /* _ASM_MAX_NUMNODES_H */ diff --git a/include/asm-x86_64/mmzone.h b/include/asm-x86_64/mmzone.h index 398c530270c2..1f8ec0b0f10f 100644 --- a/include/asm-x86_64/mmzone.h +++ b/include/asm-x86_64/mmzone.h @@ -10,7 +10,6 @@ #define VIRTUAL_BUG_ON(x) -#include #include #define MAXNODE 8 diff --git a/include/asm-x86_64/numnodes.h b/include/asm-x86_64/numnodes.h index 898bf89e1fdb..336011c3d3fd 100644 --- a/include/asm-x86_64/numnodes.h +++ b/include/asm-x86_64/numnodes.h @@ -3,10 +3,7 @@ #include -#ifdef CONFIG_DISCONTIGMEM -#define MAX_NUMNODES 8 /* APIC limit currently */ -#else -#define MAX_NUMNODES 1 -#endif +/* Max 8 Nodes - APIC limit currently */ +#define NODES_SHIFT 3 #endif diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index c66551a52d2a..5dcd62c5a9d6 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -14,9 +14,10 @@ #ifdef CONFIG_DISCONTIGMEM #include #endif -#ifndef MAX_NUMNODES -#define MAX_NUMNODES 1 +#ifndef NODES_SHIFT +#define NODES_SHIFT 0 #endif +#define MAX_NUMNODES (1 << NODES_SHIFT) /* Free memory management - zoned buddy allocator. */ #ifndef CONFIG_FORCE_MAX_ZONEORDER diff --git a/mm/slab.c b/mm/slab.c index 9b72c324d8c4..76c95b542be6 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -250,7 +250,7 @@ struct kmem_cache_s { unsigned int limit; /* 2) touched by every alloc & free from the backend */ struct kmem_list3 lists; - /* NUMA: kmem_3list_t *nodelists[NR_NODES] */ + /* NUMA: kmem_3list_t *nodelists[MAX_NUMNODES] */ unsigned int objsize; unsigned int flags; /* constant flags */ unsigned int num; /* # of objs per slab */ -- cgit v1.2.3 From 5bdcf4f8dd3335e85eca4b86cdb6a71fd1bd6602 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 4 Oct 2003 21:02:01 -0700 Subject: [PATCH] Clean up MAX_NR_NODES/NUMNODES/etc. [2/5] From: Matthew Dobson Remove MAX_NR_NODES. This value is only used in a couple of places, and it's incorrectly used in all those places as far as I can tell. Replace with MAX_NUMNODES. Create MAX_NODES_SHIFT and use this value to check NODES_SHIFT is appropriate. A possible future patch should make MAX_NODES_SHIFT vary based on 32 vs. 64 bit archs. --- arch/i386/kernel/smpboot.c | 6 +++--- include/linux/mmzone.h | 16 ++++++++++++---- mm/page_alloc.c | 2 +- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 1ab6213511ea..4ffbbb347b01 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -499,8 +499,8 @@ static struct task_struct * __init fork_by_hand(void) #ifdef CONFIG_NUMA /* which logical CPUs are on which nodes */ -cpumask_t node_2_cpu_mask[MAX_NR_NODES] = - { [0 ... MAX_NR_NODES-1] = CPU_MASK_NONE }; +cpumask_t node_2_cpu_mask[MAX_NUMNODES] = + { [0 ... MAX_NUMNODES-1] = CPU_MASK_NONE }; /* which node each logical CPU is on */ int cpu_2_node[NR_CPUS] = { [0 ... NR_CPUS-1] = 0 }; @@ -518,7 +518,7 @@ static inline void unmap_cpu_to_node(int cpu) int node; printk("Unmapping cpu %d from all nodes\n", cpu); - for (node = 0; node < MAX_NR_NODES; node ++) + for (node = 0; node < MAX_NUMNODES; node ++) cpu_clear(cpu, node_2_cpu_mask[node]); cpu_2_node[cpu] = -1; } diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 5dcd62c5a9d6..fa476e70c2a9 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -304,19 +304,27 @@ extern void setup_per_zone_pages_min(void); #define numa_node_id() (cpu_to_node(smp_processor_id())) #ifndef CONFIG_DISCONTIGMEM + extern struct pglist_data contig_page_data; #define NODE_DATA(nid) (&contig_page_data) #define NODE_MEM_MAP(nid) mem_map -#define MAX_NR_NODES 1 +#define MAX_NODES_SHIFT 0 + #else /* CONFIG_DISCONTIGMEM */ #include - -/* page->zone is currently 8 bits ... */ -#define MAX_NR_NODES (255 / MAX_NR_ZONES) +/* + * page->zone is currently 8 bits + * there are 3 zones (2 bits) + * this leaves 8-2=6 bits for nodes + */ +#define MAX_NODES_SHIFT 6 #endif /* !CONFIG_DISCONTIGMEM */ +#if NODES_SHIFT > MAX_NODES_SHIFT +#error NODES_SHIFT > MAX_NODES_SHIFT +#endif extern DECLARE_BITMAP(node_online_map, MAX_NUMNODES); extern DECLARE_BITMAP(memblk_online_map, MAX_NR_MEMBLKS); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 4ac2982747c9..c11774bf036e 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -50,7 +50,7 @@ EXPORT_SYMBOL(nr_swap_pages); * Used by page_zone() to look up the address of the struct zone whose * id is encoded in the upper bits of page->flags */ -struct zone *zone_table[MAX_NR_ZONES*MAX_NR_NODES]; +struct zone *zone_table[MAX_NR_ZONES*MAX_NUMNODES]; EXPORT_SYMBOL(zone_table); static char *zone_names[MAX_NR_ZONES] = { "DMA", "Normal", "HighMem" }; -- cgit v1.2.3 From dbe9770241821acf2c3f1961b32df766ded1169d Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 4 Oct 2003 21:02:25 -0700 Subject: [PATCH] Clean up MAX_NR_NODES/NUMNODES/etc. [3/5] From: Matthew Dobson Fix up the sh arch. sh defined NR_NODES, change sh to use standard MAX_NUMNODES instead. --- arch/sh/mm/init.c | 4 ++-- include/asm-sh/mmzone.h | 10 +++++----- include/asm-sh/numnodes.h | 7 +++++++ 3 files changed, 14 insertions(+), 7 deletions(-) create mode 100644 include/asm-sh/numnodes.h diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index 5c72add7f9d0..09261f48c624 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c @@ -51,8 +51,8 @@ unsigned long mmu_context_cache = NO_CONTEXT; #endif #ifdef CONFIG_DISCONTIGMEM -pg_data_t discontig_page_data[NR_NODES]; -bootmem_data_t discontig_node_bdata[NR_NODES]; +pg_data_t discontig_page_data[MAX_NUMNODES]; +bootmem_data_t discontig_node_bdata[MAX_NUMNODES]; #endif void show_mem(void) diff --git a/include/asm-sh/mmzone.h b/include/asm-sh/mmzone.h index fa323fc66f24..0e7406601fdf 100644 --- a/include/asm-sh/mmzone.h +++ b/include/asm-sh/mmzone.h @@ -10,14 +10,14 @@ #include +#ifdef CONFIG_DISCONTIGMEM + /* Currently, just for HP690 */ #define PHYSADDR_TO_NID(phys) ((((phys) - __MEMORY_START) >= 0x01000000)?1:0) -#define NR_NODES 2 -extern pg_data_t discontig_page_data[NR_NODES]; -extern bootmem_data_t discontig_node_bdata[NR_NODES]; +extern pg_data_t discontig_page_data[MAX_NUMNODES]; +extern bootmem_data_t discontig_node_bdata[MAX_NUMNODES]; -#ifdef CONFIG_DISCONTIGMEM /* * Following are macros that each numa implmentation must define. */ @@ -46,7 +46,7 @@ static inline int is_valid_page(struct page *page) { unsigned int i; - for (i = 0; i < NR_NODES; i++) { + for (i = 0; i < MAX_NUMNODES; i++) { if (page >= NODE_MEM_MAP(i) && page < NODE_MEM_MAP(i) + NODE_DATA(i)->node_size) return 1; diff --git a/include/asm-sh/numnodes.h b/include/asm-sh/numnodes.h new file mode 100644 index 000000000000..f73e85b72ecb --- /dev/null +++ b/include/asm-sh/numnodes.h @@ -0,0 +1,7 @@ +#ifndef _ASM_MAX_NUMNODES_H +#define _ASM_MAX_NUMNODES_H + +/* Max 2 Nodes */ +#define NODES_SHIFT 1 + +#endif /* _ASM_MAX_NUMNODES_H */ -- cgit v1.2.3 From b9fa8456448312e96e993335ecb6407038ad5b03 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 4 Oct 2003 21:02:34 -0700 Subject: [PATCH] Clean up MAX_NR_NODES/NUMNODES/etc. [4/5] From: Matthew Dobson Fix up the arm arch. This needs to be reviewed. Relatively straightforward replacement of NR_NODES with standard MAX_NUMNODES. --- arch/arm/mm/discontig.c | 6 +++--- arch/arm/mm/init.c | 12 +++--------- include/asm-arm/arch-clps711x/memory.h | 2 -- include/asm-arm/arch-sa1100/memory.h | 2 -- include/asm-arm/memory.h | 9 +++++++-- include/asm-arm/numnodes.h | 5 ++--- 6 files changed, 15 insertions(+), 21 deletions(-) diff --git a/arch/arm/mm/discontig.c b/arch/arm/mm/discontig.c index 82f972f07911..5d67df4a6073 100644 --- a/arch/arm/mm/discontig.c +++ b/arch/arm/mm/discontig.c @@ -15,7 +15,7 @@ #include #include -#if NR_NODES != 4 +#if MAX_NUMNODES != 4 #error Fix Me Please #endif @@ -23,9 +23,9 @@ * Our node_data structure for discontiguous memory. */ -static bootmem_data_t node_bootmem_data[NR_NODES]; +static bootmem_data_t node_bootmem_data[MAX_NUMNODES]; -pg_data_t discontig_node_data[NR_NODES] = { +pg_data_t discontig_node_data[MAX_NUMNODES] = { { .bdata = &node_bootmem_data[0] }, { .bdata = &node_bootmem_data[1] }, { .bdata = &node_bootmem_data[2] }, diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 90dcf272009c..5269355e1f78 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -33,12 +33,6 @@ #include #include -#ifndef CONFIG_DISCONTIGMEM -#define NR_NODES 1 -#else -#define NR_NODES 4 -#endif - #ifdef CONFIG_CPU_32 #define TABLE_OFFSET (PTRS_PER_PTE) #else @@ -178,7 +172,7 @@ find_memend_and_nodes(struct meminfo *mi, struct node_info *np) { unsigned int i, bootmem_pages = 0, memend_pfn = 0; - for (i = 0; i < NR_NODES; i++) { + for (i = 0; i < MAX_NUMNODES; i++) { np[i].start = -1U; np[i].end = 0; np[i].bootmap_pages = 0; @@ -207,7 +201,7 @@ find_memend_and_nodes(struct meminfo *mi, struct node_info *np) * we have, we're in trouble. (maybe we ought to * limit, instead of bugging?) */ - if (numnodes > NR_NODES) + if (numnodes > MAX_NUMNODES) BUG(); } @@ -365,7 +359,7 @@ static inline void free_bootmem_node_bank(int node, struct meminfo *mi) */ void __init bootmem_init(struct meminfo *mi) { - struct node_info node_info[NR_NODES], *np = node_info; + struct node_info node_info[MAX_NUMNODES], *np = node_info; unsigned int bootmap_pages, bootmap_pfn, map_pg; int node, initrd_node; diff --git a/include/asm-arm/arch-clps711x/memory.h b/include/asm-arm/arch-clps711x/memory.h index efa55531eae2..a116a7fa5232 100644 --- a/include/asm-arm/arch-clps711x/memory.h +++ b/include/asm-arm/arch-clps711x/memory.h @@ -109,8 +109,6 @@ * node 3: 0xd8000000 - 0xdfffffff */ -#define NR_NODES 4 - /* * Given a kernel address, find the home node of the underlying memory. */ diff --git a/include/asm-arm/arch-sa1100/memory.h b/include/asm-arm/arch-sa1100/memory.h index 6303e6cce320..076b3a9d41b6 100644 --- a/include/asm-arm/arch-sa1100/memory.h +++ b/include/asm-arm/arch-sa1100/memory.h @@ -74,8 +74,6 @@ * node 3: 0xd8000000 - 0xdfffffff */ -#define NR_NODES 4 - /* * Given a kernel address, find the home node of the underlying memory. */ diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h index 588c47d26338..c6c9fa67479a 100644 --- a/include/asm-arm/memory.h +++ b/include/asm-arm/memory.h @@ -89,6 +89,9 @@ static inline void *phys_to_virt(unsigned long x) * This is more complex. We have a set of mem_map arrays spread * around in memory. */ +#include +#define NUM_NODES (1 << NODES_SHIFT) + #define page_to_pfn(page) \ (( (page) - page_zone(page)->zone_mem_map) \ + page_zone(page)->zone_start_pfn) @@ -96,12 +99,12 @@ static inline void *phys_to_virt(unsigned long x) #define pfn_to_page(pfn) \ (PFN_TO_MAPBASE(pfn) + LOCAL_MAP_NR((pfn) << PAGE_SHIFT)) -#define pfn_valid(pfn) (PFN_TO_NID(pfn) < NR_NODES) +#define pfn_valid(pfn) (PFN_TO_NID(pfn) < NUM_NODES) #define virt_to_page(kaddr) \ (ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr)) -#define virt_addr_valid(kaddr) (KVADDR_TO_NID(kaddr) < NR_NODES) +#define virt_addr_valid(kaddr) (KVADDR_TO_NID(kaddr) < NUM_NODES) /* * Common discontigmem stuff. @@ -109,6 +112,8 @@ static inline void *phys_to_virt(unsigned long x) */ #define PHYS_TO_NID(addr) PFN_TO_NID((addr) >> PAGE_SHIFT) +#undef NUM_NODES + #endif /* diff --git a/include/asm-arm/numnodes.h b/include/asm-arm/numnodes.h index 4c12812f73dc..609f73b00b6a 100644 --- a/include/asm-arm/numnodes.h +++ b/include/asm-arm/numnodes.h @@ -10,8 +10,7 @@ #ifndef __ASM_ARM_NUMNODES_H #define __ASM_ARM_NUMNODES_H -#include - -#define MAX_NUMNODES NR_NODES +/* Max 4 Nodes */ +#define NODES_SHIFT 2 #endif -- cgit v1.2.3 From d513558012a8cac3c48b485eb9fa76fba8b6f795 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 4 Oct 2003 21:02:42 -0700 Subject: [PATCH] Clean up MAX_NR_NODES/NUMNODES/etc. [5/5] From: Matthew Dobson Fix up the ia64 arch. --- arch/ia64/kernel/acpi.c | 3 ++- arch/ia64/mm/discontig.c | 9 ++++----- arch/ia64/mm/numa.c | 3 +-- include/asm-ia64/acpi.h | 2 +- include/asm-ia64/mmzone.h | 44 ++++++++++++++++++++------------------------ include/asm-ia64/nodedata.h | 6 +++--- include/asm-ia64/numa.h | 10 ++-------- include/asm-ia64/numnodes.h | 9 +++++++-- include/asm-ia64/sn/pda.h | 3 ++- 9 files changed, 42 insertions(+), 47 deletions(-) diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index cd4744539021..e0b1e00bf613 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -341,7 +342,7 @@ static u32 __initdata pxm_flag[PXM_FLAG_LEN]; #define pxm_bit_test(bit) (test_bit(bit,(void *)pxm_flag)) /* maps to convert between proximity domain and logical node ID */ int __initdata pxm_to_nid_map[MAX_PXM_DOMAINS]; -int __initdata nid_to_pxm_map[NR_NODES]; +int __initdata nid_to_pxm_map[MAX_NUMNODES]; static struct acpi_table_slit __initdata *slit_table; /* diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index 7c885aa1754c..2f1b7826caf1 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -26,10 +25,10 @@ */ #define GRANULEROUNDUP(n) (((n)+IA64_GRANULE_SIZE-1) & ~(IA64_GRANULE_SIZE-1)) -static struct ia64_node_data *node_data[NR_NODES]; -static long boot_pg_data[8*NR_NODES+sizeof(pg_data_t)] __initdata; -static pg_data_t *pg_data_ptr[NR_NODES] __initdata; -static bootmem_data_t bdata[NR_NODES][NR_BANKS_PER_NODE+1] __initdata; +static struct ia64_node_data *node_data[MAX_NUMNODES]; +static long boot_pg_data[8*MAX_NUMNODES+sizeof(pg_data_t)] __initdata; +static pg_data_t *pg_data_ptr[MAX_NUMNODES] __initdata; +static bootmem_data_t bdata[MAX_NUMNODES][NR_BANKS_PER_NODE+1] __initdata; /* * Return the compact node number of this cpu. Used prior to * setting up the cpu_data area. diff --git a/arch/ia64/mm/numa.c b/arch/ia64/mm/numa.c index a734be9b874b..58ccff869f7c 100644 --- a/arch/ia64/mm/numa.c +++ b/arch/ia64/mm/numa.c @@ -15,7 +15,6 @@ #include #include #include -#include #include /* @@ -29,7 +28,7 @@ struct node_cpuid_s node_cpuid[NR_CPUS]; * This is a matrix with "distances" between nodes, they should be * proportional to the memory access latency ratios. */ -u8 numa_slit[NR_NODES * NR_NODES]; +u8 numa_slit[MAX_NUMNODES * MAX_NUMNODES]; /* Identify which cnode a physical address resides on */ int diff --git a/include/asm-ia64/acpi.h b/include/asm-ia64/acpi.h index 66d1a35f2de0..7c3c0edd574a 100644 --- a/include/asm-ia64/acpi.h +++ b/include/asm-ia64/acpi.h @@ -99,7 +99,7 @@ int acpi_get_addr_space (void *obj, u8 type, u64 *base, u64 *length,u64 *tra); /* Proximity bitmap length; _PXM is at most 255 (8 bit)*/ #define MAX_PXM_DOMAINS (256) extern int __initdata pxm_to_nid_map[MAX_PXM_DOMAINS]; -extern int __initdata nid_to_pxm_map[NR_NODES]; +extern int __initdata nid_to_pxm_map[MAX_NUMNODES]; #endif #endif /*__KERNEL__*/ diff --git a/include/asm-ia64/mmzone.h b/include/asm-ia64/mmzone.h index 8ef66c05d2b3..9e060cd61ca4 100644 --- a/include/asm-ia64/mmzone.h +++ b/include/asm-ia64/mmzone.h @@ -92,14 +92,12 @@ extern unsigned long max_low_pfn; -#ifdef CONFIG_IA64_DIG +#if defined(CONFIG_IA64_DIG) /* * Platform definitions for DIG platform with contiguous memory. */ -#define MAX_PHYSNODE_ID 8 /* Maximum node number +1 */ -#define NR_NODES 8 /* Maximum number of nodes in SSI */ - +#define MAX_PHYSNODE_ID 8 /* Maximum node number +1 */ #define MAX_PHYS_MEMORY (1UL << 40) /* 1 TB */ /* @@ -119,37 +117,34 @@ extern unsigned long max_low_pfn; # error Unsupported bank and nodesize! #endif #define BANKSIZE (1UL << BANKSHIFT) -#define BANK_OFFSET(addr) ((unsigned long)(addr) & (BANKSIZE-1)) -#define NR_BANKS (NR_BANKS_PER_NODE * NR_NODES) - -/* - * VALID_MEM_KADDR returns a boolean to indicate if a kaddr is - * potentially a valid cacheable identity mapped RAM memory address. - * Note that the RAM may or may not actually be present!! - */ -#define VALID_MEM_KADDR(kaddr) 1 - -/* - * Given a nodeid & a bank number, find the address of the mem_map - * entry for the first page of the bank. - */ -#define BANK_MEM_MAP_INDEX(kaddr) \ - (((unsigned long)(kaddr) & (MAX_PHYS_MEMORY-1)) >> BANKSHIFT) #elif defined(CONFIG_IA64_SGI_SN2) + /* * SGI SN2 discontig definitions */ #define MAX_PHYSNODE_ID 2048 /* 2048 node ids (also called nasid) */ -#define NR_NODES 128 /* Maximum number of nodes in SSI */ #define MAX_PHYS_MEMORY (1UL << 49) -#define BANKSHIFT 38 #define NR_BANKS_PER_NODE 4 +#define BANKSHIFT 38 #define SN2_NODE_SIZE (64UL*1024*1024*1024) /* 64GB per node */ #define BANKSIZE (SN2_NODE_SIZE/NR_BANKS_PER_NODE) + +#endif /* CONFIG_IA64_DIG */ + +#if defined(CONFIG_IA64_DIG) || defined (CONFIG_IA64_SGI_SN2) +/* Common defines for both platforms */ +#include #define BANK_OFFSET(addr) ((unsigned long)(addr) & (BANKSIZE-1)) -#define NR_BANKS (NR_BANKS_PER_NODE * NR_NODES) +#define NR_BANKS (NR_BANKS_PER_NODE * (1 << NODES_SHIFT)) +#define NR_MEMBLKS (NR_BANKS) + +/* + * VALID_MEM_KADDR returns a boolean to indicate if a kaddr is + * potentially a valid cacheable identity mapped RAM memory address. + * Note that the RAM may or may not actually be present!! + */ #define VALID_MEM_KADDR(kaddr) 1 /* @@ -159,5 +154,6 @@ extern unsigned long max_low_pfn; #define BANK_MEM_MAP_INDEX(kaddr) \ (((unsigned long)(kaddr) & (MAX_PHYS_MEMORY-1)) >> BANKSHIFT) -#endif /* CONFIG_IA64_DIG */ +#endif /* CONFIG_IA64_DIG || CONFIG_IA64_SGI_SN2 */ + #endif /* _ASM_IA64_MMZONE_H */ diff --git a/include/asm-ia64/nodedata.h b/include/asm-ia64/nodedata.h index 9acdcb7ffe58..f09856b1c902 100644 --- a/include/asm-ia64/nodedata.h +++ b/include/asm-ia64/nodedata.h @@ -14,7 +14,7 @@ #define _ASM_IA64_NODEDATA_H -#include +#include /* * Node Data. One of these structures is located on each node of a NUMA system. @@ -24,9 +24,9 @@ struct pglist_data; struct ia64_node_data { short active_cpu_count; short node; - struct pglist_data *pg_data_ptrs[NR_NODES]; + struct pglist_data *pg_data_ptrs[MAX_NUMNODES]; struct page *bank_mem_map_base[NR_BANKS]; - struct ia64_node_data *node_data_ptrs[NR_NODES]; + struct ia64_node_data *node_data_ptrs[MAX_NUMNODES]; short node_id_map[NR_BANKS]; }; diff --git a/include/asm-ia64/numa.h b/include/asm-ia64/numa.h index aa5864eff837..ee2e483a0719 100644 --- a/include/asm-ia64/numa.h +++ b/include/asm-ia64/numa.h @@ -16,17 +16,11 @@ #ifdef CONFIG_NUMA -#ifdef CONFIG_DISCONTIGMEM # include -# define NR_MEMBLKS (NR_BANKS) -#else -# define NR_NODES (8) -# define NR_MEMBLKS (NR_NODES * 8) -#endif #include extern volatile char cpu_to_node_map[NR_CPUS] __cacheline_aligned; -extern volatile cpumask_t node_to_cpu_mask[NR_NODES] __cacheline_aligned; +extern volatile cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned; /* Stuff below this line could be architecture independent */ @@ -60,7 +54,7 @@ extern struct node_cpuid_s node_cpuid[NR_CPUS]; * proportional to the memory access latency ratios. */ -extern u8 numa_slit[NR_NODES * NR_NODES]; +extern u8 numa_slit[MAX_NUMNODES * MAX_NUMNODES]; #define node_distance(from,to) (numa_slit[from * numnodes + to]) extern int paddr_to_nid(unsigned long paddr); diff --git a/include/asm-ia64/numnodes.h b/include/asm-ia64/numnodes.h index 1da4bdaa917f..3b71511f5d2b 100644 --- a/include/asm-ia64/numnodes.h +++ b/include/asm-ia64/numnodes.h @@ -1,7 +1,12 @@ #ifndef _ASM_MAX_NUMNODES_H #define _ASM_MAX_NUMNODES_H -#include -#define MAX_NUMNODES NR_NODES +#ifdef CONFIG_IA64_DIG +/* Max 8 Nodes */ +#define NODES_SHIFT 3 +#elif defined(CONFIG_IA64_SGI_SN2) +/* Max 128 Nodes */ +#define NODES_SHIFT 7 +#endif #endif /* _ASM_MAX_NUMNODES_H */ diff --git a/include/asm-ia64/sn/pda.h b/include/asm-ia64/sn/pda.h index 6c605727ea21..426daf9b9596 100644 --- a/include/asm-ia64/sn/pda.h +++ b/include/asm-ia64/sn/pda.h @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -56,7 +57,7 @@ typedef struct pda_s { unsigned long sn_soft_irr[4]; unsigned long sn_in_service_ivecs[4]; - short cnodeid_to_nasid_table[NR_NODES]; + short cnodeid_to_nasid_table[MAX_NUMNODES]; int sn_lb_int_war_ticks; int sn_last_irq; int sn_first_irq; -- cgit v1.2.3 From ca8878630bcd0467c21228f2d13f7b8a6649c612 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 4 Oct 2003 21:02:51 -0700 Subject: [PATCH] node enumeration fixes From: Matthew Dobson Here's a small update to the numnodes fix that went into -mm3. The biggest changes are: 1) move the actual NODES_SHIFT and MAX_NUMNODES definitions into linux/numa.h and include this in linux/mmzone.h, instead of being directly in linux/mmzone.h. This allows other files to include *just* the NUMNODES stuff w/out grabbing all of mmzone.h. 2) pull NODE_SHIFT out of linux/mm.h. This isn't used anywhere in the kernel, and it will only get confused with NODES_SHIFT. 3) Fix the IA64 patch. The original patch I had sent out hadn't been tested on IA64. It was mostly right, but there were circular dependencies. All better now, and acked by Jesse. 4) In linux/mmzone.h, insert code to define MAX_NODES_SHIFT based on the size of unsigned long. For 64-bit arches, we can have a much larger value. This allows IA64 to have 100's or 1000's of nodes. MAX_NODES_SHIFT is defined as 10 (ie: 1024 nodes) for 64-bit for now, although it could likely be much larger. For 32-bit it is 6 (ie: 64 nodes). 5) Small cleanup in include/asm-arm/memory.h. Mostly the result of the new linux/numa.h file. Much cleaner and more readable now. --- include/asm-arm/memory.h | 17 ++++++----------- include/asm-ia64/nodedata.h | 8 +++----- include/asm-ia64/numa.h | 4 ++-- include/asm-ia64/sn/pda.h | 2 +- include/linux/mm.h | 1 - include/linux/mmzone.h | 21 +++++++++++---------- include/linux/numa.h | 16 ++++++++++++++++ 7 files changed, 39 insertions(+), 30 deletions(-) create mode 100644 include/linux/numa.h diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h index c6c9fa67479a..3d9b777a0349 100644 --- a/include/asm-arm/memory.h +++ b/include/asm-arm/memory.h @@ -84,27 +84,24 @@ static inline void *phys_to_virt(unsigned long x) #define PHYS_TO_NID(addr) (0) -#else +#else /* CONFIG_DISCONTIGMEM */ + /* * This is more complex. We have a set of mem_map arrays spread * around in memory. */ -#include -#define NUM_NODES (1 << NODES_SHIFT) +#include #define page_to_pfn(page) \ (( (page) - page_zone(page)->zone_mem_map) \ + page_zone(page)->zone_start_pfn) - #define pfn_to_page(pfn) \ (PFN_TO_MAPBASE(pfn) + LOCAL_MAP_NR((pfn) << PAGE_SHIFT)) - -#define pfn_valid(pfn) (PFN_TO_NID(pfn) < NUM_NODES) +#define pfn_valid(pfn) (PFN_TO_NID(pfn) < MAX_NUMNODES) #define virt_to_page(kaddr) \ (ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr)) - -#define virt_addr_valid(kaddr) (KVADDR_TO_NID(kaddr) < NUM_NODES) +#define virt_addr_valid(kaddr) (KVADDR_TO_NID(kaddr) < MAX_NUMNODES) /* * Common discontigmem stuff. @@ -112,9 +109,7 @@ static inline void *phys_to_virt(unsigned long x) */ #define PHYS_TO_NID(addr) PFN_TO_NID((addr) >> PAGE_SHIFT) -#undef NUM_NODES - -#endif +#endif /* !CONFIG_DISCONTIGMEM */ /* * For BIO. "will die". Kill me when bio_to_phys() and bvec_to_phys() die. diff --git a/include/asm-ia64/nodedata.h b/include/asm-ia64/nodedata.h index f09856b1c902..eae5235fa8be 100644 --- a/include/asm-ia64/nodedata.h +++ b/include/asm-ia64/nodedata.h @@ -8,13 +8,11 @@ * Copyright (c) 2002 Erich Focht * Copyright (c) 2002 Kimio Suganuma */ - - #ifndef _ASM_IA64_NODEDATA_H #define _ASM_IA64_NODEDATA_H - -#include +#include +#include /* * Node Data. One of these structures is located on each node of a NUMA system. @@ -24,7 +22,7 @@ struct pglist_data; struct ia64_node_data { short active_cpu_count; short node; - struct pglist_data *pg_data_ptrs[MAX_NUMNODES]; + struct pglist_data *pg_data_ptrs[MAX_NUMNODES]; struct page *bank_mem_map_base[NR_BANKS]; struct ia64_node_data *node_data_ptrs[MAX_NUMNODES]; short node_id_map[NR_BANKS]; diff --git a/include/asm-ia64/numa.h b/include/asm-ia64/numa.h index ee2e483a0719..8b0d5edad7ba 100644 --- a/include/asm-ia64/numa.h +++ b/include/asm-ia64/numa.h @@ -16,9 +16,9 @@ #ifdef CONFIG_NUMA -# include - +#include #include + extern volatile char cpu_to_node_map[NR_CPUS] __cacheline_aligned; extern volatile cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned; diff --git a/include/asm-ia64/sn/pda.h b/include/asm-ia64/sn/pda.h index 426daf9b9596..7162968474c7 100644 --- a/include/asm-ia64/sn/pda.h +++ b/include/asm-ia64/sn/pda.h @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/linux/mm.h b/include/linux/mm.h index ca006021a13e..f72772e17665 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -323,7 +323,6 @@ static inline void put_page(struct page *page) * The zone field is never updated after free_area_init_core() * sets it, so none of the operations on it need to be atomic. */ -#define NODE_SHIFT 4 #define ZONE_SHIFT (BITS_PER_LONG - 8) struct zone; diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index fa476e70c2a9..bea51c4f5b22 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -10,14 +10,8 @@ #include #include #include +#include #include -#ifdef CONFIG_DISCONTIGMEM -#include -#endif -#ifndef NODES_SHIFT -#define NODES_SHIFT 0 -#endif -#define MAX_NUMNODES (1 << NODES_SHIFT) /* Free memory management - zoned buddy allocator. */ #ifndef CONFIG_FORCE_MAX_ZONEORDER @@ -313,12 +307,19 @@ extern struct pglist_data contig_page_data; #else /* CONFIG_DISCONTIGMEM */ #include + +#if BITS_PER_LONG == 32 /* - * page->zone is currently 8 bits - * there are 3 zones (2 bits) - * this leaves 8-2=6 bits for nodes + * with 32 bit flags field, page->zone is currently 8 bits. + * there are 3 zones (2 bits) and this leaves 8-2=6 bits for nodes. */ #define MAX_NODES_SHIFT 6 +#elif BITS_PER_LONG == 64 +/* + * with 64 bit flags field, there's plenty of room. + */ +#define MAX_NODES_SHIFT 10 +#endif #endif /* !CONFIG_DISCONTIGMEM */ diff --git a/include/linux/numa.h b/include/linux/numa.h new file mode 100644 index 000000000000..bd0c8c4e9a95 --- /dev/null +++ b/include/linux/numa.h @@ -0,0 +1,16 @@ +#ifndef _LINUX_NUMA_H +#define _LINUX_NUMA_H + +#include + +#ifdef CONFIG_DISCONTIGMEM +#include +#endif + +#ifndef NODES_SHIFT +#define NODES_SHIFT 0 +#endif + +#define MAX_NUMNODES (1 << NODES_SHIFT) + +#endif /* _LINUX_NUMA_H */ -- cgit v1.2.3 From f7719648b03199c9131b2aaca6eed193252143b6 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 4 Oct 2003 21:03:00 -0700 Subject: [PATCH] compat ioctl consolidation From: Arun Sharma , kevin.tian@intel.com Move a whole bunch of filesystem ioctl conversion functions out of per-arch files and into fs/compat_ioctl.c It moves linux32_dirent to compat.h and renames it as compat_dirent. linux32_dirent has been eliminated from ia64. Other archs should do the same. We'll leave old_linux_dirent32 as is, since it seems to be arch specific (ia64 doesn't use it for example). --- arch/ia64/ia32/ia32_ioctl.c | 34 --- arch/ia64/ia32/ia32priv.h | 7 - arch/ia64/ia32/sys_ia32.c | 10 +- arch/ppc64/kernel/ioctl32.c | 399 ---------------------------- arch/sparc64/kernel/ioctl32.c | 407 ----------------------------- arch/x86_64/ia32/ia32_ioctl.c | 526 ------------------------------------- fs/compat_ioctl.c | 585 +++++++++++++++++++++++++++++++++++++++++- include/linux/compat.h | 7 + 8 files changed, 596 insertions(+), 1379 deletions(-) diff --git a/arch/ia64/ia32/ia32_ioctl.c b/arch/ia64/ia32/ia32_ioctl.c index 2772de29bf52..4336c9a44be0 100644 --- a/arch/ia64/ia32/ia32_ioctl.c +++ b/arch/ia64/ia32/ia32_ioctl.c @@ -26,43 +26,11 @@ _ret; \ }) -#define P(i) ((void *)(unsigned long)(i)) - asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); #define CODE #include "compat_ioctl.c" -#define VFAT_IOCTL_READDIR_BOTH32 _IOR('r', 1, struct linux32_dirent[2]) -#define VFAT_IOCTL_READDIR_SHORT32 _IOR('r', 2, struct linux32_dirent[2]) - -static long -put_dirent32 (struct dirent *d, struct linux32_dirent *d32) -{ - size_t namelen = strlen(d->d_name); - - return (put_user(d->d_ino, &d32->d_ino) - || put_user(d->d_off, &d32->d_off) - || put_user(d->d_reclen, &d32->d_reclen) - || copy_to_user(d32->d_name, d->d_name, namelen + 1)); -} - -static int vfat_ioctl32(unsigned fd, unsigned cmd, void *ptr) -{ - int ret; - mm_segment_t oldfs = get_fs(); - struct dirent d[2]; - - set_fs(KERNEL_DS); - ret = sys_ioctl(fd,cmd,(unsigned long)&d); - set_fs(oldfs); - if (!ret) { - ret |= put_dirent32(&d[0], (struct linux32_dirent *)ptr); - ret |= put_dirent32(&d[1], ((struct linux32_dirent *)ptr) + 1); - } - return ret; -} - typedef int (* ioctl32_handler_t)(unsigned int, unsigned int, unsigned long, struct file *); #define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd),sys_ioctl) @@ -73,8 +41,6 @@ typedef int (* ioctl32_handler_t)(unsigned int, unsigned int, unsigned long, str }; IOCTL_TABLE_START -HANDLE_IOCTL(VFAT_IOCTL_READDIR_BOTH32, vfat_ioctl32) -HANDLE_IOCTL(VFAT_IOCTL_READDIR_SHORT32, vfat_ioctl32) #define DECLARES #include "compat_ioctl.c" #include diff --git a/arch/ia64/ia32/ia32priv.h b/arch/ia64/ia32/ia32priv.h index b1507602c842..83c0dd520f83 100644 --- a/arch/ia64/ia32/ia32priv.h +++ b/arch/ia64/ia32/ia32priv.h @@ -249,13 +249,6 @@ typedef struct siginfo32 { } _sifields; } siginfo_t32; -struct linux32_dirent { - u32 d_ino; - u32 d_off; - u16 d_reclen; - char d_name[256]; -}; - struct old_linux32_dirent { u32 d_ino; u32 d_offset; diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c index dabc0880152b..71cea1bb7513 100644 --- a/arch/ia64/ia32/sys_ia32.c +++ b/arch/ia64/ia32/sys_ia32.c @@ -707,8 +707,8 @@ sys32_settimeofday (struct compat_timeval *tv, struct timezone *tz) } struct getdents32_callback { - struct linux32_dirent * current_dir; - struct linux32_dirent * previous; + struct compat_dirent * current_dir; + struct compat_dirent * previous; int count; int error; }; @@ -722,7 +722,7 @@ static int filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino, unsigned int d_type) { - struct linux32_dirent * dirent; + struct compat_dirent * dirent; struct getdents32_callback * buf = (struct getdents32_callback *) __buf; int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1, 4); @@ -748,10 +748,10 @@ filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino, } asmlinkage long -sys32_getdents (unsigned int fd, struct linux32_dirent *dirent, unsigned int count) +sys32_getdents (unsigned int fd, struct compat_dirent *dirent, unsigned int count) { struct file * file; - struct linux32_dirent * lastdirent; + struct compat_dirent * lastdirent; struct getdents32_callback buf; int error; diff --git a/arch/ppc64/kernel/ioctl32.c b/arch/ppc64/kernel/ioctl32.c index d3d4a8cb00fb..13aba6677d29 100644 --- a/arch/ppc64/kernel/ioctl32.c +++ b/arch/ppc64/kernel/ioctl32.c @@ -328,396 +328,6 @@ static int do_ncp_setprivatedata(unsigned int fd, unsigned int cmd, unsigned lon return err; } -struct usbdevfs_ctrltransfer32 { - __u8 bRequestType; - __u8 bRequest; - __u16 wValue; - __u16 wIndex; - __u16 wLength; - __u32 timeout; /* in milliseconds */ - __u32 data; -}; - -#define USBDEVFS_CONTROL32 _IOWR('U', 0, struct usbdevfs_ctrltransfer32) - -static int do_usbdevfs_control(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct usbdevfs_ctrltransfer kctrl; - struct usbdevfs_ctrltransfer32 *uctrl; - mm_segment_t old_fs; - __u32 udata; - void *uptr, *kptr; - int err; - - uctrl = (struct usbdevfs_ctrltransfer32 *) arg; - - if (copy_from_user(&kctrl, uctrl, - (sizeof(struct usbdevfs_ctrltransfer) - - sizeof(void *)))) - return -EFAULT; - - if (get_user(udata, &uctrl->data)) - return -EFAULT; - uptr = (void *) A(udata); - - /* In usbdevice_fs, it limits the control buffer to a page, - * for simplicity so do we. - */ - if (!uptr || kctrl.wLength > PAGE_SIZE) - return -EINVAL; - - kptr = (void *)__get_free_page(GFP_KERNEL); - - if ((kctrl.bRequestType & 0x80) == 0) { - err = -EFAULT; - if (copy_from_user(kptr, uptr, kctrl.wLength)) - goto out; - } - - kctrl.data = kptr; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_ioctl(fd, USBDEVFS_CONTROL, (unsigned long)&kctrl); - set_fs(old_fs); - - if (err >= 0 && - ((kctrl.bRequestType & 0x80) != 0)) { - if (copy_to_user(uptr, kptr, kctrl.wLength)) - err = -EFAULT; - } - -out: - free_page((unsigned long) kptr); - return err; -} - -struct usbdevfs_bulktransfer32 { - unsigned int ep; - unsigned int len; - unsigned int timeout; /* in milliseconds */ - __u32 data; -}; - -#define USBDEVFS_BULK32 _IOWR('U', 2, struct usbdevfs_bulktransfer32) - -static int do_usbdevfs_bulk(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct usbdevfs_bulktransfer kbulk; - struct usbdevfs_bulktransfer32 *ubulk; - mm_segment_t old_fs; - __u32 udata; - void *uptr, *kptr; - int err; - - ubulk = (struct usbdevfs_bulktransfer32 *) arg; - - if (get_user(kbulk.ep, &ubulk->ep) || - get_user(kbulk.len, &ubulk->len) || - get_user(kbulk.timeout, &ubulk->timeout) || - get_user(udata, &ubulk->data)) - return -EFAULT; - - uptr = (void *) A(udata); - - /* In usbdevice_fs, it limits the control buffer to a page, - * for simplicity so do we. - */ - if (!uptr || kbulk.len > PAGE_SIZE) - return -EINVAL; - - kptr = (void *) __get_free_page(GFP_KERNEL); - - if ((kbulk.ep & 0x80) == 0) { - err = -EFAULT; - if (copy_from_user(kptr, uptr, kbulk.len)) - goto out; - } - - kbulk.data = kptr; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_ioctl(fd, USBDEVFS_BULK, (unsigned long) &kbulk); - set_fs(old_fs); - - if (err >= 0 && - ((kbulk.ep & 0x80) != 0)) { - if (copy_to_user(uptr, kptr, kbulk.len)) - err = -EFAULT; - } - -out: - free_page((unsigned long) kptr); - return err; -} - -/* This needs more work before we can enable it. Unfortunately - * because of the fancy asynchronous way URB status/error is written - * back to userspace, we'll need to fiddle with USB devio internals - * and/or reimplement entirely the frontend of it ourselves. -DaveM - * - * The issue is: - * - * When an URB is submitted via usbdevicefs it is put onto an - * asynchronous queue. When the URB completes, it may be reaped - * via another ioctl. During this reaping the status is written - * back to userspace along with the length of the transfer. - * - * We must translate into 64-bit kernel types so we pass in a kernel - * space copy of the usbdevfs_urb structure. This would mean that we - * must do something to deal with the async entry reaping. First we - * have to deal somehow with this transitory memory we've allocated. - * This is problematic since there are many call sites from which the - * async entries can be destroyed (and thus when we'd need to free up - * this kernel memory). One of which is the close() op of usbdevicefs. - * To handle that we'd need to make our own file_operations struct which - * overrides usbdevicefs's release op with our own which runs usbdevicefs's - * real release op then frees up the kernel memory. - * - * But how to keep track of these kernel buffers? We'd need to either - * keep track of them in some table _or_ know about usbdevicefs internals - * (ie. the exact layout of its file private, which is actually defined - * in linux/usbdevice_fs.h, the layout of the async queues are private to - * devio.c) - * - * There is one possible other solution I considered, also involving knowledge - * of usbdevicefs internals: - * - * After an URB is submitted, we "fix up" the address back to the user - * space one. This would work if the status/length fields written back - * by the async URB completion lines up perfectly in the 32-bit type with - * the 64-bit kernel type. Unfortunately, it does not because the iso - * frame descriptors, at the end of the struct, can be written back. - * - * I think we'll just need to simply duplicate the devio URB engine here. - */ -#if 0 -struct usbdevfs_urb32 { - __u8 type; - __u8 endpoint; - __s32 status; - __u32 flags; - __u32 buffer; - __s32 buffer_length; - __s32 actual_length; - __s32 start_frame; - __s32 number_of_packets; - __s32 error_count; - __u32 signr; - __u32 usercontext; /* unused */ - struct usbdevfs_iso_packet_desc iso_frame_desc[0]; -}; - -#define USBDEVFS_SUBMITURB32 _IOR('U', 10, struct usbdevfs_urb32) - -static int get_urb32(struct usbdevfs_urb *kurb, - struct usbdevfs_urb32 *uurb) -{ - if (get_user(kurb->type, &uurb->type) || - __get_user(kurb->endpoint, &uurb->endpoint) || - __get_user(kurb->status, &uurb->status) || - __get_user(kurb->flags, &uurb->flags) || - __get_user(kurb->buffer_length, &uurb->buffer_length) || - __get_user(kurb->actual_length, &uurb->actual_length) || - __get_user(kurb->start_frame, &uurb->start_frame) || - __get_user(kurb->number_of_packets, &uurb->number_of_packets) || - __get_user(kurb->error_count, &uurb->error_count) || - __get_user(kurb->signr, &uurb->signr)) - return -EFAULT; - - kurb->usercontext = 0; /* unused currently */ - - return 0; -} - -/* Just put back the values which usbdevfs actually changes. */ -static int put_urb32(struct usbdevfs_urb *kurb, - struct usbdevfs_urb32 *uurb) -{ - if (put_user(kurb->status, &uurb->status) || - __put_user(kurb->actual_length, &uurb->actual_length) || - __put_user(kurb->error_count, &uurb->error_count)) - return -EFAULT; - - if (kurb->number_of_packets != 0) { - int i; - - for (i = 0; i < kurb->number_of_packets; i++) { - if (__put_user(kurb->iso_frame_desc[i].actual_length, - &uurb->iso_frame_desc[i].actual_length) || - __put_user(kurb->iso_frame_desc[i].status, - &uurb->iso_frame_desc[i].status)) - return -EFAULT; - } - } - - return 0; -} - -static int get_urb32_isoframes(struct usbdevfs_urb *kurb, - struct usbdevfs_urb32 *uurb) -{ - unsigned int totlen; - int i; - - if (kurb->type != USBDEVFS_URB_TYPE_ISO) { - kurb->number_of_packets = 0; - return 0; - } - - if (kurb->number_of_packets < 1 || - kurb->number_of_packets > 128) - return -EINVAL; - - if (copy_from_user(&kurb->iso_frame_desc[0], - &uurb->iso_frame_desc[0], - sizeof(struct usbdevfs_iso_packet_desc) * - kurb->number_of_packets)) - return -EFAULT; - - totlen = 0; - for (i = 0; i < kurb->number_of_packets; i++) { - unsigned int this_len; - - this_len = kurb->iso_frame_desc[i].length; - if (this_len > 1023) - return -EINVAL; - - totlen += this_len; - } - - if (totlen > 32768) - return -EINVAL; - - kurb->buffer_length = totlen; - - return 0; -} - -static int do_usbdevfs_urb(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct usbdevfs_urb *kurb; - struct usbdevfs_urb32 *uurb; - mm_segment_t old_fs; - __u32 udata; - void *uptr, *kptr; - unsigned int buflen; - int err; - - uurb = (struct usbdevfs_urb32 *) arg; - - err = -ENOMEM; - kurb = kmalloc(sizeof(struct usbdevfs_urb) + - (sizeof(struct usbdevfs_iso_packet_desc) * 128), - GFP_KERNEL); - if (!kurb) - goto out; - - err = -EFAULT; - if (get_urb32(kurb, uurb)) - goto out; - - err = get_urb32_isoframes(kurb, uurb); - if (err) - goto out; - - err = -EFAULT; - if (__get_user(udata, &uurb->buffer)) - goto out; - uptr = (void *) A(udata); - - err = -ENOMEM; - buflen = kurb->buffer_length; - kptr = kmalloc(buflen, GFP_KERNEL); - if (!kptr) - goto out; - - kurb->buffer = kptr; - - err = -EFAULT; - if (copy_from_user(kptr, uptr, buflen)) - goto out_kptr; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_ioctl(fd, USBDEVFS_SUBMITURB, (unsigned long) kurb); - set_fs(old_fs); - - if (err >= 0) { - /* XXX Shit, this doesn't work for async URBs :-( XXX */ - if (put_urb32(kurb, uurb)) { - err = -EFAULT; - } else if ((kurb->endpoint & USB_DIR_IN) != 0) { - if (copy_to_user(uptr, kptr, buflen)) - err = -EFAULT; - } - } - -out_kptr: - kfree(kptr); - -out: - kfree(kurb); - return err; -} -#endif - -#define USBDEVFS_REAPURB32 _IOW('U', 12, u32) -#define USBDEVFS_REAPURBNDELAY32 _IOW('U', 13, u32) - -static int do_usbdevfs_reapurb(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs; - void *kptr; - int err; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_ioctl(fd, - (cmd == USBDEVFS_REAPURB32 ? - USBDEVFS_REAPURB : - USBDEVFS_REAPURBNDELAY), - (unsigned long) &kptr); - set_fs(old_fs); - - if (err >= 0 && - put_user(((u32)(long)kptr), (u32 *) A(arg))) - err = -EFAULT; - - return err; -} - -struct usbdevfs_disconnectsignal32 { - unsigned int signr; - u32 context; -}; - -#define USBDEVFS_DISCSIGNAL32 _IOR('U', 14, struct usbdevfs_disconnectsignal32) - -static int do_usbdevfs_discsignal(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct usbdevfs_disconnectsignal kdis; - struct usbdevfs_disconnectsignal32 *udis; - mm_segment_t old_fs; - u32 uctx; - int err; - - udis = (struct usbdevfs_disconnectsignal32 *) arg; - - if (get_user(kdis.signr, &udis->signr) || - __get_user(uctx, &udis->context)) - return -EFAULT; - - kdis.context = (void *) (long)uctx; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_ioctl(fd, USBDEVFS_DISCSIGNAL, (unsigned long) &kdis); - set_fs(old_fs); - - return err; -} #define HANDLE_IOCTL(cmd,handler) { cmd, (ioctl_trans_handler_t)handler, 0 }, #define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd,sys_ioctl) @@ -734,8 +344,6 @@ IOCTL_TABLE_START COMPATIBLE_IOCTL(TCSBRKP) COMPATIBLE_IOCTL(TIOCSTART) COMPATIBLE_IOCTL(TIOCSTOP) -COMPATIBLE_IOCTL(TIOCGSERIAL) -COMPATIBLE_IOCTL(TIOCSSERIAL) COMPATIBLE_IOCTL(TIOCSLTC) #if 0 COMPATIBLE_IOCTL(FBIOBLANK) @@ -755,13 +363,6 @@ HANDLE_IOCTL(NCP_IOC_SETOBJECTNAME_32, do_ncp_setobjectname) HANDLE_IOCTL(NCP_IOC_GETPRIVATEDATA_32, do_ncp_getprivatedata) HANDLE_IOCTL(NCP_IOC_SETPRIVATEDATA_32, do_ncp_setprivatedata) -/* USB devfs */ -HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control) -HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk) -/*HANDLE_IOCTL(USBDEVFS_SUBMITURB32, do_usbdevfs_urb)*/ -HANDLE_IOCTL(USBDEVFS_REAPURB32, do_usbdevfs_reapurb) -HANDLE_IOCTL(USBDEVFS_REAPURBNDELAY32, do_usbdevfs_reapurb) -HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal) IOCTL_TABLE_END int ioctl_table_size = ARRAY_SIZE(ioctl_start); diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index dcbe443edc41..016f005cf1a1 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -985,402 +985,6 @@ static int drm32_res_ctx(unsigned int fd, unsigned int cmd, unsigned long arg) #endif -/* HERE! */ - -struct usbdevfs_ctrltransfer32 { - __u8 bRequestType; - __u8 bRequest; - __u16 wValue; - __u16 wIndex; - __u16 wLength; - __u32 timeout; /* in milliseconds */ - __u32 data; -}; - -#define USBDEVFS_CONTROL32 _IOWR('U', 0, struct usbdevfs_ctrltransfer32) - -static int do_usbdevfs_control(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct usbdevfs_ctrltransfer kctrl; - struct usbdevfs_ctrltransfer32 *uctrl; - mm_segment_t old_fs; - __u32 udata; - void __user *uptr; - void *kptr; - int err; - - uctrl = (struct usbdevfs_ctrltransfer32 *) arg; - - if (copy_from_user(&kctrl, uctrl, - (sizeof(struct usbdevfs_ctrltransfer) - - sizeof(void *)))) - return -EFAULT; - - if (get_user(udata, &uctrl->data)) - return -EFAULT; - uptr = A(udata); - - /* In usbdevice_fs, it limits the control buffer to a page, - * for simplicity so do we. - */ - if (!uptr || kctrl.wLength > PAGE_SIZE) - return -EINVAL; - - kptr = (void *)__get_free_page(GFP_KERNEL); - - if ((kctrl.bRequestType & 0x80) == 0) { - err = -EFAULT; - if (copy_from_user(kptr, uptr, kctrl.wLength)) - goto out; - } - - kctrl.data = kptr; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_ioctl(fd, USBDEVFS_CONTROL, (unsigned long)&kctrl); - set_fs(old_fs); - - if (err >= 0 && - ((kctrl.bRequestType & 0x80) != 0)) { - if (copy_to_user(uptr, kptr, kctrl.wLength)) - err = -EFAULT; - } - -out: - free_page((unsigned long) kptr); - return err; -} - -struct usbdevfs_bulktransfer32 { - unsigned int ep; - unsigned int len; - unsigned int timeout; /* in milliseconds */ - __u32 data; -}; - -#define USBDEVFS_BULK32 _IOWR('U', 2, struct usbdevfs_bulktransfer32) - -static int do_usbdevfs_bulk(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct usbdevfs_bulktransfer kbulk; - struct usbdevfs_bulktransfer32 *ubulk; - mm_segment_t old_fs; - __u32 udata; - void __user *uptr; - void *kptr; - int err; - - ubulk = (struct usbdevfs_bulktransfer32 *) arg; - - if (get_user(kbulk.ep, &ubulk->ep) || - get_user(kbulk.len, &ubulk->len) || - get_user(kbulk.timeout, &ubulk->timeout) || - get_user(udata, &ubulk->data)) - return -EFAULT; - - uptr = A(udata); - - /* In usbdevice_fs, it limits the control buffer to a page, - * for simplicity so do we. - */ - if (!uptr || kbulk.len > PAGE_SIZE) - return -EINVAL; - - kptr = (void *) __get_free_page(GFP_KERNEL); - - if ((kbulk.ep & 0x80) == 0) { - err = -EFAULT; - if (copy_from_user(kptr, uptr, kbulk.len)) - goto out; - } - - kbulk.data = kptr; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_ioctl(fd, USBDEVFS_BULK, (unsigned long) &kbulk); - set_fs(old_fs); - - if (err >= 0 && - ((kbulk.ep & 0x80) != 0)) { - if (copy_to_user(uptr, kptr, kbulk.len)) - err = -EFAULT; - } - -out: - free_page((unsigned long) kptr); - return err; -} - -/* This needs more work before we can enable it. Unfortunately - * because of the fancy asynchronous way URB status/error is written - * back to userspace, we'll need to fiddle with USB devio internals - * and/or reimplement entirely the frontend of it ourselves. -DaveM - * - * The issue is: - * - * When an URB is submitted via usbdevicefs it is put onto an - * asynchronous queue. When the URB completes, it may be reaped - * via another ioctl. During this reaping the status is written - * back to userspace along with the length of the transfer. - * - * We must translate into 64-bit kernel types so we pass in a kernel - * space copy of the usbdevfs_urb structure. This would mean that we - * must do something to deal with the async entry reaping. First we - * have to deal somehow with this transitory memory we've allocated. - * This is problematic since there are many call sites from which the - * async entries can be destroyed (and thus when we'd need to free up - * this kernel memory). One of which is the close() op of usbdevicefs. - * To handle that we'd need to make our own file_operations struct which - * overrides usbdevicefs's release op with our own which runs usbdevicefs's - * real release op then frees up the kernel memory. - * - * But how to keep track of these kernel buffers? We'd need to either - * keep track of them in some table _or_ know about usbdevicefs internals - * (ie. the exact layout of its file private, which is actually defined - * in linux/usbdevice_fs.h, the layout of the async queues are private to - * devio.c) - * - * There is one possible other solution I considered, also involving knowledge - * of usbdevicefs internals: - * - * After an URB is submitted, we "fix up" the address back to the user - * space one. This would work if the status/length fields written back - * by the async URB completion lines up perfectly in the 32-bit type with - * the 64-bit kernel type. Unfortunately, it does not because the iso - * frame descriptors, at the end of the struct, can be written back. - * - * I think we'll just need to simply duplicate the devio URB engine here. - */ -#if 0 -struct usbdevfs_urb32 { - __u8 type; - __u8 endpoint; - __s32 status; - __u32 flags; - __u32 buffer; - __s32 buffer_length; - __s32 actual_length; - __s32 start_frame; - __s32 number_of_packets; - __s32 error_count; - __u32 signr; - __u32 usercontext; /* unused */ - struct usbdevfs_iso_packet_desc iso_frame_desc[0]; -}; - -#define USBDEVFS_SUBMITURB32 _IOR('U', 10, struct usbdevfs_urb32) - -static int get_urb32(struct usbdevfs_urb *kurb, - struct usbdevfs_urb32 *uurb) -{ - if (get_user(kurb->type, &uurb->type) || - __get_user(kurb->endpoint, &uurb->endpoint) || - __get_user(kurb->status, &uurb->status) || - __get_user(kurb->flags, &uurb->flags) || - __get_user(kurb->buffer_length, &uurb->buffer_length) || - __get_user(kurb->actual_length, &uurb->actual_length) || - __get_user(kurb->start_frame, &uurb->start_frame) || - __get_user(kurb->number_of_packets, &uurb->number_of_packets) || - __get_user(kurb->error_count, &uurb->error_count) || - __get_user(kurb->signr, &uurb->signr)) - return -EFAULT; - - kurb->usercontext = 0; /* unused currently */ - - return 0; -} - -/* Just put back the values which usbdevfs actually changes. */ -static int put_urb32(struct usbdevfs_urb *kurb, - struct usbdevfs_urb32 *uurb) -{ - if (put_user(kurb->status, &uurb->status) || - __put_user(kurb->actual_length, &uurb->actual_length) || - __put_user(kurb->error_count, &uurb->error_count)) - return -EFAULT; - - if (kurb->number_of_packets != 0) { - int i; - - for (i = 0; i < kurb->number_of_packets; i++) { - if (__put_user(kurb->iso_frame_desc[i].actual_length, - &uurb->iso_frame_desc[i].actual_length) || - __put_user(kurb->iso_frame_desc[i].status, - &uurb->iso_frame_desc[i].status)) - return -EFAULT; - } - } - - return 0; -} - -static int get_urb32_isoframes(struct usbdevfs_urb *kurb, - struct usbdevfs_urb32 *uurb) -{ - unsigned int totlen; - int i; - - if (kurb->type != USBDEVFS_URB_TYPE_ISO) { - kurb->number_of_packets = 0; - return 0; - } - - if (kurb->number_of_packets < 1 || - kurb->number_of_packets > 128) - return -EINVAL; - - if (copy_from_user(&kurb->iso_frame_desc[0], - &uurb->iso_frame_desc[0], - sizeof(struct usbdevfs_iso_packet_desc) * - kurb->number_of_packets)) - return -EFAULT; - - totlen = 0; - for (i = 0; i < kurb->number_of_packets; i++) { - unsigned int this_len; - - this_len = kurb->iso_frame_desc[i].length; - if (this_len > 1023) - return -EINVAL; - - totlen += this_len; - } - - if (totlen > 32768) - return -EINVAL; - - kurb->buffer_length = totlen; - - return 0; -} - -static int do_usbdevfs_urb(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct usbdevfs_urb *kurb; - struct usbdevfs_urb32 *uurb; - mm_segment_t old_fs; - __u32 udata; - void __user *uptr; - void *kptr; - unsigned int buflen; - int err; - - uurb = (struct usbdevfs_urb32 *) arg; - - err = -ENOMEM; - kurb = kmalloc(sizeof(struct usbdevfs_urb) + - (sizeof(struct usbdevfs_iso_packet_desc) * 128), - GFP_KERNEL); - if (!kurb) - goto out; - - err = -EFAULT; - if (get_urb32(kurb, uurb)) - goto out; - - err = get_urb32_isoframes(kurb, uurb); - if (err) - goto out; - - err = -EFAULT; - if (__get_user(udata, &uurb->buffer)) - goto out; - uptr = A(udata); - - err = -ENOMEM; - buflen = kurb->buffer_length; - kptr = kmalloc(buflen, GFP_KERNEL); - if (!kptr) - goto out; - - kurb->buffer = kptr; - - err = -EFAULT; - if (copy_from_user(kptr, uptr, buflen)) - goto out_kptr; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_ioctl(fd, USBDEVFS_SUBMITURB, (unsigned long) kurb); - set_fs(old_fs); - - if (err >= 0) { - /* XXX Shit, this doesn't work for async URBs :-( XXX */ - if (put_urb32(kurb, uurb)) { - err = -EFAULT; - } else if ((kurb->endpoint & USB_DIR_IN) != 0) { - if (copy_to_user(uptr, kptr, buflen)) - err = -EFAULT; - } - } - -out_kptr: - kfree(kptr); - -out: - kfree(kurb); - return err; -} -#endif - -#define USBDEVFS_REAPURB32 _IOW('U', 12, u32) -#define USBDEVFS_REAPURBNDELAY32 _IOW('U', 13, u32) - -static int do_usbdevfs_reapurb(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs; - void *kptr; - int err; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_ioctl(fd, - (cmd == USBDEVFS_REAPURB32 ? - USBDEVFS_REAPURB : - USBDEVFS_REAPURBNDELAY), - (unsigned long) &kptr); - set_fs(old_fs); - - if (err >= 0 && - put_user(((u32)(long)kptr), (u32 __user *) A(arg))) - err = -EFAULT; - - return err; -} - -struct usbdevfs_disconnectsignal32 { - unsigned int signr; - u32 context; -}; - -#define USBDEVFS_DISCSIGNAL32 _IOR('U', 14, struct usbdevfs_disconnectsignal32) - -static int do_usbdevfs_discsignal(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct usbdevfs_disconnectsignal kdis; - struct usbdevfs_disconnectsignal32 *udis; - mm_segment_t old_fs; - u32 uctx; - int err; - - udis = (struct usbdevfs_disconnectsignal32 *) arg; - - if (get_user(kdis.signr, &udis->signr) || - __get_user(uctx, &udis->context)) - return -EFAULT; - - kdis.context = (void *) (long)uctx; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_ioctl(fd, USBDEVFS_DISCSIGNAL, (unsigned long) &kdis); - set_fs(old_fs); - - return err; -} - typedef int (* ioctl32_handler_t)(unsigned int, unsigned int, unsigned long, struct file *); #define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd),sys_ioctl) @@ -1397,8 +1001,6 @@ IOCTL_TABLE_START COMPATIBLE_IOCTL(TCSBRKP) COMPATIBLE_IOCTL(TIOCSTART) COMPATIBLE_IOCTL(TIOCSTOP) -COMPATIBLE_IOCTL(TIOCGSERIAL) -COMPATIBLE_IOCTL(TIOCSSERIAL) COMPATIBLE_IOCTL(TIOCSLTC) COMPATIBLE_IOCTL(FBIOGTYPE) COMPATIBLE_IOCTL(FBIOSATTR) @@ -1467,9 +1069,6 @@ COMPATIBLE_IOCTL(AUDIO_GETDEV) COMPATIBLE_IOCTL(AUDIO_GETDEV_SUNOS) COMPATIBLE_IOCTL(AUDIO_FLUSH) COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE_MULTI) -/* Raw devices */ -COMPATIBLE_IOCTL(RAW_SETBIND) -COMPATIBLE_IOCTL(RAW_GETBIND) /* NCP ioctls which do not need any translations */ COMPATIBLE_IOCTL(NCP_IOC_CONN_LOGGED_IN) COMPATIBLE_IOCTL(NCP_IOC_SIGN_INIT) @@ -1575,12 +1174,6 @@ HANDLE_IOCTL(RTC32_IRQP_SET, do_rtc_ioctl) HANDLE_IOCTL(RTC32_EPOCH_READ, do_rtc_ioctl) HANDLE_IOCTL(RTC32_EPOCH_SET, do_rtc_ioctl) #endif -HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control) -HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk) -/*HANDLE_IOCTL(USBDEVFS_SUBMITURB32, do_usbdevfs_urb)*/ -HANDLE_IOCTL(USBDEVFS_REAPURB32, do_usbdevfs_reapurb) -HANDLE_IOCTL(USBDEVFS_REAPURBNDELAY32, do_usbdevfs_reapurb) -HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal) /* take care of sizeof(sizeof()) breakage */ IOCTL_TABLE_END diff --git a/arch/x86_64/ia32/ia32_ioctl.c b/arch/x86_64/ia32/ia32_ioctl.c index 517da783c616..5a1a65e4e634 100644 --- a/arch/x86_64/ia32/ia32_ioctl.c +++ b/arch/x86_64/ia32/ia32_ioctl.c @@ -38,87 +38,6 @@ static int tiocgdev(unsigned fd, unsigned cmd, unsigned int *ptr) return put_user(new_encode_dev(tty_devnum(real_tty)), ptr); } - -struct raw32_config_request -{ - compat_int_t raw_minor; - __u64 block_major; - __u64 block_minor; -} __attribute__((packed)); - -static int raw_ioctl(unsigned fd, unsigned cmd, void *ptr) -{ - int ret; - switch (cmd) { - case RAW_SETBIND: - case RAW_GETBIND: { - struct raw_config_request req; - struct raw32_config_request *user_req = ptr; - mm_segment_t oldfs = get_fs(); - - if (get_user(req.raw_minor, &user_req->raw_minor) || - get_user(req.block_major, &user_req->block_major) || - get_user(req.block_minor, &user_req->block_minor)) - return -EFAULT; - set_fs(KERNEL_DS); - ret = sys_ioctl(fd,cmd,(unsigned long)&req); - set_fs(oldfs); - break; - } - default: - ret = sys_ioctl(fd,cmd,(unsigned long)ptr); - break; - } - return ret; -} - - -#define REISERFS_IOC_UNPACK32 _IOW(0xCD,1,int) - -static int reiserfs_ioctl32(unsigned fd, unsigned cmd, unsigned long ptr) -{ - if (cmd == REISERFS_IOC_UNPACK32) - cmd = REISERFS_IOC_UNPACK; - return sys_ioctl(fd,cmd,ptr); -} - -struct dirent32 { - compat_int_t d_ino; - compat_off_t d_off; - unsigned short d_reclen; - char d_name[256]; /* We must not include limits.h! */ -}; - -#define VFAT_IOCTL_READDIR_BOTH32 _IOR('r', 1, struct dirent32 [2]) -#define VFAT_IOCTL_READDIR_SHORT32 _IOR('r', 2, struct dirent32 [2]) - -static int put_dirent32(struct dirent *src, struct dirent32 *dst) -{ - int ret; - ret = put_user(src->d_ino, &dst->d_ino); - ret |= __put_user(src->d_off, &dst->d_off); - ret |= __put_user(src->d_reclen, &dst->d_reclen); - if (__copy_to_user(&dst->d_name, src->d_name, src->d_reclen)) - ret |= -EFAULT; - return ret; -} - -static int vfat_ioctl32(unsigned fd, unsigned cmd, void *ptr) -{ - int ret; - mm_segment_t oldfs = get_fs(); - struct dirent d[2]; - - set_fs(KERNEL_DS); - ret = sys_ioctl(fd,cmd,(unsigned long)&d); - set_fs(oldfs); - if (!ret) { - ret |= put_dirent32(&d[0], (struct dirent32 *)ptr); - ret |= put_dirent32(&d[1], ((struct dirent32 *)ptr) + 1); - } - return ret; -} - #define RTC_IRQP_READ32 _IOR('p', 0x0b, unsigned int) /* Read IRQ rate */ #define RTC_IRQP_SET32 _IOW('p', 0x0c, unsigned int) /* Set IRQ rate */ #define RTC_EPOCH_READ32 _IOR('p', 0x0d, unsigned) /* Read epoch */ @@ -158,436 +77,6 @@ static int rtc32_ioctl(unsigned fd, unsigned cmd, unsigned long arg) return sys_ioctl(fd,cmd,arg); } -struct serial_struct32 { - compat_int_t type; - compat_int_t line; - compat_uint_t port; - compat_int_t irq; - compat_int_t flags; - compat_int_t xmit_fifo_size; - compat_int_t custom_divisor; - compat_int_t baud_base; - unsigned short close_delay; - char io_type; - char reserved_char[1]; - compat_int_t hub6; - unsigned short closing_wait; /* time to wait before closing */ - unsigned short closing_wait2; /* no longer used... */ - compat_uint_t iomem_base; - unsigned short iomem_reg_shift; - unsigned int port_high; - compat_int_t reserved[1]; -}; - -static int serial_struct_ioctl(unsigned fd, unsigned cmd, void *ptr) -{ - typedef struct serial_struct SS; - struct serial_struct32 *ss32 = ptr; - int err; - struct serial_struct ss; - mm_segment_t oldseg = get_fs(); - if (cmd == TIOCSSERIAL) { - if (copy_from_user(&ss, ss32, sizeof(struct serial_struct32))) - return -EFAULT; - memmove(&ss.iomem_reg_shift, ((char*)&ss.iomem_base)+4, - sizeof(SS)-offsetof(SS,iomem_reg_shift)); - ss.iomem_base = (void *)((unsigned long)ss.iomem_base & 0xffffffff); - } - set_fs(KERNEL_DS); - err = sys_ioctl(fd,cmd,(unsigned long)(&ss)); - set_fs(oldseg); - if (cmd == TIOCGSERIAL && err >= 0) { - if (__copy_to_user(ss32,&ss,offsetof(SS,iomem_base)) || - __put_user((unsigned long)ss.iomem_base >> 32 ? - 0xffffffff : (unsigned)(unsigned long)ss.iomem_base, - &ss32->iomem_base) || - __put_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift) || - __put_user(ss.port_high, &ss32->port_high)) - return -EFAULT; - } - return err; -} - - - -struct usbdevfs_ctrltransfer32 { - u8 bRequestType; - u8 bRequest; - u16 wValue; - u16 wIndex; - u16 wLength; - u32 timeout; /* in milliseconds */ - compat_caddr_t data; -}; - -#define USBDEVFS_CONTROL32 _IOWR('U', 0, struct usbdevfs_ctrltransfer32) - -static int do_usbdevfs_control(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct usbdevfs_ctrltransfer kctrl; - struct usbdevfs_ctrltransfer32 *uctrl; - mm_segment_t old_fs; - __u32 udata; - void *uptr, *kptr; - int err; - - uctrl = (struct usbdevfs_ctrltransfer32 *) arg; - - if (copy_from_user(&kctrl, uctrl, - (sizeof(struct usbdevfs_ctrltransfer) - - sizeof(void *)))) - return -EFAULT; - - if (get_user(udata, &uctrl->data)) - return -EFAULT; - uptr = compat_ptr(udata); - - /* In usbdevice_fs, it limits the control buffer to a page, - * for simplicity so do we. - */ - if (!uptr || kctrl.wLength > PAGE_SIZE) - return -EINVAL; - - kptr = (void *)__get_free_page(GFP_KERNEL); - - if ((kctrl.bRequestType & 0x80) == 0) { - err = -EFAULT; - if (copy_from_user(kptr, uptr, kctrl.wLength)) - goto out; - } - - kctrl.data = kptr; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_ioctl(fd, USBDEVFS_CONTROL, (unsigned long)&kctrl); - set_fs(old_fs); - - if (err >= 0 && - ((kctrl.bRequestType & 0x80) != 0)) { - if (copy_to_user(uptr, kptr, kctrl.wLength)) - err = -EFAULT; - } - -out: - free_page((unsigned long) kptr); - return err; -} - -struct usbdevfs_bulktransfer32 { - compat_uint_t ep; - compat_uint_t len; - compat_uint_t timeout; /* in milliseconds */ - compat_caddr_t data; -}; - -#define USBDEVFS_BULK32 _IOWR('U', 2, struct usbdevfs_bulktransfer32) - -static int do_usbdevfs_bulk(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct usbdevfs_bulktransfer kbulk; - struct usbdevfs_bulktransfer32 *ubulk; - mm_segment_t old_fs; - __u32 udata; - void *uptr, *kptr; - int err; - - ubulk = (struct usbdevfs_bulktransfer32 *) arg; - - if (get_user(kbulk.ep, &ubulk->ep) || - get_user(kbulk.len, &ubulk->len) || - get_user(kbulk.timeout, &ubulk->timeout) || - get_user(udata, &ubulk->data)) - return -EFAULT; - - uptr = compat_ptr(udata); - - /* In usbdevice_fs, it limits the control buffer to a page, - * for simplicity so do we. - */ - if (!uptr || kbulk.len > PAGE_SIZE) - return -EINVAL; - - kptr = (void *) __get_free_page(GFP_KERNEL); - - if ((kbulk.ep & 0x80) == 0) { - err = -EFAULT; - if (copy_from_user(kptr, uptr, kbulk.len)) - goto out; - } - - kbulk.data = kptr; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_ioctl(fd, USBDEVFS_BULK, (unsigned long) &kbulk); - set_fs(old_fs); - - if (err >= 0 && - ((kbulk.ep & 0x80) != 0)) { - if (copy_to_user(uptr, kptr, kbulk.len)) - err = -EFAULT; - } - -out: - free_page((unsigned long) kptr); - return err; -} - -/* This needs more work before we can enable it. Unfortunately - * because of the fancy asynchronous way URB status/error is written - * back to userspace, we'll need to fiddle with USB devio internals - * and/or reimplement entirely the frontend of it ourselves. -DaveM - * - * The issue is: - * - * When an URB is submitted via usbdevicefs it is put onto an - * asynchronous queue. When the URB completes, it may be reaped - * via another ioctl. During this reaping the status is written - * back to userspace along with the length of the transfer. - * - * We must translate into 64-bit kernel types so we pass in a kernel - * space copy of the usbdevfs_urb structure. This would mean that we - * must do something to deal with the async entry reaping. First we - * have to deal somehow with this transitory memory we've allocated. - * This is problematic since there are many call sites from which the - * async entries can be destroyed (and thus when we'd need to free up - * this kernel memory). One of which is the close() op of usbdevicefs. - * To handle that we'd need to make our own file_operations struct which - * overrides usbdevicefs's release op with our own which runs usbdevicefs's - * real release op then frees up the kernel memory. - * - * But how to keep track of these kernel buffers? We'd need to either - * keep track of them in some table _or_ know about usbdevicefs internals - * (ie. the exact layout of its file private, which is actually defined - * in linux/usbdevice_fs.h, the layout of the async queues are private to - * devio.c) - * - * There is one possible other solution I considered, also involving knowledge - * of usbdevicefs internals: - * - * After an URB is submitted, we "fix up" the address back to the user - * space one. This would work if the status/length fields written back - * by the async URB completion lines up perfectly in the 32-bit type with - * the 64-bit kernel type. Unfortunately, it does not because the iso - * frame descriptors, at the end of the struct, can be written back. - * - * I think we'll just need to simply duplicate the devio URB engine here. - */ -#if 0 -struct usbdevfs_urb32 { - unsigned char type; - unsigned char endpoint; - compat_int_t status; - compat_uint_t flags; - compat_caddr_t buffer; - compat_int_t buffer_length; - compat_int_t actual_length; - compat_int_t start_frame; - compat_int_t number_of_packets; - compat_int_t error_count; - compat_uint_t signr; - compat_caddr_t usercontext; /* unused */ - struct usbdevfs_iso_packet_desc iso_frame_desc[0]; -}; - -#define USBDEVFS_SUBMITURB32 _IOR('U', 10, struct usbdevfs_urb32) - -static int get_urb32(struct usbdevfs_urb *kurb, - struct usbdevfs_urb32 *uurb) -{ - if (get_user(kurb->type, &uurb->type) || - __get_user(kurb->endpoint, &uurb->endpoint) || - __get_user(kurb->status, &uurb->status) || - __get_user(kurb->flags, &uurb->flags) || - __get_user(kurb->buffer_length, &uurb->buffer_length) || - __get_user(kurb->actual_length, &uurb->actual_length) || - __get_user(kurb->start_frame, &uurb->start_frame) || - __get_user(kurb->number_of_packets, &uurb->number_of_packets) || - __get_user(kurb->error_count, &uurb->error_count) || - __get_user(kurb->signr, &uurb->signr)) - return -EFAULT; - - kurb->usercontext = 0; /* unused currently */ - - return 0; -} - -/* Just put back the values which usbdevfs actually changes. */ -static int put_urb32(struct usbdevfs_urb *kurb, - struct usbdevfs_urb32 *uurb) -{ - if (put_user(kurb->status, &uurb->status) || - __put_user(kurb->actual_length, &uurb->actual_length) || - __put_user(kurb->error_count, &uurb->error_count)) - return -EFAULT; - - if (kurb->number_of_packets != 0) { - int i; - - for (i = 0; i < kurb->number_of_packets; i++) { - if (__put_user(kurb->iso_frame_desc[i].actual_length, - &uurb->iso_frame_desc[i].actual_length) || - __put_user(kurb->iso_frame_desc[i].status, - &uurb->iso_frame_desc[i].status)) - return -EFAULT; - } - } - - return 0; -} - -static int get_urb32_isoframes(struct usbdevfs_urb *kurb, - struct usbdevfs_urb32 *uurb) -{ - unsigned int totlen; - int i; - - if (kurb->type != USBDEVFS_URB_TYPE_ISO) { - kurb->number_of_packets = 0; - return 0; - } - - if (kurb->number_of_packets < 1 || - kurb->number_of_packets > 128) - return -EINVAL; - - if (copy_from_user(&kurb->iso_frame_desc[0], - &uurb->iso_frame_desc[0], - sizeof(struct usbdevfs_iso_packet_desc) * - kurb->number_of_packets)) - return -EFAULT; - - totlen = 0; - for (i = 0; i < kurb->number_of_packets; i++) { - unsigned int this_len; - - this_len = kurb->iso_frame_desc[i].length; - if (this_len > 1023) - return -EINVAL; - - totlen += this_len; - } - - if (totlen > 32768) - return -EINVAL; - - kurb->buffer_length = totlen; - - return 0; -} - -static int do_usbdevfs_urb(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct usbdevfs_urb *kurb; - struct usbdevfs_urb32 *uurb; - mm_segment_t old_fs; - __u32 udata; - void *uptr, *kptr; - unsigned int buflen; - int err; - - uurb = (struct usbdevfs_urb32 *) arg; - - err = -ENOMEM; - kurb = kmalloc(sizeof(struct usbdevfs_urb) + - (sizeof(struct usbdevfs_iso_packet_desc) * 128), - GFP_KERNEL); - if (!kurb) - goto out; - - err = -EFAULT; - if (get_urb32(kurb, uurb)) - goto out; - - err = get_urb32_isoframes(kurb, uurb); - if (err) - goto out; - - err = -EFAULT; - if (__get_user(udata, &uurb->buffer)) - goto out; - uptr = compat_ptr(udata); - - buflen = kurb->buffer_length; - err = verify_area(VERIFY_WRITE, uptr, buflen); - if (err) - goto out; - - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_ioctl(fd, USBDEVFS_SUBMITURB, (unsigned long) kurb); - set_fs(old_fs); - - if (err >= 0) { - /* RED-PEN Shit, this doesn't work for async URBs :-( XXX */ - if (put_urb32(kurb, uurb)) { - err = -EFAULT; - } - } - -out: - kfree(kurb); - return err; -} -#endif - -#define USBDEVFS_REAPURB32 _IOW('U', 12, u32) -#define USBDEVFS_REAPURBNDELAY32 _IOW('U', 13, u32) - -static int do_usbdevfs_reapurb(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs; - void *kptr; - int err; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_ioctl(fd, - (cmd == USBDEVFS_REAPURB32 ? - USBDEVFS_REAPURB : - USBDEVFS_REAPURBNDELAY), - (unsigned long) &kptr); - set_fs(old_fs); - - if (err >= 0 && - put_user((u32)(u64)kptr, (u32 *)arg)) - err = -EFAULT; - - return err; -} - -struct usbdevfs_disconnectsignal32 { - compat_int_t signr; - compat_caddr_t context; -}; - -#define USBDEVFS_DISCSIGNAL32 _IOR('U', 14, struct usbdevfs_disconnectsignal32) - -static int do_usbdevfs_discsignal(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct usbdevfs_disconnectsignal kdis; - struct usbdevfs_disconnectsignal32 *udis; - mm_segment_t old_fs; - u32 uctx; - int err; - - udis = (struct usbdevfs_disconnectsignal32 *) arg; - - if (get_user(kdis.signr, &udis->signr) || - __get_user(uctx, &udis->context)) - return -EFAULT; - - kdis.context = (void *) (long)uctx; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_ioctl(fd, USBDEVFS_DISCSIGNAL, (unsigned long) &kdis); - set_fs(old_fs); - - return err; -} /* /proc/mtrr ioctls */ @@ -726,27 +215,12 @@ COMPATIBLE_IOCTL(FIOQSIZE) /* And these ioctls need translation */ HANDLE_IOCTL(TIOCGDEV, tiocgdev) -HANDLE_IOCTL(TIOCGSERIAL, serial_struct_ioctl) -HANDLE_IOCTL(TIOCSSERIAL, serial_struct_ioctl) -/* Raw devices */ -HANDLE_IOCTL(RAW_SETBIND, raw_ioctl) /* realtime device */ HANDLE_IOCTL(RTC_IRQP_READ, rtc32_ioctl) HANDLE_IOCTL(RTC_IRQP_READ32,rtc32_ioctl) HANDLE_IOCTL(RTC_IRQP_SET32, rtc32_ioctl) HANDLE_IOCTL(RTC_EPOCH_READ32, rtc32_ioctl) HANDLE_IOCTL(RTC_EPOCH_SET32, rtc32_ioctl) -HANDLE_IOCTL(REISERFS_IOC_UNPACK32, reiserfs_ioctl32) -/* VFAT */ -HANDLE_IOCTL(VFAT_IOCTL_READDIR_BOTH32, vfat_ioctl32) -HANDLE_IOCTL(VFAT_IOCTL_READDIR_SHORT32, vfat_ioctl32) - -HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control) -HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk) -/*HANDLE_IOCTL(USBDEVFS_SUBMITURB32, do_usbdevfs_urb)*/ -HANDLE_IOCTL(USBDEVFS_REAPURB32, do_usbdevfs_reapurb) -HANDLE_IOCTL(USBDEVFS_REAPURBNDELAY32, do_usbdevfs_reapurb) -HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal) /* take care of sizeof(sizeof()) breakage */ /* mtrr */ HANDLE_IOCTL(MTRRIOC32_ADD_ENTRY, mtrr_ioctl32) diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 0f8e841da093..88f750e4f16f 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -106,6 +106,7 @@ #include #include #include +#include #undef INCLUDES #endif @@ -2302,6 +2303,572 @@ static int mtd_rw_oob(unsigned int fd, unsigned int cmd, unsigned long arg) return err; } +#define VFAT_IOCTL_READDIR_BOTH32 _IOR('r', 1, struct compat_dirent[2]) +#define VFAT_IOCTL_READDIR_SHORT32 _IOR('r', 2, struct compat_dirent[2]) + +static long +put_dirent32 (struct dirent *d, struct compat_dirent *d32) +{ + int ret; + + if ((ret = verify_area(VERIFY_WRITE, d32, + sizeof(struct compat_dirent)))) + return ret; + + __put_user(d->d_ino, &d32->d_ino); + __put_user(d->d_off, &d32->d_off); + __put_user(d->d_reclen, &d32->d_reclen); + __copy_to_user(d32->d_name, d->d_name, d->d_reclen); + return ret; +} + +static int vfat_ioctl32(unsigned fd, unsigned cmd, void *ptr) +{ + int ret; + mm_segment_t oldfs = get_fs(); + struct dirent d[2]; + + switch(cmd) + { + case VFAT_IOCTL_READDIR_BOTH32: + cmd = VFAT_IOCTL_READDIR_BOTH; + break; + case VFAT_IOCTL_READDIR_SHORT32: + cmd = VFAT_IOCTL_READDIR_SHORT; + break; + } + + set_fs(KERNEL_DS); + ret = sys_ioctl(fd,cmd,(unsigned long)&d); + set_fs(oldfs); + if (ret >= 0) { + ret |= put_dirent32(&d[0], (struct compat_dirent *)ptr); + ret |= put_dirent32(&d[1], ((struct compat_dirent *)ptr) + 1); + } + return ret; +} + +#define REISERFS_IOC_UNPACK32 _IOW(0xCD,1,int) + +static int reiserfs_ioctl32(unsigned fd, unsigned cmd, unsigned long ptr) +{ + if (cmd == REISERFS_IOC_UNPACK32) + cmd = REISERFS_IOC_UNPACK; + + return sys_ioctl(fd,cmd,ptr); +} + +struct raw32_config_request +{ + compat_int_t raw_minor; + __u64 block_major; + __u64 block_minor; +} __attribute__((packed)); + +static int get_raw32_request(struct raw_config_request *req, struct raw32_config_request *user_req) +{ + __u32 lo_maj, hi_maj, lo_min, hi_min; + int ret; + + if ((ret = verify_area(VERIFY_READ, user_req, + sizeof(struct raw32_config_request)))) + return ret; + + __get_user(req->raw_minor, &user_req->raw_minor); + __get_user(lo_maj, (__u32*)&user_req->block_major); + __get_user(hi_maj, ((__u32*)(&user_req->block_major) + 1)); + __get_user(lo_min, (__u32*)&user_req->block_minor); + __get_user(hi_min, ((__u32*)(&user_req->block_minor) + 1)); + + req->block_major = lo_maj | (((__u64)hi_maj) << 32); + req->block_minor = lo_min | (((__u64)lo_min) << 32); + + return ret; +} + +static int set_raw32_request(struct raw_config_request *req, struct raw32_config_request *user_req) +{ + int ret; + + if ((ret = verify_area(VERIFY_WRITE, user_req, + sizeof(struct raw32_config_request)))) + return ret; + + __put_user(req->raw_minor, &user_req->raw_minor); + __put_user((__u32)(req->block_major), (__u32*)&user_req->block_major); + __put_user((__u32)(req->block_major >> 32), ((__u32*)(&user_req->block_major) + 1)); + __put_user((__u32)(req->block_minor), (__u32*)&user_req->block_minor); + __put_user((__u32)(req->block_minor >> 32), ((__u32*)(&user_req->block_minor) + 1)); + + return ret; +} + +static int raw_ioctl(unsigned fd, unsigned cmd, void *ptr) +{ + int ret; + + switch (cmd) { + case RAW_SETBIND: + case RAW_GETBIND: { + struct raw_config_request req; + struct raw32_config_request *user_req = ptr; + mm_segment_t oldfs = get_fs(); + + if ((ret = get_raw32_request(&req, user_req))) + return ret; + + set_fs(KERNEL_DS); + ret = sys_ioctl(fd,cmd,(unsigned long)&req); + set_fs(oldfs); + + if ((!ret) && (cmd == RAW_GETBIND)) { + ret = set_raw32_request(&req, user_req); + } + break; + } + default: + ret = sys_ioctl(fd,cmd,(unsigned long)ptr); + break; + } + return ret; +} + +struct serial_struct32 { + compat_int_t type; + compat_int_t line; + compat_uint_t port; + compat_int_t irq; + compat_int_t flags; + compat_int_t xmit_fifo_size; + compat_int_t custom_divisor; + compat_int_t baud_base; + unsigned short close_delay; + char io_type; + char reserved_char[1]; + compat_int_t hub6; + unsigned short closing_wait; /* time to wait before closing */ + unsigned short closing_wait2; /* no longer used... */ + compat_uint_t iomem_base; + unsigned short iomem_reg_shift; + unsigned int port_high; + compat_int_t reserved[1]; +}; + +static int serial_struct_ioctl(unsigned fd, unsigned cmd, void *ptr) +{ + typedef struct serial_struct SS; + typedef struct serial_struct32 SS32; + struct serial_struct32 *ss32 = ptr; + int err; + struct serial_struct ss; + mm_segment_t oldseg = get_fs(); + __u32 udata; + + if (cmd == TIOCSSERIAL) { + if (verify_area(VERIFY_READ, ss32, sizeof(SS32))) + return -EFAULT; + __copy_from_user(&ss, ss32, offsetof(SS32, iomem_base)); + __get_user(udata, &ss32->iomem_base); + ss.iomem_base = compat_ptr(udata); + __get_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift); + __get_user(ss.port_high, &ss32->port_high); + ss.iomap_base = 0UL; + } + set_fs(KERNEL_DS); + err = sys_ioctl(fd,cmd,(unsigned long)(&ss)); + set_fs(oldseg); + if (cmd == TIOCGSERIAL && err >= 0) { + if (verify_area(VERIFY_WRITE, ss32, sizeof(SS32))) + return -EFAULT; + __copy_to_user(ss32,&ss,offsetof(SS32,iomem_base)); + __put_user((unsigned long)ss.iomem_base >> 32 ? + 0xffffffff : (unsigned)(unsigned long)ss.iomem_base, + &ss32->iomem_base); + __put_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift); + __put_user(ss.port_high, &ss32->port_high); + + } + return err; +} + +struct usbdevfs_ctrltransfer32 { + u8 bRequestType; + u8 bRequest; + u16 wValue; + u16 wIndex; + u16 wLength; + u32 timeout; /* in milliseconds */ + compat_caddr_t data; +}; + +#define USBDEVFS_CONTROL32 _IOWR('U', 0, struct usbdevfs_ctrltransfer32) + +static int do_usbdevfs_control(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct usbdevfs_ctrltransfer kctrl; + struct usbdevfs_ctrltransfer32 *uctrl; + mm_segment_t old_fs; + __u32 udata; + void *uptr, *kptr; + int err; + + uctrl = (struct usbdevfs_ctrltransfer32 *) arg; + + if (copy_from_user(&kctrl, uctrl, + (sizeof(struct usbdevfs_ctrltransfer32) - + sizeof(compat_caddr_t)))) + return -EFAULT; + + if (get_user(udata, &uctrl->data)) + return -EFAULT; + uptr = compat_ptr(udata); + /* In usbdevice_fs, it limits the control buffer to a page, + * for simplicity so do we. + */ + if (!uptr || kctrl.wLength > PAGE_SIZE) + return -EINVAL; + + kptr = (void *)__get_free_page(GFP_KERNEL); + + if ((kctrl.bRequestType & USB_DIR_IN) == 0) { + err = -EFAULT; + if (copy_from_user(kptr, uptr, kctrl.wLength)) + goto out; + } + + kctrl.data = kptr; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = sys_ioctl(fd, USBDEVFS_CONTROL, (unsigned long)&kctrl); + set_fs(old_fs); + + if (err >= 0 && + ((kctrl.bRequestType & USB_DIR_IN) != 0)) { + if (copy_to_user(uptr, kptr, kctrl.wLength)) + err = -EFAULT; + } + +out: + free_page((unsigned long) kptr); + return err; +} + + +struct usbdevfs_bulktransfer32 { + compat_uint_t ep; + compat_uint_t len; + compat_uint_t timeout; /* in milliseconds */ + compat_caddr_t data; +}; + +#define USBDEVFS_BULK32 _IOWR('U', 2, struct usbdevfs_bulktransfer32) + +static int do_usbdevfs_bulk(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct usbdevfs_bulktransfer kbulk; + struct usbdevfs_bulktransfer32 *ubulk; + mm_segment_t old_fs; + __u32 udata; + void *uptr, *kptr; + int err; + + ubulk = (struct usbdevfs_bulktransfer32 *) arg; + + if (get_user(kbulk.ep, &ubulk->ep) || + get_user(kbulk.len, &ubulk->len) || + get_user(kbulk.timeout, &ubulk->timeout) || + get_user(udata, &ubulk->data)) + return -EFAULT; + + uptr = compat_ptr(udata); + + /* In usbdevice_fs, it limits the control buffer to a page, + * for simplicity so do we. + */ + if (!uptr || kbulk.len > PAGE_SIZE) + return -EINVAL; + + kptr = (void *) __get_free_page(GFP_KERNEL); + + if ((kbulk.ep & 0x80) == 0) { + err = -EFAULT; + if (copy_from_user(kptr, uptr, kbulk.len)) + goto out; + } + + kbulk.data = kptr; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = sys_ioctl(fd, USBDEVFS_BULK, (unsigned long) &kbulk); + set_fs(old_fs); + + if (err >= 0 && + ((kbulk.ep & 0x80) != 0)) { + if (copy_to_user(uptr, kptr, kbulk.len)) + err = -EFAULT; + } + +out: + free_page((unsigned long) kptr); + return err; +} + +/* This needs more work before we can enable it. Unfortunately + * because of the fancy asynchronous way URB status/error is written + * back to userspace, we'll need to fiddle with USB devio internals + * and/or reimplement entirely the frontend of it ourselves. -DaveM + * + * The issue is: + * + * When an URB is submitted via usbdevicefs it is put onto an + * asynchronous queue. When the URB completes, it may be reaped + * via another ioctl. During this reaping the status is written + * back to userspace along with the length of the transfer. + * + * We must translate into 64-bit kernel types so we pass in a kernel + * space copy of the usbdevfs_urb structure. This would mean that we + * must do something to deal with the async entry reaping. First we + * have to deal somehow with this transitory memory we've allocated. + * This is problematic since there are many call sites from which the + * async entries can be destroyed (and thus when we'd need to free up + * this kernel memory). One of which is the close() op of usbdevicefs. + * To handle that we'd need to make our own file_operations struct which + * overrides usbdevicefs's release op with our own which runs usbdevicefs's + * real release op then frees up the kernel memory. + * + * But how to keep track of these kernel buffers? We'd need to either + * keep track of them in some table _or_ know about usbdevicefs internals + * (ie. the exact layout of its file private, which is actually defined + * in linux/usbdevice_fs.h, the layout of the async queues are private to + * devio.c) + * + * There is one possible other solution I considered, also involving knowledge + * of usbdevicefs internals: + * + * After an URB is submitted, we "fix up" the address back to the user + * space one. This would work if the status/length fields written back + * by the async URB completion lines up perfectly in the 32-bit type with + * the 64-bit kernel type. Unfortunately, it does not because the iso + * frame descriptors, at the end of the struct, can be written back. + * + * I think we'll just need to simply duplicate the devio URB engine here. + */ +#if 0 +struct usbdevfs_urb32 { + unsigned char type; + unsigned char endpoint; + compat_int_t status; + compat_uint_t flags; + compat_caddr_t buffer; + compat_int_t buffer_length; + compat_int_t actual_length; + compat_int_t start_frame; + compat_int_t number_of_packets; + compat_int_t error_count; + compat_uint_t signr; + compat_caddr_t usercontext; /* unused */ + struct usbdevfs_iso_packet_desc iso_frame_desc[0]; +}; + +#define USBDEVFS_SUBMITURB32 _IOR('U', 10, struct usbdevfs_urb32) + +static int get_urb32(struct usbdevfs_urb *kurb, + struct usbdevfs_urb32 *uurb) +{ + if (get_user(kurb->type, &uurb->type) || + __get_user(kurb->endpoint, &uurb->endpoint) || + __get_user(kurb->status, &uurb->status) || + __get_user(kurb->flags, &uurb->flags) || + __get_user(kurb->buffer_length, &uurb->buffer_length) || + __get_user(kurb->actual_length, &uurb->actual_length) || + __get_user(kurb->start_frame, &uurb->start_frame) || + __get_user(kurb->number_of_packets, &uurb->number_of_packets) || + __get_user(kurb->error_count, &uurb->error_count) || + __get_user(kurb->signr, &uurb->signr)) + return -EFAULT; + + kurb->usercontext = 0; /* unused currently */ + + return 0; +} + +/* Just put back the values which usbdevfs actually changes. */ +static int put_urb32(struct usbdevfs_urb *kurb, + struct usbdevfs_urb32 *uurb) +{ + if (put_user(kurb->status, &uurb->status) || + __put_user(kurb->actual_length, &uurb->actual_length) || + __put_user(kurb->error_count, &uurb->error_count)) + return -EFAULT; + + if (kurb->number_of_packets != 0) { + int i; + + for (i = 0; i < kurb->number_of_packets; i++) { + if (__put_user(kurb->iso_frame_desc[i].actual_length, + &uurb->iso_frame_desc[i].actual_length) || + __put_user(kurb->iso_frame_desc[i].status, + &uurb->iso_frame_desc[i].status)) + return -EFAULT; + } + } + + return 0; +} + +static int get_urb32_isoframes(struct usbdevfs_urb *kurb, + struct usbdevfs_urb32 *uurb) +{ + unsigned int totlen; + int i; + + if (kurb->type != USBDEVFS_URB_TYPE_ISO) { + kurb->number_of_packets = 0; + return 0; + } + + if (kurb->number_of_packets < 1 || + kurb->number_of_packets > 128) + return -EINVAL; + + if (copy_from_user(&kurb->iso_frame_desc[0], + &uurb->iso_frame_desc[0], + sizeof(struct usbdevfs_iso_packet_desc) * + kurb->number_of_packets)) + return -EFAULT; + + totlen = 0; + for (i = 0; i < kurb->number_of_packets; i++) { + unsigned int this_len; + + this_len = kurb->iso_frame_desc[i].length; + if (this_len > 1023) + return -EINVAL; + + totlen += this_len; + } + + if (totlen > 32768) + return -EINVAL; + + kurb->buffer_length = totlen; + + return 0; +} + +static int do_usbdevfs_urb(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct usbdevfs_urb *kurb; + struct usbdevfs_urb32 *uurb; + mm_segment_t old_fs; + __u32 udata; + void *uptr, *kptr; + unsigned int buflen; + int err; + + uurb = (struct usbdevfs_urb32 *) arg; + + err = -ENOMEM; + kurb = kmalloc(sizeof(struct usbdevfs_urb) + + (sizeof(struct usbdevfs_iso_packet_desc) * 128), + GFP_KERNEL); + if (!kurb) + goto out; + + err = -EFAULT; + if (get_urb32(kurb, uurb)) + goto out; + + err = get_urb32_isoframes(kurb, uurb); + if (err) + goto out; + + err = -EFAULT; + if (__get_user(udata, &uurb->buffer)) + goto out; + uptr = compat_ptr(udata); + + buflen = kurb->buffer_length; + err = verify_area(VERIFY_WRITE, uptr, buflen); + if (err) + goto out; + + + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = sys_ioctl(fd, USBDEVFS_SUBMITURB, (unsigned long) kurb); + set_fs(old_fs); + + if (err >= 0) { + /* RED-PEN Shit, this doesn't work for async URBs :-( XXX */ + if (put_urb32(kurb, uurb)) { + err = -EFAULT; + } + } + +out: + kfree(kurb); + return err; +} +#endif + +#define USBDEVFS_REAPURB32 _IOW('U', 12, u32) +#define USBDEVFS_REAPURBNDELAY32 _IOW('U', 13, u32) + +static int do_usbdevfs_reapurb(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs; + void *kptr; + int err; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = sys_ioctl(fd, + (cmd == USBDEVFS_REAPURB32 ? + USBDEVFS_REAPURB : + USBDEVFS_REAPURBNDELAY), + (unsigned long) &kptr); + set_fs(old_fs); + + if (err >= 0 && + put_user((u32)(u64)kptr, (u32 *)arg)) + err = -EFAULT; + + return err; +} + +struct usbdevfs_disconnectsignal32 { + compat_int_t signr; + compat_caddr_t context; +}; + +#define USBDEVFS_DISCSIGNAL32 _IOR('U', 14, struct usbdevfs_disconnectsignal32) + +static int do_usbdevfs_discsignal(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct usbdevfs_disconnectsignal kdis; + struct usbdevfs_disconnectsignal32 *udis; + mm_segment_t old_fs; + u32 uctx; + int err; + + udis = (struct usbdevfs_disconnectsignal32 *) arg; + + if (get_user(kdis.signr, &udis->signr) || + __get_user(uctx, &udis->context)) + return -EFAULT; + + kdis.context = (void *) (long)uctx; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = sys_ioctl(fd, USBDEVFS_DISCSIGNAL, (unsigned long) &kdis); + set_fs(old_fs); + + return err; +} #undef CODE #endif @@ -2443,6 +3010,22 @@ HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_ioctl) HANDLE_IOCTL(BLKBSZGET_32, do_blkbszget) HANDLE_IOCTL(BLKBSZSET_32, do_blkbszset) HANDLE_IOCTL(BLKGETSIZE64_32, do_blkgetsize64) - +/* vfat */ +HANDLE_IOCTL(VFAT_IOCTL_READDIR_BOTH32, vfat_ioctl32) +HANDLE_IOCTL(VFAT_IOCTL_READDIR_SHORT32, vfat_ioctl32) +HANDLE_IOCTL(REISERFS_IOC_UNPACK32, reiserfs_ioctl32) +/* Raw devices */ +HANDLE_IOCTL(RAW_SETBIND, raw_ioctl) +HANDLE_IOCTL(RAW_GETBIND, raw_ioctl) +/* Serial */ +HANDLE_IOCTL(TIOCGSERIAL, serial_struct_ioctl) +HANDLE_IOCTL(TIOCSSERIAL, serial_struct_ioctl) +/* Usbdevfs */ +HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control) +HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk) +/*HANDLE_IOCTL(USBDEVFS_SUBMITURB32, do_usbdevfs_urb)*/ +HANDLE_IOCTL(USBDEVFS_REAPURB32, do_usbdevfs_reapurb) +HANDLE_IOCTL(USBDEVFS_REAPURBNDELAY32, do_usbdevfs_reapurb) +HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal) #undef DECLARES #endif diff --git a/include/linux/compat.h b/include/linux/compat.h index b338ca16f5af..3e8e53bdd42e 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -90,5 +90,12 @@ struct compat_statfs64 { __u32 f_spare[5]; }; +struct compat_dirent { + u32 d_ino; + compat_off_t d_off; + u16 d_reclen; + char d_name[256]; +}; + #endif /* CONFIG_COMPAT */ #endif /* _LINUX_COMPAT_H */ -- cgit v1.2.3 From 62f75b2956e49a7c3aa58ac642f9acad193a2ac0 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 4 Oct 2003 21:03:09 -0700 Subject: [PATCH] document the macro for translating PROT_ to VM_ bits From: Muli Ben-Yehuda Shed some much-needed light. --- include/linux/mman.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/include/linux/mman.h b/include/linux/mman.h index cfb6ac61bbde..07da84fcbd15 100644 --- a/include/linux/mman.h +++ b/include/linux/mman.h @@ -28,8 +28,13 @@ static inline void vm_unacct_memory(long pages) vm_acct_memory(-pages); } -/* Optimisation macro. */ -#define _calc_vm_trans(x,bit1,bit2) \ +/* + * Optimisation macro. It is equivalent to: + * (x & bit1) ? bit2 : 0 + * but this version is faster. + * ("bit1" and "bit2" must be single bits) + */ +#define _calc_vm_trans(x, bit1, bit2) \ ((bit1) <= (bit2) ? ((x) & (bit1)) * ((bit2) / (bit1)) \ : ((x) & (bit1)) / ((bit1) / (bit2))) -- cgit v1.2.3 From 9ff547bd81529d58fdac8dba008049afe032a288 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 4 Oct 2003 21:03:17 -0700 Subject: [PATCH] /proc/sys/auxv From: Roland McGrath This was supposed to be part of the recent mm_struct.saved_auxv[] patch. The /proc addition is half the reason for the patch, and the more important one (letting you debug live processes, while NT_AUXV in core dumps lets you debug dead ones). The patch below was supposed to be part of the original. --- fs/proc/base.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/fs/proc/base.c b/fs/proc/base.c index 640cddefdb78..3cc64eb275b1 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -53,6 +53,7 @@ enum pid_directory_inos { PROC_TGID_EXE, PROC_TGID_FD, PROC_TGID_ENVIRON, + PROC_TGID_AUXV, PROC_TGID_CMDLINE, PROC_TGID_STAT, PROC_TGID_STATM, @@ -75,6 +76,7 @@ enum pid_directory_inos { PROC_TID_EXE, PROC_TID_FD, PROC_TID_ENVIRON, + PROC_TID_AUXV, PROC_TID_CMDLINE, PROC_TID_STAT, PROC_TID_STATM, @@ -104,6 +106,7 @@ static struct pid_entry tgid_base_stuff[] = { E(PROC_TGID_TASK, "task", S_IFDIR|S_IRUGO|S_IXUGO), E(PROC_TGID_FD, "fd", S_IFDIR|S_IRUSR|S_IXUSR), E(PROC_TGID_ENVIRON, "environ", S_IFREG|S_IRUSR), + E(PROC_TGID_AUXV, "auxv", S_IFREG|S_IRUSR), E(PROC_TGID_STATUS, "status", S_IFREG|S_IRUGO), E(PROC_TGID_CMDLINE, "cmdline", S_IFREG|S_IRUGO), E(PROC_TGID_STAT, "stat", S_IFREG|S_IRUGO), @@ -125,6 +128,7 @@ static struct pid_entry tgid_base_stuff[] = { static struct pid_entry tid_base_stuff[] = { E(PROC_TID_FD, "fd", S_IFDIR|S_IRUSR|S_IXUSR), E(PROC_TID_ENVIRON, "environ", S_IFREG|S_IRUSR), + E(PROC_TID_AUXV, "auxv", S_IFREG|S_IRUSR), E(PROC_TID_STATUS, "status", S_IFREG|S_IRUGO), E(PROC_TID_CMDLINE, "cmdline", S_IFREG|S_IRUGO), E(PROC_TID_STAT, "stat", S_IFREG|S_IRUGO), @@ -322,6 +326,25 @@ out: return res; } +static int proc_pid_auxv(struct task_struct *task, char *buffer) +{ + int res = 0; + struct mm_struct *mm = get_task_mm(task); + if (mm) { + unsigned int nwords = 0; + do + nwords += 2; + while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */ + res = nwords * sizeof(mm->saved_auxv[0]); + if (res > PAGE_SIZE) + res = PAGE_SIZE; + memcpy(buffer, mm->saved_auxv, res); + mmput(mm); + } + return res; +} + + #ifdef CONFIG_KALLSYMS /* * Provides a wchan file via kallsyms in a proper one-value-per-file format. @@ -1271,6 +1294,11 @@ static struct dentry *proc_pident_lookup(struct inode *dir, inode->i_fop = &proc_info_file_operations; ei->op.proc_read = proc_pid_environ; break; + case PROC_TID_AUXV: + case PROC_TGID_AUXV: + inode->i_fop = &proc_info_file_operations; + ei->op.proc_read = proc_pid_auxv; + break; case PROC_TID_STATUS: case PROC_TGID_STATUS: inode->i_fop = &proc_info_file_operations; -- cgit v1.2.3 From 1820a80d7833df5c7401f442633092df3185dc20 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 4 Oct 2003 21:03:26 -0700 Subject: [PATCH] kernel documentation fixes From: Michael Still The patch squelches build errors in the kernel-doc make targets by adding documentation to arguements previously not documented, and updating the argument names where they have changed. --- arch/i386/kernel/mca.c | 4 +++- drivers/block/ll_rw_blk.c | 8 ++++---- drivers/pci/pci.c | 6 ++++-- drivers/serial/8250.c | 6 ++++-- drivers/serial/serial_core.c | 4 ++-- fs/devfs/base.c | 5 +++-- fs/inode.c | 8 ++++++-- fs/locks.c | 10 ++++++---- fs/super.c | 11 ++++++----- include/linux/list.h | 2 +- include/linux/skbuff.h | 2 ++ kernel/kmod.c | 3 ++- mm/slab.c | 4 ++-- net/core/dev.c | 2 ++ sound/oss/via82cxxx_audio.c | 1 + 15 files changed, 48 insertions(+), 28 deletions(-) diff --git a/arch/i386/kernel/mca.c b/arch/i386/kernel/mca.c index 7ecca527cd54..57d118e4d6e5 100644 --- a/arch/i386/kernel/mca.c +++ b/arch/i386/kernel/mca.c @@ -132,7 +132,9 @@ struct resource mca_standard_resources[] = { #define MCA_STANDARD_RESOURCES (sizeof(mca_standard_resources)/sizeof(struct resource)) /** - * mca_read_pos - read the POS registers into a memory buffer + * mca_read_and_store_pos - read the POS registers into a memory buffer + * @pos: a char pointer to 8 bytes, contains the POS register value on + * successful return * * Returns 1 if a card actually exists (i.e. the pos isn't * all 0xff) or 0 otherwise diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 0e71b28f621c..473121c6b686 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -119,7 +119,7 @@ static void set_queue_congested(request_queue_t *q, int rw) /** * blk_get_backing_dev_info - get the address of a queue's backing_dev_info - * @dev: device + * @bdev: device * * Locates the passed device's request queue and returns the address of its * backing_dev_info @@ -414,8 +414,8 @@ void blk_queue_segment_boundary(request_queue_t *q, unsigned long mask) /** * blk_queue_dma_alignment - set dma length and memory alignment - * @q: the request queue for the device - * @dma_mask: alignment mask + * @q: the request queue for the device + * @mask: alignment mask * * description: * set required memory and length aligment for direct dma transactions. @@ -1152,7 +1152,7 @@ void blk_stop_queue(request_queue_t *q) /** * blk_run_queue - run a single device queue - * @q The queue to run + * @q: The queue to run */ void blk_run_queue(struct request_queue *q) { diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 3227f4dfdede..0ed0c02fc5ab 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -126,11 +126,13 @@ pci_find_capability(struct pci_dev *dev, int cap) /** * pci_bus_find_capability - query for devices' capabilities - * @dev: PCI device to query - * @cap: capability code + * @bus: the PCI bus to query + * @devfn: PCI device to query + * @cap: capability code * * Like pci_find_capability() but works for pci devices that do not have a * pci_dev structure set up yet. + * * Returns the address of the requested capability structure within the * device's PCI configuration space or 0 in case the device does not * support it. diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 7d0479c472ca..2a4d19615529 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -2111,7 +2111,8 @@ void serial8250_get_irq_map(unsigned int *map) /** * serial8250_suspend_port - suspend one serial port - * @line: serial line number + * @line: serial line number + * @level: the level of port suspension, as per uart_suspend_port * * Suspend one serial port. */ @@ -2122,7 +2123,8 @@ void serial8250_suspend_port(int line) /** * serial8250_resume_port - resume one serial port - * @line: serial line number + * @line: serial line number + * @level: the level of port resumption, as per uart_resume_port * * Resume one serial port. */ diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 064b9631201f..6cf18b46136f 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -263,9 +263,9 @@ static void uart_shutdown(struct uart_state *state) /** * uart_update_timeout - update per-port FIFO timeout. - * @port: uart_port structure describing the port. + * @port: uart_port structure describing the port * @cflag: termios cflag value - * @quot: uart clock divisor quotient + * @baud: speed of the port * * Set the port FIFO timeout value. The @cflag value should * reflect the actual hardware settings. diff --git a/fs/devfs/base.c b/fs/devfs/base.c index 73894d9af19c..1d8b7410e175 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -973,8 +973,9 @@ static struct devfs_entry *_devfs_search_dir (struct devfs_entry *dir, /** * _devfs_alloc_entry - Allocate a devfs entry. - * @name: The name of the entry. - * @namelen: The number of characters in @name. + * @name: the name of the entry + * @namelen: the number of characters in @name + * @mode: the mode for the entry * * Allocate a devfs entry and returns a pointer to the entry on success, else * %NULL. diff --git a/fs/inode.c b/fs/inode.c index 71c2c4d37697..76d7881f2b60 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -255,6 +255,9 @@ void clear_inode(struct inode *inode) EXPORT_SYMBOL(clear_inode); /* + * dispose_list - dispose of the contents of a local list + * @head: the head of the list to free + * * Dispose-list gets a local list with local inodes in it, so it doesn't * need to worry about list corruption and SMP locks. */ @@ -739,11 +742,11 @@ EXPORT_SYMBOL(igrab); /** * ifind - internal function, you want ilookup5() or iget5(). * @sb: super block of file system to search - * @hashval: hash value (usually inode number) to search for + * @head: the head of the list to search * @test: callback used for comparisons between inodes * @data: opaque data pointer to pass to @test * - * ifind() searches for the inode specified by @hashval and @data in the inode + * ifind() searches for the inode specified by @data in the inode * cache. This is a generalized version of ifind_fast() for file systems where * the inode number is not sufficient for unique identification of an inode. * @@ -775,6 +778,7 @@ static inline struct inode *ifind(struct super_block *sb, /** * ifind_fast - internal function, you want ilookup() or iget(). * @sb: super block of file system to search + * @head: head of the list to search * @ino: inode number to search for * * ifind_fast() searches for the inode @ino in the inode cache. This is for diff --git a/fs/locks.c b/fs/locks.c index d7a2688c8e5c..9fc4b5cd5c64 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -928,10 +928,10 @@ int locks_mandatory_locked(struct inode *inode) * locks_mandatory_area - Check for a conflicting lock * @read_write: %FLOCK_VERIFY_WRITE for exclusive access, %FLOCK_VERIFY_READ * for shared - * @inode: the file to check - * @file: how the file was opened (if it was) - * @offset: start of area to check - * @count: length of area to check + * @inode: the file to check + * @filp: how the file was opened (if it was) + * @offset: start of area to check + * @count: length of area to check * * Searches the inode's list of locks to find any POSIX locks which conflict. * This function is called from locks_verify_area() and @@ -1119,6 +1119,7 @@ out: /** * lease_get_mtime * @inode: the inode + * @time: pointer to a timespec which will contain the last modified time * * This is to force NFS clients to flush their caches for files with * exclusive leases. The justification is that if someone has an @@ -1726,6 +1727,7 @@ posix_block_lock(struct file_lock *blocker, struct file_lock *waiter) /** * posix_unblock_lock - stop waiting for a file lock + * @filp: how the file was opened * @waiter: the lock which was waiting * * lockd needs to block waiting for locks. diff --git a/fs/super.c b/fs/super.c index 67a017529056..2117f5c12423 100644 --- a/fs/super.c +++ b/fs/super.c @@ -138,8 +138,8 @@ void deactivate_super(struct super_block *s) EXPORT_SYMBOL(deactivate_super); /** - * grab_super - acquire an active reference - * @s - reference we are trying to make active + * grab_super - acquire an active reference + * @s: reference we are trying to make active * * Tries to acquire an active reference. grab_super() is used when we * had just found a superblock in super_blocks or fs_type->fs_supers @@ -368,8 +368,8 @@ restart: } /** - * get_super - get the superblock of a device - * @dev: device to get the superblock for + * get_super - get the superblock of a device + * @bdev: device to get the superblock for * * Scans the superblock list and finds the superblock of the file system * mounted on the device given. %NULL is returned if no match is found. @@ -461,10 +461,11 @@ static void mark_files_ro(struct super_block *sb) } /** - * do_remount_sb - asks filesystem to change mount options. + * do_remount_sb - asks filesystem to change mount options. * @sb: superblock in question * @flags: numeric part of options * @data: the rest of options + * @force: whether or not to force the change * * Alters the mount options of a mounted file system. */ diff --git a/include/linux/list.h b/include/linux/list.h index 9e218f0e471c..5fdf945bbf93 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -449,7 +449,7 @@ static __inline__ void hlist_del(struct hlist_node *n) /** * hlist_del_rcu - deletes entry from hash list without re-initialization - * @entry: the element to delete from the hash list. + * @n: the element to delete from the hash list. * * Note: list_unhashed() on entry does not return true after this, * the entry is in an undefined state. It is useful for RCU based diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 81b3289dbe68..2aeb35d62c2d 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -152,6 +152,7 @@ struct skb_shared_info { * @sk: Socket we are owned by * @stamp: Time we arrived * @dev: Device we arrived on/are leaving by + * @real_dev: The real device we are using * @h: Transport layer header * @nh: Network layer header * @mac: Link layer header @@ -179,6 +180,7 @@ struct skb_shared_info { * @nfct: Associated connection, if any * @nf_debug: Netfilter debugging * @nf_bridge: Saved data about a bridged frame - see br_netfilter.c + * @private: Data which is private to the HIPPI implementation * @tc_index: Traffic control index */ diff --git a/kernel/kmod.c b/kernel/kmod.c index 98d809689092..f5d658f704d9 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -47,7 +47,8 @@ char modprobe_path[256] = "/sbin/modprobe"; /** * request_module - try to load a kernel module - * @module_name: Name of module + * @fmt: printf style format string for the name of the module + * @varargs: arguements as specified in the format string * * Load a module using the user mode module loader. The function returns * zero on success or a negative errno code on failure. Note that a diff --git a/mm/slab.c b/mm/slab.c index 76c95b542be6..3b216e910d5e 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2675,8 +2675,8 @@ struct seq_operations slabinfo_op = { * slabinfo_write - Tuning for the slab allocator * @file: unused * @buffer: user buffer - * @count: data len - * @data: unused + * @count: data length + * @ppos: unused */ ssize_t slabinfo_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) diff --git a/net/core/dev.c b/net/core/dev.c index 49c662e1d31d..b601f110b1b9 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -915,6 +915,8 @@ int unregister_netdevice_notifier(struct notifier_block *nb) /** * call_netdevice_notifiers - call all network notifier blocks + * @val: value passed unmodified to notifier function + * @v: pointer passed unmodified to notifier function * * Call all network notifier blocks. Parameters and return value * are as for notifier_call_chain(). diff --git a/sound/oss/via82cxxx_audio.c b/sound/oss/via82cxxx_audio.c index 1836e6934af2..360306ecae43 100644 --- a/sound/oss/via82cxxx_audio.c +++ b/sound/oss/via82cxxx_audio.c @@ -1844,6 +1844,7 @@ static void via_ac97_cleanup (struct via_info *card) /** * via_intr_channel - handle an interrupt for a single channel + * @card: unused * @chan: handle interrupt for this channel * * This is the "meat" of the interrupt handler, -- cgit v1.2.3 From 9626f94d83eadcb569471d72ee4ce9f0fbb66379 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 4 Oct 2003 21:03:36 -0700 Subject: [PATCH] EISA_bus cleanup From: Marc Zyngier , Christoph Hellwig I'd like to kill willy's CONFIG_EISA_ALWAYS kludge. So make EISA_bus a variable always when CONFIG_EISA is set and initialize it to 1 for alpha. We probably want to do that only if the system actually supports eisa, but I keep the old behaviour for now. --- arch/alpha/Kconfig | 15 --------------- arch/alpha/kernel/setup.c | 6 ++++++ drivers/eisa/eisa-bus.c | 7 ++----- include/linux/eisa.h | 16 ++++++---------- 4 files changed, 14 insertions(+), 30 deletions(-) diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 9a985819b95e..e7766d3ec6d8 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -471,21 +471,6 @@ config EISA bool depends on ALPHA_GENERIC || ALPHA_JENSEN || ALPHA_ALCOR || ALPHA_MIKASA || ALPHA_SABLE || ALPHA_LYNX || ALPHA_NORITAKE || ALPHA_RAWHIDE default y - ---help--- - The Extended Industry Standard Architecture (EISA) bus was - developed as an open alternative to the IBM MicroChannel bus. - - The EISA bus provided some of the features of the IBM MicroChannel - bus while maintaining backward compatibility with cards made for - the older ISA bus. The EISA bus saw limited use between 1988 and - 1995 when it was made obsolete by the PCI bus. - - Say Y here if you are building a kernel for an EISA-based machine. - - Otherwise, say N. - -config EISA_ALWAYS - def_bool EISA config SMP bool "Symmetric multi-processing support" diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c index deb4a3bb130a..eab5371047f4 100644 --- a/arch/alpha/kernel/setup.c +++ b/arch/alpha/kernel/setup.c @@ -33,6 +33,7 @@ #include #include #include +#include #ifdef CONFIG_MAGIC_SYSRQ #include #include @@ -680,6 +681,11 @@ setup_arch(char **cmdline_p) /* Default root filesystem to sda2. */ ROOT_DEV = Root_SDA2; +#ifdef CONFIG_EISA + /* FIXME: only set this when we actually have EISA in this box? */ + EISA_bus = 1; +#endif + /* * Check ASN in HWRPB for validity, report if bad. * FIXME: how was this failing? Should we trust it instead, diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c index 89c64b01e812..368001ad784c 100644 --- a/drivers/eisa/eisa-bus.c +++ b/drivers/eisa/eisa-bus.c @@ -422,11 +422,8 @@ module_param_array(disable_dev, int, disable_dev_count, 0444); postcore_initcall (eisa_init); -#ifndef CONFIG_EISA_ALWAYS -int EISA_bus; -EXPORT_SYMBOL(EISA_bus); -#endif - +int EISA_bus; /* for legacy drivers */ +EXPORT_SYMBOL (EISA_bus); EXPORT_SYMBOL (eisa_bus_type); EXPORT_SYMBOL (eisa_driver_register); EXPORT_SYMBOL (eisa_driver_unregister); diff --git a/include/linux/eisa.h b/include/linux/eisa.h index dc76d57b10d0..4079242dced8 100644 --- a/include/linux/eisa.h +++ b/include/linux/eisa.h @@ -4,16 +4,6 @@ #include #include -#ifdef CONFIG_EISA -# ifdef CONFIG_EISA_ALWAYS -# define EISA_bus 1 -# else - extern int EISA_bus; -# endif -#else -# define EISA_bus 0 -#endif - #define EISA_SIG_LEN 8 #define EISA_MAX_SLOTS 8 @@ -108,4 +98,10 @@ struct eisa_root_device { int eisa_root_register (struct eisa_root_device *root); +#ifdef CONFIG_EISA +extern int EISA_bus; +#else +# define EISA_bus 0 +#endif + #endif -- cgit v1.2.3 From 3101501b8dc5f8b662f3a3d5f83cdac245cd133c Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 4 Oct 2003 21:03:45 -0700 Subject: [PATCH] ext3 block allocator locking fix When the BKL was removed from ext3 we lost locking coverage for get_block()-versus-get_block(). Nobody seems to have hit the race because get_block() almost always runs under i_sem: only memory pressure-based writeout over a file hole runs outside i_sem. ext2 uses the dedicated i_meta_lock spinlock in the inode to provide the needed locking. But ext3 already has an rwsem around all the get_block() activity to protect it from truncate-related races. So this patch just converts that rwsem into a semaphore, so concurrent get_block() can never occur. This will be more efficient than adding the new spinlock. We lose the ability to have two threads run get_block() against the same file at the same time but again, that only happens during pageout over a hole anyway. (Kudos Alex Tomas for noticing the bug) --- fs/ext3/inode.c | 12 +++++++----- fs/ext3/super.c | 2 +- include/linux/ext3_fs_i.h | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 859926a49565..1144f75b0662 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -812,15 +812,17 @@ out: if (err == -EAGAIN) goto changed; - if (ext3_find_goal(inode, iblock, chain, partial, &goal) < 0) + down(&ei->truncate_sem); + if (ext3_find_goal(inode, iblock, chain, partial, &goal) < 0) { + up(&ei->truncate_sem); goto changed; + } left = (chain + depth) - partial; /* * Block out ext3_truncate while we alter the tree */ - down_read(&ei->truncate_sem); err = ext3_alloc_branch(handle, inode, left, goal, offsets+(partial-chain), partial); @@ -832,7 +834,7 @@ out: if (!err) err = ext3_splice_branch(handle, inode, iblock, chain, partial, left); - up_read(&ei->truncate_sem); + up(&ei->truncate_sem); if (err == -EAGAIN) goto changed; if (err) @@ -2205,7 +2207,7 @@ void ext3_truncate(struct inode * inode) * From here we block out all ext3_get_block() callers who want to * modify the block allocation tree. */ - down_write(&ei->truncate_sem); + down(&ei->truncate_sem); if (n == 1) { /* direct blocks */ ext3_free_data(handle, inode, NULL, i_data+offsets[0], @@ -2269,7 +2271,7 @@ do_indirects: case EXT3_TIND_BLOCK: ; } - up_write(&ei->truncate_sem); + up(&ei->truncate_sem); inode->i_mtime = inode->i_ctime = CURRENT_TIME; ext3_mark_inode_dirty(handle, inode); diff --git a/fs/ext3/super.c b/fs/ext3/super.c index cb753bcdaabf..f93524850ee0 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -460,7 +460,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) #ifdef CONFIG_EXT3_FS_XATTR init_rwsem(&ei->xattr_sem); #endif - init_rwsem(&ei->truncate_sem); + init_MUTEX(&ei->truncate_sem); inode_init_once(&ei->vfs_inode); } } diff --git a/include/linux/ext3_fs_i.h b/include/linux/ext3_fs_i.h index 1181cfae7142..7451cdcfb9da 100644 --- a/include/linux/ext3_fs_i.h +++ b/include/linux/ext3_fs_i.h @@ -106,7 +106,7 @@ struct ext3_inode_info { * during recovery. Hence we must fix the get_block-vs-truncate race * by other means, so we have truncate_sem. */ - struct rw_semaphore truncate_sem; + struct semaphore truncate_sem; struct inode vfs_inode; }; -- cgit v1.2.3 From 86b7683a5de769b35b96ea11e9f6f93c0af1c183 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 4 Oct 2003 21:03:53 -0700 Subject: [PATCH] dscc4 driver fixes From: Francois Romieu - dscc4_release_ring() must not appear in dscc4_{open/close} as the rings are allocated/freed in dscc4_{found1/free1}; - more elegant handling of return status in dscc4_found1(). --- drivers/net/wan/dscc4.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index 19fa852f82c8..86d347b25a55 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -107,7 +107,7 @@ #include /* Version */ -static const char version[] = "$Id: dscc4.c,v 1.159 2002/04/10 22:05:17 romieu Exp $ for Linux\n"; +static const char version[] = "$Id: dscc4.c,v 1.173 2003/09/20 23:55:34 romieu Exp $ for Linux\n"; static int debug; static int quartz; @@ -592,7 +592,7 @@ static inline int dscc4_xpr_ack(struct dscc4_dev_priv *dpriv) return (i >= 0 ) ? i : -EAGAIN; } -#if 0 +#if 0 /* dscc4_{rx/tx}_reset are both unreliable - more tweak needed */ static void dscc4_rx_reset(struct dscc4_dev_priv *dpriv, struct net_device *dev) { unsigned long flags; @@ -864,7 +864,7 @@ static int dscc4_found1(struct pci_dev *pdev, unsigned long ioaddr) { struct dscc4_pci_priv *ppriv; struct dscc4_dev_priv *root; - int i = 0; + int i, ret = -ENOMEM; root = (struct dscc4_dev_priv *) kmalloc(dev_per_card*sizeof(*root), GFP_KERNEL); @@ -905,7 +905,8 @@ static int dscc4_found1(struct pci_dev *pdev, unsigned long ioaddr) hdlc->xmit = dscc4_start_xmit; hdlc->attach = dscc4_hdlc_attach; - if (register_hdlc_device(hdlc)) { + ret = register_hdlc_device(hdlc); + if (ret < 0) { printk(KERN_ERR "%s: unable to register\n", DRV_NAME); goto err_unregister; } @@ -913,17 +914,20 @@ static int dscc4_found1(struct pci_dev *pdev, unsigned long ioaddr) dscc4_init_registers(dpriv, d); dpriv->parity = PARITY_CRC16_PR0_CCITT; dpriv->encoding = ENCODING_NRZ; - if (dscc4_init_ring(d)) { + + ret = dscc4_init_ring(d); + if (ret < 0) { unregister_hdlc_device(hdlc); goto err_unregister; } } - if (dscc4_set_quartz(root, quartz) < 0) + ret = dscc4_set_quartz(root, quartz); + if (ret < 0) goto err_unregister; ppriv->root = root; spin_lock_init(&ppriv->lock); pci_set_drvdata(pdev, ppriv); - return 0; + return ret; err_unregister: while (--i >= 0) { @@ -934,7 +938,7 @@ err_unregister: err_free_dev: kfree(root); err_out: - return -1; + return ret; }; /* FIXME: get rid of the unneeded code */ @@ -1098,7 +1102,6 @@ done: err_disable_scc_events: scc_writel(0xffffffff, dpriv, dev, IMR); scc_patchl(PowerUp | Vis, 0, dpriv, dev, CCR0); - dscc4_release_ring(dpriv); err_out: hdlc_close(hdlc); err: @@ -1164,7 +1167,6 @@ static int dscc4_close(struct net_device *dev) dpriv->flags |= FakeReset; hdlc_close(hdlc); - dscc4_release_ring(dpriv); return 0; } -- cgit v1.2.3 From 9697ce4cdbdf2c6e5f30d462fcfece58cb0e0da4 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 4 Oct 2003 21:04:02 -0700 Subject: [PATCH] cpufreq sysfs oops fix From: Dominik Brodowski Fix an ordering problem whcih was causing cpufreq oopses in sysfs. --- drivers/cpufreq/cpufreq.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 27a220880340..25ba41b0f6a7 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -449,6 +449,9 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) if (!kobject_get(&data->kobj)) return -EFAULT; + if (cpufreq_driver->target) + __cpufreq_governor(data, CPUFREQ_GOV_STOP); + kobject_unregister(&data->kobj); kobject_put(&data->kobj); @@ -459,9 +462,6 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) */ wait_for_completion(&data->kobj_unregister); - if (cpufreq_driver->target) - __cpufreq_governor(data, CPUFREQ_GOV_STOP); - if (cpufreq_driver->exit) cpufreq_driver->exit(data); -- cgit v1.2.3 From 1bd563fd41bf28b72605b4c4b9254d31f20a3814 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 4 Oct 2003 21:04:11 -0700 Subject: [PATCH] move job control fields from task_struct to From: Roland McGrath This patch completes what was started with the `process_group' accessor function, moving all the job control-related fields from task_struct into signal_struct and using process_foo accessor functions to read them. All these things are per-process in POSIX, none per-thread. Off hand it's hard to come up with the hairy MT scenarios in which the existing code would do insane things, but trust me, they're there. At any rate, all the uses being done via inline accessor functions now has got to be all good. I did a "make allyesconfig" build and caught the few random drivers and whatnot that referred to these fields. I was surprised to find how few references to ->tty there really were to fix up. I'm sure there will be a few more fixups needed in non-x86 code. The only actual testing of a running kernel with these patches I've done is on my normal minimal x86 config. Everything works fine as it did before as far as I can tell. One issue that may be of concern is the lack of any locking on multiple threads diddling these fields. I don't think it really matters, though there might be some obscure races that could produce inconsistent job control results. Nothing shattering, I'm sure; probably only something like a multi-threaded program calling setsid while its other threads do tty i/o, which never happens in reality. This is the same situation we get by using ->group_leader->foo without other synchronization, which seemed to be the trend and noone was worried about it. --- arch/ia64/kernel/unaligned.c | 2 +- drivers/char/n_tty.c | 3 +- drivers/char/rocket.c | 2 +- drivers/char/tty_io.c | 88 ++++++++++++++++++++--------------------- drivers/char/vt.c | 2 +- drivers/char/vt_ioctl.c | 3 +- drivers/net/slip.c | 2 +- fs/binfmt_elf.c | 4 +- fs/dquot.c | 10 ++--- fs/exec.c | 5 +++ fs/open.c | 2 +- fs/proc/array.c | 8 ++-- include/linux/sched.h | 32 +++++++++++---- kernel/acct.c | 2 +- kernel/exit.c | 22 +++++------ kernel/fork.c | 14 +++++-- kernel/pid.c | 8 ++-- kernel/signal.c | 5 ++- kernel/sys.c | 18 ++++----- net/ipv4/netfilter/ipt_owner.c | 2 +- net/ipv6/netfilter/ip6t_owner.c | 2 +- 21 files changed, 132 insertions(+), 104 deletions(-) diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c index 95f77b1dfa11..c6afad0dd189 100644 --- a/arch/ia64/kernel/unaligned.c +++ b/arch/ia64/kernel/unaligned.c @@ -1347,7 +1347,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) * be holding locks... */ if (user_mode(regs)) - tty_write_message(current->tty, buf); + tty_write_message(process_tty(current), buf); buf[len-1] = '\0'; /* drop '\r' */ printk(KERN_WARNING "%s", buf); /* watch for command names containing %s */ } diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 44d551ba1091..4a3fc4deb24a 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -974,7 +974,8 @@ do_it_again: /* NOTE: not yet done after every sleep pending a thorough check of the logic of this change. -- jlc */ /* don't stop on /dev/console */ - if (file->f_op->write != redirected_tty_write && current->tty == tty) { + if (file->f_op->write != redirected_tty_write && + process_tty(current) == tty) { if (tty->pgrp <= 0) printk("read_chan: tty->pgrp <= 0!\n"); else if (process_group(current) != tty->pgrp) { diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 843c4b5f8bd8..7c1f55bc1574 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -953,7 +953,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp) /* * Info->count is now 1; so it's safe to sleep now. */ - info->session = current->session; + info->session = process_session(current); info->pgrp = process_group(current); if ((info->flags & ROCKET_INITIALIZED) == 0) { diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 31a43060d708..6191811d0ecf 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -314,7 +314,7 @@ struct tty_driver *get_tty_driver(dev_t device, int *index) */ int tty_check_change(struct tty_struct * tty) { - if (current->tty != tty) + if (process_tty(current) != tty) return 0; if (tty->pgrp <= 0) { printk(KERN_WARNING "tty_check_change: tty->pgrp <= 0!\n"); @@ -481,14 +481,14 @@ void do_tty_hangup(void *data) if (tty->session > 0) { struct list_head *l; for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid) { - if (p->tty == tty) - p->tty = NULL; - if (!p->leader) + if (process_tty(p) == tty) + p->signal->tty = NULL; + if (!process_session_leader(p)) continue; send_group_sig_info(SIGHUP, SEND_SIG_PRIV, p); send_group_sig_info(SIGCONT, SEND_SIG_PRIV, p); if (tty->pgrp > 0) - p->tty_old_pgrp = tty->pgrp; + p->signal->tty_old_pgrp = tty->pgrp; } } read_unlock(&tasklist_lock); @@ -565,15 +565,15 @@ void disassociate_ctty(int on_exit) lock_kernel(); - tty = current->tty; + tty = process_tty(current); if (tty) { tty_pgrp = tty->pgrp; if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) tty_vhangup(tty); } else { - if (current->tty_old_pgrp) { - kill_pg(current->tty_old_pgrp, SIGHUP, on_exit); - kill_pg(current->tty_old_pgrp, SIGCONT, on_exit); + if (current->signal->tty_old_pgrp) { + kill_pg(current->signal->tty_old_pgrp, SIGHUP, on_exit); + kill_pg(current->signal->tty_old_pgrp, SIGCONT, on_exit); } unlock_kernel(); return; @@ -584,13 +584,13 @@ void disassociate_ctty(int on_exit) kill_pg(tty_pgrp, SIGCONT, on_exit); } - current->tty_old_pgrp = 0; + current->signal->tty_old_pgrp = 0; tty->session = 0; tty->pgrp = -1; read_lock(&tasklist_lock); - for_each_task_pid(current->session, PIDTYPE_SID, p, l, pid) - p->tty = NULL; + for_each_task_pid(process_session(current), PIDTYPE_SID, p, l, pid) + p->signal->tty = NULL; read_unlock(&tasklist_lock); unlock_kernel(); } @@ -1218,10 +1218,10 @@ static void release_dev(struct file * filp) read_lock(&tasklist_lock); for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid) - p->tty = NULL; + p->signal->tty = NULL; if (o_tty) for_each_task_pid(o_tty->session, PIDTYPE_SID, p,l, pid) - p->tty = NULL; + p->signal->tty = NULL; read_unlock(&tasklist_lock); } @@ -1292,10 +1292,10 @@ static int tty_open(struct inode * inode, struct file * filp) retry_open: noctty = filp->f_flags & O_NOCTTY; if (device == MKDEV(TTYAUX_MAJOR,0)) { - if (!current->tty) + if (!process_tty(current)) return -ENXIO; - driver = current->tty->driver; - index = current->tty->index; + driver = process_tty(current)->driver; + index = process_tty(current)->index; filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */ /* noctty = 1; */ goto got_driver; @@ -1389,15 +1389,13 @@ got_driver: filp->f_op = &tty_fops; goto retry_open; } - if (!noctty && - current->leader && - !current->tty && - tty->session == 0) { + if (!noctty && process_session_leader(current) && + !process_tty(current) && tty->session == 0) { task_lock(current); - current->tty = tty; + current->signal->tty = tty; task_unlock(current); - current->tty_old_pgrp = 0; - tty->session = current->session; + current->signal->tty_old_pgrp = 0; + tty->session = process_session(current); tty->pgrp = process_group(current); } return 0; @@ -1455,7 +1453,7 @@ static int tiocsti(struct tty_struct *tty, char * arg) { char ch, mbz = 0; - if ((current->tty != tty) && !capable(CAP_SYS_ADMIN)) + if ((process_tty(current) != tty) && !capable(CAP_SYS_ADMIN)) return -EPERM; if (get_user(ch, arg)) return -EFAULT; @@ -1541,14 +1539,14 @@ static int tiocsctty(struct tty_struct *tty, int arg) struct pid *pid; task_t *p; - if (current->leader && - (current->session == tty->session)) + if (process_session_leader(current) && + (process_session(current) == tty->session)) return 0; /* * The process must be a session leader and * not have a controlling tty already. */ - if (!current->leader || current->tty) + if (!process_session_leader(current) || process_tty(current)) return -EPERM; if (tty->session > 0) { /* @@ -1562,16 +1560,16 @@ static int tiocsctty(struct tty_struct *tty, int arg) read_lock(&tasklist_lock); for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid) - p->tty = NULL; + p->signal->tty = NULL; read_unlock(&tasklist_lock); } else return -EPERM; } task_lock(current); - current->tty = tty; + current->signal->tty = tty; task_unlock(current); - current->tty_old_pgrp = 0; - tty->session = current->session; + current->signal->tty_old_pgrp = 0; + tty->session = process_session(current); tty->pgrp = process_group(current); return 0; } @@ -1582,12 +1580,13 @@ static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t * (tty == real_tty) is a cheap way of * testing if the tty is NOT a master pty. */ - if (tty == real_tty && current->tty != real_tty) + if (tty == real_tty && process_tty(current) != real_tty) return -ENOTTY; return put_user(real_tty->pgrp, arg); } -static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t *arg) +static int tiocspgrp(struct tty_struct *tty, + struct tty_struct *real_tty, pid_t *arg) { pid_t pgrp; int retval = tty_check_change(real_tty); @@ -1596,15 +1595,14 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t return -ENOTTY; if (retval) return retval; - if (!current->tty || - (current->tty != real_tty) || - (real_tty->session != current->session)) + if (!process_tty(current) || (process_tty(current) != real_tty) || + (real_tty->session != process_session(current))) return -ENOTTY; if (get_user(pgrp, (pid_t *) arg)) return -EFAULT; if (pgrp < 0) return -EINVAL; - if (session_of_pgrp(pgrp) != current->session) + if (session_of_pgrp(pgrp) != process_session(current)) return -EPERM; real_tty->pgrp = pgrp; return 0; @@ -1616,7 +1614,7 @@ static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t * * (tty == real_tty) is a cheap way of * testing if the tty is NOT a master pty. */ - if (tty == real_tty && current->tty != real_tty) + if (tty == real_tty && process_tty(current) != real_tty) return -ENOTTY; if (real_tty->session <= 0) return -ENOTTY; @@ -1774,12 +1772,12 @@ int tty_ioctl(struct inode * inode, struct file * file, clear_bit(TTY_EXCLUSIVE, &tty->flags); return 0; case TIOCNOTTY: - if (current->tty != tty) + if (process_tty(current) != tty) return -ENOTTY; - if (current->leader) + if (process_session_leader(current)) disassociate_ctty(0); task_lock(current); - current->tty = NULL; + current->signal->tty = NULL; task_unlock(current); return 0; case TIOCSCTTY: @@ -1883,10 +1881,10 @@ static void __do_SAK(void *arg) tty->driver->flush_buffer(tty); read_lock(&tasklist_lock); for_each_task_pid(session, PIDTYPE_SID, p, l, pid) { - if (p->tty == tty || session > 0) { + if (process_tty(p) == tty || session > 0) { printk(KERN_NOTICE "SAK: killed process %d" - " (%s): p->session==tty->session\n", - p->pid, p->comm); + " (%s): process_session(p)==tty->session\n", + p->pid, p->comm); send_sig(SIGKILL, p, 1); continue; } diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 464c3404d4dc..1bbc8a6f51c8 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -2226,7 +2226,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) if (tty->driver->type != TTY_DRIVER_TYPE_CONSOLE) return -EINVAL; - if (current->tty != tty && !capable(CAP_SYS_ADMIN)) + if (process_tty(current) != tty && !capable(CAP_SYS_ADMIN)) return -EPERM; if (get_user(type, (char *)arg)) return -EFAULT; diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index ca817c0758ad..967d6ce1823c 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c @@ -380,7 +380,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. */ perm = 0; - if (current->tty == tty || capable(CAP_SYS_TTY_CONFIG)) + if (process_tty(current) == tty || capable(CAP_SYS_TTY_CONFIG)) perm = 1; kbd = kbd_table + console; @@ -1188,4 +1188,3 @@ void change_console(unsigned int new_console) complete_change_console(new_console); } - diff --git a/drivers/net/slip.c b/drivers/net/slip.c index 601df52ebb29..2ca38bcdc848 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -1307,7 +1307,7 @@ static int sl_ioctl(struct net_device *dev,struct ifreq *rq,int cmd) /* Resolve race condition, when ioctl'ing hanged up and opened by another process device. */ - if (sl->tty != current->tty && sl->pid != current->pid) { + if (sl->tty != process_tty(current) && sl->pid != current->pid) { spin_unlock_bh(&sl->lock); return -EPERM; } diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 2cdd10da42fd..505c73aa94ee 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1084,7 +1084,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus, prstatus->pr_pid = p->pid; prstatus->pr_ppid = p->parent->pid; prstatus->pr_pgrp = process_group(p); - prstatus->pr_sid = p->session; + prstatus->pr_sid = process_session(p); jiffies_to_timeval(p->utime, &prstatus->pr_utime); jiffies_to_timeval(p->stime, &prstatus->pr_stime); jiffies_to_timeval(p->cutime, &prstatus->pr_cutime); @@ -1112,7 +1112,7 @@ static void fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, psinfo->pr_pid = p->pid; psinfo->pr_ppid = p->parent->pid; psinfo->pr_pgrp = process_group(p); - psinfo->pr_sid = p->session; + psinfo->pr_sid = process_session(p); i = p->state ? ffz(~p->state) + 1 : 0; psinfo->pr_state = i; diff --git a/fs/dquot.c b/fs/dquot.c index 9b3a6aae6c5f..4110e97e3bf5 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -668,12 +668,12 @@ static void print_warning(struct dquot *dquot, const char warntype) if (!need_print_warning(dquot) || (flag && test_and_set_bit(flag, &dquot->dq_flags))) return; - tty_write_message(current->tty, dquot->dq_sb->s_id); + tty_write_message(process_tty(current), dquot->dq_sb->s_id); if (warntype == ISOFTWARN || warntype == BSOFTWARN) - tty_write_message(current->tty, ": warning, "); + tty_write_message(process_tty(current), ": warning, "); else - tty_write_message(current->tty, ": write failed, "); - tty_write_message(current->tty, quotatypes[dquot->dq_type]); + tty_write_message(process_tty(current), ": write failed, "); + tty_write_message(process_tty(current), quotatypes[dquot->dq_type]); switch (warntype) { case IHARDWARN: msg = " file limit reached.\n"; @@ -694,7 +694,7 @@ static void print_warning(struct dquot *dquot, const char warntype) msg = " block quota exceeded.\n"; break; } - tty_write_message(current->tty, msg); + tty_write_message(process_tty(current), msg); } static inline void flush_warnings(struct dquot **dquots, char *warntype) diff --git a/fs/exec.c b/fs/exec.c index 84d224e71d3a..e4bc842cd9c7 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -596,6 +596,11 @@ static inline int de_thread(struct task_struct *tsk) newsig->group_stop_count = 0; newsig->curr_target = NULL; init_sigpending(&newsig->shared_pending); + + newsig->pgrp = oldsig->pgrp; + newsig->session = oldsig->session; + newsig->leader = oldsig->leader; + newsig->tty_old_pgrp = oldsig->tty_old_pgrp; } if (thread_group_empty(current)) diff --git a/fs/open.c b/fs/open.c index b5550e9049af..cac72d129b71 100644 --- a/fs/open.c +++ b/fs/open.c @@ -1019,7 +1019,7 @@ out_unlock: asmlinkage long sys_vhangup(void) { if (capable(CAP_SYS_TTY_CONFIG)) { - tty_vhangup(current->tty); + tty_vhangup(process_tty(current)); return 0; } return -EPERM; diff --git a/fs/proc/array.c b/fs/proc/array.c index 1eba76a6f603..7029fc9eb211 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -304,9 +304,9 @@ int proc_pid_stat(struct task_struct *task, char * buffer) mm = task->mm; if(mm) mm = mmgrab(mm); - if (task->tty) { - tty_pgrp = task->tty->pgrp; - tty_nr = new_encode_dev(tty_devnum(task->tty)); + if (process_tty(task)) { + tty_pgrp = process_tty(task)->pgrp; + tty_nr = new_encode_dev(tty_devnum(process_tty(task))); } task_unlock(task); if (mm) { @@ -345,7 +345,7 @@ int proc_pid_stat(struct task_struct *task, char * buffer) state, ppid, process_group(task), - task->session, + process_session(task), tty_nr, tty_pgrp, task->flags, diff --git a/include/linux/sched.h b/include/linux/sched.h index 21a1c416594c..a504b6a92ccf 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -264,6 +264,15 @@ struct signal_struct { /* thread group stop support, overloads group_exit_code too */ int group_stop_count; + + /* job control IDs */ + pid_t pgrp; + pid_t tty_old_pgrp; + pid_t session; + /* boolean value for session group leader */ + int leader; + + struct tty_struct *tty; /* NULL if no tty */ }; /* @@ -366,12 +375,7 @@ struct task_struct { unsigned long personality; int did_exec:1; pid_t pid; - pid_t __pgrp; /* Accessed via process_group() */ - pid_t tty_old_pgrp; - pid_t session; pid_t tgid; - /* boolean value for session group leader */ - int leader; /* * pointers to (original) parent process, youngest child, younger sibling, * older sibling, respectively. (p->father can be replaced with @@ -415,7 +419,6 @@ struct task_struct { char comm[16]; /* file system info */ int link_count, total_link_count; - struct tty_struct *tty; /* NULL if no tty */ unsigned int locks; /* How many file locks are being held */ /* ipc stuff */ struct sysv_sem sysvsem; @@ -469,7 +472,22 @@ struct task_struct { static inline pid_t process_group(struct task_struct *tsk) { - return tsk->group_leader->__pgrp; + return tsk->signal->pgrp; +} + +static inline pid_t process_session(struct task_struct *tsk) +{ + return tsk->signal->session; +} + +static inline int process_session_leader(struct task_struct *tsk) +{ + return tsk->signal->leader; +} + +static inline struct tty_struct *process_tty(struct task_struct *tsk) +{ + return tsk->signal->tty; } extern void __put_task_struct(struct task_struct *tsk); diff --git a/kernel/acct.c b/kernel/acct.c index a679f4bb9854..37e98d713023 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -343,7 +343,7 @@ static void do_acct_process(long exitcode, struct file *file) /* we really need to bite the bullet and change layout */ ac.ac_uid = current->uid; ac.ac_gid = current->gid; - ac.ac_tty = current->tty ? old_encode_dev(tty_devnum(current->tty)) : 0; + ac.ac_tty = process_tty(current) ? old_encode_dev(tty_devnum(process_tty(current))) : 0; ac.ac_flag = 0; if (current->flags & PF_FORKNOEXEC) diff --git a/kernel/exit.c b/kernel/exit.c index c565fd69d559..a87c12eed85d 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -119,13 +119,13 @@ int session_of_pgrp(int pgrp) read_lock(&tasklist_lock); for_each_task_pid(pgrp, PIDTYPE_PGID, p, l, pid) - if (p->session > 0) { - sid = p->session; + if (process_session(p) > 0) { + sid = process_session(p); goto out; } p = find_task_by_pid(pgrp); if (p) - sid = p->session; + sid = process_session(p); out: read_unlock(&tasklist_lock); @@ -153,7 +153,7 @@ static int will_become_orphaned_pgrp(int pgrp, task_t *ignored_task) || p->real_parent->pid == 1) continue; if (process_group(p->real_parent) != pgrp - && p->real_parent->session == p->session) { + && process_session(p->real_parent) == process_session(p)) { ret = 0; break; } @@ -242,14 +242,14 @@ void __set_special_pids(pid_t session, pid_t pgrp) { struct task_struct *curr = current; - if (curr->session != session) { + if (process_session(curr) != session) { detach_pid(curr, PIDTYPE_SID); - curr->session = session; + curr->signal->session = session; attach_pid(curr, PIDTYPE_SID, session); } if (process_group(curr) != pgrp) { detach_pid(curr, PIDTYPE_PGID); - curr->group_leader->__pgrp = pgrp; + curr->signal->pgrp = pgrp; attach_pid(curr, PIDTYPE_PGID, pgrp); } } @@ -303,7 +303,7 @@ void daemonize(const char *name, ...) exit_mm(current); set_special_pids(1, 1); - current->tty = NULL; + current->signal->tty = NULL; /* Block and flush all signals */ sigfillset(&blocked); @@ -509,7 +509,7 @@ static inline void reparent_thread(task_t *p, task_t *father, int traced) * outside, so the child pgrp is now orphaned. */ if ((process_group(p) != process_group(father)) && - (p->session == father->session)) { + (process_session(p) == process_session(father))) { int pgrp = process_group(p); if (will_become_orphaned_pgrp(pgrp, NULL) && has_stopped_jobs(pgrp)) { @@ -619,7 +619,7 @@ static void exit_notify(struct task_struct *tsk) t = tsk->real_parent; if ((process_group(t) != process_group(tsk)) && - (t->session == tsk->session) && + (process_session(t) == process_session(tsk)) && will_become_orphaned_pgrp(process_group(tsk), tsk) && has_stopped_jobs(process_group(tsk))) { __kill_pg_info(SIGHUP, (void *)1, process_group(tsk)); @@ -714,7 +714,7 @@ NORET_TYPE void do_exit(long code) exit_itimers(tsk); exit_thread(); - if (tsk->leader) + if (process_session_leader(tsk)) disassociate_ctty(1); module_put(tsk->thread_info->exec_domain->module); diff --git a/kernel/fork.c b/kernel/fork.c index 2005c5c180de..f804f3124820 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -725,6 +725,12 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts sig->curr_target = NULL; init_sigpending(&sig->shared_pending); + sig->tty = process_tty(current); + sig->pgrp = process_group(current); + sig->session = process_session(current); + sig->leader = 0; /* session leadership doesn't inherit */ + sig->tty_old_pgrp = 0; + return 0; } @@ -771,7 +777,9 @@ struct task_struct *copy_process(unsigned long clone_flags, * Thread groups must share signals as well, and detached threads * can only be started up within the thread group. */ - if ((clone_flags & CLONE_THREAD) && !(clone_flags & CLONE_SIGHAND)) + if ((clone_flags & CLONE_THREAD) && + (clone_flags & (CLONE_SIGHAND|CLONE_DETACHED)) != + (CLONE_SIGHAND|CLONE_DETACHED)) return ERR_PTR(-EINVAL); /* @@ -876,8 +884,6 @@ struct task_struct *copy_process(unsigned long clone_flags, init_timer(&p->real_timer); p->real_timer.data = (unsigned long) p; - p->leader = 0; /* session leadership doesn't inherit */ - p->tty_old_pgrp = 0; p->utime = p->stime = 0; p->cutime = p->cstime = 0; p->array = NULL; @@ -1022,7 +1028,7 @@ struct task_struct *copy_process(unsigned long clone_flags, if (thread_group_leader(p)) { attach_pid(p, PIDTYPE_TGID, p->tgid); attach_pid(p, PIDTYPE_PGID, process_group(p)); - attach_pid(p, PIDTYPE_SID, p->session); + attach_pid(p, PIDTYPE_SID, process_session(p)); if (p->pid) __get_cpu_var(process_counts)++; } else diff --git a/kernel/pid.c b/kernel/pid.c index 713f54eaeda9..97bdf534c9f3 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -250,14 +250,14 @@ void switch_exec_pids(task_t *leader, task_t *thread) attach_pid(thread, PIDTYPE_PID, thread->pid); attach_pid(thread, PIDTYPE_TGID, thread->tgid); - attach_pid(thread, PIDTYPE_PGID, leader->__pgrp); - attach_pid(thread, PIDTYPE_SID, thread->session); + attach_pid(thread, PIDTYPE_PGID, thread->signal->pgrp); + attach_pid(thread, PIDTYPE_SID, thread->signal->session); list_add_tail(&thread->tasks, &init_task.tasks); attach_pid(leader, PIDTYPE_PID, leader->pid); attach_pid(leader, PIDTYPE_TGID, leader->tgid); - attach_pid(leader, PIDTYPE_PGID, leader->__pgrp); - attach_pid(leader, PIDTYPE_SID, leader->session); + attach_pid(leader, PIDTYPE_PGID, leader->signal->pgrp); + attach_pid(leader, PIDTYPE_SID, leader->signal->session); } /* diff --git a/kernel/signal.c b/kernel/signal.c index 852da1a009da..469deaeeff56 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -593,7 +593,8 @@ static int check_kill_permission(int sig, struct siginfo *info, error = -EPERM; if ((!info || ((unsigned long)info != 1 && (unsigned long)info != 2 && SI_FROMUSER(info))) - && ((sig != SIGCONT) || (current->session != t->session)) + && ((sig != SIGCONT) || + (process_session(current) != process_session(t))) && (current->euid ^ t->suid) && (current->euid ^ t->uid) && (current->uid ^ t->suid) && (current->uid ^ t->uid) && !capable(CAP_KILL)) @@ -1102,7 +1103,7 @@ kill_sl_info(int sig, struct siginfo *info, pid_t sid) retval = -ESRCH; read_lock(&tasklist_lock); for_each_task_pid(sid, PIDTYPE_SID, p, l, pid) { - if (!p->leader) + if (!process_session_leader(p)) continue; err = group_send_sig_info(sig, info, p); if (retval) diff --git a/kernel/sys.c b/kernel/sys.c index 9eda26d6745c..6f8f43156ab3 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -951,7 +951,7 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) if (p->parent == current || p->real_parent == current) { err = -EPERM; - if (p->session != current->session) + if (process_session(p) != process_session(current)) goto out; err = -EACCES; if (p->did_exec) @@ -963,7 +963,7 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) } err = -EPERM; - if (p->leader) + if (process_session_leader(p)) goto out; if (pgid != pid) { @@ -972,7 +972,7 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) struct list_head *l; for_each_task_pid(pgid, PIDTYPE_PGID, p, l, pid) - if (p->session == current->session) + if (process_session(p) == process_session(current)) goto ok_pgid; goto out; } @@ -984,7 +984,7 @@ ok_pgid: if (process_group(p) != pgid) { detach_pid(p, PIDTYPE_PGID); - p->group_leader->__pgrp = pgid; + p->signal->pgrp = pgid; attach_pid(p, PIDTYPE_PGID, pgid); } @@ -1026,7 +1026,7 @@ asmlinkage long sys_getpgrp(void) asmlinkage long sys_getsid(pid_t pid) { if (!pid) { - return current->session; + return process_session(current); } else { int retval; struct task_struct *p; @@ -1038,7 +1038,7 @@ asmlinkage long sys_getsid(pid_t pid) if(p) { retval = security_task_getsid(p); if (!retval) - retval = p->session; + retval = process_session(p); } read_unlock(&tasklist_lock); return retval; @@ -1059,10 +1059,10 @@ asmlinkage long sys_setsid(void) if (pid) goto out; - current->leader = 1; + current->signal->leader = 1; __set_special_pids(current->pid, current->pid); - current->tty = NULL; - current->tty_old_pgrp = 0; + current->signal->tty = NULL; + current->signal->tty_old_pgrp = 0; err = process_group(current); out: write_unlock_irq(&tasklist_lock); diff --git a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c index 279263f2d160..4e7f9558ab75 100644 --- a/net/ipv4/netfilter/ipt_owner.c +++ b/net/ipv4/netfilter/ipt_owner.c @@ -90,7 +90,7 @@ match_sid(const struct sk_buff *skb, pid_t sid) read_lock(&tasklist_lock); do_each_thread(g, p) { struct files_struct *files; - if (p->session != sid) + if (process_session(p) != sid) continue; task_lock(p); diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c index cf230014ccce..e05916bf7f49 100644 --- a/net/ipv6/netfilter/ip6t_owner.c +++ b/net/ipv6/netfilter/ip6t_owner.c @@ -56,7 +56,7 @@ match_sid(const struct sk_buff *skb, pid_t sid) read_lock(&tasklist_lock); do_each_thread(g, p) { struct files_struct *files; - if (p->session != sid) + if (process_session(p) != sid) continue; task_lock(p); -- cgit v1.2.3 From 3479607fae84bd00f1f6fbdf34d10b2106e39b0f Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 4 Oct 2003 21:04:20 -0700 Subject: [PATCH] fix "compat ioctl consolidation" for "move job A little fix which is needed if both the "compat ioctl consolidation" and "move job control fields from task_struct to signal_struct" patches are applied. --- fs/compat_ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 88f750e4f16f..16c7de3c9d1b 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -1574,7 +1574,7 @@ static int vt_check(struct file *file) * To have permissions to do most of the vt ioctls, we either have * to be the owner of the tty, or super-user. */ - if (current->tty == tty || capable(CAP_SYS_ADMIN)) + if (process_tty(current) == tty || capable(CAP_SYS_ADMIN)) return 1; return 0; } -- cgit v1.2.3 From 11d3c5ea4e4b16afcbe5f0966ed44b8b8f5ce5e5 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 4 Oct 2003 21:04:28 -0700 Subject: [PATCH] fix pte_chain leak in do_no_page() From: "V. Rajesh" Fix a rare pte_chain memory leak in do_no_page() --- mm/memory.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mm/memory.c b/mm/memory.c index be552e3cffbd..7e105f02d82b 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1441,6 +1441,7 @@ retry: sequence = atomic_read(&mapping->truncate_count); spin_unlock(&mm->page_table_lock); page_cache_release(new_page); + pte_chain_free(pte_chain); goto retry; } page_table = pte_offset_map(pmd, address); -- cgit v1.2.3