diff options
| author | Linus Torvalds <torvalds@penguin.transmeta.com> | 2003-01-14 01:08:14 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@penguin.transmeta.com> | 2003-01-14 01:08:14 -0800 |
| commit | 200ce8b3fe4fa22d95da992de667a9097c97c529 (patch) | |
| tree | a11a303e9a7da68e21cb3deb09a84c6d24140896 | |
| parent | 9f9618b6ae0025f394834c6ec53a37baed5cdeb7 (diff) | |
| parent | 1105415188b0cf41e28c0145e827b60a975e45d7 (diff) | |
Merge http://fbdev.bkbits.net:8080/fbdev-2.5
into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
79 files changed, 1708 insertions, 752 deletions
diff --git a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt index d2e805565bdc..f6abc861c271 100644 --- a/Documentation/crypto/api-intro.txt +++ b/Documentation/crypto/api-intro.txt @@ -80,6 +80,10 @@ should also be added: alias digest_null crypto_null alias compress_null crypto_null +The SHA384 algorithm shares code within the SHA512 module, so you'll +also need: + alias sha384 sha512 + DEVELOPER NOTES @@ -182,7 +186,7 @@ Original developers of the crypto algorithms: Andrew Tridgell and Steve French (MD4) Colin Plumb (MD5) Steve Reid (SHA1) - Jean-Luc Cooke (SHA256) + Jean-Luc Cooke (SHA256, SHA384, SHA512) Kazunori Miyazawa / USAGI (HMAC) Matthew Skala (Twofish) Dag Arne Osvik (Serpent) @@ -201,9 +205,11 @@ Twofish algorithm contributors: Werner Koch Marc Mutz -SHA256 algorithm contributors: +SHA256/384/512 algorithm contributors: Andrew McDonald - + Kyle McMartin + Herbert Valerio Riedel + AES algorithm contributors: Alexander Kjeldaas Herbert Valerio Riedel diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 7e6df7d5f2da..58e4c2d4b239 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S @@ -10,7 +10,7 @@ * This file is included twice in entry-common.S */ #ifndef NR_syscalls -#define NR_syscalls 256 +#define NR_syscalls 288 #else __syscall_start: @@ -253,6 +253,24 @@ __syscall_start: .long sys_lremovexattr .long sys_fremovexattr .long sys_tkill + .long sys_sendfile64 +/* 240 */ .long sys_futex + .long sys_sched_setaffinity + .long sys_sched_getaffinity + .long sys_io_setup + .long sys_io_destroy +/* 245 */ .long sys_io_getevents + .long sys_io_submit + .long sys_io_cancel + .long sys_exit_group + .long sys_lookup_dcookie +/* 250 */ .long sys_epoll_create + .long sys_epoll_ctl + .long sys_epoll_wait + .long sys_remap_file_pages + .long sys_ni_syscall /* sys_set_thread_area */ +/* 255 */ .long sys_ni_syscall /* sys_get_thread_area */ + .long sys_ni_syscall /* sys_set_tid_address */ __syscall_end: .rept NR_syscalls - (__syscall_end - __syscall_start) / 4 diff --git a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c index 2d71baa76351..9a55cfdb6cbe 100644 --- a/arch/arm/mach-integrator/cpu.c +++ b/arch/arm/mach-integrator/cpu.c @@ -228,4 +228,4 @@ static int __init integrator_cpu_init(void) return 0; } -core_initcall(integrator_cpu_init); +arch_initcall(integrator_cpu_init); diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c index b4226692b902..9c1c4ba81c4e 100644 --- a/arch/arm/mach-sa1100/cpu-sa1100.c +++ b/arch/arm/mach-sa1100/cpu-sa1100.c @@ -232,4 +232,4 @@ static int __init sa1100_dram_init(void) return ret; } -core_initcall(sa1100_dram_init); +arch_initcall(sa1100_dram_init); diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c index 2ab03f867d86..ecfc2c113a7e 100644 --- a/arch/arm/mach-sa1100/cpu-sa1110.c +++ b/arch/arm/mach-sa1100/cpu-sa1110.c @@ -345,4 +345,4 @@ static int __init sa1110_clk_init(void) return 0; } -core_initcall(sa1110_clk_init); +arch_initcall(sa1110_clk_init); diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c index d0272733c39b..762a1a8d8c01 100644 --- a/arch/i386/kernel/cpu/amd.c +++ b/arch/i386/kernel/cpu/amd.c @@ -56,7 +56,7 @@ static void __init init_amd(struct cpuinfo_x86 *c) if (inl (CBAR) & CBAR_ENB) outl (0 | CBAR_KEY, CBAR); } - + break; case 5: if( c->x86_model < 6 ) { diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c index af05636fe86d..722d29cc1b3a 100644 --- a/arch/i386/kernel/cpu/proc.c +++ b/arch/i386/kernel/cpu/proc.c @@ -22,7 +22,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov", "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx", - "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", NULL, + "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe", /* AMD-defined */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index b5403396d199..155876ea5314 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -139,6 +139,39 @@ config NR_CPUS depends on SMP default "64" +config CPU_FREQ + bool "CPU Frequency scaling" + help + Clock scaling allows you to change the clock speed of CPUs on the + fly. Currently there is only a sparc64 driver for UltraSPARC-III + processors. + + For details, take a look at linux/Documentation/cpufreq. + + If in doubt, say N. + +config CPU_FREQ_PROC_INTF + bool "/proc/cpufreq interface (DEPRECATED)" + depends on CPU_FREQ && PROC_FS + help + This enables the /proc/cpufreq interface for controlling + CPUFreq. Please note that it is recommended to use the sysfs + interface instead (which is built automatically). + + For details, take a look at linux/Documentation/cpufreq. + + If in doubt, say N. + +config US3_FREQ + tristate "UltraSPARC-III CPU Frequency driver" + depends on CPU_FREQ + help + This adds the CPUFreq driver for UltraSPARC-III processors. + + For details, take a look at linux/Documentation/cpufreq. + + If in doubt, say N. + # Identify this as a Sparc64 build config SPARC64 bool diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 322a6f191154..dcfab416133c 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o ioctl32.o obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o obj-$(CONFIG_BINFMT_AOUT32) += binfmt_aout32.o obj-$(CONFIG_MODULES) += module.o +obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o ifdef CONFIG_SUNOS_EMUL obj-y += sys_sunos32.o sunos_ioctl32.o diff --git a/arch/sparc64/kernel/us3_cpufreq.c b/arch/sparc64/kernel/us3_cpufreq.c new file mode 100644 index 000000000000..520860cd46da --- /dev/null +++ b/arch/sparc64/kernel/us3_cpufreq.c @@ -0,0 +1,250 @@ +/* us3_cpufreq.c: UltraSPARC-III cpu frequency support + * + * Copyright (C) 2003 David S. Miller (davem@redhat.com) + * + * Many thanks to Dominik Brodowski for fixing up the cpufreq + * infrastructure in order to make this driver easier to implement. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/smp.h> +#include <linux/cpufreq.h> +#include <linux/threads.h> +#include <linux/slab.h> +#include <linux/init.h> + +static struct cpufreq_driver *cpufreq_us3_driver; + +/* Index by [(CPU * 4) + INDEX] (first three indices are + * actual us3 divisor entries, last is for CPUFREQ_TABLE_END) + */ +static struct cpufreq_frequency_table *us3_freq_table; + +/* UltraSPARC-III has three dividers: 1, 2, and 32. These are controlled + * in the Safari config register. + */ +#define SAFARI_CFG_DIV_1 0x0000000000000000UL +#define SAFARI_CFG_DIV_2 0x0000000040000000UL +#define SAFARI_CFG_DIV_32 0x0000000080000000UL +#define SAFARI_CFG_DIV_MASK 0x00000000C0000000UL + +static unsigned long read_safari_cfg(void) +{ + unsigned long ret; + + __asm__ __volatile__("ldxa [%%g0] %1, %0" + : "=&r" (ret) + : "i" (ASI_SAFARI_CONFIG)); + return ret; +} + +static void write_safari_cfg(unsigned long val) +{ + __asm__ __volatile__("stxa %0, [%%g0] %1\n\t" + "membar #Sync" + : /* no outputs */ + : "r" (val), "i" (ASI_SAFARI_CONFIG) + : "memory"); +} + +#ifndef CONFIG_SMP +extern unsigned long up_clock_tick; +#endif + +static __inline__ unsigned long get_clock_tick(unsigned int cpu) +{ +#ifdef CONFIG_SMP + return cpu_data[cpu].clock_tick; +#else + return up_clock_tick; +#endif +} + +static unsigned long get_current_freq(unsigned int cpu, unsigned long safari_cfg) +{ + unsigned long clock_tick = get_clock_tick(cpu); + unsigned long ret; + + switch (safari_cfg & SAFARI_CFG_DIV_MASK) { + case SAFARI_CFG_DIV_1: + ret = clock_tick / 1; + break; + case SAFARI_CFG_DIV_2: + ret = clock_tick / 2; + break; + case SAFARI_CFG_DIV_32: + ret = clock_tick / 32; + break; + default: + BUG(); + }; + + return ret; +} + +static void us3_set_cpu_divider_index(unsigned int cpu, unsigned int index) +{ + unsigned long new_bits, new_freq, reg, cpus_allowed; + struct cpufreq_freqs freqs; + + if (!cpu_online(cpu)) + return; + + cpus_allowed = current->cpus_allowed; + set_cpus_allowed(current, (1UL << cpu)); + + new_freq = get_clock_tick(cpu); + switch (index) { + case 0: + new_bits = SAFARI_CFG_DIV_1; + new_freq /= 1; + break; + case 1: + new_bits = SAFARI_CFG_DIV_2; + new_freq /= 2; + break; + case 2: + new_bits = SAFARI_CFG_DIV_32; + new_freq /= 32; + break; + + default: + BUG(); + }; + + reg = read_safari_cfg(); + + freqs.old = get_current_freq(cpu, reg); + freqs.new = new_freq; + freqs.cpu = cpu; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + reg &= ~SAFARI_CFG_DIV_MASK; + reg |= new_bits; + write_safari_cfg(reg); + + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + set_cpus_allowed(current, cpus_allowed); +} + +static int us3_setpolicy(struct cpufreq_policy *policy) +{ + unsigned int new_index = 0; + + if (cpufreq_frequency_table_setpolicy(policy, + &us3_freq_table[(policy->cpu * 4) + 0], + &new_index)) + return -EINVAL; + + us3_set_cpu_divider_index(policy->cpu, new_index); + + return 0; +} + +static int us3_verify(struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, + &us3_freq_table[(policy->cpu * 4) + 0]); +} + +#ifndef CONFIG_SMP +extern unsigned long up_clock_tick; +#endif + +static void __init us3_init_freq_table(unsigned int cpu) +{ + unsigned long clock_tick = get_clock_tick(cpu); + + us3_freq_table[(cpu * 4) + 0].index = 0; + us3_freq_table[(cpu * 4) + 0].frequency = clock_tick / 1; + us3_freq_table[(cpu * 4) + 1].index = 1; + us3_freq_table[(cpu * 4) + 1].frequency = clock_tick / 2; + us3_freq_table[(cpu * 4) + 2].index = 2; + us3_freq_table[(cpu * 4) + 2].frequency = clock_tick / 32; + us3_freq_table[(cpu * 4) + 3].index = 0; + us3_freq_table[(cpu * 4) + 3].frequency = CPUFREQ_TABLE_END; +} + +static int __init us3freq_init(void) +{ + struct cpufreq_driver *driver; + unsigned long manuf, impl, ver; + int i, ret; + + __asm__("rdpr %%ver, %0" : "=r" (ver)); + manuf = ((ver >> 48) & 0xffff); + impl = ((ver >> 32) & 0xffff); + + /* XXX Maybe accept cheetah+ too? */ + if (manuf == 0x3e && impl == 0x14) { + driver = kmalloc(sizeof(struct cpufreq_driver) + + (NR_CPUS * sizeof(struct cpufreq_policy)), + GFP_KERNEL); + if (!driver) + return -ENOMEM; + us3_freq_table = kmalloc( + (NR_CPUS * 4 * sizeof(struct cpufreq_frequency_table)), + GFP_KERNEL); + if (!us3_freq_table) { + kfree(driver); + return -ENOMEM; + } + + driver->policy = (struct cpufreq_policy *) (driver + 1); + driver->verify = us3_verify; + driver->setpolicy = us3_setpolicy; + + for (i = 0; i < NR_CPUS; i++) { + driver->policy[i].cpu = i; + us3_init_freq_table(i); + ret = cpufreq_frequency_table_cpuinfo(&driver->policy[i], + &us3_freq_table[(i * 4) + 0]); + if (ret) { + kfree(driver); + kfree(us3_freq_table); + us3_freq_table = NULL; + return ret; + } + driver->policy[i].policy = CPUFREQ_POLICY_PERFORMANCE; + us3_set_cpu_divider_index(i, 0); + } + cpufreq_us3_driver = driver; + ret = cpufreq_register_driver(driver); + if (ret) { + kfree(driver); + cpufreq_us3_driver = NULL; + kfree(us3_freq_table); + us3_freq_table = NULL; + return ret; + } + return 0; + } + + return -ENODEV; +} + +static void __exit us3freq_exit(void) +{ + int i; + + if (cpufreq_us3_driver) { + for (i = 0; i < NR_CPUS; i++) + us3_set_cpu_divider_index(i, 0); + cpufreq_unregister_driver(cpufreq_us3_driver); + + kfree(cpufreq_us3_driver); + cpufreq_us3_driver = NULL; + kfree(us3_freq_table); + us3_freq_table = NULL; + } +} + +MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); +MODULE_DESCRIPTION("cpufreq driver for UltraSPARC-III"); +MODULE_LICENSE("GPL"); + +module_init(us3freq_init); +module_exit(us3freq_exit); diff --git a/crypto/Kconfig b/crypto/Kconfig index 3fbb8e5108b6..8b81dcd7da4b 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -53,6 +53,18 @@ config CRYPTO_SHA256 This version of SHA implements a 256 bit hash with 128 bits of security against collision attacks. +config CRYPTO_SHA512 + tristate "SHA384 and SHA512 digest algorithms" + depends on CRYPTO + help + SHA512 secure hash standard (DFIPS 180-2). + + This version of SHA implements a 512 bit hash with 256 bits of + security against collision attacks. + + This code also includes SHA-384, a 384 bit hash with 192 bits + of security against collision attacks. + config CRYPTO_DES tristate "DES and Triple DES EDE cipher algorithms" depends on CRYPTO diff --git a/crypto/Makefile b/crypto/Makefile index c05967e3ba0d..fa66d0d7ad91 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_CRYPTO_MD4) += md4.o obj-$(CONFIG_CRYPTO_MD5) += md5.o obj-$(CONFIG_CRYPTO_SHA1) += sha1.o obj-$(CONFIG_CRYPTO_SHA256) += sha256.o +obj-$(CONFIG_CRYPTO_SHA512) += sha512.o obj-$(CONFIG_CRYPTO_DES) += des.o obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o diff --git a/crypto/des.c b/crypto/des.c index 08ca675c24f7..edc648ed891b 100644 --- a/crypto/des.c +++ b/crypto/des.c @@ -1279,10 +1279,8 @@ static int __init init(void) goto out; ret = crypto_register_alg(&des3_ede_alg); - if (ret < 0) { + if (ret < 0) crypto_unregister_alg(&des_alg); - goto out; - } out: return ret; } diff --git a/crypto/sha512.c b/crypto/sha512.c new file mode 100644 index 000000000000..686bb1198397 --- /dev/null +++ b/crypto/sha512.c @@ -0,0 +1,373 @@ +/* SHA-512 code by Jean-Luc Cooke <jlcooke@certainkey.com> + * + * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com> + * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk> + * Copyright (c) 2003 Kyle McMartin <kyle@debian.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + */ + +#include <linux/kernel.h> +#include <linux/module.h> + +#include <linux/mm.h> +#include <linux/init.h> +#include <linux/crypto.h> + +#include <asm/scatterlist.h> +#include <asm/byteorder.h> + +#define SHA384_DIGEST_SIZE 48 +#define SHA512_DIGEST_SIZE 64 +#define SHA384_HMAC_BLOCK_SIZE 96 +#define SHA512_HMAC_BLOCK_SIZE 128 + +struct sha512_ctx { + u64 state[8]; + u32 count[4]; + u8 buf[128]; +}; + +static inline u64 Ch(u64 x, u64 y, u64 z) +{ + return ((x & y) ^ (~x & z)); +} + +static inline u64 Maj(u64 x, u64 y, u64 z) +{ + return ((x & y) ^ (x & z) ^ (y & z)); +} + +static inline u64 RORu64(u64 x, u64 y) +{ + return (x >> y) | (x << (64 - y)); +} + +const u64 sha512_K[80] = { + 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, + 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019, + 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, + 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, + 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, + 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, + 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275, + 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, + 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, + 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725, + 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, + 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, + 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, + 0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001, + 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218, + 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, + 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, + 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, + 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, + 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, + 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, + 0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207, + 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, + 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, + 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, + 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, + 0x5fcb6fab3ad6faec, 0x6c44198c4a475817, +}; + +#define e0(x) (RORu64(x,28) ^ RORu64(x,34) ^ RORu64(x,39)) +#define e1(x) (RORu64(x,14) ^ RORu64(x,18) ^ RORu64(x,41)) +#define s0(x) (RORu64(x, 1) ^ RORu64(x, 8) ^ (x >> 7)) +#define s1(x) (RORu64(x,19) ^ RORu64(x,61) ^ (x >> 6)) + +/* H* initial state for SHA-512 */ +#define H0 0x6a09e667f3bcc908 +#define H1 0xbb67ae8584caa73b +#define H2 0x3c6ef372fe94f82b +#define H3 0xa54ff53a5f1d36f1 +#define H4 0x510e527fade682d1 +#define H5 0x9b05688c2b3e6c1f +#define H6 0x1f83d9abfb41bd6b +#define H7 0x5be0cd19137e2179 + +/* H'* initial state for SHA-384 */ +#define HP0 0xcbbb9d5dc1059ed8 +#define HP1 0x629a292a367cd507 +#define HP2 0x9159015a3070dd17 +#define HP3 0x152fecd8f70e5939 +#define HP4 0x67332667ffc00b31 +#define HP5 0x8eb44a8768581511 +#define HP6 0xdb0c2e0d64f98fa7 +#define HP7 0x47b5481dbefa4fa4 + +static inline void LOAD_OP(int I, u64 *W, const u8 *input) +{ + u64 t1 = input[(8*I) ] & 0xff; + t1 <<= 8; + t1 |= input[(8*I)+1] & 0xff; + t1 <<= 8; + t1 |= input[(8*I)+2] & 0xff; + t1 <<= 8; + t1 |= input[(8*I)+3] & 0xff; + t1 <<= 8; + t1 |= input[(8*I)+4] & 0xff; + t1 <<= 8; + t1 |= input[(8*I)+5] & 0xff; + t1 <<= 8; + t1 |= input[(8*I)+6] & 0xff; + t1 <<= 8; + t1 |= input[(8*I)+7] & 0xff; + W[I] = t1; +} + +static inline void BLEND_OP(int I, u64 *W) +{ + W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16]; +} + +static void +sha512_transform(u64 *state, const u8 *input) +{ + u64 a, b, c, d, e, f, g, h, t1, t2; + u64 W[80]; + + int i; + + /* load the input */ + for (i = 0; i < 16; i++) + LOAD_OP(i, W, input); + + for (i = 16; i < 80; i++) { + BLEND_OP(i, W); + } + + /* load the state into our registers */ + a=state[0]; b=state[1]; c=state[2]; d=state[3]; + e=state[4]; f=state[5]; g=state[6]; h=state[7]; + + /* now iterate */ + for (i=0; i<80; i+=8) { + t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i ] + W[i ]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[i+1]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[i+2]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[i+3]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[i+4]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[i+5]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[i+6]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[i+7]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + } + + state[0] += a; state[1] += b; state[2] += c; state[3] += d; + state[4] += e; state[5] += f; state[6] += g; state[7] += h; + + /* erase our data */ + a = b = c = d = e = f = g = h = t1 = t2 = 0; + memset(W, 0, 80 * sizeof(u64)); +} + +static void +sha512_init(void *ctx) +{ + struct sha512_ctx *sctx = ctx; + sctx->state[0] = H0; + sctx->state[1] = H1; + sctx->state[2] = H2; + sctx->state[3] = H3; + sctx->state[4] = H4; + sctx->state[5] = H5; + sctx->state[6] = H6; + sctx->state[7] = H7; + sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0; + memset(sctx->buf, 0, sizeof(sctx->buf)); +} + +static void +sha384_init(void *ctx) +{ + struct sha512_ctx *sctx = ctx; + sctx->state[0] = HP0; + sctx->state[1] = HP1; + sctx->state[2] = HP2; + sctx->state[3] = HP3; + sctx->state[4] = HP4; + sctx->state[5] = HP5; + sctx->state[6] = HP6; + sctx->state[7] = HP7; + sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0; + memset(sctx->buf, 0, sizeof(sctx->buf)); +} + +static void +sha512_update(void *ctx, const u8 *data, unsigned int len) +{ + struct sha512_ctx *sctx = ctx; + + unsigned int i, index, part_len; + + /* Compute number of bytes mod 128 */ + index = (unsigned int)((sctx->count[0] >> 3) & 0x7F); + + /* Update number of bits */ + if ((sctx->count[0] += (len << 3)) < (len << 3)) { + if ((sctx->count[1] += 1) < 1) + if ((sctx->count[2] += 1) < 1) + sctx->count[3]++; + sctx->count[1] += (len >> 29); + } + + part_len = 128 - index; + + /* Transform as many times as possible. */ + if (len >= part_len) { + memcpy(&sctx->buf[index], data, part_len); + sha512_transform(sctx->state, sctx->buf); + + for (i = part_len; i + 127 < len; i+=128) + sha512_transform(sctx->state, &data[i]); + + index = 0; + } else { + i = 0; + } + + /* Buffer remaining input */ + memcpy(&sctx->buf[index], &data[i], len - i); +} + +static void +sha512_final(void *ctx, u8 *hash) +{ + struct sha512_ctx *sctx = ctx; + + const static u8 padding[128] = { 0x80, }; + + u32 t; + u64 t2; + u8 bits[128]; + unsigned int index, pad_len; + int i, j; + + index = pad_len = t = i = j = 0; + t2 = 0; + + /* Save number of bits */ + t = sctx->count[0]; + bits[15] = t; t>>=8; + bits[14] = t; t>>=8; + bits[13] = t; t>>=8; + bits[12] = t; + t = sctx->count[1]; + bits[11] = t; t>>=8; + bits[10] = t; t>>=8; + bits[9 ] = t; t>>=8; + bits[8 ] = t; + t = sctx->count[2]; + bits[7 ] = t; t>>=8; + bits[6 ] = t; t>>=8; + bits[5 ] = t; t>>=8; + bits[4 ] = t; + t = sctx->count[3]; + bits[3 ] = t; t>>=8; + bits[2 ] = t; t>>=8; + bits[1 ] = t; t>>=8; + bits[0 ] = t; + + /* Pad out to 112 mod 128. */ + index = (sctx->count[0] >> 3) & 0x7f; + pad_len = (index < 112) ? (112 - index) : ((128+112) - index); + sha512_update(sctx, padding, pad_len); + + /* Append length (before padding) */ + sha512_update(sctx, bits, 16); + + /* Store state in digest */ + for (i = j = 0; i < 8; i++, j += 8) { + t2 = sctx->state[i]; + hash[j+7] = (char)t2 & 0xff; t2>>=8; + hash[j+6] = (char)t2 & 0xff; t2>>=8; + hash[j+5] = (char)t2 & 0xff; t2>>=8; + hash[j+4] = (char)t2 & 0xff; t2>>=8; + hash[j+3] = (char)t2 & 0xff; t2>>=8; + hash[j+2] = (char)t2 & 0xff; t2>>=8; + hash[j+1] = (char)t2 & 0xff; t2>>=8; + hash[j ] = (char)t2 & 0xff; + } + + /* Zeroize sensitive information. */ + memset(sctx, 0, sizeof(struct sha512_ctx)); +} + +static void sha384_final(void *ctx, u8 *hash) +{ + struct sha512_ctx *sctx = ctx; + u8 D[64]; + + sha512_final(sctx, D); + + memcpy(hash, D, 48); + memset(D, 0, 64); +} + +static struct crypto_alg sha512 = { + .cra_name = "sha512", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = SHA512_HMAC_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sha512_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(sha512.cra_list), + .cra_u = { .digest = { + .dia_digestsize = SHA512_DIGEST_SIZE, + .dia_init = sha512_init, + .dia_update = sha512_update, + .dia_final = sha512_final } + } +}; + +static struct crypto_alg sha384 = { + .cra_name = "sha384", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = SHA384_HMAC_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sha512_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(sha384.cra_list), + .cra_u = { .digest = { + .dia_digestsize = SHA384_DIGEST_SIZE, + .dia_init = sha384_init, + .dia_update = sha512_update, + .dia_final = sha384_final } + } +}; + +static int __init init(void) +{ + int ret = 0; + + if ((ret = crypto_register_alg(&sha384)) < 0) + goto out; + if ((ret = crypto_register_alg(&sha512)) < 0) + crypto_unregister_alg(&sha384); +out: + return ret; +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&sha384); + crypto_unregister_alg(&sha512); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SHA-512 and SHA-384 Secure Hash Algorithms"); diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 3c2ce9382bdd..bcce9065242a 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -48,7 +48,7 @@ static char *tvmem; static char *check[] = { "des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish", - "twofish", "serpent", + "twofish", "serpent", "sha384", "sha512", "md4", "aes", NULL }; @@ -549,6 +549,110 @@ test_sha256(void) crypto_free_tfm(tfm); } +static void +test_sha384(void) +{ + char *p; + unsigned int i; + struct crypto_tfm *tfm; + struct sha384_testvec *sha384_tv; + struct scatterlist sg[2]; + unsigned int tsize; + char result[SHA384_DIGEST_SIZE]; + + printk("\ntesting sha384\n"); + + tsize = sizeof (sha384_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + + memcpy(tvmem, sha384_tv_template, tsize); + sha384_tv = (void *) tvmem; + + tfm = crypto_alloc_tfm("sha384", 0); + if (tfm == NULL) { + printk("failed to load transform for sha384\n"); + return; + } + + for (i = 0; i < SHA384_TEST_VECTORS; i++) { + printk("test %u:\n", i + 1); + memset(result, 0, sizeof (result)); + + p = sha384_tv[i].plaintext; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = strlen(sha384_tv[i].plaintext); + + crypto_digest_init(tfm); + crypto_digest_update(tfm, sg, 1); + crypto_digest_final(tfm, result); + + hexdump(result, crypto_tfm_alg_digestsize(tfm)); + printk("%s\n", + memcmp(result, sha384_tv[i].digest, + crypto_tfm_alg_digestsize(tfm)) ? "fail" : + "pass"); + } + + crypto_free_tfm(tfm); +} + +static void +test_sha512(void) +{ + char *p; + unsigned int i; + struct crypto_tfm *tfm; + struct sha512_testvec *sha512_tv; + struct scatterlist sg[2]; + unsigned int tsize; + char result[SHA512_DIGEST_SIZE]; + + printk("\ntesting sha512\n"); + + tsize = sizeof (sha512_tv_template); + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + return; + } + + memcpy(tvmem, sha512_tv_template, tsize); + sha512_tv = (void *) tvmem; + + tfm = crypto_alloc_tfm("sha512", 0); + if (tfm == NULL) { + printk("failed to load transform for sha512\n"); + return; + } + + for (i = 0; i < SHA512_TEST_VECTORS; i++) { + printk("test %u:\n", i + 1); + memset(result, 0, sizeof (result)); + + p = sha512_tv[i].plaintext; + sg[0].page = virt_to_page(p); + sg[0].offset = ((long) p & ~PAGE_MASK); + sg[0].length = strlen(sha512_tv[i].plaintext); + + crypto_digest_init(tfm); + crypto_digest_update(tfm, sg, 1); + crypto_digest_final(tfm, result); + + hexdump(result, crypto_tfm_alg_digestsize(tfm)); + printk("%s\n", + memcmp(result, sha512_tv[i].digest, + crypto_tfm_alg_digestsize(tfm)) ? "fail" : + "pass"); + } + + crypto_free_tfm(tfm); +} + void test_des(void) { @@ -2117,6 +2221,8 @@ do_test(void) test_twofish(); test_serpent(); test_aes(); + test_sha384(); + test_sha512(); #ifdef CONFIG_CRYPTO_HMAC test_hmac_md5(); test_hmac_sha1(); @@ -2163,7 +2269,15 @@ do_test(void) case 10: test_aes(); break; + + case 11: + test_sha384(); + break; + case 12: + test_sha512(); + break; + #ifdef CONFIG_CRYPTO_HMAC case 100: test_hmac_md5(); diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h index 3fbd49ed18ac..b8e328e90545 100644 --- a/crypto/tcrypt.h +++ b/crypto/tcrypt.h @@ -20,6 +20,8 @@ #define MD4_DIGEST_SIZE 16 #define SHA1_DIGEST_SIZE 20 #define SHA256_DIGEST_SIZE 32 +#define SHA384_DIGEST_SIZE 48 +#define SHA512_DIGEST_SIZE 64 /* * MD4 test vectors from RFC1320 @@ -591,6 +593,113 @@ struct sha256_testvec { }; /* + * SHA384 test vectors from from NIST and kerneli + */ +#define SHA384_TEST_VECTORS 4 + +struct sha384_testvec { + char plaintext[128]; + char digest[SHA384_DIGEST_SIZE]; +} sha384_tv_template[] = { + + { "abc", + { 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b, + 0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07, + 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63, + 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed, + 0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23, + 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7 } + }, + + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 0x33, 0x91, 0xfd, 0xdd, 0xfc, 0x8d, 0xc7, 0x39, + 0x37, 0x07, 0xa6, 0x5b, 0x1b, 0x47, 0x09, 0x39, + 0x7c, 0xf8, 0xb1, 0xd1, 0x62, 0xaf, 0x05, 0xab, + 0xfe, 0x8f, 0x45, 0x0d, 0xe5, 0xf3, 0x6b, 0xc6, + 0xb0, 0x45, 0x5a, 0x85, 0x20, 0xbc, 0x4e, 0x6f, + 0x5f, 0xe9, 0x5b, 0x1f, 0xe3, 0xc8, 0x45, 0x2b } + }, + + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + { 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8, + 0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47, + 0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2, + 0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12, + 0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9, + 0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39 } + }, + + { "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd" + "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", + { 0x3d, 0x20, 0x89, 0x73, 0xab, 0x35, 0x08, 0xdb, + 0xbd, 0x7e, 0x2c, 0x28, 0x62, 0xba, 0x29, 0x0a, + 0xd3, 0x01, 0x0e, 0x49, 0x78, 0xc1, 0x98, 0xdc, + 0x4d, 0x8f, 0xd0, 0x14, 0xe5, 0x82, 0x82, 0x3a, + 0x89, 0xe1, 0x6f, 0x9b, 0x2a, 0x7b, 0xbc, 0x1a, + 0xc9, 0x38, 0xe2, 0xd1, 0x99, 0xe8, 0xbe, 0xa4 } + }, +}; + +/* + * SHA512 test vectors from from NIST and kerneli + */ +#define SHA512_TEST_VECTORS 4 + +struct sha512_testvec { + char plaintext[128]; + char digest[SHA512_DIGEST_SIZE]; +} sha512_tv_template[] = { + + { "abc", + { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, + 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31, + 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, + 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, + 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, + 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd, + 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, + 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f } + }, + + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 0x20, 0x4a, 0x8f, 0xc6, 0xdd, 0xa8, 0x2f, 0x0a, + 0x0c, 0xed, 0x7b, 0xeb, 0x8e, 0x08, 0xa4, 0x16, + 0x57, 0xc1, 0x6e, 0xf4, 0x68, 0xb2, 0x28, 0xa8, + 0x27, 0x9b, 0xe3, 0x31, 0xa7, 0x03, 0xc3, 0x35, + 0x96, 0xfd, 0x15, 0xc1, 0x3b, 0x1b, 0x07, 0xf9, + 0xaa, 0x1d, 0x3b, 0xea, 0x57, 0x78, 0x9c, 0xa0, + 0x31, 0xad, 0x85, 0xc7, 0xa7, 0x1d, 0xd7, 0x03, + 0x54, 0xec, 0x63, 0x12, 0x38, 0xca, 0x34, 0x45 } + }, + + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, + 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f, + 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1, + 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18, + 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4, + 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a, + 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54, + 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 } + }, + + { "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd" + "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", + { 0x93, 0x0d, 0x0c, 0xef, 0xcb, 0x30, 0xff, 0x11, + 0x33, 0xb6, 0x89, 0x81, 0x21, 0xf1, 0xcf, 0x3d, + 0x27, 0x57, 0x8a, 0xfc, 0xaf, 0xe8, 0x67, 0x7c, + 0x52, 0x57, 0xcf, 0x06, 0x99, 0x11, 0xf7, 0x5d, + 0x8f, 0x58, 0x31, 0xb5, 0x6e, 0xbf, 0xda, 0x67, + 0xb2, 0x78, 0xe6, 0x6d, 0xff, 0x8b, 0x84, 0xfe, + 0x2b, 0x28, 0x70, 0xf7, 0x42, 0xa5, 0x80, 0xd8, + 0xed, 0xb4, 0x19, 0x87, 0x23, 0x28, 0x50, 0xc9 + } + }, +}; + +/* * DES test vectors. */ #define DES_ENC_TEST_VECTORS 5 diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index d2305841c676..9b8e1bf03917 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c @@ -22,12 +22,14 @@ #include <linux/init.h> #include <linux/proc_fs.h> #include <linux/apm_bios.h> +#include <linux/kbd_kern.h> +#include <linux/timer.h> #include <asm/uaccess.h> #include <asm/io.h> #include <linux/i8k.h> -#define I8K_VERSION "1.7 21/11/2001" +#define I8K_VERSION "1.13 14/05/2002" #define I8K_SMM_FN_STATUS 0x0025 #define I8K_SMM_POWER_STATUS 0x0069 @@ -55,6 +57,19 @@ #define DELL_SIGNATURE "Dell Computer" +/* Interval between polling of keys, in jiffies. */ +#define I8K_POLL_INTERVAL (HZ/20) +#define I8K_REPEAT_DELAY 250 /* 250 ms */ +#define I8K_REPEAT_RATE 10 + +/* + * (To be escaped) Scancodes for the keys. These were chosen to match other + * "Internet" keyboards. + */ +#define I8K_KEYS_UP_SCANCODE 0x30 +#define I8K_KEYS_DOWN_SCANCODE 0x2e +#define I8K_KEYS_MUTE_SCANCODE 0x20 + static char *supported_models[] = { "Inspiron", "Latitude", @@ -67,19 +82,34 @@ static char bios_version [4] = "?"; static char serial_number[16] = "?"; static int force = 0; +static int restricted = 0; +static int handle_buttons = 0; +static int repeat_delay = I8K_REPEAT_DELAY; +static int repeat_rate = I8K_REPEAT_RATE; static int power_status = 0; +static struct timer_list i8k_keys_timer; + MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)"); MODULE_DESCRIPTION("Driver for accessing SMM BIOS on Dell laptops"); MODULE_LICENSE("GPL"); MODULE_PARM(force, "i"); +MODULE_PARM(restricted, "i"); +MODULE_PARM(handle_buttons, "i"); +MODULE_PARM(repeat_delay, "i"); +MODULE_PARM(repeat_rate, "i"); MODULE_PARM(power_status, "i"); MODULE_PARM_DESC(force, "Force loading without checking for supported models"); +MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set"); +MODULE_PARM_DESC(handle_buttons, "Generate keyboard events for i8k buttons"); +MODULE_PARM_DESC(repeat_delay, "I8k buttons repeat delay (ms)"); +MODULE_PARM_DESC(repeat_rate, "I8k buttons repeat rate"); MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k"); static ssize_t i8k_read(struct file *, char *, size_t, loff_t *); static int i8k_ioctl(struct inode *, struct file *, unsigned int, unsigned long); +static void i8k_keys_set_timer(void); static struct file_operations i8k_fops = { .read = i8k_read, @@ -370,6 +400,9 @@ static int i8k_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, break; case I8K_SET_FAN: + if (restricted && !capable(CAP_SYS_ADMIN)) { + return -EPERM; + } if (copy_from_user(&val, (int *)arg, sizeof(int))) { return -EFAULT; } @@ -483,6 +516,61 @@ static ssize_t i8k_read(struct file *f, char *buffer, size_t len, loff_t *fpos) return len; } +/* + * i8k_keys stuff. Thanks to David Bustos <bustos@caltech.edu> + */ + +static unsigned char i8k_keys_make_scancode(int x) { + switch (x) { + case I8K_FN_UP: return I8K_KEYS_UP_SCANCODE; + case I8K_FN_DOWN: return I8K_KEYS_DOWN_SCANCODE; + case I8K_FN_MUTE: return I8K_KEYS_MUTE_SCANCODE; + } + + return 0; +} + +static void i8k_keys_poll(unsigned long data) { + static int last = 0; + static int repeat = 0; + + int curr; + + curr = i8k_get_fn_status(); + if (curr >= 0) { + if (curr != last) { + repeat = jiffies + (HZ * repeat_delay / 1000); + + if (last != 0) { + handle_scancode(0xe0, 0); + handle_scancode(i8k_keys_make_scancode(last), 0); + } + + if (curr != 0) { + handle_scancode(0xe0, 1); + handle_scancode(i8k_keys_make_scancode(curr), 1); + } + } else { + /* Generate keyboard repeat events with current scancode -- dz */ + if ((curr) && (repeat_rate > 0) && (jiffies >= repeat)) { + repeat = jiffies + (HZ / repeat_rate); + handle_scancode(0xe0, 1); + handle_scancode(i8k_keys_make_scancode(curr), 1); + } + } + + last = curr; + } + + /* Reset the timer. */ + i8k_keys_set_timer(); +} + +static void i8k_keys_set_timer() { + i8k_keys_timer.expires = jiffies + I8K_POLL_INTERVAL; + add_timer(&i8k_keys_timer); +} + static char* __init string_trim(char *s, int size) { int len; @@ -757,6 +845,16 @@ int __init i8k_init(void) "Dell laptop SMM driver v%s Massimo Dal Zotto (dz@debian.org)\n", I8K_VERSION); + /* Register the i8k_keys timer. */ + if (handle_buttons) { + printk(KERN_INFO + "i8k: enabling buttons events, delay=%d, rate=%d\n", + repeat_delay, repeat_rate); + init_timer(&i8k_keys_timer); + i8k_keys_timer.function = i8k_keys_poll; + i8k_keys_set_timer(); + } + return 0; } @@ -771,6 +869,11 @@ void cleanup_module(void) /* Remove the proc entry */ remove_proc_entry("i8k", NULL); + /* Unregister the i8k_keys timer. */ + while (handle_buttons && !del_timer(&i8k_keys_timer)) { + schedule_timeout(I8K_POLL_INTERVAL); + } + printk(KERN_INFO "i8k: module unloaded\n"); } #endif diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index d39c31afe0e4..68a000ff62a9 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1836,6 +1836,8 @@ static void __do_SAK(void *arg) #else struct tty_struct *tty = arg; struct task_struct *p; + struct list_head *l; + struct pid *pid; int session; int i; struct file *filp; @@ -1848,9 +1850,8 @@ static void __do_SAK(void *arg) if (tty->driver.flush_buffer) tty->driver.flush_buffer(tty); read_lock(&tasklist_lock); - for_each_process(p) { - if ((p->tty == tty) || - ((session > 0) && (p->session == session))) { + for_each_task_pid(session, PIDTYPE_SID, p, l, pid) { + if (p->tty == tty || session > 0) { printk(KERN_NOTICE "SAK: killed process %d" " (%s): p->session==tty->session\n", p->pid, p->comm); diff --git a/drivers/char/watchdog/acquirewdt.c b/drivers/char/watchdog/acquirewdt.c index b509fb731454..68bcc26aecf4 100644 --- a/drivers/char/watchdog/acquirewdt.c +++ b/drivers/char/watchdog/acquirewdt.c @@ -24,24 +24,18 @@ #include <linux/config.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/types.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/sched.h> #include <linux/miscdevice.h> #include <linux/watchdog.h> -#include <linux/slab.h> #include <linux/ioport.h> -#include <linux/fcntl.h> -#include <asm/io.h> -#include <asm/uaccess.h> -#include <asm/system.h> #include <linux/notifier.h> #include <linux/reboot.h> #include <linux/init.h> #include <linux/spinlock.h> -#include <linux/smp_lock.h> + +#include <asm/io.h> +#include <asm/uaccess.h> +#include <asm/system.h> static int acq_is_open; static spinlock_t acq_lock; diff --git a/drivers/char/watchdog/advantechwdt.c b/drivers/char/watchdog/advantechwdt.c index f994c8fc5e69..f8d265607111 100644 --- a/drivers/char/watchdog/advantechwdt.c +++ b/drivers/char/watchdog/advantechwdt.c @@ -13,64 +13,49 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. - * - * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide - * warranty for any of this software. This material is provided - * "AS-IS" and at no charge. + * + * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. * * (c) Copyright 1995 Alan Cox <alan@redhat.com> * - * 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com> - * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT - * Added timeout module option to override default + * 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com> + * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT */ #include <linux/config.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/types.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/sched.h> #include <linux/miscdevice.h> #include <linux/watchdog.h> -#include <linux/slab.h> #include <linux/ioport.h> -#include <linux/fcntl.h> -#include <asm/io.h> -#include <asm/uaccess.h> -#include <asm/system.h> #include <linux/notifier.h> #include <linux/reboot.h> #include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/smp_lock.h> -static int advwdt_is_open; +#include <asm/io.h> +#include <asm/uaccess.h> +#include <asm/system.h> + +static unsigned long advwdt_is_open; static char adv_expect_close; -static spinlock_t advwdt_lock; /* * You must set these - there is no sane way to probe for this board. * * To enable or restart, write the timeout value in seconds (1 to 63) - * to I/O port WDT_START. To disable, read I/O port WDT_STOP. + * to I/O port wdt_start. To disable, read I/O port wdt_stop. * Both are 0x443 for most boards (tested on a PCA-6276VE-00B1), but * check your manual (at least the PCA-6159 seems to be different - - * the manual says WDT_STOP is 0x43, not 0x443). + * the manual says wdt_stop is 0x43, not 0x443). * (0x43 is also a write-only control register for the 8254 timer!) - * - * TODO: module parameters to set the I/O port addresses */ -#define WDT_STOP 0x443 -#define WDT_START 0x443 - -#define WD_TIMO 60 /* 1 minute */ +static int wdt_stop = 0x443; +static int wdt_start = 0x443; -static int timeout = WD_TIMO; /* in seconds */ -MODULE_PARM(timeout,"i"); -MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=60)"); +static int wd_margin = 60; /* 60 sec default timeout */ #ifdef CONFIG_WATCHDOG_NOWAYOUT static int nowayout = 1; @@ -84,12 +69,44 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CON /* * Kernel methods. */ - + +#ifndef MODULE + +static int __init adv_setup(char *str) +{ + int ints[4]; + + str = get_options(str, ARRAY_SIZE(ints), ints); + + if(ints[0] > 0){ + wdt_stop = ints[1]; + if(ints[0] > 1) + wdt_start = ints[2]; + } + + return 1; +} + +__setup("advwdt=", adv_setup); + +#endif /* !MODULE */ + +MODULE_PARM(wdt_stop, "i"); +MODULE_PARM_DESC(wdt_stop, "Advantech WDT 'stop' io port (default 0x443)"); +MODULE_PARM(wdt_start, "i"); +MODULE_PARM_DESC(wdt_start, "Advantech WDT 'start' io port (default 0x443)"); + static void advwdt_ping(void) { /* Write a watchdog value */ - outb_p(timeout, WDT_START); + outb_p(wd_margin, wdt_start); +} + +static void +advwdt_disable(void) +{ + inb_p(wdt_stop); } static ssize_t @@ -118,16 +135,11 @@ advwdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) return count; } -static ssize_t -advwdt_read(struct file *file, char *buf, size_t count, loff_t *ppos) -{ - return -EINVAL; -} - static int advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + int new_margin; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, @@ -139,16 +151,47 @@ advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))) return -EFAULT; break; - + case WDIOC_GETSTATUS: - if (copy_to_user((int *)arg, &advwdt_is_open, sizeof(int))) - return -EFAULT; - break; + case WDIOC_GETBOOTSTATUS: + return put_user(0, (int *)arg); case WDIOC_KEEPALIVE: advwdt_ping(); break; + case WDIOC_SETTIMEOUT: + if (get_user(new_margin, (int *)arg)) + return -EFAULT; + if ((new_margin < 1) || (new_margin > 63)) + return -EINVAL; + wd_margin = new_margin; + advwdt_ping(); + /* Fall */ + + case WDIOC_GETTIMEOUT: + return put_user(wd_margin, (int *)arg); + + case WDIOC_SETOPTIONS: + { + int options, retval = -EINVAL; + + if (get_user(options, (int *)arg)) + return -EFAULT; + + if (options & WDIOS_DISABLECARD) { + advwdt_disable(); + retval = 0; + } + + if (options & WDIOS_ENABLECARD) { + advwdt_ping(); + retval = 0; + } + + return retval; + } + default: return -ENOTTY; } @@ -158,37 +201,27 @@ advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, static int advwdt_open(struct inode *inode, struct file *file) { - if (minor(inode->i_rdev) == WATCHDOG_MINOR) { - spin_lock(&advwdt_lock); - if (advwdt_is_open) { - spin_unlock(&advwdt_lock); - return -EBUSY; - } - - if (nowayout) - MOD_INC_USE_COUNT; + if (test_and_set_bit(0, &advwdt_is_open)) + return -EBUSY; + /* + * Activate + */ - /* Activate */ - advwdt_is_open = 1; - advwdt_ping(); - spin_unlock(&advwdt_lock); - return 0; - } else { - return -ENODEV; - } + advwdt_ping(); + return 0; } static int advwdt_close(struct inode *inode, struct file *file) { - if (minor(inode->i_rdev) == WATCHDOG_MINOR) { - spin_lock(&advwdt_lock); - if (!nowayout) - inb_p(WDT_STOP); - - advwdt_is_open = 0; - spin_unlock(&advwdt_lock); + if (adv_expect_close == 42) { + advwdt_disable(); + } else { + printk(KERN_CRIT "advancetechwdt: Unexpected close, not stopping watchdog!\n"); + advwdt_ping(); } + clear_bit(0, &advwdt_is_open); + adv_expect_close = 0; return 0; } @@ -200,10 +233,10 @@ static int advwdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { - if (code == SYS_DOWN || code == SYS_HALT) + if (code == SYS_DOWN || code == SYS_HALT) { /* Turn the WDT off */ - inb_p(WDT_STOP); - + advwdt_disable(); + } return NOTIFY_DONE; } @@ -213,7 +246,6 @@ advwdt_notify_sys(struct notifier_block *this, unsigned long code, static struct file_operations advwdt_fops = { .owner = THIS_MODULE, - .read = advwdt_read, .write = advwdt_write, .ioctl = advwdt_ioctl, .open = advwdt_open, @@ -237,35 +269,22 @@ static struct notifier_block advwdt_notifier = { .priority = 0 }; -static void __init -advwdt_validate_timeout(void) -{ - if (timeout < 1 || timeout > 63) { - timeout = WD_TIMO; - printk(KERN_INFO "advantechwdt: timeout value must be 1 <= x <= 63, using %d\n", timeout); - } -} - static int __init advwdt_init(void) { - printk("WDT driver for Advantech single board computer initialising.\n"); + printk(KERN_INFO "WDT driver for Advantech single board computer initialising.\n"); - advwdt_validate_timeout(); - spin_lock_init(&advwdt_lock); if (misc_register(&advwdt_miscdev)) return -ENODEV; -#if WDT_START != WDT_STOP - if (!request_region(WDT_STOP, 1, "Advantech WDT")) { - misc_deregister(&advwdt_miscdev); + if (wdt_stop != wdt_start) + if (!request_region(wdt_stop, 1, "Advantech WDT")) { + misc_deregister(&advwdt_miscdev); return -EIO; } -#endif - if (!request_region(WDT_START, 1, "Advantech WDT")) { + if (!request_region(wdt_start, 1, "Advantech WDT")) { misc_deregister(&advwdt_miscdev); -#if WDT_START != WDT_STOP - release_region(WDT_STOP, 1); -#endif + if (wdt_stop != wdt_start) + release_region(wdt_stop, 1); return -EIO; } register_reboot_notifier(&advwdt_notifier); @@ -277,14 +296,15 @@ advwdt_exit(void) { misc_deregister(&advwdt_miscdev); unregister_reboot_notifier(&advwdt_notifier); -#if WDT_START != WDT_STOP - release_region(WDT_STOP,1); -#endif - release_region(WDT_START,1); + if(wdt_stop != wdt_start) + release_region(wdt_stop,1); + release_region(wdt_start,1); } module_init(advwdt_init); module_exit(advwdt_exit); MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Marek Michalkiewicz <marekm@linux.org.pl>"); +MODULE_DESCRIPTION("Advantech Single Board Computer WDT driver"); diff --git a/drivers/char/watchdog/alim7101_wdt.c b/drivers/char/watchdog/alim7101_wdt.c index 653ae2d767fe..126384bc4094 100644 --- a/drivers/char/watchdog/alim7101_wdt.c +++ b/drivers/char/watchdog/alim7101_wdt.c @@ -30,26 +30,20 @@ */ #include <linux/module.h> -#include <linux/version.h> #include <linux/types.h> -#include <linux/errno.h> -#include <linux/kernel.h> #include <linux/timer.h> -#include <linux/sched.h> #include <linux/miscdevice.h> #include <linux/watchdog.h> -#include <linux/slab.h> #include <linux/ioport.h> -#include <linux/fcntl.h> -#include <linux/smp_lock.h> -#include <asm/io.h> -#include <asm/uaccess.h> -#include <asm/system.h> #include <linux/notifier.h> #include <linux/reboot.h> #include <linux/init.h> #include <linux/pci.h> +#include <asm/io.h> +#include <asm/uaccess.h> +#include <asm/system.h> + #define OUR_NAME "alim7101_wdt" #define WDT_ENABLE 0x9C diff --git a/drivers/char/watchdog/eurotechwdt.c b/drivers/char/watchdog/eurotechwdt.c index 46c015c372a9..d7378c9102be 100644 --- a/drivers/char/watchdog/eurotechwdt.c +++ b/drivers/char/watchdog/eurotechwdt.c @@ -3,78 +3,82 @@ * * (c) Copyright 2001 Ascensit <support@ascensit.com> * (c) Copyright 2001 Rodolfo Giometti <giometti@ascensit.com> + * (c) Copyright 2002 Rob Radez <rob@osinvestor.com> * * Based on wdt.c. * Original copyright messages: * - * (c) Copyright 1996-1997 Alan Cox <alan@redhat.com>, All Rights Reserved. - * http://www.redhat.com + * (c) Copyright 1996-1997 Alan Cox <alan@redhat.com>, All Rights Reserved. + * http://www.redhat.com * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. * - * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide - * warranty for any of this software. This material is provided - * "AS-IS" and at no charge. + * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. * - * (c) Copyright 1995 Alan Cox <alan@lxorguk.ukuu.org.uk> + * (c) Copyright 1995 Alan Cox <alan@lxorguk.ukuu.org.uk>* + */ + +/* Changelog: + * + * 2002/04/25 - Rob Radez + * clean up #includes + * clean up locking + * make __setup param unique + * proper options in watchdog_info + * add WDIOC_GETSTATUS and WDIOC_SETOPTIONS ioctls + * add expect_close support * - * 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com> - * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT - * Added timeout module option to override default + * 2001 - Rodolfo Giometti + * Initial release + * + * 2002.05.30 - Joel Becker <joel.becker@oracle.com> + * Added Matt Domsch's nowayout module option. */ #include <linux/config.h> #include <linux/interrupt.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/types.h> -#include <linux/errno.h> -#include <linux/kernel.h> #include <linux/miscdevice.h> #include <linux/watchdog.h> -#include <linux/slab.h> #include <linux/ioport.h> -#include <linux/fcntl.h> #include <linux/notifier.h> #include <linux/reboot.h> #include <linux/init.h> -#include <linux/spinlock.h> #include <asm/io.h> #include <asm/uaccess.h> #include <asm/system.h> -static int eurwdt_is_open; -static spinlock_t eurwdt_lock; +static unsigned long eurwdt_is_open; +static int eurwdt_timeout; static char eur_expect_close; - + /* * You must set these - there is no sane way to probe for this board. - * You can use wdt=x,y to set these now. + * You can use eurwdt=x,y to set these now. */ static int io = 0x3f0; static int irq = 10; static char *ev = "int"; -#define WDT_TIMEOUT 60 /* 1 minute */ -static int timeout = WDT_TIMEOUT; - -MODULE_PARM(timeout,"i"); -MODULE_PARM_DESC(timeout, "Eurotech WDT timeout in seconds (default=60)"); +#define WDT_TIMEOUT 60 /* 1 minute */ #ifdef CONFIG_WATCHDOG_NOWAYOUT static int nowayout = 1; #else static int nowayout = 0; #endif + MODULE_PARM(nowayout,"i"); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); - /* * Some symbolic names */ @@ -115,7 +119,7 @@ str = get_options (str, ARRAY_SIZE(ints), ints); return 1; } -__setup("wdt=", eurwdt_setup); +__setup("eurwdt=", eurwdt_setup); #endif /* !MODULE */ @@ -124,22 +128,13 @@ MODULE_PARM_DESC(io, "Eurotech WDT io port (default=0x3f0)"); MODULE_PARM(irq, "i"); MODULE_PARM_DESC(irq, "Eurotech WDT irq (default=10)"); MODULE_PARM(ev, "s"); -MODULE_PARM_DESC(ev, "Eurotech WDT event type (default is `reboot')"); +MODULE_PARM_DESC(ev, "Eurotech WDT event type (default is `int')"); /* * Programming support */ -static void __init eurwdt_validate_timeout(void) -{ - if (timeout < 0 || timeout > 255) { - timeout = WDT_TIMEOUT; - printk(KERN_INFO "eurwdt: timeout must be 0 < x < 255, using %d\n", - timeout); - } -} - static inline void eurwdt_write_reg(u8 index, u8 data) { outb(index, io); @@ -214,7 +209,7 @@ void eurwdt_interrupt(int irq, void *dev_id, struct pt_regs *regs) static void eurwdt_ping(void) { /* Write the watchdog default value */ - eurwdt_set_timeout(timeout); + eurwdt_set_timeout(eurwdt_timeout); } /** @@ -250,10 +245,9 @@ loff_t *ppos) } } eurwdt_ping(); /* the default timeout */ - return 1; } - return 0; + return count; } /** @@ -271,12 +265,13 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { static struct watchdog_info ident = { - .options = WDIOF_CARDRESET, + .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, .identity = "WDT Eurotech CPU-1220/1410", }; int time; + int options, retval = -EINVAL; switch(cmd) { default: @@ -286,6 +281,7 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file, return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)) ? -EFAULT : 0; + case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, (int *) arg); @@ -301,9 +297,26 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file, if (time < 0 || time > 255) return -EINVAL; - timeout = time; + eurwdt_timeout = time; eurwdt_set_timeout(time); - return 0; + /* Fall */ + + case WDIOC_GETTIMEOUT: + return put_user(eurwdt_timeout, (int *)arg); + + case WDIOC_SETOPTIONS: + if (get_user(options, (int *)arg)) + return -EFAULT; + if (options & WDIOS_DISABLECARD) { + eurwdt_disable_timer(); + retval = 0; + } + if (options & WDIOS_ENABLECARD) { + eurwdt_activate_timer(); + eurwdt_ping(); + retval = 0; + } + return retval; } } @@ -318,32 +331,12 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file, static int eurwdt_open(struct inode *inode, struct file *file) { - switch (minor(inode->i_rdev)) { - case WATCHDOG_MINOR: - spin_lock(&eurwdt_lock); - if (eurwdt_is_open) { - spin_unlock(&eurwdt_lock); - return -EBUSY; - } - if (nowayout) - MOD_INC_USE_COUNT; - - eurwdt_is_open = 1; - - /* Activate the WDT */ - eurwdt_activate_timer(); - - spin_unlock(&eurwdt_lock); - - MOD_INC_USE_COUNT; - return 0; - - case TEMP_MINOR: - return 0; - - default: - return -ENODEV; - } + if (test_and_set_bit(0, &eurwdt_is_open)) + return -EBUSY; + eurwdt_timeout = WDT_TIMEOUT; /* initial timeout */ + /* Activate the WDT */ + eurwdt_activate_timer(); + return 0; } /** @@ -360,14 +353,14 @@ static int eurwdt_open(struct inode *inode, struct file *file) static int eurwdt_release(struct inode *inode, struct file *file) { - if (minor(inode->i_rdev) == WATCHDOG_MINOR) { - if (!nowayout) - eurwdt_disable_timer(); - - eurwdt_is_open = 0; - MOD_DEC_USE_COUNT; - } - + if (eur_expect_close == 42) { + eurwdt_disable_timer(); + } else { + printk(KERN_CRIT "eurwdt: Unexpected close, not stopping watchdog!\n"); + eurwdt_ping(); + } + clear_bit(0, &eurwdt_is_open); + eur_expect_close = 0; return 0; } @@ -456,7 +449,6 @@ static int __init eurwdt_init(void) { int ret; - eurwdt_validate_timeout(); ret = misc_register(&eurwdt_miscdev); if (ret) { printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n", @@ -489,8 +481,6 @@ static int __init eurwdt_init(void) " - timeout event: %s\n", io, irq, (!strcmp("int", ev) ? "int" : "reboot")); - spin_lock_init(&eurwdt_lock); - out: return ret; diff --git a/drivers/char/watchdog/i810-tco.c b/drivers/char/watchdog/i810-tco.c index f24465c0a8d5..8f571d22fd58 100644 --- a/drivers/char/watchdog/i810-tco.c +++ b/drivers/char/watchdog/i810-tco.c @@ -47,9 +47,6 @@ #include <linux/module.h> #include <linux/types.h> -#include <linux/kernel.h> -#include <linux/fs.h> -#include <linux/mm.h> #include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/reboot.h> diff --git a/drivers/char/watchdog/ib700wdt.c b/drivers/char/watchdog/ib700wdt.c index 68a9454a6dae..4f1a5916c229 100644 --- a/drivers/char/watchdog/ib700wdt.c +++ b/drivers/char/watchdog/ib700wdt.c @@ -33,24 +33,18 @@ #include <linux/config.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/types.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/sched.h> #include <linux/miscdevice.h> #include <linux/watchdog.h> -#include <linux/slab.h> #include <linux/ioport.h> -#include <linux/fcntl.h> -#include <asm/io.h> -#include <asm/uaccess.h> -#include <asm/system.h> #include <linux/notifier.h> #include <linux/reboot.h> #include <linux/init.h> #include <linux/spinlock.h> -#include <linux/smp_lock.h> + +#include <asm/io.h> +#include <asm/uaccess.h> +#include <asm/system.h> static int ibwdt_is_open; static spinlock_t ibwdt_lock; @@ -92,15 +86,32 @@ static int expect_close = 0; * */ +static int wd_times[] = { + 30, /* 0x0 */ + 28, /* 0x1 */ + 26, /* 0x2 */ + 24, /* 0x3 */ + 22, /* 0x4 */ + 20, /* 0x5 */ + 18, /* 0x6 */ + 16, /* 0x7 */ + 14, /* 0x8 */ + 12, /* 0x9 */ + 10, /* 0xA */ + 8, /* 0xB */ + 6, /* 0xC */ + 4, /* 0xD */ + 2, /* 0xE */ + 0, /* 0xF */ +}; + #define WDT_STOP 0x441 #define WDT_START 0x443 +/* Default timeout */ #define WD_TIMO 0 /* 30 seconds +/- 20%, from table */ -static int timeout_val = WD_TIMO; /* value in table */ -static int timeout = 30; /* in seconds */ -MODULE_PARM(timeout,"i"); -MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, 0 < n < 30, must be even (default=30)"); +static int wd_margin = WD_TIMO; #ifdef CONFIG_WATCHDOG_NOWAYOUT static int nowayout = 1; @@ -111,22 +122,16 @@ static int nowayout = 0; MODULE_PARM(nowayout,"i"); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); + /* * Kernel methods. */ -static void __init -ibwdt_validate_timeout(void) -{ - timeout_val = (30 - timeout) / 2; - if (timeout_val < 0 || timeout_val > 0xF) timeout_val = WD_TIMO; -} - static void ibwdt_ping(void) { /* Write a watchdog value */ - outb_p(timeout_val, WDT_START); + outb_p(wd_times[wd_margin], WDT_START); } static ssize_t @@ -145,7 +150,6 @@ ibwdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) for (i = 0; i != count; i++) { char c; - if (get_user(c, buf + i)) return -EFAULT; if (c == 'V') @@ -168,6 +172,8 @@ static int ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + int i, new_margin; + static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, @@ -189,6 +195,22 @@ ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ibwdt_ping(); break; + case WDIOC_SETTIMEOUT: + if (get_user(new_margin, (int *)arg)) + return -EFAULT; + if ((new_margin < 0) || (new_margin > 30)) + return -EINVAL; + for (i = 0x0F; i > -1; i--) + if (wd_times[i] > new_margin) + break; + wd_margin = i; + ibwdt_ping(); + /* Fall */ + + case WDIOC_GETTIMEOUT: + return put_user(wd_times[wd_margin], (int *)arg); + break; + default: return -ENOTTY; } @@ -223,7 +245,7 @@ ibwdt_close(struct inode *inode, struct file *file) if (minor(inode->i_rdev) == WATCHDOG_MINOR) { spin_lock(&ibwdt_lock); if (expect_close) - outb_p(timeout_val, WDT_STOP); + outb_p(wd_times[wd_margin], WDT_STOP); else printk(KERN_CRIT "WDT device closed unexpectedly. WDT will not stop!\n"); @@ -243,7 +265,7 @@ ibwdt_notify_sys(struct notifier_block *this, unsigned long code, { if (code == SYS_DOWN || code == SYS_HALT) { /* Turn the WDT off */ - outb_p(timeout_val, WDT_STOP); + outb_p(wd_times[wd_margin], WDT_STOP); } return NOTIFY_DONE; } @@ -283,7 +305,6 @@ ibwdt_init(void) { printk("WDT driver for IB700 single board computer initialising.\n"); - ibwdt_validate_timeout(); spin_lock_init(&ibwdt_lock); if (misc_register(&ibwdt_miscdev)) return -ENODEV; diff --git a/drivers/char/watchdog/indydog.c b/drivers/char/watchdog/indydog.c index c41dac5b6b07..23697570bcdb 100644 --- a/drivers/char/watchdog/indydog.c +++ b/drivers/char/watchdog/indydog.c @@ -19,7 +19,6 @@ #include <linux/mm.h> #include <linux/miscdevice.h> #include <linux/watchdog.h> -#include <linux/smp_lock.h> #include <linux/init.h> #include <asm/uaccess.h> #include <asm/sgi/sgimc.h> diff --git a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c index 3d78c2f37ec6..7a67ceeac45f 100644 --- a/drivers/char/watchdog/machzwd.c +++ b/drivers/char/watchdog/machzwd.c @@ -30,25 +30,19 @@ #include <linux/config.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/types.h> -#include <linux/errno.h> -#include <linux/kernel.h> #include <linux/timer.h> #include <linux/jiffies.h> #include <linux/miscdevice.h> #include <linux/watchdog.h> -#include <linux/slab.h> #include <linux/ioport.h> -#include <linux/fcntl.h> -#include <linux/smp_lock.h> -#include <asm/io.h> -#include <asm/uaccess.h> -#include <asm/system.h> #include <linux/notifier.h> #include <linux/reboot.h> #include <linux/init.h> +#include <asm/io.h> +#include <asm/uaccess.h> +#include <asm/system.h> /* ports */ #define ZF_IOBASE 0x218 diff --git a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c index f19a5d9230ef..e207ef305c2c 100644 --- a/drivers/char/watchdog/mixcomwd.c +++ b/drivers/char/watchdog/mixcomwd.c @@ -38,15 +38,11 @@ #include <linux/module.h> #include <linux/config.h> #include <linux/types.h> -#include <linux/kernel.h> -#include <linux/fs.h> -#include <linux/mm.h> #include <linux/miscdevice.h> #include <linux/ioport.h> #include <linux/watchdog.h> #include <linux/reboot.h> #include <linux/init.h> -#include <linux/smp_lock.h> #include <asm/uaccess.h> #include <asm/io.h> diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c index be2bcd00c5fa..1c36b8c4fe24 100644 --- a/drivers/char/watchdog/pcwd.c +++ b/drivers/char/watchdog/pcwd.c @@ -45,27 +45,17 @@ */ #include <linux/module.h> - #include <linux/types.h> -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/tty.h> #include <linux/timer.h> #include <linux/config.h> -#include <linux/kernel.h> #include <linux/wait.h> -#include <linux/string.h> #include <linux/slab.h> #include <linux/ioport.h> #include <linux/delay.h> #include <linux/miscdevice.h> -#include <linux/fs.h> -#include <linux/mm.h> #include <linux/watchdog.h> #include <linux/init.h> -#include <linux/proc_fs.h> #include <linux/spinlock.h> -#include <linux/smp_lock.h> #include <asm/uaccess.h> #include <asm/io.h> diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c index 874539eb4309..8af274c64eaa 100644 --- a/drivers/char/watchdog/sa1100_wdt.c +++ b/drivers/char/watchdog/sa1100_wdt.c @@ -24,7 +24,6 @@ #include <linux/fs.h> #include <linux/miscdevice.h> #include <linux/watchdog.h> -#include <linux/smp_lock.h> #include <linux/init.h> #include <asm/hardware.h> diff --git a/drivers/char/watchdog/sbc60xxwdt.c b/drivers/char/watchdog/sbc60xxwdt.c index 4b61d1a8db40..15fbbd831cc4 100644 --- a/drivers/char/watchdog/sbc60xxwdt.c +++ b/drivers/char/watchdog/sbc60xxwdt.c @@ -56,25 +56,20 @@ */ #include <linux/module.h> -#include <linux/version.h> #include <linux/types.h> -#include <linux/errno.h> -#include <linux/kernel.h> #include <linux/timer.h> #include <linux/jiffies.h> #include <linux/miscdevice.h> #include <linux/watchdog.h> -#include <linux/slab.h> #include <linux/ioport.h> -#include <linux/fcntl.h> -#include <linux/smp_lock.h> -#include <asm/io.h> -#include <asm/uaccess.h> -#include <asm/system.h> #include <linux/notifier.h> #include <linux/reboot.h> #include <linux/init.h> +#include <asm/io.h> +#include <asm/uaccess.h> +#include <asm/system.h> + #define OUR_NAME "sbc60xxwdt" /* diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c index 005cdaa5c4cf..20133a652d3e 100644 --- a/drivers/char/watchdog/sc1200wdt.c +++ b/drivers/char/watchdog/sc1200wdt.c @@ -28,21 +28,20 @@ #include <linux/config.h> #include <linux/module.h> -#include <linux/kernel.h> #include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/ioport.h> #include <linux/spinlock.h> -#include <linux/ioport.h> -#include <asm/semaphore.h> -#include <asm/io.h> -#include <asm/uaccess.h> #include <linux/notifier.h> #include <linux/reboot.h> #include <linux/init.h> #include <linux/isapnp.h> #include <linux/pci.h> +#include <asm/semaphore.h> +#include <asm/io.h> +#include <asm/uaccess.h> + #define SC1200_MODULE_VER "build 20020303" #define SC1200_MODULE_NAME "sc1200wdt" #define PFX SC1200_MODULE_NAME ": " diff --git a/drivers/char/watchdog/sc520_wdt.c b/drivers/char/watchdog/sc520_wdt.c index 1d30c4ef4f29..3a98c8b6d760 100644 --- a/drivers/char/watchdog/sc520_wdt.c +++ b/drivers/char/watchdog/sc520_wdt.c @@ -49,25 +49,19 @@ */ #include <linux/module.h> -#include <linux/version.h> #include <linux/types.h> -#include <linux/errno.h> -#include <linux/kernel.h> #include <linux/timer.h> -#include <linux/sched.h> #include <linux/miscdevice.h> #include <linux/watchdog.h> -#include <linux/slab.h> #include <linux/ioport.h> -#include <linux/fcntl.h> -#include <linux/smp_lock.h> -#include <asm/io.h> -#include <asm/uaccess.h> -#include <asm/system.h> #include <linux/notifier.h> #include <linux/reboot.h> #include <linux/init.h> +#include <asm/io.h> +#include <asm/uaccess.h> +#include <asm/system.h> + /* * The SC520 can timeout anywhere from 492us to 32.21s. * If we reset the watchdog every ~250ms we should be safe. diff --git a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c index eba57eb21513..6d02fe2edfcd 100644 --- a/drivers/char/watchdog/scx200_wdt.c +++ b/drivers/char/watchdog/scx200_wdt.c @@ -19,19 +19,17 @@ #include <linux/config.h> #include <linux/module.h> -#include <linux/errno.h> -#include <linux/kernel.h> #include <linux/init.h> #include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/notifier.h> #include <linux/reboot.h> #include <linux/pci.h> +#include <linux/scx200.h> + #include <asm/uaccess.h> #include <asm/io.h> -#include <linux/scx200.h> - #define NAME "scx200_wdt" MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>"); diff --git a/drivers/char/watchdog/shwdt.c b/drivers/char/watchdog/shwdt.c index 2f32ebc5708e..f5ae26556a31 100644 --- a/drivers/char/watchdog/shwdt.c +++ b/drivers/char/watchdog/shwdt.c @@ -16,7 +16,6 @@ #include <linux/config.h> #include <linux/module.h> #include <linux/init.h> -#include <linux/kernel.h> #include <linux/types.h> #include <linux/miscdevice.h> #include <linux/watchdog.h> diff --git a/drivers/char/watchdog/softdog.c b/drivers/char/watchdog/softdog.c index 7abbabad53fc..658414d74ee7 100644 --- a/drivers/char/watchdog/softdog.c +++ b/drivers/char/watchdog/softdog.c @@ -27,21 +27,21 @@ * 19980911 Alan Cox * Made SMP safe for 2.3.x * - * 20011214 Matt Domsch <Matt_Domsch@dell.com> - * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT - * Didn't add timeout option, as soft_margin option already exists. + * 20011127 Joel Becker (jlbec@evilplan.org> + * Added soft_noboot; Allows testing the softdog trigger without + * requiring a recompile. + * Added WDIOC_GETTIMEOUT and WDIOC_SETTIMOUT. + * + * 20020530 Joel Becker <joel.becker@oracle.com> + * Added Matt Domsch's nowayout module option. */ #include <linux/module.h> #include <linux/config.h> #include <linux/types.h> -#include <linux/kernel.h> -#include <linux/fs.h> -#include <linux/mm.h> #include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/reboot.h> -#include <linux/smp_lock.h> #include <linux/init.h> #include <asm/uaccess.h> @@ -49,8 +49,15 @@ static int expect_close = 0; static int soft_margin = TIMER_MARGIN; /* in seconds */ +#ifdef ONLY_TESTING +static int soft_noboot = 1; +#else +static int soft_noboot = 0; +#endif /* ONLY_TESTING */ MODULE_PARM(soft_margin,"i"); +MODULE_PARM(soft_noboot,"i"); +MODULE_LICENSE("GPL"); #ifdef CONFIG_WATCHDOG_NOWAYOUT static int nowayout = 1; @@ -60,7 +67,6 @@ static int nowayout = 0; MODULE_PARM(nowayout,"i"); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); -MODULE_LICENSE("GPL"); /* * Our timer @@ -70,7 +76,7 @@ static void watchdog_fire(unsigned long); static struct timer_list watchdog_ticktock = TIMER_INITIALIZER(watchdog_fire, 0, 0); -static int timer_alive; +static unsigned long timer_alive; /* @@ -79,13 +85,14 @@ static int timer_alive; static void watchdog_fire(unsigned long data) { -#ifdef ONLY_TESTING - printk(KERN_CRIT "SOFTDOG: Would Reboot.\n"); -#else - printk(KERN_CRIT "SOFTDOG: Initiating system reboot.\n"); - machine_restart(NULL); - printk("WATCHDOG: Reboot didn't ?????\n"); -#endif + if (soft_noboot) + printk(KERN_CRIT "SOFTDOG: Triggered - Reboot ignored.\n"); + else + { + printk(KERN_CRIT "SOFTDOG: Initiating system reboot.\n"); + machine_restart(NULL); + printk("SOFTDOG: Reboot didn't ?????\n"); + } } /* @@ -94,7 +101,7 @@ static void watchdog_fire(unsigned long data) static int softdog_open(struct inode *inode, struct file *file) { - if(timer_alive) + if(test_and_set_bit(0, &timer_alive)) return -EBUSY; if (nowayout) { MOD_INC_USE_COUNT; @@ -103,7 +110,6 @@ static int softdog_open(struct inode *inode, struct file *file) * Activate timer */ mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ)); - timer_alive=1; return 0; } @@ -113,12 +119,12 @@ static int softdog_release(struct inode *inode, struct file *file) * Shut off the timer. * Lock it in if it's a module and we set nowayout */ - if(!nowayout) { + if (expect_close) { del_timer(&watchdog_ticktock); } else { printk(KERN_CRIT "SOFTDOG: WDT device closed unexpectedly. WDT will not stop!\n"); } - timer_alive=0; + clear_bit(0, &timer_alive); return 0; } @@ -156,6 +162,7 @@ static ssize_t softdog_write(struct file *file, const char *data, size_t len, lo static int softdog_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + int new_margin; static struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .identity = "Software Watchdog", @@ -173,6 +180,16 @@ static int softdog_ioctl(struct inode *inode, struct file *file, case WDIOC_KEEPALIVE: mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ)); return 0; + case WDIOC_SETTIMEOUT: + if (get_user(new_margin, (int *)arg)) + return -EFAULT; + if (new_margin < 1) + return -EINVAL; + soft_margin = new_margin; + mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ)); + /* Fall */ + case WDIOC_GETTIMEOUT: + return put_user(soft_margin, (int *)arg); } } diff --git a/drivers/char/watchdog/w83877f_wdt.c b/drivers/char/watchdog/w83877f_wdt.c index 152c5cf41311..5a852f657b5b 100644 --- a/drivers/char/watchdog/w83877f_wdt.c +++ b/drivers/char/watchdog/w83877f_wdt.c @@ -42,24 +42,18 @@ */ #include <linux/module.h> -#include <linux/version.h> #include <linux/types.h> -#include <linux/errno.h> -#include <linux/kernel.h> #include <linux/timer.h> #include <linux/jiffies.h> #include <linux/miscdevice.h> #include <linux/watchdog.h> -#include <linux/slab.h> #include <linux/ioport.h> -#include <linux/fcntl.h> -#include <linux/smp_lock.h> -#include <asm/io.h> -#include <asm/uaccess.h> -#include <asm/system.h> #include <linux/notifier.h> #include <linux/reboot.h> #include <linux/init.h> +#include <asm/io.h> +#include <asm/uaccess.h> +#include <asm/system.h> #define OUR_NAME "w83877f_wdt" @@ -220,6 +214,8 @@ static int fop_open(struct inode * inode, struct file * file) case WATCHDOG_MINOR: /* Just in case we're already talking to someone... */ if(test_and_set_bit(0, &wdt_is_open)) { + /* Davej: Is this unlock bogus? */ + spin_unlock(&wdt_spinlock); return -EBUSY; } /* Good, fire up the show */ @@ -242,7 +238,7 @@ static int fop_close(struct inode * inode, struct file * file) printk(OUR_NAME ": device file closed unexpectedly. Will not stop the WDT!\n"); } } - wdt_is_open = 0; + clear_bit(0, &wdt_is_open); return 0; } diff --git a/drivers/char/watchdog/wafer5823wdt.c b/drivers/char/watchdog/wafer5823wdt.c index dc611c96835e..858713e435f5 100644 --- a/drivers/char/watchdog/wafer5823wdt.c +++ b/drivers/char/watchdog/wafer5823wdt.c @@ -27,16 +27,15 @@ */ #include <linux/module.h> -#include <linux/kernel.h> #include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/ioport.h> -#include <asm/io.h> -#include <asm/uaccess.h> #include <linux/notifier.h> #include <linux/reboot.h> #include <linux/init.h> #include <linux/spinlock.h> +#include <asm/io.h> +#include <asm/uaccess.h> static unsigned long wafwdt_is_open; static spinlock_t wafwdt_lock; diff --git a/drivers/char/watchdog/wdt.c b/drivers/char/watchdog/wdt.c index f50fd376e0ec..6b7a2ea9f054 100644 --- a/drivers/char/watchdog/wdt.c +++ b/drivers/char/watchdog/wdt.c @@ -27,22 +27,17 @@ * Tim Hockin : Added insmod parameters, comment cleanup * Parameterized timeout * Tigran Aivazian : Restructured wdt_init() to handle failures - * Matt Domsch : added nowayout and timeout module options + * Joel Becker : Added WDIOC_GET/SETTIMEOUT + * Matt Domsch : Added nowayout module option */ #include <linux/config.h> #include <linux/interrupt.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/types.h> -#include <linux/errno.h> -#include <linux/kernel.h> #include <linux/miscdevice.h> #include <linux/watchdog.h> -#include "wd501p.h" -#include <linux/slab.h> #include <linux/ioport.h> -#include <linux/fcntl.h> #include <linux/notifier.h> #include <linux/reboot.h> #include <linux/init.h> @@ -50,6 +45,7 @@ #include <asm/io.h> #include <asm/uaccess.h> #include <asm/system.h> +#include "wd501p.h" static unsigned long wdt_is_open; static int expect_close; @@ -62,12 +58,10 @@ static int expect_close; static int io=0x240; static int irq=11; +/* Default margin */ #define WD_TIMO (100*60) /* 1 minute */ -static int timeout_val = WD_TIMO; /* value passed to card */ -static int timeout = 60; /* in seconds */ -MODULE_PARM(timeout,"i"); -MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=60)"); +static int wd_margin = WD_TIMO; #ifdef CONFIG_WATCHDOG_NOWAYOUT static int nowayout = 1; @@ -78,12 +72,6 @@ static int nowayout = 0; MODULE_PARM(nowayout,"i"); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); -static void __init -wdt_validate_timeout(void) -{ - timeout_val = timeout * 100; -} - #ifndef MODULE /** @@ -238,7 +226,7 @@ static void wdt_ping(void) /* Write a watchdog value */ inb_p(WDT_DC); wdt_ctr_mode(1,2); - wdt_ctr_load(1,timeout_val); /* Timeout */ + wdt_ctr_load(1,wd_margin); /* Timeout */ outb_p(0, WDT_DC); } @@ -329,6 +317,8 @@ static ssize_t wdt_read(struct file *file, char *buf, size_t count, loff_t *ptr) static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + int new_margin; + static struct watchdog_info ident= { .options = WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER @@ -353,6 +343,17 @@ static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, case WDIOC_KEEPALIVE: wdt_ping(); return 0; + case WDIOC_SETTIMEOUT: + if (get_user(new_margin, (int *)arg)) + return -EFAULT; + /* Arbitrary, can't find the card's limits */ + if ((new_margin < 0) || (new_margin > 60)) + return -EINVAL; + wd_margin = new_margin * 100; + wdt_ping(); + /* Fall */ + case WDIOC_GETTIMEOUT: + return put_user(wd_margin / 100, (int *)arg); } } @@ -375,19 +376,17 @@ static int wdt_open(struct inode *inode, struct file *file) case WATCHDOG_MINOR: if(test_and_set_bit(0, &wdt_is_open)) return -EBUSY; - if (nowayout) { - MOD_INC_USE_COUNT; - } /* * Activate */ + wdt_is_open=1; inb_p(WDT_DC); /* Disable */ wdt_ctr_mode(0,3); wdt_ctr_mode(1,2); wdt_ctr_mode(2,0); wdt_ctr_load(0, 8948); /* count at 100Hz */ - wdt_ctr_load(1,timeout_val); /* Timeout */ + wdt_ctr_load(1,wd_margin); /* Timeout 120 seconds */ wdt_ctr_load(2,65535); outb_p(0, WDT_DC); /* Enable */ return 0; @@ -525,7 +524,6 @@ static int __init wdt_init(void) { int ret; - wdt_validate_timeout(); ret = misc_register(&wdt_miscdev); if (ret) { printk(KERN_ERR "wdt: can't misc_register on minor=%d\n", WATCHDOG_MINOR); diff --git a/drivers/char/watchdog/wdt285.c b/drivers/char/watchdog/wdt285.c index 639ab2aa4edc..c9a6fac7404d 100644 --- a/drivers/char/watchdog/wdt285.c +++ b/drivers/char/watchdog/wdt285.c @@ -25,7 +25,6 @@ #include <linux/reboot.h> #include <linux/init.h> #include <linux/interrupt.h> -#include <linux/smp_lock.h> #include <asm/irq.h> #include <asm/uaccess.h> @@ -124,10 +123,10 @@ static ssize_t watchdog_write(struct file *file, const char *data, size_t len, l static int watchdog_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - int i; + int i, new_margin; static struct watchdog_info ident= { - 0, + WDIOF_SETTIMEOUT, 0, "Footbridge Watchdog" }; @@ -145,6 +144,17 @@ static int watchdog_ioctl(struct inode *inode, struct file *file, case WDIOC_KEEPALIVE: watchdog_ping(); return 0; + case WDIOC_SETTIMEOUT: + if (get_user(new_margin, (int *)arg)) + return -EFAULT; + /* Arbitrary, can't find the card's limits */ + if ((new_marg < 0) || (new_margin > 60)) + return -EINVAL; + soft_margin = new_margin; + watchdog_ping(); + /* Fall */ + case WDIOC_GETTIMEOUT: + return put_user(soft_margin, (int *)arg); } } @@ -166,10 +176,15 @@ static struct miscdevice watchdog_miscdev= static int __init footbridge_watchdog_init(void) { + int retval; + if (machine_is_netwinder()) return -ENODEV; - misc_register(&watchdog_miscdev); + retval = misc_register(&watchdog_miscdev); + if(retval < 0) + return retval; + printk("Footbridge Watchdog Timer: 0.01, timer margin: %d sec\n", soft_margin); if (machine_is_cats()) diff --git a/drivers/char/watchdog/wdt977.c b/drivers/char/watchdog/wdt977.c index 28c9e5842917..5b12542844b5 100644 --- a/drivers/char/watchdog/wdt977.c +++ b/drivers/char/watchdog/wdt977.c @@ -25,7 +25,6 @@ #include <linux/fs.h> #include <linux/miscdevice.h> #include <linux/init.h> -#include <linux/smp_lock.h> #include <linux/watchdog.h> #include <asm/io.h> diff --git a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c index 588f369ede0d..1e8b81c91969 100644 --- a/drivers/char/watchdog/wdt_pci.c +++ b/drivers/char/watchdog/wdt_pci.c @@ -30,21 +30,18 @@ * Alan Cox : Split ISA and PCI cards into two drivers * Jeff Garzik : PCI cleanups * Tigran Aivazian : Restructured wdtpci_init_one() to handle failures - * Matt Domsch : added nowayout and timeout module options + * Joel Becker : Added WDIOC_GET/SETTIMEOUT + * Zwane Mwaikambo : Magic char closing, locking changes, cleanups + * Matt Domsch : nowayout module option */ #include <linux/config.h> #include <linux/interrupt.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/types.h> -#include <linux/errno.h> -#include <linux/kernel.h> #include <linux/miscdevice.h> #include <linux/watchdog.h> -#include <linux/slab.h> #include <linux/ioport.h> -#include <linux/fcntl.h> #include <linux/notifier.h> #include <linux/reboot.h> #include <linux/init.h> @@ -72,23 +69,18 @@ #define PCI_DEVICE_ID_WDG_CSM 0x22c0 #endif -static unsigned long wdt_is_open; +static struct semaphore open_sem; +static spinlock_t wdtpci_lock; static int expect_close = 0; -/* - * You must set these - there is no sane way to probe for this board. - * You can use wdt=x,y to set these now. - */ - -static int io=0x240; -static int irq=11; +static int io; +static int irq; +/* Default timeout */ #define WD_TIMO (100*60) /* 1 minute */ +#define WD_TIMO_MAX (WD_TIMO*60) /* 1 hour(?) */ -static int timeout_val = WD_TIMO; /* value passed to card */ -static int timeout = 60; /* in seconds */ -MODULE_PARM(timeout,"i"); -MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=60)"); +static int wd_margin = WD_TIMO; #ifdef CONFIG_WATCHDOG_NOWAYOUT static int nowayout = 1; @@ -99,43 +91,6 @@ static int nowayout = 0; MODULE_PARM(nowayout,"i"); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); -static void __init -wdtpci_validate_timeout(void) -{ - timeout_val = timeout * 100; -} - -#ifndef MODULE - -/** - * wdtpci_setup: - * @str: command line string - * - * Setup options. The board isn't really probe-able so we have to - * get the user to tell us the configuration. Sane people build it - * modular but the others come here. - */ - -static int __init wdtpci_setup(char *str) -{ - int ints[4]; - - str = get_options (str, ARRAY_SIZE(ints), ints); - - if (ints[0] > 0) - { - io = ints[1]; - if(ints[0] > 1) - irq = ints[2]; - } - - return 1; -} - -__setup("wdt=", wdtpci_setup); - -#endif /* !MODULE */ - /* * Programming support */ @@ -251,11 +206,15 @@ static void wdtpci_interrupt(int irq, void *dev_id, struct pt_regs *regs) static void wdtpci_ping(void) { + unsigned long flags; + /* Write a watchdog value */ + spin_lock_irqsave(&wdtpci_lock, flags); inb_p(WDT_DC); wdtpci_ctr_mode(1,2); - wdtpci_ctr_load(1,timeout_val); /* Timeout */ + wdtpci_ctr_load(1,wd_margin); /* Timeout */ outb_p(0, WDT_DC); + spin_unlock_irqrestore(&wdtpci_lock, flags); } /** @@ -275,10 +234,12 @@ static ssize_t wdtpci_write(struct file *file, const char *buf, size_t count, lo if (ppos != &file->f_pos) return -ESPIPE; - if(count) - { + if (count) { if (!nowayout) { size_t i; + + expect_close = 0; + for (i = 0; i != count; i++) { char c; if(get_user(c, buf+i)) @@ -288,9 +249,9 @@ static ssize_t wdtpci_write(struct file *file, const char *buf, size_t count, lo } } wdtpci_ping(); - return 1; } - return 0; + + return count; } /** @@ -342,6 +303,7 @@ static ssize_t wdtpci_read(struct file *file, char *buf, size_t count, loff_t *p static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + int new_margin; static struct watchdog_info ident = { .options = WDIOF_OVERHEAT | WDIOF_POWERUNDER | WDIOF_POWEROVER | WDIOF_EXTERN1 | @@ -366,6 +328,18 @@ static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd case WDIOC_KEEPALIVE: wdtpci_ping(); return 0; + case WDIOC_SETTIMEOUT: + if (get_user(new_margin, (int *)arg)) + return -EFAULT; + /* Arbitrary, can't find the card's limits */ + new_margin *= 100; + if ((new_margin < 0) || (new_margin > WD_TIMO_MAX)) + return -EINVAL; + wd_margin = new_margin; + wdtpci_ping(); + /* Fall */ + case WDIOC_GETTIMEOUT: + return put_user(wd_margin / 100, (int *)arg); } } @@ -383,20 +357,22 @@ static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd static int wdtpci_open(struct inode *inode, struct file *file) { + unsigned long flags; + switch(minor(inode->i_rdev)) { case WATCHDOG_MINOR: - if( test_and_set_bit(0,&wdt_is_open) ) - { + if (down_trylock(&open_sem)) return -EBUSY; - } + if (nowayout) { MOD_INC_USE_COUNT; } /* * Activate */ - + spin_lock_irqsave(&wdtpci_lock, flags); + inb_p(WDT_DC); /* Disable */ /* @@ -418,9 +394,10 @@ static int wdtpci_open(struct inode *inode, struct file *file) wdtpci_ctr_mode(1,2); wdtpci_ctr_mode(2,1); wdtpci_ctr_load(0,20833); /* count at 100Hz */ - wdtpci_ctr_load(1,timeout_val); /* Timeout */ + wdtpci_ctr_load(1,wd_margin);/* Timeout 60 seconds */ /* DO NOT LOAD CTR2 on PCI card! -- JPN */ outb_p(0, WDT_DC); /* Enable */ + spin_unlock_irqrestore(&wdtpci_lock, flags); return 0; case TEMP_MINOR: return 0; @@ -443,13 +420,19 @@ static int wdtpci_open(struct inode *inode, struct file *file) static int wdtpci_release(struct inode *inode, struct file *file) { - if(minor(inode->i_rdev)==WATCHDOG_MINOR) - { - if (!nowayout) { + + if (minor(inode->i_rdev)==WATCHDOG_MINOR) { + unsigned long flags; + if (expect_close) { + spin_lock_irqsave(&wdtpci_lock, flags); inb_p(WDT_DC); /* Disable counters */ wdtpci_ctr_load(2,0); /* 0 length reset pulses now */ + spin_unlock_irqrestore(&wdtpci_lock, flags); + } else { + printk(KERN_CRIT PFX "Unexpected close, not stopping timer!"); + wdtpci_ping(); } - clear_bit(0, &wdt_is_open ); + up(&open_sem); } return 0; } @@ -469,11 +452,14 @@ static int wdtpci_release(struct inode *inode, struct file *file) static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { - if(code==SYS_DOWN || code==SYS_HALT) - { + unsigned long flags; + + if (code==SYS_DOWN || code==SYS_HALT) { /* Turn the card off */ + spin_lock_irqsave(&wdtpci_lock, flags); inb_p(WDT_DC); wdtpci_ctr_load(2,0); + spin_unlock_irqrestore(&wdtpci_lock, flags); } return NOTIFY_DONE; } @@ -533,6 +519,9 @@ static int __init wdtpci_init_one (struct pci_dev *dev, if (pci_enable_device (dev)) goto out; + sema_init(&open_sem, 1); + spin_lock_init(&wdtpci_lock); + irq = dev->irq; io = pci_resource_start (dev, 2); printk ("WDT501-P(PCI-WDG-CSM) driver 0.07 at %X " @@ -650,8 +639,6 @@ static int __init wdtpci_init(void) if (rc < 1) return -ENODEV; - - wdtpci_validate_timeout(); return 0; } diff --git a/drivers/hotplug/acpiphp_glue.c b/drivers/hotplug/acpiphp_glue.c index 6c16481c4102..7350c4071228 100644 --- a/drivers/hotplug/acpiphp_glue.c +++ b/drivers/hotplug/acpiphp_glue.c @@ -712,8 +712,9 @@ find_p2p_bridge (acpi_handle handle, u32 lvl, void *context, void **rv) /* find hot-pluggable slots, and then find P2P bridge */ -static int add_bridges (acpi_handle *handle) +static int add_bridges(struct acpi_device *device) { + acpi_handle *handle = device->handle; acpi_status status; unsigned long tmp; int seg, bus; @@ -767,36 +768,6 @@ static int add_bridges (acpi_handle *handle) } -/* callback routine to enumerate all the bridges in ACPI namespace */ -static acpi_status -find_host_bridge (acpi_handle handle, u32 lvl, void *context, void **rv) -{ - acpi_status status; - struct acpi_device_info info; - char objname[5]; - struct acpi_buffer buffer = { .length = sizeof(objname), - .pointer = objname }; - - status = acpi_get_object_info(handle, &info); - if (ACPI_FAILURE(status)) { - dbg("%s: failed to get bridge information\n", __FUNCTION__); - return AE_OK; /* continue */ - } - - info.hardware_id[sizeof(info.hardware_id)-1] = '\0'; - - /* TBD use acpi_get_devices() API */ - if (info.current_status && - (info.valid & ACPI_VALID_HID) && - strcmp(info.hardware_id, ACPI_PCI_HOST_HID) == 0) { - acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer); - dbg("checking PCI-hotplug capable bridges under [%s]\n", objname); - add_bridges(handle); - } - return AE_OK; -} - - static int power_on_slot (struct acpiphp_slot *slot) { acpi_status status; @@ -1157,6 +1128,14 @@ static void handle_hotplug_event_func (acpi_handle handle, u32 type, void *conte } } +static struct acpi_driver acpi_pci_hp_driver = { + .name = "pci_hp", + .class = "", + .ids = ACPI_PCI_HOST_HID, + .ops = { + .add = add_bridges, + } +}; /** * acpiphp_glue_init - initializes all PCI hotplug - ACPI glue data structures @@ -1169,9 +1148,7 @@ int acpiphp_glue_init (void) if (list_empty(&pci_root_buses)) return -1; - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, find_host_bridge, - NULL, NULL); + status = acpi_bus_register_driver(&acpi_pci_hp_driver); if (ACPI_FAILURE(status)) { err("%s: acpi_walk_namespace() failed\n", __FUNCTION__); diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index cd971f0d27b0..27d327707358 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -768,7 +768,7 @@ static void sunsab_set_termios(struct uart_port *port, struct termios *termios, { struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; unsigned long flags; - int baud = uart_get_baud_rate(port, termios); + int baud = uart_get_baud_rate(port, termios, old, 0, 4000000); spin_lock_irqsave(&up->port.lock, flags); sunsab_convert_to_sab(up, termios->c_cflag, termios->c_iflag, baud); diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index 377e6ba931e9..c4d53718daa8 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c @@ -417,7 +417,7 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode) struct buffer_head *bitmap_bh = NULL; struct buffer_head *bh2; int group; - ino_t ino; + unsigned long ino; struct inode * inode; struct ext3_group_desc * gdp; struct ext3_super_block * es; @@ -463,7 +463,7 @@ repeat: BUFFER_TRACE(bitmap_bh, "get_write_access"); err = ext3_journal_get_write_access(handle, bitmap_bh); if (err) goto fail; - + if (ext3_set_bit(ino, bitmap_bh->b_data)) { ext3_error (sb, "ext3_new_inode", "bit already set for inode %lu", ino); @@ -619,19 +619,18 @@ fail2: } /* Verify that we are loading a valid orphan from disk */ -struct inode *ext3_orphan_get (struct super_block * sb, ino_t ino) +struct inode *ext3_orphan_get(struct super_block *sb, unsigned long ino) { - ino_t max_ino = le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count); + unsigned long max_ino = le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count); unsigned long block_group; int bit; struct buffer_head *bitmap_bh = NULL; struct inode *inode = NULL; - + /* Error cases - e2fsck has already cleaned up for us */ if (ino > max_ino) { ext3_warning(sb, __FUNCTION__, - "bad orphan ino %lu! e2fsck was run?\n", - (unsigned long) ino); + "bad orphan ino %lu! e2fsck was run?\n", ino); goto out; } @@ -640,8 +639,7 @@ struct inode *ext3_orphan_get (struct super_block * sb, ino_t ino) bitmap_bh = read_inode_bitmap(sb, block_group); if (!bitmap_bh) { ext3_warning(sb, __FUNCTION__, - "inode bitmap error for orphan %lu\n", - (unsigned long) ino); + "inode bitmap error for orphan %lu\n", ino); goto out; } @@ -653,19 +651,17 @@ struct inode *ext3_orphan_get (struct super_block * sb, ino_t ino) !(inode = iget(sb, ino)) || is_bad_inode(inode) || NEXT_ORPHAN(inode) > max_ino) { ext3_warning(sb, __FUNCTION__, - "bad orphan inode %lu! e2fsck was run?\n", (unsigned long)ino); + "bad orphan inode %lu! e2fsck was run?\n", ino); printk(KERN_NOTICE "ext3_test_bit(bit=%d, block=%llu) = %d\n", - bit, - (unsigned long long)bitmap_bh->b_blocknr, - ext3_test_bit(bit, bitmap_bh->b_data)); + bit, (unsigned long long)bitmap_bh->b_blocknr, + ext3_test_bit(bit, bitmap_bh->b_data)); printk(KERN_NOTICE "inode=%p\n", inode); if (inode) { printk(KERN_NOTICE "is_bad_inode(inode)=%d\n", is_bad_inode(inode)); - printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%d\n", + printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n", NEXT_ORPHAN(inode)); - printk(KERN_NOTICE "max_ino=%lu\n", - (unsigned long) max_ino); + printk(KERN_NOTICE "max_ino=%lu\n", max_ino); } /* Avoid freeing blocks if we got a bad deleted inode */ if (inode && inode->i_nlink == 0) diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index a5e85ef29d2c..ccdb52c9cc77 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -1098,20 +1098,14 @@ out: return ret; } -static int journal_dirty_sync_data(handle_t *handle, struct buffer_head *bh) -{ - return ext3_journal_dirty_data(handle, bh, 0); -} - -/* - * For ext3_writepage(). We also brelse() the buffer to account for - * the bget() which ext3_writepage() performs. - */ -static int journal_dirty_async_data(handle_t *handle, struct buffer_head *bh) +static int +ext3_journal_dirty_data(handle_t *handle, struct buffer_head *bh) { - int ret = ext3_journal_dirty_data(handle, bh, 1); - __brelse(bh); - return ret; + int err = journal_dirty_data(handle, bh); + if (err) + ext3_journal_abort_handle(__FUNCTION__, __FUNCTION__, + bh, handle,err); + return err; } /* For commit_write() in data=journal mode */ @@ -1154,7 +1148,7 @@ static int ext3_commit_write(struct file *file, struct page *page, } else { if (ext3_should_order_data(inode)) { ret = walk_page_buffers(handle, page_buffers(page), - from, to, NULL, journal_dirty_sync_data); + from, to, NULL, ext3_journal_dirty_data); } /* Be careful here if generic_commit_write becomes a * required invocation after block_prepare_write. */ @@ -1228,7 +1222,13 @@ static sector_t ext3_bmap(struct address_space *mapping, sector_t block) static int bget_one(handle_t *handle, struct buffer_head *bh) { - atomic_inc(&bh->b_count); + get_bh(bh); + return 0; +} + +static int bput_one(handle_t *handle, struct buffer_head *bh) +{ + put_bh(bh); return 0; } @@ -1348,7 +1348,9 @@ static int ext3_writepage(struct page *page, struct writeback_control *wbc) /* And attach them to the current transaction */ if (order_data) { err = walk_page_buffers(handle, page_bufs, - 0, PAGE_CACHE_SIZE, NULL, journal_dirty_async_data); + 0, PAGE_CACHE_SIZE, NULL, ext3_journal_dirty_data); + walk_page_buffers(handle, page_bufs, 0, + PAGE_CACHE_SIZE, NULL, bput_one); if (!ret) ret = err; } @@ -1587,7 +1589,7 @@ static int ext3_block_truncate_page(handle_t *handle, err = ext3_journal_dirty_metadata(handle, bh); } else { if (ext3_should_order_data(inode)) - err = ext3_journal_dirty_data(handle, bh, 0); + err = ext3_journal_dirty_data(handle, bh); mark_buffer_dirty(bh); } diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 630dbff4001c..055dee6f64c8 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -1871,10 +1871,10 @@ int ext3_orphan_del(handle_t *handle, struct inode *inode) struct list_head *prev; struct ext3_inode_info *ei = EXT3_I(inode); struct ext3_sb_info *sbi; - ino_t ino_next; + unsigned long ino_next; struct ext3_iloc iloc; int err = 0; - + lock_super(inode->i_sb); if (list_empty(&ei->i_orphan)) { unlock_super(inode->i_sb); @@ -1885,7 +1885,7 @@ int ext3_orphan_del(handle_t *handle, struct inode *inode) prev = ei->i_orphan.prev; sbi = EXT3_SB(inode->i_sb); - jbd_debug(4, "remove inode %ld from orphan list\n", inode->i_ino); + jbd_debug(4, "remove inode %lu from orphan list\n", inode->i_ino); list_del_init(&ei->i_orphan); @@ -1895,13 +1895,13 @@ int ext3_orphan_del(handle_t *handle, struct inode *inode) * list in memory. */ if (!handle) goto out; - + err = ext3_reserve_inode_write(handle, inode, &iloc); if (err) goto out_err; if (prev == &sbi->s_orphan) { - jbd_debug(4, "superblock will point to %ld\n", ino_next); + jbd_debug(4, "superblock will point to %lu\n", ino_next); BUFFER_TRACE(sbi->s_sbh, "get_write_access"); err = ext3_journal_get_write_access(handle, sbi->s_sbh); if (err) @@ -1912,8 +1912,8 @@ int ext3_orphan_del(handle_t *handle, struct inode *inode) struct ext3_iloc iloc2; struct inode *i_prev = &list_entry(prev, struct ext3_inode_info, i_orphan)->vfs_inode; - - jbd_debug(4, "orphan inode %ld will point to %ld\n", + + jbd_debug(4, "orphan inode %lu will point to %lu\n", i_prev->i_ino, ino_next); err = ext3_reserve_inode_write(handle, i_prev, &iloc2); if (err) @@ -1928,7 +1928,7 @@ int ext3_orphan_del(handle_t *handle, struct inode *inode) if (err) goto out_brelse; -out_err: +out_err: ext3_std_error(inode->i_sb, err); out: unlock_super(inode->i_sb); diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 204e264a1783..bb8bf302da95 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -457,11 +457,8 @@ static struct address_space_operations hugetlbfs_aops = { }; struct file_operations hugetlbfs_file_operations = { - .read = generic_file_read, - .write = generic_file_write, .mmap = hugetlbfs_file_mmap, .fsync = simple_sync_file, - .sendfile = generic_file_sendfile, }; static struct inode_operations hugetlbfs_dir_inode_operations = { diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c index d640e23a1bf1..79b606822382 100644 --- a/fs/jbd/checkpoint.c +++ b/fs/jbd/checkpoint.c @@ -585,7 +585,6 @@ void __journal_drop_transaction(journal_t *journal, transaction_t *transaction) J_ASSERT (transaction->t_ilist == NULL); J_ASSERT (transaction->t_buffers == NULL); J_ASSERT (transaction->t_sync_datalist == NULL); - J_ASSERT (transaction->t_async_datalist == NULL); J_ASSERT (transaction->t_forget == NULL); J_ASSERT (transaction->t_iobuf_list == NULL); J_ASSERT (transaction->t_shadow_list == NULL); diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index f61bce34d072..12d4a744f07f 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c @@ -264,37 +264,6 @@ write_out_data_locked: goto write_out_data_locked; sync_datalist_empty: - /* - * Wait for all the async writepage data. As they become unlocked - * in end_buffer_async_write(), the only place where they can be - * reaped is in try_to_free_buffers(), and we're locked against - * that. - */ - while ((jh = commit_transaction->t_async_datalist)) { - struct buffer_head *bh = jh2bh(jh); - if (buffer_locked(bh)) { - spin_unlock(&journal_datalist_lock); - unlock_journal(journal); - wait_on_buffer(bh); - lock_journal(journal); - spin_lock(&journal_datalist_lock); - continue; /* List may have changed */ - } - if (jh->b_next_transaction) { - /* - * For writepage() buffers in journalled data mode: a - * later transaction may want the buffer for "metadata" - */ - __journal_refile_buffer(jh); - } else { - BUFFER_TRACE(bh, "finished async writeout: unfile"); - __journal_unfile_buffer(jh); - jh->b_transaction = NULL; - __journal_remove_journal_head(bh); - BUFFER_TRACE(bh, "finished async writeout: refile"); - __brelse(bh); - } - } spin_unlock(&journal_datalist_lock); /* @@ -304,7 +273,6 @@ sync_datalist_empty: * clean by now, so check that it is in fact empty. */ J_ASSERT (commit_transaction->t_sync_datalist == NULL); - J_ASSERT (commit_transaction->t_async_datalist == NULL); jbd_debug (3, "JBD: commit phase 3\n"); @@ -629,7 +597,6 @@ skip_commit: /* The journal should be unlocked by now. */ jbd_debug(3, "JBD: commit phase 7\n"); J_ASSERT(commit_transaction->t_sync_datalist == NULL); - J_ASSERT(commit_transaction->t_async_datalist == NULL); J_ASSERT(commit_transaction->t_buffers == NULL); J_ASSERT(commit_transaction->t_checkpoint_list == NULL); J_ASSERT(commit_transaction->t_iobuf_list == NULL); diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index f7e4c3a0c627..e62a542396a6 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -578,9 +578,6 @@ static void jbd_unexpected_dirty_buffer(struct journal_head *jh) * part of the transaction, that is). * * Returns an error code or 0 on success. - * - * In full data journalling mode the buffer may be of type BJ_AsyncData, - * because we're write()ing a buffer which is also part of a shared mapping. */ static int @@ -949,26 +946,16 @@ out: * The buffer is placed on the transaction's data list and is marked as * belonging to the transaction. * - * If `async' is set then the writebabk will be initiated by the caller - * using submit_bh -> end_buffer_async_write. We put the buffer onto - * t_async_datalist. - * * Returns error number or 0 on success. * * journal_dirty_data() can be called via page_launder->ext3_writepage * by kswapd. So it cannot block. Happily, there's nothing here * which needs lock_journal if `async' is set. - * - * When the buffer is on the current transaction we freely move it - * between BJ_AsyncData and BJ_SyncData according to who tried to - * change its state last. */ - -int journal_dirty_data (handle_t *handle, struct buffer_head *bh, int async) +int journal_dirty_data (handle_t *handle, struct buffer_head *bh) { journal_t *journal = handle->h_transaction->t_journal; int need_brelse = 0; - int wanted_jlist = async ? BJ_AsyncData : BJ_SyncData; struct journal_head *jh; if (is_handle_aborted(handle)) @@ -1046,8 +1033,7 @@ int journal_dirty_data (handle_t *handle, struct buffer_head *bh, int async) * the write() data. */ if (jh->b_jlist != BJ_None && - jh->b_jlist != BJ_SyncData && - jh->b_jlist != BJ_AsyncData) { + jh->b_jlist != BJ_SyncData) { JBUFFER_TRACE(jh, "Not stealing"); goto no_journal; } @@ -1058,7 +1044,7 @@ int journal_dirty_data (handle_t *handle, struct buffer_head *bh, int async) * again because that can cause the write-out loop in * commit to never terminate. */ - if (!async && buffer_dirty(bh)) { + if (buffer_dirty(bh)) { atomic_inc(&bh->b_count); spin_unlock(&journal_datalist_lock); need_brelse = 1; @@ -1084,18 +1070,18 @@ int journal_dirty_data (handle_t *handle, struct buffer_head *bh, int async) * committing transaction, so might still be left on that * transaction's metadata lists. */ - if (jh->b_jlist != wanted_jlist) { + if (jh->b_jlist != BJ_SyncData) { JBUFFER_TRACE(jh, "not on correct data list: unfile"); J_ASSERT_JH(jh, jh->b_jlist != BJ_Shadow); __journal_unfile_buffer(jh); jh->b_transaction = NULL; JBUFFER_TRACE(jh, "file as data"); __journal_file_buffer(jh, handle->h_transaction, - wanted_jlist); + BJ_SyncData); } } else { JBUFFER_TRACE(jh, "not on a transaction"); - __journal_file_buffer(jh, handle->h_transaction, wanted_jlist); + __journal_file_buffer(jh, handle->h_transaction, BJ_SyncData); } no_journal: spin_unlock(&journal_datalist_lock); @@ -1559,12 +1545,12 @@ __blist_del_buffer(struct journal_head **list, struct journal_head *jh) * Remove a buffer from the appropriate transaction list. * * Note that this function can *change* the value of - * bh->b_transaction->t_sync_datalist, t_async_datalist, t_buffers, t_forget, + * bh->b_transaction->t_sync_datalist, t_buffers, t_forget, * t_iobuf_list, t_shadow_list, t_log_list or t_reserved_list. If the caller * is holding onto a copy of one of thee pointers, it could go bad. * Generally the caller needs to re-read the pointer from the transaction_t. * - * If bh->b_jlist is BJ_SyncData or BJ_AsyncData then we may have been called + * If bh->b_jlist is BJ_SyncData then we may have been called * via journal_try_to_free_buffer() or journal_clean_data_list(). In that * case, journal_datalist_lock will be held, and the journal may not be locked. */ @@ -1590,9 +1576,6 @@ void __journal_unfile_buffer(struct journal_head *jh) case BJ_SyncData: list = &transaction->t_sync_datalist; break; - case BJ_AsyncData: - list = &transaction->t_async_datalist; - break; case BJ_Metadata: transaction->t_nr_buffers--; J_ASSERT_JH(jh, transaction->t_nr_buffers >= 0); @@ -1658,7 +1641,7 @@ static inline int __journal_try_to_free_buffer(struct buffer_head *bh) goto out; if (jh->b_transaction != 0 && jh->b_cp_transaction == 0) { - if (jh->b_jlist == BJ_SyncData || jh->b_jlist==BJ_AsyncData) { + if (jh->b_jlist == BJ_SyncData) { /* A written-back ordered data buffer */ JBUFFER_TRACE(jh, "release data"); __journal_unfile_buffer(jh); @@ -1994,9 +1977,6 @@ void __journal_file_buffer(struct journal_head *jh, case BJ_SyncData: list = &transaction->t_sync_datalist; break; - case BJ_AsyncData: - list = &transaction->t_async_datalist; - break; case BJ_Metadata: transaction->t_nr_buffers++; list = &transaction->t_buffers; diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 089790f3b34a..62af20aecec2 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -221,7 +221,6 @@ out_fail: int proc_fill_super(struct super_block *s, void *data, int silent) { struct inode * root_inode; - struct task_struct *p; s->s_blocksize = 1024; s->s_blocksize_bits = 10; @@ -234,11 +233,7 @@ int proc_fill_super(struct super_block *s, void *data, int silent) /* * Fixup the root inode's nlink value */ - read_lock(&tasklist_lock); - for_each_process(p) - if (p->pid) - root_inode->i_nlink++; - read_unlock(&tasklist_lock); + root_inode->i_nlink += nr_processes(); s->s_root = d_alloc_root(root_inode); if (!s->s_root) goto out_no_root; diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index fff23ee7ca2b..ba036340fcd1 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c @@ -140,9 +140,10 @@ static int meminfo_read_proc(char *page, char **start, off_t off, struct page_state ps; unsigned long inactive; unsigned long active; + unsigned long free; get_page_state(&ps); - get_zone_counts(&active, &inactive); + get_zone_counts(&active, &inactive, &free); /* * display in kilobytes. diff --git a/fs/xfs/linux/xfs_linux.h b/fs/xfs/linux/xfs_linux.h index efcff94b19dd..70496e24ff69 100644 --- a/fs/xfs/linux/xfs_linux.h +++ b/fs/xfs/linux/xfs_linux.h @@ -42,6 +42,7 @@ #include <linux/sched.h> #include <linux/bitops.h> #include <linux/major.h> +#include <linux/pagemap.h> #include <linux/vfs.h> #include <asm/page.h> @@ -169,7 +170,6 @@ typedef struct xfs_dirent { /* data from readdir() */ #define DEFAULT_PROJID 0 #define dfltprid DEFAULT_PROJID -#define MAXNAMELEN 256 #define MAXPATHLEN 1024 #define FINVIS 0x0100 /* don't update timestamps - XFS */ diff --git a/fs/xfs/linux/xfs_lrw.c b/fs/xfs/linux/xfs_lrw.c index b1fed677d5ed..d08561facca0 100644 --- a/fs/xfs/linux/xfs_lrw.c +++ b/fs/xfs/linux/xfs_lrw.c @@ -872,13 +872,12 @@ XFS_log_write_unmount_ro(bhv_desc_t *bdp) int error; mp = XFS_BHVTOM(bdp); - xfs_binval(mp->m_ddev_targp); + pagebuf_delwri_flush(mp->m_ddev_targp, PBDF_WAIT, &pincount); + xfs_finish_reclaim_all(mp); do { - xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE | XFS_LOG_SYNC); VFS_SYNC(XFS_MTOVFS(mp), SYNC_ATTR|SYNC_WAIT, NULL, error); - pagebuf_delwri_flush(mp->m_ddev_targp, - PBDF_WAIT, &pincount); + pagebuf_delwri_flush(mp->m_ddev_targp, PBDF_WAIT, &pincount); if (pincount == 0) {delay(50); count++;} } while (count < 2); diff --git a/fs/xfs/linux/xfs_vnode.h b/fs/xfs/linux/xfs_vnode.h index 5e094d8bc810..abd56b0bc175 100644 --- a/fs/xfs/linux/xfs_vnode.h +++ b/fs/xfs/linux/xfs_vnode.h @@ -671,13 +671,14 @@ extern void vn_rele(struct vnode *); #define VN_HOLD(vp) ((void)vn_hold(vp)) #define VN_RELE(vp) (iput(LINVFS_GET_IP(vp))) -#endif /* ! (defined(CONFIG_XFS_VNODE_TRACING) */ +#endif /* ! (defined(CONFIG_XFS_VNODE_TRACING)) */ /* * Vname handling macros. */ #define VNAME(dentry) ((char *) (dentry)->d_name.name) #define VNAMELEN(dentry) ((dentry)->d_name.len) +#define VNAME_TO_VNODE(dentry) (LINVFS_GET_VP((dentry)->d_inode)) /* * Vnode spinlock manipulation. diff --git a/fs/xfs/pagebuf/page_buf.c b/fs/xfs/pagebuf/page_buf.c index 76f6d213b013..905dfcf757a6 100644 --- a/fs/xfs/pagebuf/page_buf.c +++ b/fs/xfs/pagebuf/page_buf.c @@ -1108,7 +1108,7 @@ _pagebuf_wait_unpin( * pagebuf_iodone * * pagebuf_iodone marks a buffer for which I/O is in progress - * done with respect to that I/O. The pb_done routine, if + * done with respect to that I/O. The pb_iodone routine, if * present, will be called as a side-effect. */ void @@ -1173,7 +1173,7 @@ pagebuf_ioerror( /* mark/clear buffer error flag */ * pagebuf_iostart initiates I/O on a buffer, based on the flags supplied. * If necessary, it will arrange for any disk space allocation required, * and it will break up the request if the block mappings require it. - * An pb_iodone routine in the buffer supplied will only be called + * The pb_iodone routine in the buffer supplied will only be called * when all of the subsidiary I/O requests, if any, have been completed. * pagebuf_iostart calls the pagebuf_ioinitiate routine or * pagebuf_iorequest, if the former routine is not defined, to start @@ -1317,7 +1317,7 @@ pagebuf_iorequest( /* start real I/O */ /* Set the count to 1 initially, this will stop an I/O * completion callout which happens before we have started - * all the I/O from calling iodone too early + * all the I/O from calling pagebuf_iodone too early. */ atomic_set(&pb->pb_io_remaining, 1); diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c index d6fe5d8b6983..cbedf29d7586 100644 --- a/fs/xfs/support/debug.c +++ b/fs/xfs/support/debug.c @@ -41,7 +41,10 @@ static char message[256]; /* keep it off the stack */ static spinlock_t xfs_err_lock = SPIN_LOCK_UNLOCKED; /* Translate from CE_FOO to KERN_FOO, err_level(CE_FOO) == KERN_FOO */ -static char *err_level[8] = {KERN_EMERG, KERN_ALERT, KERN_CRIT, +#define XFS_MAX_ERR_LEVEL 7 +#define XFS_ERR_MASK ((1 << 3) - 1) +static char *err_level[XFS_MAX_ERR_LEVEL+1] = + {KERN_EMERG, KERN_ALERT, KERN_CRIT, KERN_ERR, KERN_WARNING, KERN_NOTICE, KERN_INFO, KERN_DEBUG}; @@ -82,15 +85,22 @@ void cmn_err(register int level, char *fmt, ...) { char *fp = fmt; - va_list ap; + int len; + int flags; + va_list ap; - spin_lock(&xfs_err_lock); + level &= XFS_ERR_MASK; + if (level > XFS_MAX_ERR_LEVEL) + level = XFS_MAX_ERR_LEVEL; + spin_lock_irqsave(&xfs_err_lock,flags); va_start(ap, fmt); if (*fmt == '!') fp++; - vsprintf(message, fp, ap); - printk("%s%s\n", err_level[level], message); + len = vsprintf(message, fp, ap); + if (message[len-1] != '\n') + strcat(message, "\n"); + printk("%s%s", err_level[level], message); va_end(ap); - spin_unlock(&xfs_err_lock); + spin_unlock_irqrestore(&xfs_err_lock,flags); if (level == CE_PANIC) BUG(); @@ -100,10 +110,18 @@ cmn_err(register int level, char *fmt, ...) void icmn_err(register int level, char *fmt, va_list ap) { - spin_lock(&xfs_err_lock); - vsprintf(message, fmt, ap); - spin_unlock(&xfs_err_lock); - printk("%s%s\n", err_level[level], message); + int len; + int flags; + + level &= XFS_ERR_MASK; + if(level > XFS_MAX_ERR_LEVEL) + level = XFS_MAX_ERR_LEVEL; + spin_lock_irqsave(&xfs_err_lock,flags); + len = vsprintf(message, fmt, ap); + if (message[len-1] != '\n') + strcat(message, "\n"); + spin_unlock_irqrestore(&xfs_err_lock,flags); + printk("%s%s", err_level[level], message); if (level == CE_PANIC) BUG(); } diff --git a/fs/xfs/xfs_dir.c b/fs/xfs/xfs_dir.c index ddb243978027..0631c9c1deb3 100644 --- a/fs/xfs/xfs_dir.c +++ b/fs/xfs/xfs_dir.c @@ -386,9 +386,6 @@ xfs_dir_lookup(xfs_trans_t *trans, xfs_inode_t *dp, char *name, int namelen, int retval; ASSERT((dp->i_d.di_mode & IFMT) == IFDIR); - if (namelen >= MAXNAMELEN) { - return(XFS_ERROR(EINVAL)); - } XFS_STATS_INC(xfsstats.xs_dir_lookup); /* @@ -479,9 +476,6 @@ xfs_dir_replace(xfs_trans_t *trans, xfs_inode_t *dp, char *name, int namelen, int retval; ASSERT((dp->i_d.di_mode & IFMT) == IFDIR); - if (namelen >= MAXNAMELEN) { - return(XFS_ERROR(EINVAL)); - } if ((retval = xfs_dir_ino_validate(trans->t_mountp, inum))) return retval; diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index b47e2a939415..766cbdfa4099 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c @@ -232,10 +232,8 @@ xfs_dir2_lookup( int v; /* type-checking value */ ASSERT((dp->i_d.di_mode & IFMT) == IFDIR); - if (namelen >= MAXNAMELEN) { - return XFS_ERROR(EINVAL); - } XFS_STATS_INC(xfsstats.xs_dir_lookup); + /* * Fill in the arg structure for this request. */ @@ -395,9 +393,7 @@ xfs_dir2_replace( int v; /* type-checking value */ ASSERT((dp->i_d.di_mode & IFMT) == IFDIR); - if (namelen >= MAXNAMELEN) { - return XFS_ERROR(EINVAL); - } + if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) { return rval; } diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index d0720edd79cd..79227f00b1a1 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -414,11 +414,9 @@ void xfs_ifork_next_set(xfs_inode_t *ip, int w, int n); * max file offset is 2^(31+PAGE_SHIFT) - 1 (due to linux page cache) * * NOTE: XFS itself can handle 2^63 - 1 (largest positive value of xfs_fsize_t) - * but Linux can't go above 2^(31+PAGE_SHIFT)-1: the Linux VM uses a 32 bit - * signed variable to index cache data, so 2^31 * PAGE_SIZE is as big as - * you can go. + * but this is the Linux limit. */ -#define XFS_MAX_FILE_OFFSET ((long long)((1ULL<<(31+PAGE_SHIFT))-1ULL)) +#define XFS_MAX_FILE_OFFSET MAX_LFS_FILESIZE #if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_ITOV) struct vnode *xfs_itov(xfs_inode_t *ip); @@ -483,6 +481,7 @@ void xfs_iunlock_map_shared(xfs_inode_t *, uint); void xfs_ifunlock(xfs_inode_t *); void xfs_ireclaim(xfs_inode_t *); int xfs_finish_reclaim(xfs_inode_t *, int, int); +int xfs_finish_reclaim_all(struct xfs_mount *); /* * xfs_inode.c prototypes. diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 9a72b4036048..617eead8f16d 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -2952,7 +2952,6 @@ xlog_recover_process_iunlinks(xlog_t *log) if (!error) { ASSERT(ip->i_d.di_nlink == 0); - ASSERT(ip->i_d.di_mode != 0); /* setup for the next pass */ agino = INT_GET(dip->di_next_unlinked, @@ -2970,7 +2969,9 @@ xlog_recover_process_iunlinks(xlog_t *log) ip->i_d.di_dmevmask = 0; /* - * Drop our reference to the + * If this is a new inode, handle + * it specially. Otherwise, + * just drop our reference to the * inode. If there are no * other references, this will * send the inode to @@ -2978,7 +2979,10 @@ xlog_recover_process_iunlinks(xlog_t *log) * truncate the file and free * the inode. */ - VN_RELE(XFS_ITOV(ip)); + if (ip->i_d.di_mode == 0) + xfs_iput_new(ip, 0); + else + VN_RELE(XFS_ITOV(ip)); } else { /* * We can't read in the inode diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c index f329e8133bf1..aad9dbbcc205 100644 --- a/fs/xfs/xfs_rename.c +++ b/fs/xfs/xfs_rename.c @@ -72,14 +72,13 @@ int xfs_rename_skip, xfs_rename_nskip; * We are renaming dp1/name1 to dp2/name2. * * Return ENOENT if dp1 does not exist, other lookup errors, or 0 for success. - * Return EAGAIN if the caller needs to try again. */ STATIC int xfs_lock_for_rename( xfs_inode_t *dp1, /* old (source) directory inode */ xfs_inode_t *dp2, /* new (target) directory inode */ - vname_t *dentry1, /* old entry name */ - vname_t *dentry2, /* new entry name */ + vname_t *vname1,/* old entry name */ + vname_t *vname2,/* new entry name */ xfs_inode_t **ipp1, /* inode of old entry */ xfs_inode_t **ipp2, /* inode of new entry, if it already exists, NULL otherwise. */ @@ -102,7 +101,7 @@ xfs_lock_for_rename( * to see if we still have the right inodes, directories, etc. */ lock_mode = xfs_ilock_map_shared(dp1); - error = xfs_get_dir_entry(dentry1, &ip1); + error = xfs_get_dir_entry(vname1, &ip1); if (error) { xfs_iunlock_map_shared(dp1, lock_mode); return error; @@ -123,7 +122,7 @@ xfs_lock_for_rename( } error = xfs_dir_lookup_int(XFS_ITOBHV(dp2), lock_mode, - dentry2, &inum2, &ip2); + vname2, &inum2, &ip2); if (error == ENOENT) { /* target does not need to exist. */ inum2 = 0; } else if (error) { @@ -213,20 +212,15 @@ xfs_lock_for_rename( int rename_which_error_return = 0; -#ifdef DEBUG -int xfs_rename_agains; -int xfs_renames; -#endif - /* * xfs_rename */ int xfs_rename( bhv_desc_t *src_dir_bdp, - vname_t *src_dentry, + vname_t *src_vname, vnode_t *target_dir_vp, - vname_t *target_dentry, + vname_t *target_vname, cred_t *credp) { xfs_trans_t *tp; @@ -246,15 +240,11 @@ xfs_rename( int spaceres; int target_link_zero = 0; int num_inodes; - char *src_name = VNAME(src_dentry); - char *target_name = VNAME(target_dentry); - int src_namelen; - int target_namelen; -#ifdef DEBUG - int retries; + char *src_name = VNAME(src_vname); + char *target_name = VNAME(target_vname); + int src_namelen = VNAMELEN(src_vname); + int target_namelen = VNAMELEN(target_vname); - xfs_renames++; -#endif src_dir_vp = BHV_TO_VNODE(src_dir_bdp); vn_trace_entry(src_dir_vp, "xfs_rename", (inst_t *)__return_address); vn_trace_entry(target_dir_vp, "xfs_rename", (inst_t *)__return_address); @@ -268,14 +258,10 @@ xfs_rename( if (target_dir_bdp == NULL) { return XFS_ERROR(EXDEV); } - src_namelen = VNAMELEN(src_dentry); - if (src_namelen >= MAXNAMELEN) - return XFS_ERROR(ENAMETOOLONG); - target_namelen = VNAMELEN(target_dentry); - if (target_namelen >= MAXNAMELEN) - return XFS_ERROR(ENAMETOOLONG); + src_dp = XFS_BHVTOI(src_dir_bdp); target_dp = XFS_BHVTOI(target_dir_bdp); + if (DM_EVENT_ENABLED(src_dir_vp->v_vfsp, src_dp, DM_EVENT_RENAME) || DM_EVENT_ENABLED(target_dir_vp->v_vfsp, target_dp, DM_EVENT_RENAME)) { @@ -290,9 +276,6 @@ xfs_rename( } /* Return through std_return after this point. */ -#ifdef DEBUG - retries = 0; -#endif /* * Lock all the participating inodes. Depending upon whether * the target_name exists in the target directory, and @@ -302,15 +285,9 @@ xfs_rename( * does not exist in the source directory. */ tp = NULL; - do { - error = xfs_lock_for_rename(src_dp, target_dp, src_dentry, - target_dentry, &src_ip, &target_ip, inodes, - &num_inodes); -#ifdef DEBUG - if (error == EAGAIN) - xfs_rename_agains++; -#endif - } while (error == EAGAIN); + error = xfs_lock_for_rename(src_dp, target_dp, src_vname, + target_vname, &src_ip, &target_ip, inodes, + &num_inodes); if (error) { rename_which_error_return = __LINE__; diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c index 380f14d076eb..9059b4261e89 100644 --- a/fs/xfs/xfs_utils.c +++ b/fs/xfs/xfs_utils.c @@ -47,9 +47,7 @@ xfs_get_dir_entry( vnode_t *vp; bhv_desc_t *bdp; - ASSERT(dentry->d_inode); - - vp = LINVFS_GET_VP(dentry->d_inode); + vp = VNAME_TO_VNODE(dentry); bdp = vn_bhv_lookup_unlocked(VN_BHV_HEAD(vp), &xfs_vnodeops); if (!bdp) { *ipp = NULL; diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index a7e011fdd76a..f86e0f65def0 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c @@ -926,7 +926,7 @@ xfs_syncsub( IPOINTER_CLR; \ } -#define PREEMPT_MASK 0x7f +#define XFS_PREEMPT_MASK 0x7f if (bypassed) *bypassed = 0; @@ -1395,7 +1395,7 @@ xfs_syncsub( * if we have looped many times without dropping the * lock. */ - if ((++preempt & PREEMPT_MASK) == 0) { + if ((++preempt & XFS_PREEMPT_MASK) == 0) { if (mount_locked) { IPOINTER_INSERT(ip, mp); } diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 10a84831f40d..c1b5ad834e2c 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -82,7 +82,7 @@ xfs_open( /* * xfs_getattr */ -int +STATIC int xfs_getattr( bhv_desc_t *bdp, vattr_t *vap, @@ -1935,8 +1935,6 @@ xfs_create( dm_di_mode = vap->va_mode|VTTOIF(vap->va_type); namelen = VNAMELEN(dentry); - if (namelen >= MAXNAMELEN) - return XFS_ERROR(ENAMETOOLONG); if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_CREATE)) { error = dm_send_namesp_event(DM_EVENT_CREATE, @@ -2433,8 +2431,7 @@ xfs_remove( return XFS_ERROR(EIO); namelen = VNAMELEN(dentry); - if (namelen >= MAXNAMELEN) - return XFS_ERROR(ENAMETOOLONG); + if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_REMOVE)) { error = dm_send_namesp_event(DM_EVENT_REMOVE, dir_bdp, DM_RIGHT_NULL, NULL, DM_RIGHT_NULL, @@ -2668,8 +2665,6 @@ xfs_link( vn_trace_entry(src_vp, __FUNCTION__, (inst_t *)__return_address); target_namelen = VNAMELEN(dentry); - if (target_namelen >= MAXNAMELEN) - return XFS_ERROR(ENAMETOOLONG); if (src_vp->v_type == VDIR) return XFS_ERROR(EPERM); @@ -2857,8 +2852,6 @@ xfs_mkdir( return XFS_ERROR(EIO); dir_namelen = VNAMELEN(dentry); - if (dir_namelen >= MAXNAMELEN) - return XFS_ERROR(ENAMETOOLONG); tp = NULL; dp_joined_to_trans = B_FALSE; @@ -3100,8 +3093,6 @@ xfs_rmdir( if (XFS_FORCED_SHUTDOWN(XFS_BHVTOI(dir_bdp)->i_mount)) return XFS_ERROR(EIO); namelen = VNAMELEN(dentry); - if (namelen >= MAXNAMELEN) - return XFS_ERROR(ENAMETOOLONG); if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_REMOVE)) { error = dm_send_namesp_event(DM_EVENT_REMOVE, @@ -3415,8 +3406,7 @@ xfs_symlink( return XFS_ERROR(EIO); link_namelen = VNAMELEN(dentry); - if (link_namelen >= MAXNAMELEN) - return XFS_ERROR(ENAMETOOLONG); + /* * Check component lengths of the target path name. */ @@ -4070,6 +4060,49 @@ xfs_finish_reclaim( return 0; } +int +xfs_finish_reclaim_all(xfs_mount_t *mp) +{ + int purged; + xfs_inode_t *ip; + vnode_t *vp; + int done = 0; + + while (!done) { + purged = 0; + XFS_MOUNT_ILOCK(mp); + ip = mp->m_inodes; + if (ip == NULL) { + break; + } + do { + /* Make sure we skip markers inserted by sync */ + if (ip->i_mount == NULL) { + ip = ip->i_mnext; + continue; + } + + /* + * It's up to our caller to purge the root + * and quota vnodes later. + */ + vp = XFS_ITOV_NULL(ip); + + if (!vp) { + XFS_MOUNT_IUNLOCK(mp); + xfs_finish_reclaim(ip, 0, XFS_IFLUSH_ASYNC); + purged = 1; + break; + } + } while (ip != mp->m_inodes); + + done = !purged; + } + + XFS_MOUNT_IUNLOCK(mp); + return 0; +} + /* * xfs_alloc_file_space() * This routine allocates disk space for the given file. diff --git a/include/asm-arm/ide.h b/include/asm-arm/ide.h index e872974aa009..79204592dd68 100644 --- a/include/asm-arm/ide.h +++ b/include/asm-arm/ide.h @@ -36,8 +36,6 @@ * The following are not needed for the non-m68k ports */ #define ide_ack_intr(hwif) (1) -#define ide_release_lock(lock) do {} while (0) -#define ide_get_lock(lock, hdlr, data) do {} while (0) #endif /* __KERNEL__ */ diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h index a5dc6bb96720..4aaab2f3bb00 100644 --- a/include/asm-arm/unistd.h +++ b/include/asm-arm/unistd.h @@ -1,7 +1,7 @@ /* * linux/include/asm-arm/unistd.h * - * Copyright (C) 2001 Russell King + * Copyright (C) 2001-2003 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -32,7 +32,7 @@ #define __NR_write (__NR_SYSCALL_BASE+ 4) #define __NR_open (__NR_SYSCALL_BASE+ 5) #define __NR_close (__NR_SYSCALL_BASE+ 6) -#define __NR_waitpid (__NR_SYSCALL_BASE+ 7) +#define __NR_waitpid (__NR_SYSCALL_BASE+ 7) /* removed */ #define __NR_creat (__NR_SYSCALL_BASE+ 8) #define __NR_link (__NR_SYSCALL_BASE+ 9) #define __NR_unlink (__NR_SYSCALL_BASE+ 10) @@ -42,8 +42,8 @@ #define __NR_mknod (__NR_SYSCALL_BASE+ 14) #define __NR_chmod (__NR_SYSCALL_BASE+ 15) #define __NR_lchown (__NR_SYSCALL_BASE+ 16) -#define __NR_break (__NR_SYSCALL_BASE+ 17) - +#define __NR_break (__NR_SYSCALL_BASE+ 17) /* removed */ + /* 18 was sys_stat */ #define __NR_lseek (__NR_SYSCALL_BASE+ 19) #define __NR_getpid (__NR_SYSCALL_BASE+ 20) #define __NR_mount (__NR_SYSCALL_BASE+ 21) @@ -56,11 +56,11 @@ #define __NR_pause (__NR_SYSCALL_BASE+ 29) #define __NR_utime (__NR_SYSCALL_BASE+ 30) -#define __NR_stty (__NR_SYSCALL_BASE+ 31) -#define __NR_gtty (__NR_SYSCALL_BASE+ 32) +#define __NR_stty (__NR_SYSCALL_BASE+ 31) /* removed */ +#define __NR_gtty (__NR_SYSCALL_BASE+ 32) /* removed */ #define __NR_access (__NR_SYSCALL_BASE+ 33) #define __NR_nice (__NR_SYSCALL_BASE+ 34) -#define __NR_ftime (__NR_SYSCALL_BASE+ 35) +#define __NR_ftime (__NR_SYSCALL_BASE+ 35) /* removed */ #define __NR_sync (__NR_SYSCALL_BASE+ 36) #define __NR_kill (__NR_SYSCALL_BASE+ 37) #define __NR_rename (__NR_SYSCALL_BASE+ 38) @@ -69,22 +69,22 @@ #define __NR_dup (__NR_SYSCALL_BASE+ 41) #define __NR_pipe (__NR_SYSCALL_BASE+ 42) #define __NR_times (__NR_SYSCALL_BASE+ 43) -#define __NR_prof (__NR_SYSCALL_BASE+ 44) +#define __NR_prof (__NR_SYSCALL_BASE+ 44) /* removed */ #define __NR_brk (__NR_SYSCALL_BASE+ 45) #define __NR_setgid (__NR_SYSCALL_BASE+ 46) #define __NR_getgid (__NR_SYSCALL_BASE+ 47) -#define __NR_signal (__NR_SYSCALL_BASE+ 48) +#define __NR_signal (__NR_SYSCALL_BASE+ 48) /* removed */ #define __NR_geteuid (__NR_SYSCALL_BASE+ 49) #define __NR_getegid (__NR_SYSCALL_BASE+ 50) #define __NR_acct (__NR_SYSCALL_BASE+ 51) #define __NR_umount2 (__NR_SYSCALL_BASE+ 52) -#define __NR_lock (__NR_SYSCALL_BASE+ 53) +#define __NR_lock (__NR_SYSCALL_BASE+ 53) /* removed */ #define __NR_ioctl (__NR_SYSCALL_BASE+ 54) #define __NR_fcntl (__NR_SYSCALL_BASE+ 55) -#define __NR_mpx (__NR_SYSCALL_BASE+ 56) +#define __NR_mpx (__NR_SYSCALL_BASE+ 56) /* removed */ #define __NR_setpgid (__NR_SYSCALL_BASE+ 57) -#define __NR_ulimit (__NR_SYSCALL_BASE+ 58) - +#define __NR_ulimit (__NR_SYSCALL_BASE+ 58) /* removed */ + /* 59 was sys_olduname */ #define __NR_umask (__NR_SYSCALL_BASE+ 60) #define __NR_chroot (__NR_SYSCALL_BASE+ 61) #define __NR_ustat (__NR_SYSCALL_BASE+ 62) @@ -93,8 +93,8 @@ #define __NR_getpgrp (__NR_SYSCALL_BASE+ 65) #define __NR_setsid (__NR_SYSCALL_BASE+ 66) #define __NR_sigaction (__NR_SYSCALL_BASE+ 67) -#define __NR_sgetmask (__NR_SYSCALL_BASE+ 68) -#define __NR_ssetmask (__NR_SYSCALL_BASE+ 69) +#define __NR_sgetmask (__NR_SYSCALL_BASE+ 68) /* removed */ +#define __NR_ssetmask (__NR_SYSCALL_BASE+ 69) /* removed */ #define __NR_setreuid (__NR_SYSCALL_BASE+ 70) #define __NR_setregid (__NR_SYSCALL_BASE+ 71) #define __NR_sigsuspend (__NR_SYSCALL_BASE+ 72) @@ -109,7 +109,7 @@ #define __NR_setgroups (__NR_SYSCALL_BASE+ 81) #define __NR_select (__NR_SYSCALL_BASE+ 82) #define __NR_symlink (__NR_SYSCALL_BASE+ 83) - + /* 84 was sys_lstat */ #define __NR_readlink (__NR_SYSCALL_BASE+ 85) #define __NR_uselib (__NR_SYSCALL_BASE+ 86) #define __NR_swapon (__NR_SYSCALL_BASE+ 87) @@ -123,7 +123,7 @@ #define __NR_fchown (__NR_SYSCALL_BASE+ 95) #define __NR_getpriority (__NR_SYSCALL_BASE+ 96) #define __NR_setpriority (__NR_SYSCALL_BASE+ 97) -#define __NR_profil (__NR_SYSCALL_BASE+ 98) +#define __NR_profil (__NR_SYSCALL_BASE+ 98) /* removed */ #define __NR_statfs (__NR_SYSCALL_BASE+ 99) #define __NR_fstatfs (__NR_SYSCALL_BASE+100) #define __NR_ioperm (__NR_SYSCALL_BASE+101) @@ -134,8 +134,8 @@ #define __NR_stat (__NR_SYSCALL_BASE+106) #define __NR_lstat (__NR_SYSCALL_BASE+107) #define __NR_fstat (__NR_SYSCALL_BASE+108) - - + /* 109 was sys_uname */ + /* 110 was sys_iopl */ #define __NR_vhangup (__NR_SYSCALL_BASE+111) #define __NR_idle (__NR_SYSCALL_BASE+112) #define __NR_syscall (__NR_SYSCALL_BASE+113) /* syscall to call a syscall! */ @@ -152,10 +152,10 @@ #define __NR_adjtimex (__NR_SYSCALL_BASE+124) #define __NR_mprotect (__NR_SYSCALL_BASE+125) #define __NR_sigprocmask (__NR_SYSCALL_BASE+126) -#define __NR_create_module (__NR_SYSCALL_BASE+127) +#define __NR_create_module (__NR_SYSCALL_BASE+127) /* removed */ #define __NR_init_module (__NR_SYSCALL_BASE+128) #define __NR_delete_module (__NR_SYSCALL_BASE+129) -#define __NR_get_kernel_syms (__NR_SYSCALL_BASE+130) +#define __NR_get_kernel_syms (__NR_SYSCALL_BASE+130) /* removed */ #define __NR_quotactl (__NR_SYSCALL_BASE+131) #define __NR_getpgid (__NR_SYSCALL_BASE+132) #define __NR_fchdir (__NR_SYSCALL_BASE+133) @@ -191,8 +191,8 @@ #define __NR_mremap (__NR_SYSCALL_BASE+163) #define __NR_setresuid (__NR_SYSCALL_BASE+164) #define __NR_getresuid (__NR_SYSCALL_BASE+165) -#define __NR_vm86 (__NR_SYSCALL_BASE+166) -#define __NR_query_module (__NR_SYSCALL_BASE+167) +#define __NR_vm86 (__NR_SYSCALL_BASE+166) /* removed */ +#define __NR_query_module (__NR_SYSCALL_BASE+167) /* removed */ #define __NR_poll (__NR_SYSCALL_BASE+168) #define __NR_nfsservctl (__NR_SYSCALL_BASE+169) #define __NR_setresgid (__NR_SYSCALL_BASE+170) @@ -264,6 +264,24 @@ #define __NR_lremovexattr (__NR_SYSCALL_BASE+236) #define __NR_fremovexattr (__NR_SYSCALL_BASE+237) #define __NR_tkill (__NR_SYSCALL_BASE+238) +#define __NR_sendfile64 (__NR_SYSCALL_BASE+239) +#define __NR_futex (__NR_SYSCALL_BASE+240) +#define __NR_sched_setaffinity (__NR_SYSCALL_BASE+241) +#define __NR_sched_getaffinity (__NR_SYSCALL_BASE+242) +#define __NR_io_setup (__NR_SYSCALL_BASE+243) +#define __NR_io_destroy (__NR_SYSCALL_BASE+244) +#define __NR_io_getevents (__NR_SYSCALL_BASE+245) +#define __NR_io_submit (__NR_SYSCALL_BASE+246) +#define __NR_io_cancel (__NR_SYSCALL_BASE+247) +#define __NR_exit_group (__NR_SYSCALL_BASE+248) +#define __NR_lookup_dcookie (__NR_SYSCALL_BASE+249) +#define __NR_epoll_create (__NR_SYSCALL_BASE+250) +#define __NR_epoll_ctl (__NR_SYSCALL_BASE+251) +#define __NR_epoll_wait (__NR_SYSCALL_BASE+252) +#define __NR_remap_file_pages (__NR_SYSCALL_BASE+253) + /* 254 for set_thread_area */ + /* 255 for get_thread_area */ + /* 256 for set_tid_address */ /* * The following SWIs are ARM private. diff --git a/include/asm-sparc64/bug.h b/include/asm-sparc64/bug.h index 7acd49b93509..603ada787ac2 100644 --- a/include/asm-sparc64/bug.h +++ b/include/asm-sparc64/bug.h @@ -13,5 +13,8 @@ extern void do_BUG(const char *file, int line); #define BUG() __builtin_trap() #endif +#define PAGE_BUG(page) do { \ + BUG(); \ +} while (0) #endif diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h index f909a967778e..0612ce8e8274 100644 --- a/include/linux/ext3_fs.h +++ b/include/linux/ext3_fs.h @@ -707,7 +707,7 @@ extern int ext3fs_dirhash(const char *name, int len, struct /* ialloc.c */ extern struct inode * ext3_new_inode (handle_t *, struct inode *, int); extern void ext3_free_inode (handle_t *, struct inode *); -extern struct inode * ext3_orphan_get (struct super_block *, ino_t); +extern struct inode * ext3_orphan_get (struct super_block *, unsigned long); extern unsigned long ext3_count_free_inodes (struct super_block *); extern unsigned long ext3_count_dirs (struct super_block *); extern void ext3_check_inodes_bitmap (struct super_block *); diff --git a/include/linux/ext3_jbd.h b/include/linux/ext3_jbd.h index 1985ecee6a3f..13508f6053b9 100644 --- a/include/linux/ext3_jbd.h +++ b/include/linux/ext3_jbd.h @@ -132,16 +132,6 @@ __ext3_journal_get_write_access(const char *where, return err; } -static inline int -__ext3_journal_dirty_data(const char *where, - handle_t *handle, struct buffer_head *bh, int async) -{ - int err = journal_dirty_data(handle, bh, async); - if (err) - ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err); - return err; -} - static inline void ext3_journal_forget(handle_t *handle, struct buffer_head *bh) { @@ -183,8 +173,6 @@ __ext3_journal_dirty_metadata(const char *where, __ext3_journal_get_undo_access(__FUNCTION__, (handle), (bh)) #define ext3_journal_get_write_access(handle, bh) \ __ext3_journal_get_write_access(__FUNCTION__, (handle), (bh)) -#define ext3_journal_dirty_data(handle, bh, async) \ - __ext3_journal_dirty_data(__FUNCTION__, (handle), (bh), (async)) #define ext3_journal_revoke(handle, blocknr, bh) \ __ext3_journal_revoke(__FUNCTION__, (handle), (blocknr), (bh)) #define ext3_journal_get_create_access(handle, bh) \ diff --git a/include/linux/jbd.h b/include/linux/jbd.h index f3e44482a298..47a20ce63fa8 100644 --- a/include/linux/jbd.h +++ b/include/linux/jbd.h @@ -360,13 +360,6 @@ struct transaction_s */ struct journal_head * t_sync_datalist; - /* - * Doubly-linked circular list of all writepage data buffers - * still to be written before this transaction can be committed. - * Protected by journal_datalist_lock. - */ - struct journal_head * t_async_datalist; - /* Doubly-linked circular list of all forget buffers (superseded buffers which we can un-checkpoint once this transaction commits) */ @@ -654,8 +647,7 @@ extern int journal_extend (handle_t *, int nblocks); extern int journal_get_write_access (handle_t *, struct buffer_head *); extern int journal_get_create_access (handle_t *, struct buffer_head *); extern int journal_get_undo_access (handle_t *, struct buffer_head *); -extern int journal_dirty_data (handle_t *, - struct buffer_head *, int async); +extern int journal_dirty_data (handle_t *, struct buffer_head *); extern int journal_dirty_metadata (handle_t *, struct buffer_head *); extern void journal_release_buffer (handle_t *, struct buffer_head *); extern void journal_forget (handle_t *, struct buffer_head *); @@ -806,14 +798,13 @@ extern int journal_blocks_per_page(struct inode *inode); /* journaling buffer types */ #define BJ_None 0 /* Not journaled */ #define BJ_SyncData 1 /* Normal data: flush before commit */ -#define BJ_AsyncData 2 /* writepage data: wait on it before commit */ -#define BJ_Metadata 3 /* Normal journaled metadata */ -#define BJ_Forget 4 /* Buffer superseded by this transaction */ -#define BJ_IO 5 /* Buffer is for temporary IO use */ -#define BJ_Shadow 6 /* Buffer contents being shadowed to the log */ -#define BJ_LogCtl 7 /* Buffer contains log descriptors */ -#define BJ_Reserved 8 /* Buffer is reserved for access by journal */ -#define BJ_Types 9 +#define BJ_Metadata 2 /* Normal journaled metadata */ +#define BJ_Forget 3 /* Buffer superseded by this transaction */ +#define BJ_IO 4 /* Buffer is for temporary IO use */ +#define BJ_Shadow 5 /* Buffer contents being shadowed to the log */ +#define BJ_LogCtl 6 /* Buffer contains log descriptors */ +#define BJ_Reserved 7 /* Buffer is reserved for access by journal */ +#define BJ_Types 8 extern int jbd_blocks_per_page(struct inode *inode); @@ -860,8 +851,7 @@ static inline int buffer_jdirty(struct buffer_head *bh) static inline int buffer_jbd_data(struct buffer_head *bh) { return SPLICE_LOCK(buffer_jbd(bh), - bh2jh(bh)->b_jlist == BJ_SyncData || - bh2jh(bh)->b_jlist == BJ_AsyncData); + bh2jh(bh)->b_jlist == BJ_SyncData); } #ifdef CONFIG_SMP diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h index 396d4178b14c..b7b3da409f8a 100644 --- a/include/linux/miscdevice.h +++ b/include/linux/miscdevice.h @@ -18,6 +18,7 @@ #define RTC_MINOR 135 #define EFI_RTC_MINOR 136 /* EFI Time services */ #define SUN_OPENPROM_MINOR 139 +#define DMAPI_MINOR 140 /* DMAPI */ #define NVRAM_MINOR 144 #define I2O_MINOR 166 #define MICROCODE_MINOR 184 diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 14ce2049de71..bcb57ed21a8d 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -193,7 +193,8 @@ typedef struct pglist_data { extern int numnodes; extern struct pglist_data *pgdat_list; -void get_zone_counts(unsigned long *active, unsigned long *inactive); +void get_zone_counts(unsigned long *active, unsigned long *inactive, + unsigned long *free); void build_all_zonelists(void); void wakeup_kswapd(struct zone *zone); diff --git a/include/linux/sched.h b/include/linux/sched.h index 1295d071376a..931cdf559eb2 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -27,6 +27,7 @@ #include <linux/compiler.h> #include <linux/completion.h> #include <linux/pid.h> +#include <linux/percpu.h> struct exec_domain; @@ -87,6 +88,8 @@ extern unsigned long avenrun[]; /* Load averages */ extern int nr_threads; extern int last_pid; +DECLARE_PER_CPU(unsigned long, process_counts); +extern int nr_processes(void); extern unsigned long nr_running(void); extern unsigned long nr_uninterruptible(void); extern unsigned long nr_iowait(void); diff --git a/include/linux/xattr.h b/include/linux/xattr.h index a7eb1b4188bd..9e967b58ee2e 100644 --- a/include/linux/xattr.h +++ b/include/linux/xattr.h @@ -4,7 +4,7 @@ Extended attributes handling. Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org> - Copyright (C) 2001 SGI - Silicon Graphics, Inc <linux-xfs@oss.sgi.com> + Copyright (c) 2001-2002 Silicon Graphics, Inc. All Rights Reserved. */ #ifndef _LINUX_XATTR_H #define _LINUX_XATTR_H diff --git a/kernel/exit.c b/kernel/exit.c index 1841978bfa4c..743ed76ed243 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -41,6 +41,8 @@ static struct dentry * __unhash_process(struct task_struct *p) if (thread_group_leader(p)) { detach_pid(p, PIDTYPE_PGID); detach_pid(p, PIDTYPE_SID); + if (p->pid) + per_cpu(process_counts, smp_processor_id())--; } REMOVE_LINKS(p); @@ -191,7 +193,7 @@ int is_orphaned_pgrp(int pgrp) return will_become_orphaned_pgrp(pgrp, 0); } -static inline int __has_stopped_jobs(int pgrp) +static inline int has_stopped_jobs(int pgrp) { int retval = 0; struct task_struct *p; @@ -207,17 +209,6 @@ static inline int __has_stopped_jobs(int pgrp) return retval; } -static inline int has_stopped_jobs(int pgrp) -{ - int retval; - - read_lock(&tasklist_lock); - retval = __has_stopped_jobs(pgrp); - read_unlock(&tasklist_lock); - - return retval; -} - /** * reparent_to_init() - Reparent the calling kernel thread to the init task. * @@ -504,7 +495,7 @@ static inline void reparent_thread(task_t *p, task_t *father, int traced) (p->session == father->session)) { int pgrp = p->pgrp; - if (__will_become_orphaned_pgrp(pgrp, 0) && __has_stopped_jobs(pgrp)) { + if (__will_become_orphaned_pgrp(pgrp, 0) && has_stopped_jobs(pgrp)) { __kill_pg_info(SIGHUP, (void *)1, pgrp); __kill_pg_info(SIGCONT, (void *)1, pgrp); } @@ -589,7 +580,7 @@ static void exit_notify(void) if ((t->pgrp != current->pgrp) && (t->session == current->session) && __will_become_orphaned_pgrp(current->pgrp, current) && - __has_stopped_jobs(current->pgrp)) { + has_stopped_jobs(current->pgrp)) { __kill_pg_info(SIGHUP, (void *)1, current->pgrp); __kill_pg_info(SIGCONT, (void *)1, current->pgrp); } diff --git a/kernel/fork.c b/kernel/fork.c index 115a5eae0d6b..0ba9e64b5821 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -48,6 +48,8 @@ int nr_threads; int max_threads; unsigned long total_forks; /* Handle normal Linux uptimes. */ +DEFINE_PER_CPU(unsigned long, process_counts) = 0; + rwlock_t tasklist_lock __cacheline_aligned = RW_LOCK_UNLOCKED; /* outer */ /* @@ -57,6 +59,18 @@ rwlock_t tasklist_lock __cacheline_aligned = RW_LOCK_UNLOCKED; /* outer */ */ static task_t *task_cache[NR_CPUS] __cacheline_aligned; +int nr_processes(void) +{ + int cpu; + int total = 0; + + for (cpu = 0; cpu < NR_CPUS; cpu++) { + if (cpu_online(cpu)) + total += per_cpu(process_counts, cpu); + } + return total; +} + void __put_task_struct(struct task_struct *tsk) { if (tsk != current) { @@ -931,6 +945,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, attach_pid(p, PIDTYPE_TGID, p->tgid); attach_pid(p, PIDTYPE_PGID, p->pgrp); attach_pid(p, PIDTYPE_SID, p->session); + if (p->pid) + per_cpu(process_counts, smp_processor_id())++; } else link_pid(p, p->pids + PIDTYPE_TGID, &p->group_leader->pids[PIDTYPE_TGID].pid); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 1c8015736d61..3969ad493b35 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -776,15 +776,18 @@ void get_full_page_state(struct page_state *ret) __get_page_state(ret, sizeof(*ret) / sizeof(unsigned long)); } -void get_zone_counts(unsigned long *active, unsigned long *inactive) +void get_zone_counts(unsigned long *active, + unsigned long *inactive, unsigned long *free) { struct zone *zone; *active = 0; *inactive = 0; + *free = 0; for_each_zone(zone) { *active += zone->nr_active; *inactive += zone->nr_inactive; + *free += zone->free_pages; } } @@ -838,6 +841,7 @@ void show_free_areas(void) int cpu, temperature; unsigned long active; unsigned long inactive; + unsigned long free; struct zone *zone; for_each_zone(zone) { @@ -863,7 +867,7 @@ void show_free_areas(void) } get_page_state(&ps); - get_zone_counts(&active, &inactive); + get_zone_counts(&active, &inactive, &free); printk("\nFree pages: %11ukB (%ukB HighMem)\n", K(nr_free_pages()), diff --git a/mm/readahead.c b/mm/readahead.c index 00de3dcc2829..bd28c3b4f1ca 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -477,7 +477,8 @@ unsigned long max_sane_readahead(unsigned long nr) { unsigned long active; unsigned long inactive; + unsigned long free; - get_zone_counts(&active, &inactive); - return min(nr, inactive / 2); + get_zone_counts(&active, &inactive, &free); + return min(nr, (inactive + free) / 2); } |
