summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-s3c2410/cpu.h3
-rw-r--r--arch/arm/mach-s3c2410/devs.c19
-rw-r--r--arch/arm/mach-s3c2410/mach-bast.c7
-rw-r--r--arch/arm/mach-s3c2410/mach-h1940.c3
-rw-r--r--arch/arm/mach-s3c2410/mach-n30.c5
-rw-r--r--arch/arm/mach-s3c2410/mach-rx3715.c15
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2410.c5
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2440.c15
-rw-r--r--arch/arm/mach-s3c2410/mach-vr1000.c7
-rw-r--r--arch/arm/mach-s3c2410/pm.c11
-rw-r--r--arch/ia64/mm/extable.c9
-rw-r--r--drivers/char/agp/Kconfig6
-rw-r--r--drivers/char/agp/agp.h2
-rw-r--r--drivers/char/agp/generic.c26
-rw-r--r--drivers/char/agp/uninorth-agp.c273
-rw-r--r--drivers/char/s3c2410-rtc.c5
-rw-r--r--drivers/char/watchdog/s3c2410_wdt.c6
-rw-r--r--drivers/serial/s3c2410.c10
-rw-r--r--fs/lockd/clntproc.c39
-rw-r--r--fs/lockd/host.c4
-rw-r--r--fs/locks.c9
-rw-r--r--fs/namei.c33
-rw-r--r--fs/nfs/dir.c170
-rw-r--r--fs/nfs/file.c61
-rw-r--r--fs/nfs/inode.c48
-rw-r--r--fs/nfs/mount_clnt.c4
-rw-r--r--fs/nfs/nfs3proc.c76
-rw-r--r--fs/nfs/nfs4proc.c419
-rw-r--r--fs/nfs/nfs4state.c76
-rw-r--r--fs/nfs/nfs4xdr.c26
-rw-r--r--fs/nfs/nfsroot.c13
-rw-r--r--fs/nfs/proc.c56
-rw-r--r--fs/nfs/read.c2
-rw-r--r--fs/nfs/unlink.c9
-rw-r--r--fs/nfs/write.c29
-rw-r--r--fs/nfsd/nfs4callback.c4
-rw-r--r--include/asm-arm/arch-s3c2410/debug-macro.S8
-rw-r--r--include/asm-arm/arch-s3c2410/entry-macro.S9
-rw-r--r--include/asm-arm/arch-s3c2410/io.h9
-rw-r--r--include/asm-arm/arch-s3c2410/map.h118
-rw-r--r--include/asm-arm/arch-s3c2410/regs-clock.h15
-rw-r--r--include/asm-arm/arch-s3c2410/regs-gpio.h5
-rw-r--r--include/asm-arm/arch-s3c2410/regs-iis.h11
-rw-r--r--include/asm-arm/arch-s3c2410/regs-irq.h5
-rw-r--r--include/asm-arm/arch-s3c2410/regs-lcd.h3
-rw-r--r--include/asm-arm/arch-s3c2410/regs-mem.h3
-rw-r--r--include/asm-arm/arch-s3c2410/regs-rtc.h3
-rw-r--r--include/asm-arm/arch-s3c2410/regs-serial.h9
-rw-r--r--include/asm-arm/arch-s3c2410/regs-timer.h3
-rw-r--r--include/asm-arm/arch-s3c2410/regs-udc.h3
-rw-r--r--include/asm-arm/arch-s3c2410/regs-watchdog.h3
-rw-r--r--include/asm-ppc/uninorth.h7
-rw-r--r--include/asm-ppc64/agp.h13
-rw-r--r--include/linux/lockd/lockd.h3
-rw-r--r--include/linux/namei.h2
-rw-r--r--include/linux/nfs_fs.h47
-rw-r--r--include/linux/nfs_fs_sb.h1
-rw-r--r--include/linux/nfs_xdr.h12
-rw-r--r--include/linux/pci_ids.h3
-rw-r--r--include/linux/sunrpc/auth.h19
-rw-r--r--include/linux/sunrpc/auth_gss.h7
-rw-r--r--include/linux/sunrpc/clnt.h2
-rw-r--r--include/linux/sunrpc/gss_api.h14
-rw-r--r--include/linux/sunrpc/sched.h8
-rw-r--r--include/linux/sunrpc/xprt.h3
-rw-r--r--kernel/printk.c9
-rw-r--r--lib/extable.c8
-rw-r--r--net/sunrpc/auth.c185
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c584
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_mech.c105
-rw-r--r--net/sunrpc/auth_gss/gss_mech_switch.c8
-rw-r--r--net/sunrpc/auth_gss/gss_spkm3_mech.c131
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c5
-rw-r--r--net/sunrpc/auth_null.c60
-rw-r--r--net/sunrpc/auth_unix.c74
-rw-r--r--net/sunrpc/clnt.c43
-rw-r--r--net/sunrpc/pmap_clnt.c5
-rw-r--r--net/sunrpc/sched.c7
-rw-r--r--net/sunrpc/xprt.c5
79 files changed, 1918 insertions, 1164 deletions
diff --git a/arch/arm/mach-s3c2410/cpu.h b/arch/arm/mach-s3c2410/cpu.h
index 30594b007a50..39556c4516b5 100644
--- a/arch/arm/mach-s3c2410/cpu.h
+++ b/arch/arm/mach-s3c2410/cpu.h
@@ -15,9 +15,10 @@
* 04-Jan-2005 BJD New uart initialisation
* 10-Jan-2005 BJD Moved generic init here, specific to cpu headers
* 14-Jan-2005 BJD Added s3c24xx_init_clocks() call
+ * 10-Mar-2005 LCVR Changed S3C2410_{VA,SZ} to S3C24XX_{VA,SZ} on IODESC_ENT
*/
-#define IODESC_ENT(x) { S3C2410_VA_##x, S3C2410_PA_##x, S3C2410_SZ_##x, MT_DEVICE }
+#define IODESC_ENT(x) { S3C24XX_VA_##x, S3C2410_PA_##x, S3C24XX_SZ_##x, MT_DEVICE }
#ifndef MHZ
#define MHZ (1000*1000)
diff --git a/arch/arm/mach-s3c2410/devs.c b/arch/arm/mach-s3c2410/devs.c
index d6f1fd8f9977..64792f678668 100644
--- a/arch/arm/mach-s3c2410/devs.c
+++ b/arch/arm/mach-s3c2410/devs.c
@@ -10,6 +10,7 @@
* published by the Free Software Foundation.
*
* Modifications:
+ * 10-Mar-2005 LCVR Changed S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
* 10-Feb-2005 BJD Added camera from guillaume.gourat@nexvision.tv
* 29-Aug-2004 BJD Added timers 0 through 3
* 29-Aug-2004 BJD Changed index of devices we only have one of to -1
@@ -46,7 +47,7 @@ struct platform_device *s3c24xx_uart_devs[3];
static struct resource s3c_usb_resource[] = {
[0] = {
.start = S3C2410_PA_USBHOST,
- .end = S3C2410_PA_USBHOST + S3C2410_SZ_USBHOST,
+ .end = S3C2410_PA_USBHOST + S3C24XX_SZ_USBHOST,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -76,7 +77,7 @@ EXPORT_SYMBOL(s3c_device_usb);
static struct resource s3c_lcd_resource[] = {
[0] = {
.start = S3C2410_PA_LCD,
- .end = S3C2410_PA_LCD + S3C2410_SZ_LCD,
+ .end = S3C2410_PA_LCD + S3C24XX_SZ_LCD,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -107,7 +108,7 @@ EXPORT_SYMBOL(s3c_device_lcd);
static struct resource s3c_nand_resource[] = {
[0] = {
.start = S3C2410_PA_NAND,
- .end = S3C2410_PA_NAND + S3C2410_SZ_NAND,
+ .end = S3C2410_PA_NAND + S3C24XX_SZ_NAND,
.flags = IORESOURCE_MEM,
}
};
@@ -126,7 +127,7 @@ EXPORT_SYMBOL(s3c_device_nand);
static struct resource s3c_usbgadget_resource[] = {
[0] = {
.start = S3C2410_PA_USBDEV,
- .end = S3C2410_PA_USBDEV + S3C2410_SZ_USBDEV,
+ .end = S3C2410_PA_USBDEV + S3C24XX_SZ_USBDEV,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -151,7 +152,7 @@ EXPORT_SYMBOL(s3c_device_usbgadget);
static struct resource s3c_wdt_resource[] = {
[0] = {
.start = S3C2410_PA_WATCHDOG,
- .end = S3C2410_PA_WATCHDOG + S3C2410_SZ_WATCHDOG,
+ .end = S3C2410_PA_WATCHDOG + S3C24XX_SZ_WATCHDOG,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -176,7 +177,7 @@ EXPORT_SYMBOL(s3c_device_wdt);
static struct resource s3c_i2c_resource[] = {
[0] = {
.start = S3C2410_PA_IIC,
- .end = S3C2410_PA_IIC + S3C2410_SZ_IIC,
+ .end = S3C2410_PA_IIC + S3C24XX_SZ_IIC,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -201,7 +202,7 @@ EXPORT_SYMBOL(s3c_device_i2c);
static struct resource s3c_iis_resource[] = {
[0] = {
.start = S3C2410_PA_IIS,
- .end = S3C2410_PA_IIS + S3C2410_SZ_IIS,
+ .end = S3C2410_PA_IIS + S3C24XX_SZ_IIS,
.flags = IORESOURCE_MEM,
}
};
@@ -255,7 +256,7 @@ EXPORT_SYMBOL(s3c_device_rtc);
static struct resource s3c_adc_resource[] = {
[0] = {
.start = S3C2410_PA_ADC,
- .end = S3C2410_PA_ADC + S3C2410_SZ_ADC,
+ .end = S3C2410_PA_ADC + S3C24XX_SZ_ADC,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -278,7 +279,7 @@ struct platform_device s3c_device_adc = {
static struct resource s3c_sdi_resource[] = {
[0] = {
.start = S3C2410_PA_SDI,
- .end = S3C2410_PA_SDI + S3C2410_SZ_SDI,
+ .end = S3C2410_PA_SDI + S3C24XX_SZ_SDI,
.flags = IORESOURCE_MEM,
},
[1] = {
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index 792481c4dc89..e825cddc0ad6 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -24,6 +24,7 @@
* 10-Jan-2005 BJD Removed include of s3c2410.h
* 14-Jan-2005 BJD Add support for muitlple NAND devices
* 03-Mar-2005 BJD Ensured that bast-cpld.h is included
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*/
#include <linux/kernel.h>
@@ -82,8 +83,8 @@
static struct map_desc bast_iodesc[] __initdata = {
/* ISA IO areas */
- { S3C2410_VA_ISA_BYTE, PA_CS2(BAST_PA_ISAIO), SZ_16M, MT_DEVICE },
- { S3C2410_VA_ISA_WORD, PA_CS3(BAST_PA_ISAIO), SZ_16M, MT_DEVICE },
+ { S3C24XX_VA_ISA_BYTE, PA_CS2(BAST_PA_ISAIO), SZ_16M, MT_DEVICE },
+ { S3C24XX_VA_ISA_WORD, PA_CS3(BAST_PA_ISAIO), SZ_16M, MT_DEVICE },
/* we could possibly compress the next set down into a set of smaller tables
* pagetables, but that would mean using an L2 section, and it still means
@@ -409,7 +410,7 @@ static __init void bast_init_machine(void)
MACHINE_START(BAST, "Simtec-BAST")
MAINTAINER("Ben Dooks <ben@simtec.co.uk>")
- BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART)
+ BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C24XX_VA_UART)
BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
MAPIO(bast_map_io)
INITIRQ(bast_init_irq)
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index e834c00c3019..b2f11209c5b4 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -23,6 +23,7 @@
* 04-Jan-2005 BJD Updated uart init call
* 10-Jan-2005 BJD Removed include of s3c2410.h
* 14-Jan-2005 BJD Added clock init
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*/
#include <linux/kernel.h>
@@ -117,7 +118,7 @@ void __init h1940_init_irq(void)
MACHINE_START(H1940, "IPAQ-H1940")
MAINTAINER("Ben Dooks <ben@fluff.org>")
- BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART)
+ BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C24XX_VA_UART)
BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
MAPIO(h1940_map_io)
INITIRQ(h1940_init_irq)
diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c
index 044c8d9e04a0..a687b7ffb608 100644
--- a/arch/arm/mach-s3c2410/mach-n30.c
+++ b/arch/arm/mach-s3c2410/mach-n30.c
@@ -11,6 +11,9 @@
* 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
* published by the Free Software Foundation.
+ *
+ * Modifications:
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*/
#include <linux/kernel.h>
@@ -138,7 +141,7 @@ void __init n30_init(void)
MACHINE_START(N30, "Acer-N30")
MAINTAINER("Christer Weinigel <christer@weinigel.se>, Ben Dooks <ben-linux@fluff.org>")
- BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART)
+ BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C24XX_VA_UART)
BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
.timer = &s3c24xx_timer,
diff --git a/arch/arm/mach-s3c2410/mach-rx3715.c b/arch/arm/mach-s3c2410/mach-rx3715.c
index cd8d4ff93fbd..2c776fb6956a 100644
--- a/arch/arm/mach-s3c2410/mach-rx3715.c
+++ b/arch/arm/mach-s3c2410/mach-rx3715.c
@@ -10,10 +10,11 @@
* published by the Free Software Foundation.
*
* Modifications:
- * 16-Sep-2004 BJD Copied from mach-h1940.c
- * 25-Oct-2004 BJD Updates for 2.6.10-rc1
- * 10-Jan-2005 BJD Removed include of s3c2410.h s3c2440.h
- * 14-Jan-2005 BJD Added new clock init
+ * 16-Sep-2004 BJD Copied from mach-h1940.c
+ * 25-Oct-2004 BJD Updates for 2.6.10-rc1
+ * 10-Jan-2005 BJD Removed include of s3c2410.h s3c2440.h
+ * 14-Jan-2005 BJD Added new clock init
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*/
#include <linux/kernel.h>
@@ -48,8 +49,8 @@
static struct map_desc rx3715_iodesc[] __initdata = {
/* dump ISA space somewhere unused */
- { S3C2410_VA_ISA_WORD, S3C2410_CS3, SZ_16M, MT_DEVICE },
- { S3C2410_VA_ISA_BYTE, S3C2410_CS3, SZ_16M, MT_DEVICE },
+ { S3C24XX_VA_ISA_WORD, S3C2410_CS3, SZ_16M, MT_DEVICE },
+ { S3C24XX_VA_ISA_BYTE, S3C2410_CS3, SZ_16M, MT_DEVICE },
};
static struct s3c2410_uartcfg rx3715_uartcfgs[] = {
@@ -114,7 +115,7 @@ static void __init rx3715_init_machine(void)
MACHINE_START(RX3715, "IPAQ-RX3715")
MAINTAINER("Ben Dooks <ben@fluff.org>")
- BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART)
+ BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C24XX_VA_UART)
BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
MAPIO(rx3715_map_io)
INITIRQ(rx3715_init_irq)
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
index cd272f79f06e..5d3e915920c5 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c
@@ -26,6 +26,9 @@
* @History:
* derived from linux/arch/arm/mach-s3c2410/mach-bast.c, written by
* Ben Dooks <ben@simtec.co.uk>
+ *
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
+ *
***********************************************************************/
#include <linux/kernel.h>
@@ -110,7 +113,7 @@ void __init smdk2410_init_irq(void)
MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
* to SMDK2410 */
MAINTAINER("Jonas Dietsche")
- BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART)
+ BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C24XX_VA_UART)
BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
MAPIO(smdk2410_map_io)
INITIRQ(smdk2410_init_irq)
diff --git a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2410/mach-smdk2440.c
index 0d1608f0239b..0122f6a9ca43 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2440.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2440.c
@@ -12,10 +12,11 @@
* published by the Free Software Foundation.
*
* Modifications:
- * 01-Nov-2004 BJD Initial version
- * 12-Nov-2004 BJD Updated for release
- * 04-Jan-2005 BJD Fixes for pre-release
- * 22-Feb-2005 BJD Updated for 2.6.11-rc5 relesa
+ * 01-Nov-2004 BJD Initial version
+ * 12-Nov-2004 BJD Updated for release
+ * 04-Jan-2005 BJD Fixes for pre-release
+ * 22-Feb-2005 BJD Updated for 2.6.11-rc5 relesa
+ * 10-Mar-2005 LCVR Replaced S3C2410_VA by S3C24XX_VA
*/
#include <linux/kernel.h>
@@ -50,8 +51,8 @@
static struct map_desc smdk2440_iodesc[] __initdata = {
/* ISA IO Space map (memory space selected by A24) */
- { S3C2410_VA_ISA_WORD, S3C2410_CS2, SZ_16M, MT_DEVICE },
- { S3C2410_VA_ISA_BYTE, S3C2410_CS2, SZ_16M, MT_DEVICE },
+ { S3C24XX_VA_ISA_WORD, S3C2410_CS2, SZ_16M, MT_DEVICE },
+ { S3C24XX_VA_ISA_BYTE, S3C2410_CS2, SZ_16M, MT_DEVICE },
};
#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
@@ -123,7 +124,7 @@ void __init smdk2440_machine_init(void)
MACHINE_START(S3C2440, "SMDK2440")
MAINTAINER("Ben Dooks <ben@fluff.org>")
- BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART)
+ BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C24XX_VA_UART)
BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
.init_irq = s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
index 0949e1910290..8cc7db518ab7 100644
--- a/arch/arm/mach-s3c2410/mach-vr1000.c
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c
@@ -25,6 +25,7 @@
* 15-Jan-2005 BJD Add serial port device definition
* 20-Jan-2005 BJD Use UPF_IOREMAP for ports
* 10-Feb-2005 BJD Added power-off capability
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*/
#include <linux/kernel.h>
@@ -77,8 +78,8 @@
static struct map_desc vr1000_iodesc[] __initdata = {
/* ISA IO areas */
- { S3C2410_VA_ISA_BYTE, PA_CS2(BAST_PA_ISAIO), SZ_16M, MT_DEVICE },
- { S3C2410_VA_ISA_WORD, PA_CS3(BAST_PA_ISAIO), SZ_16M, MT_DEVICE },
+ { S3C24XX_VA_ISA_BYTE, PA_CS2(BAST_PA_ISAIO), SZ_16M, MT_DEVICE },
+ { S3C24XX_VA_ISA_WORD, PA_CS3(BAST_PA_ISAIO), SZ_16M, MT_DEVICE },
/* we could possibly compress the next set down into a set of smaller tables
* pagetables, but that would mean using an L2 section, and it still means
@@ -307,7 +308,7 @@ void __init vr1000_init_irq(void)
MACHINE_START(VR1000, "Thorcom-VR1000")
MAINTAINER("Ben Dooks <ben@simtec.co.uk>")
- BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART)
+ BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C24XX_VA_UART)
BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
MAPIO(vr1000_map_io)
INITIRQ(vr1000_init_irq)
diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c
index ea7c25a50c73..c96fd16afb4e 100644
--- a/arch/arm/mach-s3c2410/pm.c
+++ b/arch/arm/mach-s3c2410/pm.c
@@ -24,6 +24,9 @@
* Parts based on arch/arm/mach-pxa/pm.c
*
* Thanks to Dimitry Andric for debugging
+ *
+ * Modifications:
+ * 10-Mar-2005 LCVR Changed S3C2410_VA_UART to S3C24XX_VA_UART
*/
#include <linux/config.h>
@@ -144,9 +147,11 @@ static struct sleep_save gpio_save[] = {
SAVE_ITEM((va) + S3C2410_UBRDIV)
static struct sleep_save uart_save[] = {
- SAVE_UART(S3C2410_VA_UART0),
- SAVE_UART(S3C2410_VA_UART1),
- SAVE_UART(S3C2410_VA_UART2),
+ SAVE_UART(S3C24XX_VA_UART0),
+ SAVE_UART(S3C24XX_VA_UART1),
+#ifndef CONFIG_CPU_S3C2400
+ SAVE_UART(S3C24XX_VA_UART2),
+#endif
};
/* debug
diff --git a/arch/ia64/mm/extable.c b/arch/ia64/mm/extable.c
index 8e72e01b424d..6d259e34f359 100644
--- a/arch/ia64/mm/extable.c
+++ b/arch/ia64/mm/extable.c
@@ -17,10 +17,15 @@ static int cmp_ex(const void *a, const void *b)
u64 lip = (u64) &l->addr + l->addr;
u64 rip = (u64) &r->addr + r->addr;
- return lip - rip;
+ /* avoid overflow */
+ if (lip > rip)
+ return 1;
+ if (lip < rip)
+ return -1;
+ return 0;
}
-static void swap_ex(void *a, void *b)
+static void swap_ex(void *a, void *b, int size)
{
struct exception_table_entry *l = a, *r = b, tmp;
u64 delta = (u64) r - (u64) l;
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
index 3f7c4bbb3f51..2b15c4ce84f0 100644
--- a/drivers/char/agp/Kconfig
+++ b/drivers/char/agp/Kconfig
@@ -1,6 +1,6 @@
config AGP
tristate "/dev/agpgart (AGP Support)" if !GART_IOMMU
- depends on ALPHA || IA64 || PPC32 || X86
+ depends on ALPHA || IA64 || PPC || X86
default y if GART_IOMMU
---help---
AGP (Accelerated Graphics Port) is a bus system mainly used to
@@ -146,11 +146,11 @@ config AGP_ALPHA_CORE
default AGP
config AGP_UNINORTH
- tristate "Apple UniNorth AGP support"
+ tristate "Apple UniNorth & U3 AGP support"
depends on AGP && PPC_PMAC
help
This option gives you AGP support for Apple machines with a
- UniNorth bridge.
+ UniNorth or U3 (Apple G5) bridge.
config AGP_EFFICEON
tristate "Transmeta Efficeon support"
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index ad08df4ae223..ad9c11391d81 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -322,7 +322,7 @@ extern int agp_try_unsupported_boot;
#define AGPCTRL_GTLBEN (1<<7)
#define AGP2_RESERVED_MASK 0x00fffcc8
-#define AGP3_RESERVED_MASK 0x00ff00cc
+#define AGP3_RESERVED_MASK 0x00ff00c4
#define AGP_ERRATA_FASTWRITES 1<<0
#define AGP_ERRATA_SBA 1<<1
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index 6338ebd5642c..05a248d5a9fb 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -515,13 +515,9 @@ static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_
printk (KERN_INFO PFX "%s tried to set rate=x0. Setting to AGP3 x4 mode.\n", current->comm);
*requested_mode |= AGPSTAT3_4X;
}
- if (tmp == 3) {
- printk (KERN_INFO PFX "%s tried to set rate=x3. Setting to AGP3 x4 mode.\n", current->comm);
- *requested_mode |= AGPSTAT3_4X;
- }
- if (tmp >3) {
- printk (KERN_INFO PFX "%s tried to set rate=x%d. Setting to AGP3 x8 mode.\n", current->comm, tmp);
- *requested_mode |= AGPSTAT3_8X;
+ if (tmp >= 3) {
+ printk (KERN_INFO PFX "%s tried to set rate=x%d. Setting to AGP3 x8 mode.\n", current->comm, tmp * 4);
+ *requested_mode = (*requested_mode & ~7) | AGPSTAT3_8X;
}
/* ARQSZ - Set the value to the maximum one.
@@ -632,26 +628,18 @@ done:
u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 requested_mode, u32 bridge_agpstat)
{
struct pci_dev *device = NULL;
- u8 cap_ptr = 0;
u32 vga_agpstat;
+ u8 cap_ptr;
- while (!cap_ptr) {
+ for (;;) {
device = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, device);
if (!device) {
printk (KERN_INFO PFX "Couldn't find an AGP VGA controller.\n");
return 0;
}
cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP);
- if (!cap_ptr) {
- pci_dev_put(device);
- continue;
- }
- if ((device->bus->self->vendor != bridge->dev->vendor) &&
- (device->bus->self->device != bridge->dev->device)) {
- pci_dev_put(device);
- cap_ptr = 0;
- continue;
- }
+ if (cap_ptr)
+ break;
}
/*
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
index 263e001fa994..0f248239b4ba 100644
--- a/drivers/char/agp/uninorth-agp.c
+++ b/drivers/char/agp/uninorth-agp.c
@@ -9,8 +9,23 @@
#include <linux/delay.h>
#include <asm/uninorth.h>
#include <asm/pci-bridge.h>
+#include <asm/prom.h>
#include "agp.h"
+/*
+ * NOTES for uninorth3 (G5 AGP) supports :
+ *
+ * There maybe also possibility to have bigger cache line size for
+ * agp (see pmac_pci.c and look for cache line). Need to be investigated
+ * by someone.
+ *
+ * PAGE size are hardcoded but this may change, see asm/page.h.
+ *
+ * Jerome Glisse <j.glisse@gmail.com>
+ */
+static int uninorth_rev;
+static int is_u3;
+
static int uninorth_fetch_size(void)
{
int i;
@@ -40,14 +55,20 @@ static int uninorth_fetch_size(void)
static void uninorth_tlbflush(struct agp_memory *mem)
{
+ u32 ctrl = UNI_N_CFG_GART_ENABLE;
+
+ if (is_u3)
+ ctrl |= U3_N_CFG_GART_PERFRD;
pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
- UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_INVAL);
- pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
- UNI_N_CFG_GART_ENABLE);
- pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
- UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_2xRESET);
- pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
- UNI_N_CFG_GART_ENABLE);
+ ctrl | UNI_N_CFG_GART_INVAL);
+ pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, ctrl);
+
+ if (uninorth_rev <= 0x30) {
+ pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
+ ctrl | UNI_N_CFG_GART_2xRESET);
+ pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
+ ctrl);
+ }
}
static void uninorth_cleanup(void)
@@ -57,14 +78,16 @@ static void uninorth_cleanup(void)
pci_read_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, &tmp);
if (!(tmp & UNI_N_CFG_GART_ENABLE))
return;
- pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
- UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_INVAL);
- pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
- 0);
- pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
- UNI_N_CFG_GART_2xRESET);
- pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
- 0);
+ tmp |= UNI_N_CFG_GART_INVAL;
+ pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, tmp);
+ pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, 0);
+
+ if (uninorth_rev <= 0x30) {
+ pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
+ UNI_N_CFG_GART_2xRESET);
+ pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
+ 0);
+ }
}
static int uninorth_configure(void)
@@ -87,8 +110,21 @@ static int uninorth_configure(void)
* the AGP aperture isn't mapped at bus physical address 0
*/
agp_bridge->gart_bus_addr = 0;
+#ifdef CONFIG_PPC64
+ /* Assume U3 or later on PPC64 systems */
+ /* high 4 bits of GART physical address go in UNI_N_CFG_AGP_BASE */
+ pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_AGP_BASE,
+ (agp_bridge->gatt_bus_addr >> 32) & 0xf);
+#else
pci_write_config_dword(agp_bridge->dev,
UNI_N_CFG_AGP_BASE, agp_bridge->gart_bus_addr);
+#endif
+
+ if (is_u3) {
+ pci_write_config_dword(agp_bridge->dev,
+ UNI_N_CFG_GART_DUMMY_PAGE,
+ agp_bridge->scratch_page_real >> 12);
+ }
return 0;
}
@@ -111,13 +147,14 @@ static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start,
j = pg_start;
while (j < (pg_start + mem->page_count)) {
- if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j]))
+ if (agp_bridge->gatt_table[j])
return -EBUSY;
j++;
}
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
- agp_bridge->gatt_table[j] = cpu_to_le32((mem->memory[i] & 0xfffff000) | 0x00000001UL);
+ agp_bridge->gatt_table[j] =
+ cpu_to_le32((mem->memory[i] & 0xFFFFF000UL) | 0x1UL);
flush_dcache_range((unsigned long)__va(mem->memory[i]),
(unsigned long)__va(mem->memory[i])+0x1000);
}
@@ -130,17 +167,90 @@ static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start,
return 0;
}
+static int u3_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
+{
+ int i, num_entries;
+ void *temp;
+ u32 *gp;
+
+ temp = agp_bridge->current_size;
+ num_entries = A_SIZE_32(temp)->num_entries;
+
+ if (type != 0 || mem->type != 0)
+ /* We know nothing of memory types */
+ return -EINVAL;
+ if ((pg_start + mem->page_count) > num_entries)
+ return -EINVAL;
+
+ gp = (u32 *) &agp_bridge->gatt_table[pg_start];
+ for (i = 0; i < mem->page_count; ++i) {
+ if (gp[i]) {
+ printk("u3_insert_memory: entry 0x%x occupied (%x)\n",
+ i, gp[i]);
+ return -EBUSY;
+ }
+ }
+
+ for (i = 0; i < mem->page_count; i++) {
+ gp[i] = (mem->memory[i] >> PAGE_SHIFT) | 0x80000000UL;
+ flush_dcache_range((unsigned long)__va(mem->memory[i]),
+ (unsigned long)__va(mem->memory[i])+0x1000);
+ }
+ mb();
+ flush_dcache_range((unsigned long)gp, (unsigned long) &gp[i]);
+ uninorth_tlbflush(mem);
+
+ return 0;
+}
+
+int u3_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
+{
+ size_t i;
+ u32 *gp;
+
+ if (type != 0 || mem->type != 0)
+ /* We know nothing of memory types */
+ return -EINVAL;
+
+ gp = (u32 *) &agp_bridge->gatt_table[pg_start];
+ for (i = 0; i < mem->page_count; ++i)
+ gp[i] = 0;
+ mb();
+ flush_dcache_range((unsigned long)gp, (unsigned long) &gp[i]);
+ uninorth_tlbflush(mem);
+
+ return 0;
+}
+
static void uninorth_agp_enable(struct agp_bridge_data *bridge, u32 mode)
{
- u32 command, scratch;
+ u32 command, scratch, status;
int timeout;
pci_read_config_dword(bridge->dev,
bridge->capndx + PCI_AGP_STATUS,
- &command);
+ &status);
- command = agp_collect_device_status(bridge, mode, command);
- command |= 0x100;
+ command = agp_collect_device_status(bridge, mode, status);
+ command |= PCI_AGP_COMMAND_AGP;
+
+ if (uninorth_rev == 0x21) {
+ /*
+ * Darwin disable AGP 4x on this revision, thus we
+ * may assume it's broken. This is an AGP2 controller.
+ */
+ command &= ~AGPSTAT2_4X;
+ }
+
+ if ((uninorth_rev >= 0x30) && (uninorth_rev <= 0x33)) {
+ /*
+ * We need to to set REQ_DEPTH to 7 for U3 versions 1.0, 2.1,
+ * 2.2 and 2.3, Darwin do so.
+ */
+ if ((command >> AGPSTAT_RQ_DEPTH_SHIFT) > 7)
+ command = (command & ~AGPSTAT_RQ_DEPTH)
+ | (7 << AGPSTAT_RQ_DEPTH_SHIFT);
+ }
uninorth_tlbflush(NULL);
@@ -152,11 +262,17 @@ static void uninorth_agp_enable(struct agp_bridge_data *bridge, u32 mode)
pci_read_config_dword(bridge->dev,
bridge->capndx + PCI_AGP_COMMAND,
&scratch);
- } while ((scratch & 0x100) == 0 && ++timeout < 1000);
- if ((scratch & 0x100) == 0)
+ } while ((scratch & PCI_AGP_COMMAND_AGP) == 0 && ++timeout < 1000);
+ if ((scratch & PCI_AGP_COMMAND_AGP) == 0)
printk(KERN_ERR PFX "failed to write UniNorth AGP command reg\n");
- agp_device_command(command, 0);
+ if (uninorth_rev >= 0x30) {
+ /* This is an AGP V3 */
+ agp_device_command(command, (status & AGPSTAT_MODE_3_0));
+ } else {
+ /* AGP V2 */
+ agp_device_command(command, 0);
+ }
uninorth_tlbflush(NULL);
}
@@ -229,12 +345,12 @@ static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
struct page *page;
/* We can't handle 2 level gatt's */
- if (agp_bridge->driver->size_type == LVL2_APER_SIZE)
+ if (bridge->driver->size_type == LVL2_APER_SIZE)
return -EINVAL;
table = NULL;
- i = agp_bridge->aperture_size_idx;
- temp = agp_bridge->current_size;
+ i = bridge->aperture_size_idx;
+ temp = bridge->current_size;
size = page_order = num_entries = 0;
do {
@@ -246,11 +362,11 @@ static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
if (table == NULL) {
i++;
- agp_bridge->current_size = A_IDX32(agp_bridge);
+ bridge->current_size = A_IDX32(bridge);
} else {
- agp_bridge->aperture_size_idx = i;
+ bridge->aperture_size_idx = i;
}
- } while (!table && (i < agp_bridge->driver->num_aperture_sizes));
+ } while (!table && (i < bridge->driver->num_aperture_sizes));
if (table == NULL)
return -ENOMEM;
@@ -260,14 +376,12 @@ static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
SetPageReserved(page);
- agp_bridge->gatt_table_real = (u32 *) table;
- agp_bridge->gatt_table = (u32 *)table;
- agp_bridge->gatt_bus_addr = virt_to_phys(table);
+ bridge->gatt_table_real = (u32 *) table;
+ bridge->gatt_table = (u32 *)table;
+ bridge->gatt_bus_addr = virt_to_phys(table);
- for (i = 0; i < num_entries; i++) {
- agp_bridge->gatt_table[i] =
- (unsigned long) agp_bridge->scratch_page;
- }
+ for (i = 0; i < num_entries; i++)
+ bridge->gatt_table[i] = 0;
flush_dcache_range((unsigned long)table, (unsigned long)table_end);
@@ -281,7 +395,7 @@ static int uninorth_free_gatt_table(struct agp_bridge_data *bridge)
void *temp;
struct page *page;
- temp = agp_bridge->current_size;
+ temp = bridge->current_size;
page_order = A_SIZE_32(temp)->page_order;
/* Do not worry about freeing memory, because if this is
@@ -289,13 +403,13 @@ static int uninorth_free_gatt_table(struct agp_bridge_data *bridge)
* from the table.
*/
- table = (char *) agp_bridge->gatt_table_real;
+ table = (char *) bridge->gatt_table_real;
table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
ClearPageReserved(page);
- free_pages((unsigned long) agp_bridge->gatt_table_real, page_order);
+ free_pages((unsigned long) bridge->gatt_table_real, page_order);
return 0;
}
@@ -320,6 +434,22 @@ static struct aper_size_info_32 uninorth_sizes[7] =
{4, 1024, 0, 1}
};
+/*
+ * Not sure that u3 supports that high aperture sizes but it
+ * would strange if it did not :)
+ */
+static struct aper_size_info_32 u3_sizes[8] =
+{
+ {512, 131072, 7, 128},
+ {256, 65536, 6, 64},
+ {128, 32768, 5, 32},
+ {64, 16384, 4, 16},
+ {32, 8192, 3, 8},
+ {16, 4096, 2, 4},
+ {8, 2048, 1, 2},
+ {4, 1024, 0, 1}
+};
+
struct agp_bridge_driver uninorth_agp_driver = {
.owner = THIS_MODULE,
.aperture_sizes = (void *)uninorth_sizes,
@@ -344,6 +474,31 @@ struct agp_bridge_driver uninorth_agp_driver = {
.cant_use_aperture = 1,
};
+struct agp_bridge_driver u3_agp_driver = {
+ .owner = THIS_MODULE,
+ .aperture_sizes = (void *)u3_sizes,
+ .size_type = U32_APER_SIZE,
+ .num_aperture_sizes = 8,
+ .configure = uninorth_configure,
+ .fetch_size = uninorth_fetch_size,
+ .cleanup = uninorth_cleanup,
+ .tlb_flush = uninorth_tlbflush,
+ .mask_memory = agp_generic_mask_memory,
+ .masks = NULL,
+ .cache_flush = null_cache_flush,
+ .agp_enable = uninorth_agp_enable,
+ .create_gatt_table = uninorth_create_gatt_table,
+ .free_gatt_table = uninorth_free_gatt_table,
+ .insert_memory = u3_insert_memory,
+ .remove_memory = u3_remove_memory,
+ .alloc_by_type = agp_generic_alloc_by_type,
+ .free_by_type = agp_generic_free_by_type,
+ .agp_alloc_page = agp_generic_alloc_page,
+ .agp_destroy_page = agp_generic_destroy_page,
+ .cant_use_aperture = 1,
+ .needs_scratch_page = 1,
+};
+
static struct agp_device_ids uninorth_agp_device_ids[] __devinitdata = {
{
.device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP,
@@ -361,6 +516,18 @@ static struct agp_device_ids uninorth_agp_device_ids[] __devinitdata = {
.device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP2,
.chipset_name = "UniNorth 2",
},
+ {
+ .device_id = PCI_DEVICE_ID_APPLE_U3_AGP,
+ .chipset_name = "U3",
+ },
+ {
+ .device_id = PCI_DEVICE_ID_APPLE_U3L_AGP,
+ .chipset_name = "U3L",
+ },
+ {
+ .device_id = PCI_DEVICE_ID_APPLE_U3H_AGP,
+ .chipset_name = "U3H",
+ },
};
static int __devinit agp_uninorth_probe(struct pci_dev *pdev,
@@ -368,6 +535,7 @@ static int __devinit agp_uninorth_probe(struct pci_dev *pdev,
{
struct agp_device_ids *devs = uninorth_agp_device_ids;
struct agp_bridge_data *bridge;
+ struct device_node *uninorth_node;
u8 cap_ptr;
int j;
@@ -389,13 +557,36 @@ static int __devinit agp_uninorth_probe(struct pci_dev *pdev,
return -ENODEV;
found:
+ /* Set revision to 0 if we could not read it. */
+ uninorth_rev = 0;
+ is_u3 = 0;
+ /* Locate core99 Uni-N */
+ uninorth_node = of_find_node_by_name(NULL, "uni-n");
+ /* Locate G5 u3 */
+ if (uninorth_node == NULL) {
+ is_u3 = 1;
+ uninorth_node = of_find_node_by_name(NULL, "u3");
+ }
+ if (uninorth_node) {
+ int *revprop = (int *)
+ get_property(uninorth_node, "device-rev", NULL);
+ if (revprop != NULL)
+ uninorth_rev = *revprop & 0x3f;
+ of_node_put(uninorth_node);
+ }
+
bridge = agp_alloc_bridge();
if (!bridge)
return -ENOMEM;
- bridge->driver = &uninorth_agp_driver;
+ if (is_u3)
+ bridge->driver = &u3_agp_driver;
+ else
+ bridge->driver = &uninorth_agp_driver;
+
bridge->dev = pdev;
bridge->capndx = cap_ptr;
+ bridge->flags = AGP_ERRATA_FASTWRITES;
/* Fill in the mode register */
pci_read_config_dword(pdev, cap_ptr+PCI_AGP_STATUS, &bridge->mode);
diff --git a/drivers/char/s3c2410-rtc.c b/drivers/char/s3c2410-rtc.c
index b953eaa20de0..ec666395a26c 100644
--- a/drivers/char/s3c2410-rtc.c
+++ b/drivers/char/s3c2410-rtc.c
@@ -13,6 +13,7 @@
* 08-Nov-2004 BJD Initial creation
* 12-Nov-2004 BJD Added periodic IRQ and PM code
* 22-Nov-2004 BJD Sign-test on alarm code to check for <0
+ * 10-Mar-2005 LCVR Changed S3C2410_VA_RTC to S3C24XX_VA_RTC
*/
#include <linux/module.h>
@@ -38,8 +39,8 @@
/* need this for the RTC_AF definitions */
#include <linux/mc146818rtc.h>
-#undef S3C2410_VA_RTC
-#define S3C2410_VA_RTC s3c2410_rtc_base
+#undef S3C24XX_VA_RTC
+#define S3C24XX_VA_RTC s3c2410_rtc_base
static struct resource *s3c2410_rtc_mem;
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c
index 47480f8c7b42..1add6e29aa3a 100644
--- a/drivers/char/watchdog/s3c2410_wdt.c
+++ b/drivers/char/watchdog/s3c2410_wdt.c
@@ -26,6 +26,8 @@
* 05-Oct-2004 BJD Added semaphore init to stop crashes on open
* Fixed tmr_count / wdt_count confusion
* Added configurable debug
+ *
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*/
#include <linux/module.h>
@@ -48,8 +50,8 @@
#include <asm/arch/map.h>
#include <asm/hardware/clock.h>
-#undef S3C2410_VA_WATCHDOG
-#define S3C2410_VA_WATCHDOG (0)
+#undef S3C24XX_VA_WATCHDOG
+#define S3C24XX_VA_WATCHDOG (0)
#include <asm/arch/regs-watchdog.h>
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index a012c4cd9b76..6269797bd95b 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -29,6 +29,8 @@
* 06-Mar-2005 BJD Add s3c2440 fclk clock source
*
* 09-Mar-2005 BJD Add s3c2400 support
+ *
+ * 10-Mar-2005 LCVR Changed S3C2410_VA_UART to S3C24XX_VA_UART
*/
/* Note on 2440 fclk clock source handling
@@ -1093,7 +1095,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
port->mapbase = res->start;
port->membase = (void __iomem *)(res->start - S3C2410_PA_UART);
- port->membase += S3C2410_VA_UART;
+ port->membase += S3C24XX_VA_UART;
port->irq = platform_get_irq(platdev, 0);
ourport->clk = clk_get(&platdev->dev, "uart");
@@ -1441,9 +1443,9 @@ static int s3c2440_serial_getsource(struct uart_port *port,
/* the fun of calculating the uart divisors on
* the s3c2440 */
- ucon0 = __raw_readl(S3C2410_VA_UART0 + S3C2410_UCON);
- ucon1 = __raw_readl(S3C2410_VA_UART1 + S3C2410_UCON);
- ucon2 = __raw_readl(S3C2410_VA_UART2 + S3C2410_UCON);
+ ucon0 = __raw_readl(S3C24XX_VA_UART0 + S3C2410_UCON);
+ ucon1 = __raw_readl(S3C24XX_VA_UART1 + S3C2410_UCON);
+ ucon2 = __raw_readl(S3C24XX_VA_UART2 + S3C2410_UCON);
printk("ucons: %08lx, %08lx, %08lx\n", ucon0, ucon1, ucon2);
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 5fc0a3b0f870..8494023e48eb 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -322,14 +322,13 @@ static int nlm_wait_on_grace(wait_queue_head_t *queue)
/*
* Generic NLM call
*/
-int
+static int
nlmclnt_call(struct nlm_rqst *req, u32 proc)
{
struct nlm_host *host = req->a_host;
struct rpc_clnt *clnt;
struct nlm_args *argp = &req->a_args;
struct nlm_res *resp = &req->a_res;
- struct file *filp = argp->lock.fl.fl_file;
struct rpc_message msg = {
.rpc_argp = argp,
.rpc_resp = resp,
@@ -339,9 +338,6 @@ nlmclnt_call(struct nlm_rqst *req, u32 proc)
dprintk("lockd: call procedure %d on %s\n",
(int)proc, host->h_name);
- if (filp)
- msg.rpc_cred = nfs_file_cred(filp);
-
do {
if (host->h_reclaiming && !argp->reclaim)
goto in_grace_period;
@@ -428,14 +424,13 @@ nlmsvc_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback)
return status;
}
-int
+static int
nlmclnt_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback)
{
struct nlm_host *host = req->a_host;
struct rpc_clnt *clnt;
struct nlm_args *argp = &req->a_args;
struct nlm_res *resp = &req->a_res;
- struct file *file = argp->lock.fl.fl_file;
struct rpc_message msg = {
.rpc_argp = argp,
.rpc_resp = resp,
@@ -450,11 +445,9 @@ nlmclnt_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback)
return -ENOLCK;
msg.rpc_proc = &clnt->cl_procinfo[proc];
- /* bootstrap and kick off the async RPC call */
- if (file)
- msg.rpc_cred = nfs_file_cred(file);
/* Increment host refcount */
nlm_get_host(host);
+ /* bootstrap and kick off the async RPC call */
status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, callback, req);
if (status < 0)
nlm_release_host(host);
@@ -516,6 +509,24 @@ static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *ho
fl->fl_ops = &nlmclnt_lock_ops;
}
+static void do_vfs_lock(struct file_lock *fl)
+{
+ int res = 0;
+ switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) {
+ case FL_POSIX:
+ res = posix_lock_file_wait(fl->fl_file, fl);
+ break;
+ case FL_FLOCK:
+ res = flock_lock_file_wait(fl->fl_file, fl);
+ break;
+ default:
+ BUG();
+ }
+ if (res < 0)
+ printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
+ __FUNCTION__);
+}
+
/*
* LOCK: Try to create a lock
*
@@ -564,9 +575,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
fl->fl_u.nfs_fl.state = host->h_state;
fl->fl_u.nfs_fl.flags |= NFS_LCK_GRANTED;
fl->fl_flags |= FL_SLEEP;
- if (posix_lock_file_wait(fl->fl_file, fl) < 0)
- printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
- __FUNCTION__);
+ do_vfs_lock(fl);
}
status = nlm_stat_to_errno(resp->status);
out:
@@ -635,7 +644,7 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
nlmclnt_unlock_callback);
/* Hrmf... Do the unlock early since locks_remove_posix()
* really expects us to free the lock synchronously */
- posix_lock_file(fl->fl_file, fl);
+ do_vfs_lock(fl);
if (status < 0) {
nlmclnt_release_lockargs(req);
kfree(req);
@@ -648,7 +657,7 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
if (status < 0)
return status;
- posix_lock_file(fl->fl_file, fl);
+ do_vfs_lock(fl);
if (resp->status == NLM_LCK_GRANTED)
return 0;
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 54f25ae2ad64..52707c5ad6ea 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -110,7 +110,6 @@ nlm_lookup_host(int server, struct sockaddr_in *sin,
host->h_addr.sin_port = 0; /* ouch! */
host->h_version = version;
host->h_proto = proto;
- host->h_authflavor = RPC_AUTH_UNIX;
host->h_rpcclnt = NULL;
init_MUTEX(&host->h_sema);
host->h_nextrebind = jiffies + NLM_HOST_REBIND;
@@ -191,8 +190,9 @@ nlm_bind_host(struct nlm_host *host)
xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout);
+ /* Existing NLM servers accept AUTH_UNIX only */
clnt = rpc_create_client(xprt, host->h_name, &nlm_program,
- host->h_version, host->h_authflavor);
+ host->h_version, RPC_AUTH_UNIX);
if (IS_ERR(clnt)) {
xprt_destroy(xprt);
goto forgetit;
diff --git a/fs/locks.c b/fs/locks.c
index 80c58d97b84c..1792ce547af7 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1865,8 +1865,13 @@ void locks_remove_flock(struct file *filp)
return;
if (filp->f_op && filp->f_op->flock) {
- struct file_lock fl = { .fl_flags = FL_FLOCK,
- .fl_type = F_UNLCK };
+ struct file_lock fl = {
+ .fl_pid = current->tgid,
+ .fl_file = filp,
+ .fl_flags = FL_FLOCK,
+ .fl_type = F_UNLCK,
+ .fl_end = OFFSET_MAX,
+ };
filp->f_op->flock(filp, F_SETLKW, &fl);
}
diff --git a/fs/namei.c b/fs/namei.c
index 63e3e6494f8d..ed5f58498300 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -681,7 +681,7 @@ fail:
*
* We expect 'base' to be positive and a directory.
*/
-int fastcall link_path_walk(const char * name, struct nameidata *nd)
+static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
{
struct path next;
struct inode *inode;
@@ -881,6 +881,37 @@ return_err:
return err;
}
+/*
+ * Wrapper to retry pathname resolution whenever the underlying
+ * file system returns an ESTALE.
+ *
+ * Retry the whole path once, forcing real lookup requests
+ * instead of relying on the dcache.
+ */
+int fastcall link_path_walk(const char *name, struct nameidata *nd)
+{
+ struct nameidata save = *nd;
+ int result;
+
+ /* make sure the stuff we saved doesn't go away */
+ dget(save.dentry);
+ mntget(save.mnt);
+
+ result = __link_path_walk(name, nd);
+ if (result == -ESTALE) {
+ *nd = save;
+ dget(nd->dentry);
+ mntget(nd->mnt);
+ nd->flags |= LOOKUP_REVAL;
+ result = __link_path_walk(name, nd);
+ }
+
+ dput(save.dentry);
+ mntput(save.mnt);
+
+ return result;
+}
+
int fastcall path_walk(const char * name, struct nameidata *nd)
{
current->total_link_count = 0;
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 1018f1f97c2a..cb094d03287c 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -529,13 +529,24 @@ static inline void nfs_renew_times(struct dentry * dentry)
}
static inline
-int nfs_lookup_verify_inode(struct inode *inode, int isopen)
+int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd)
{
struct nfs_server *server = NFS_SERVER(inode);
- if (isopen && !(server->flags & NFS_MOUNT_NOCTO))
- return __nfs_revalidate_inode(server, inode);
+ if (nd != NULL) {
+ int ndflags = nd->flags;
+ /* VFS wants an on-the-wire revalidation */
+ if (ndflags & LOOKUP_REVAL)
+ goto out_force;
+ /* This is an open(2) */
+ if ((ndflags & LOOKUP_OPEN) &&
+ !(ndflags & LOOKUP_CONTINUE) &&
+ !(server->flags & NFS_MOUNT_NOCTO))
+ goto out_force;
+ }
return nfs_revalidate_inode(server, inode);
+out_force:
+ return __nfs_revalidate_inode(server, inode);
}
/*
@@ -579,16 +590,12 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
struct nfs_fh fhandle;
struct nfs_fattr fattr;
unsigned long verifier;
- int isopen = 0;
parent = dget_parent(dentry);
lock_kernel();
dir = parent->d_inode;
inode = dentry->d_inode;
- if (nd && !(nd->flags & LOOKUP_CONTINUE) && (nd->flags & LOOKUP_OPEN))
- isopen = 1;
-
if (!inode) {
if (nfs_neg_need_reval(dir, dentry, nd))
goto out_bad;
@@ -602,11 +609,12 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
}
/* Revalidate parent directory attribute cache */
- nfs_revalidate_inode(NFS_SERVER(dir), dir);
+ if (nfs_revalidate_inode(NFS_SERVER(dir), dir) < 0)
+ goto out_zap_parent;
/* Force a full look up iff the parent directory has changed */
if (nfs_check_verifier(dir, dentry)) {
- if (nfs_lookup_verify_inode(inode, isopen))
+ if (nfs_lookup_verify_inode(inode, nd))
goto out_zap_parent;
goto out_valid;
}
@@ -722,7 +730,11 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
lock_kernel();
/* Revalidate parent directory attribute cache */
- nfs_revalidate_inode(NFS_SERVER(dir), dir);
+ error = nfs_revalidate_inode(NFS_SERVER(dir), dir);
+ if (error < 0) {
+ res = ERR_PTR(error);
+ goto out_unlock;
+ }
/* If we're doing an exclusive create, optimize away the lookup */
if (nfs_is_exclusive_create(dir, nd))
@@ -780,6 +792,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
{
struct dentry *res = NULL;
struct inode *inode = NULL;
+ int error;
/* Check that we are indeed trying to open this file */
if (!is_atomic_open(dir, nd))
@@ -798,7 +811,11 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
/* Open the file on the server */
lock_kernel();
/* Revalidate parent directory attribute cache */
- nfs_revalidate_inode(NFS_SERVER(dir), dir);
+ error = nfs_revalidate_inode(NFS_SERVER(dir), dir);
+ if (error < 0) {
+ res = ERR_PTR(error);
+ goto out;
+ }
if (nd->intent.open.flags & O_CREAT) {
nfs_begin_data_update(dir);
@@ -808,7 +825,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
inode = nfs4_atomic_open(dir, dentry, nd);
unlock_kernel();
if (IS_ERR(inode)) {
- int error = PTR_ERR(inode);
+ error = PTR_ERR(inode);
switch (error) {
/* Make a negative dentry */
case -ENOENT:
@@ -938,7 +955,7 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc)
/*
* Code common to create, mkdir, and mknod.
*/
-static int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
+int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
struct nfs_fattr *fattr)
{
struct inode *inode;
@@ -959,14 +976,12 @@ static int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
if (error < 0)
goto out_err;
}
- inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
- if (inode) {
- d_instantiate(dentry, inode);
- nfs_renew_times(dentry);
- nfs_set_verifier(dentry, nfs_save_change_attribute(dentry->d_parent->d_inode));
- return 0;
- }
error = -ENOMEM;
+ inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
+ if (inode == NULL)
+ goto out_err;
+ d_instantiate(dentry, inode);
+ return 0;
out_err:
d_drop(dentry);
return error;
@@ -982,7 +997,6 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
struct nameidata *nd)
{
struct iattr attr;
- struct inode *inode;
int error;
int open_flags = 0;
@@ -997,18 +1011,17 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
lock_kernel();
nfs_begin_data_update(dir);
- inode = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags);
+ error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags);
nfs_end_data_update(dir);
- if (!IS_ERR(inode)) {
- d_instantiate(dentry, inode);
- nfs_renew_times(dentry);
- nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
- error = 0;
- } else {
- error = PTR_ERR(inode);
- d_drop(dentry);
- }
+ if (error != 0)
+ goto out_err;
+ nfs_renew_times(dentry);
+ nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+ unlock_kernel();
+ return 0;
+out_err:
unlock_kernel();
+ d_drop(dentry);
return error;
}
@@ -1019,9 +1032,7 @@ static int
nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
{
struct iattr attr;
- struct nfs_fattr fattr;
- struct nfs_fh fhandle;
- int error;
+ int status;
dfprintk(VFS, "NFS: mknod(%s/%ld, %s\n", dir->i_sb->s_id,
dir->i_ino, dentry->d_name.name);
@@ -1034,15 +1045,18 @@ nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
lock_kernel();
nfs_begin_data_update(dir);
- error = NFS_PROTO(dir)->mknod(dir, &dentry->d_name, &attr, rdev,
- &fhandle, &fattr);
+ status = NFS_PROTO(dir)->mknod(dir, dentry, &attr, rdev);
nfs_end_data_update(dir);
- if (!error)
- error = nfs_instantiate(dentry, &fhandle, &fattr);
- else
- d_drop(dentry);
+ if (status != 0)
+ goto out_err;
+ nfs_renew_times(dentry);
+ nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
unlock_kernel();
- return error;
+ return 0;
+out_err:
+ unlock_kernel();
+ d_drop(dentry);
+ return status;
}
/*
@@ -1051,8 +1065,6 @@ nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
struct iattr attr;
- struct nfs_fattr fattr;
- struct nfs_fh fhandle;
int error;
dfprintk(VFS, "NFS: mkdir(%s/%ld, %s\n", dir->i_sb->s_id,
@@ -1062,23 +1074,17 @@ static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
attr.ia_mode = mode | S_IFDIR;
lock_kernel();
-#if 0
- /*
- * Always drop the dentry, we can't always depend on
- * the fattr returned by the server (AIX seems to be
- * broken). We're better off doing another lookup than
- * depending on potentially bogus information.
- */
- d_drop(dentry);
-#endif
nfs_begin_data_update(dir);
- error = NFS_PROTO(dir)->mkdir(dir, &dentry->d_name, &attr, &fhandle,
- &fattr);
+ error = NFS_PROTO(dir)->mkdir(dir, dentry, &attr);
nfs_end_data_update(dir);
- if (!error)
- error = nfs_instantiate(dentry, &fhandle, &fattr);
- else
- d_drop(dentry);
+ if (error != 0)
+ goto out_err;
+ nfs_renew_times(dentry);
+ nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+ unlock_kernel();
+ return 0;
+out_err:
+ d_drop(dentry);
unlock_kernel();
return error;
}
@@ -1107,7 +1113,7 @@ static int nfs_sillyrename(struct inode *dir, struct dentry *dentry)
static unsigned int sillycounter;
const int i_inosize = sizeof(dir->i_ino)*2;
const int countersize = sizeof(sillycounter)*2;
- const int slen = strlen(".nfs") + i_inosize + countersize;
+ const int slen = sizeof(".nfs") + i_inosize + countersize - 1;
char silly[slen+1];
struct qstr qsilly;
struct dentry *sdentry;
@@ -1498,34 +1504,52 @@ out:
int nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
{
struct rpc_cred *cred;
- int res;
+ int res = 0;
if (mask == 0)
- return 0;
+ goto out;
+ /* Is this sys_access() ? */
+ if (nd != NULL && (nd->flags & LOOKUP_ACCESS))
+ goto force_lookup;
- /* Are we checking permissions on anything other than lookup/execute? */
- if ((mask & MAY_EXEC) == 0) {
- /* We only need to check permissions on file open() and access() */
- if (!nd || !(nd->flags & (LOOKUP_OPEN|LOOKUP_ACCESS)))
- return 0;
- /* NFSv4 has atomic_open... */
- if (NFS_PROTO(inode)->version > 3 && (nd->flags & LOOKUP_OPEN))
- return 0;
+ switch (inode->i_mode & S_IFMT) {
+ case S_IFLNK:
+ goto out;
+ case S_IFREG:
+ /* NFSv4 has atomic_open... */
+ if (nfs_server_capable(inode, NFS_CAP_ATOMIC_OPEN)
+ && nd != NULL
+ && (nd->flags & LOOKUP_OPEN))
+ goto out;
+ break;
+ case S_IFDIR:
+ /*
+ * Optimize away all write operations, since the server
+ * will check permissions when we perform the op.
+ */
+ if ((mask & MAY_WRITE) && !(mask & MAY_READ))
+ goto out;
}
+force_lookup:
lock_kernel();
if (!NFS_PROTO(inode)->access)
goto out_notsup;
cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
- res = nfs_do_access(inode, cred, mask);
- put_rpccred(cred);
+ if (!IS_ERR(cred)) {
+ res = nfs_do_access(inode, cred, mask);
+ put_rpccred(cred);
+ } else
+ res = PTR_ERR(cred);
unlock_kernel();
+out:
return res;
out_notsup:
- nfs_revalidate_inode(NFS_SERVER(inode), inode);
- res = generic_permission(inode, mask, NULL);
+ res = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+ if (res == 0)
+ res = generic_permission(inode, mask, NULL);
unlock_kernel();
return res;
}
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 57ccbd277fce..bae0528bad8a 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -44,6 +44,8 @@ static ssize_t nfs_file_write(struct kiocb *, const char __user *, size_t, loff_
static int nfs_file_flush(struct file *);
static int nfs_fsync(struct file *, struct dentry *dentry, int datasync);
static int nfs_check_flags(int flags);
+static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl);
+static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl);
struct file_operations nfs_file_operations = {
.llseek = remote_llseek,
@@ -57,6 +59,7 @@ struct file_operations nfs_file_operations = {
.release = nfs_file_release,
.fsync = nfs_fsync,
.lock = nfs_lock,
+ .flock = nfs_flock,
.sendfile = nfs_file_sendfile,
.check_flags = nfs_check_flags,
};
@@ -312,6 +315,25 @@ static int do_getlk(struct file *filp, int cmd, struct file_lock *fl)
return status;
}
+static int do_vfs_lock(struct file *file, struct file_lock *fl)
+{
+ int res = 0;
+ switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) {
+ case FL_POSIX:
+ res = posix_lock_file_wait(file, fl);
+ break;
+ case FL_FLOCK:
+ res = flock_lock_file_wait(file, fl);
+ break;
+ default:
+ BUG();
+ }
+ if (res < 0)
+ printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
+ __FUNCTION__);
+ return res;
+}
+
static int do_unlk(struct file *filp, int cmd, struct file_lock *fl)
{
struct inode *inode = filp->f_mapping->host;
@@ -338,7 +360,7 @@ static int do_unlk(struct file *filp, int cmd, struct file_lock *fl)
if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM))
status = NFS_PROTO(inode)->lock(filp, cmd, fl);
else
- status = posix_lock_file_wait(filp, fl);
+ status = do_vfs_lock(filp, fl);
unlock_kernel();
rpc_clnt_sigunmask(NFS_CLIENT(inode), &oldset);
return status;
@@ -377,9 +399,9 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl)
* the process exits.
*/
if (status == -EINTR || status == -ERESTARTSYS)
- posix_lock_file_wait(filp, fl);
+ do_vfs_lock(filp, fl);
} else
- status = posix_lock_file_wait(filp, fl);
+ status = do_vfs_lock(filp, fl);
unlock_kernel();
if (status < 0)
goto out;
@@ -401,8 +423,7 @@ out:
/*
* Lock a (portion of) a file
*/
-int
-nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
+static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
{
struct inode * inode = filp->f_mapping->host;
@@ -418,6 +439,27 @@ nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
return -ENOLCK;
+ if (IS_GETLK(cmd))
+ return do_getlk(filp, cmd, fl);
+ if (fl->fl_type == F_UNLCK)
+ return do_unlk(filp, cmd, fl);
+ return do_setlk(filp, cmd, fl);
+}
+
+/*
+ * Lock a (portion of) a file
+ */
+static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
+{
+ struct inode * inode = filp->f_mapping->host;
+
+ dprintk("NFS: nfs_flock(f=%s/%ld, t=%x, fl=%x)\n",
+ inode->i_sb->s_id, inode->i_ino,
+ fl->fl_type, fl->fl_flags);
+
+ if (!inode)
+ return -EINVAL;
+
/*
* No BSD flocks over NFS allowed.
* Note: we could try to fake a POSIX lock request here by
@@ -425,11 +467,14 @@ nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
* Not sure whether that would be unique, though, or whether
* that would break in other places.
*/
- if (!fl->fl_owner || !(fl->fl_flags & FL_POSIX))
+ if (!(fl->fl_flags & FL_FLOCK))
return -ENOLCK;
- if (IS_GETLK(cmd))
- return do_getlk(filp, cmd, fl);
+ /* We're simulating flock() locks using posix locks on the server */
+ fl->fl_owner = (fl_owner_t)filp;
+ fl->fl_start = 0;
+ fl->fl_end = OFFSET_MAX;
+
if (fl->fl_type == F_UNLCK)
return do_unlk(filp, cmd, fl);
return do_setlk(filp, cmd, fl);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 5e732f7cd6b5..6345f26e87ee 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -64,6 +64,8 @@ static void nfs_umount_begin(struct super_block *);
static int nfs_statfs(struct super_block *, struct kstatfs *);
static int nfs_show_options(struct seq_file *, struct vfsmount *);
+static struct rpc_program nfs_program;
+
static struct super_operations nfs_sops = {
.alloc_inode = nfs_alloc_inode,
.destroy_inode = nfs_destroy_inode,
@@ -78,7 +80,7 @@ static struct super_operations nfs_sops = {
/*
* RPC cruft for NFS
*/
-struct rpc_stat nfs_rpcstat = {
+static struct rpc_stat nfs_rpcstat = {
.program = &nfs_program
};
static struct rpc_version * nfs_version[] = {
@@ -95,7 +97,7 @@ static struct rpc_version * nfs_version[] = {
#endif
};
-struct rpc_program nfs_program = {
+static struct rpc_program nfs_program = {
.name = "nfs",
.number = NFS_PROGRAM,
.nrvers = sizeof(nfs_version) / sizeof(nfs_version[0]),
@@ -247,6 +249,7 @@ nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
.fattr = &fattr,
};
int no_root_error = 0;
+ unsigned long max_rpc_payload;
/* We probably want something more informative here */
snprintf(sb->s_id, sizeof(sb->s_id), "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev));
@@ -283,6 +286,12 @@ nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
if (fsinfo.wtmax >= 512 && server->wsize > fsinfo.wtmax)
server->wsize = nfs_block_size(fsinfo.wtmax, NULL);
+ max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL);
+ if (server->rsize > max_rpc_payload)
+ server->rsize = max_rpc_payload;
+ if (server->wsize > max_rpc_payload)
+ server->wsize = max_rpc_payload;
+
server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
if (server->rpages > NFS_READ_MAXIOV) {
server->rpages = NFS_READ_MAXIOV;
@@ -317,6 +326,9 @@ nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
if (sb->s_maxbytes > MAX_LFS_FILESIZE)
sb->s_maxbytes = MAX_LFS_FILESIZE;
+ server->client->cl_intr = (server->flags & NFS_MOUNT_INTR) ? 1 : 0;
+ server->client->cl_softrtry = (server->flags & NFS_MOUNT_SOFT) ? 1 : 0;
+
/* We're airborne Set socket buffersize */
rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);
return 0;
@@ -364,9 +376,8 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data)
goto out_fail;
}
- clnt->cl_intr = (server->flags & NFS_MOUNT_INTR) ? 1 : 0;
- clnt->cl_softrtry = (server->flags & NFS_MOUNT_SOFT) ? 1 : 0;
- clnt->cl_droppriv = (server->flags & NFS_MOUNT_BROKEN_SUID) ? 1 : 0;
+ clnt->cl_intr = 1;
+ clnt->cl_softrtry = 1;
clnt->cl_chatty = 1;
return clnt;
@@ -538,7 +549,6 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
{ NFS_MOUNT_NOCTO, ",nocto", "" },
{ NFS_MOUNT_NOAC, ",noac", "" },
{ NFS_MOUNT_NONLM, ",nolock", ",lock" },
- { NFS_MOUNT_BROKEN_SUID, ",broken_suid", "" },
{ 0, NULL, NULL }
};
struct proc_nfs_info *nfs_infop;
@@ -792,7 +802,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
* Wait for the inode to get unlocked.
* (Used for NFS_INO_LOCKED and NFS_INO_REVALIDATING).
*/
-int
+static int
nfs_wait_on_inode(struct inode *inode, int flag)
{
struct rpc_clnt *clnt = NFS_CLIENT(inode);
@@ -856,6 +866,12 @@ struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
void put_nfs_open_context(struct nfs_open_context *ctx)
{
if (atomic_dec_and_test(&ctx->count)) {
+ if (!list_empty(&ctx->list)) {
+ struct inode *inode = ctx->dentry->d_inode;
+ spin_lock(&inode->i_lock);
+ list_del(&ctx->list);
+ spin_unlock(&inode->i_lock);
+ }
if (ctx->state != NULL)
nfs4_close_state(ctx->state, ctx->mode);
if (ctx->cred != NULL)
@@ -904,7 +920,7 @@ void nfs_file_clear_open_context(struct file *filp)
if (ctx) {
filp->private_data = NULL;
spin_lock(&inode->i_lock);
- list_del(&ctx->list);
+ list_move_tail(&ctx->list, &NFS_I(inode)->open_files);
spin_unlock(&inode->i_lock);
put_nfs_open_context(ctx);
}
@@ -918,8 +934,9 @@ int nfs_open(struct inode *inode, struct file *filp)
struct nfs_open_context *ctx;
struct rpc_cred *cred;
- if ((cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0)) == NULL)
- return -ENOMEM;
+ cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
+ if (IS_ERR(cred))
+ return PTR_ERR(cred);
ctx = alloc_nfs_open_context(filp->f_dentry, cred);
put_rpccred(cred);
if (ctx == NULL)
@@ -1542,6 +1559,7 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
if (data->wsize != 0)
server->wsize = nfs_block_size(data->wsize, NULL);
server->flags = data->flags & NFS_MOUNT_FLAGMASK;
+ server->caps = NFS_CAP_ATOMIC_OPEN;
server->acregmin = data->acregmin*HZ;
server->acregmax = data->acregmax*HZ;
@@ -1609,9 +1627,17 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
err = PTR_ERR(clnt);
goto out_fail;
}
+ clnt->cl_intr = 1;
+ clnt->cl_softrtry = 1;
clnt->cl_chatty = 1;
clp->cl_rpcclient = clnt;
clp->cl_cred = rpcauth_lookupcred(clnt->cl_auth, 0);
+ if (IS_ERR(clp->cl_cred)) {
+ up_write(&clp->cl_sem);
+ err = PTR_ERR(clp->cl_cred);
+ clp->cl_cred = NULL;
+ goto out_fail;
+ }
memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr));
nfs_idmap_new(clp);
}
@@ -1634,8 +1660,6 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
return PTR_ERR(clnt);
}
- clnt->cl_intr = (server->flags & NFS4_MOUNT_INTR) ? 1 : 0;
- clnt->cl_softrtry = (server->flags & NFS4_MOUNT_SOFT) ? 1 : 0;
server->client = clnt;
if (server->nfs4_state->cl_idmap == NULL) {
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index 857e3ea4c40b..9d3ddad96d9e 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -31,7 +31,7 @@
static struct rpc_clnt * mnt_create(char *, struct sockaddr_in *,
int, int);
-struct rpc_program mnt_program;
+static struct rpc_program mnt_program;
struct mnt_fhstatus {
unsigned int status;
@@ -174,7 +174,7 @@ static struct rpc_version * mnt_version[] = {
static struct rpc_stat mnt_stats;
-struct rpc_program mnt_program = {
+static struct rpc_program mnt_program = {
.name = "mount",
.number = NFS_MNT_PROGRAM,
.nrvers = sizeof(mnt_version)/sizeof(mnt_version[0]),
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 828945d68342..3878494dfc2c 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -295,7 +295,7 @@ static int nfs3_proc_commit(struct nfs_write_data *cdata)
* Create a regular file.
* For now, we don't implement O_EXCL.
*/
-static struct inode *
+static int
nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
int flags)
{
@@ -342,29 +342,19 @@ again:
break;
case NFS3_CREATE_UNCHECKED:
- goto exit;
+ goto out;
}
goto again;
}
-exit:
- dprintk("NFS reply create: %d\n", status);
-
+ if (status == 0)
+ status = nfs_instantiate(dentry, &fhandle, &fattr);
if (status != 0)
goto out;
- if (fhandle.size == 0 || !(fattr.valid & NFS_ATTR_FATTR)) {
- status = nfs3_proc_lookup(dir, &dentry->d_name, &fhandle, &fattr);
- if (status != 0)
- goto out;
- }
/* When we created the file with exclusive semantics, make
* sure we set the attributes afterwards. */
if (arg.createmode == NFS3_CREATE_EXCLUSIVE) {
- struct nfs3_sattrargs arg = {
- .fh = &fhandle,
- .sattr = sattr,
- };
dprintk("NFS call setattr (post-create)\n");
if (!(sattr->ia_valid & ATTR_ATIME_SET))
@@ -375,20 +365,13 @@ exit:
/* Note: we could use a guarded setattr here, but I'm
* not sure this buys us anything (and I'd have
* to revamp the NFSv3 XDR code) */
- fattr.valid = 0;
- status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SETATTR,
- &arg, &fattr, 0);
+ status = nfs3_proc_setattr(dentry, &fattr, sattr);
+ nfs_refresh_inode(dentry->d_inode, &fattr);
dprintk("NFS reply setattr (post-create): %d\n", status);
}
- if (status == 0) {
- struct inode *inode;
- inode = nfs_fhget(dir->i_sb, &fhandle, &fattr);
- if (inode)
- return inode;
- status = -ENOMEM;
- }
out:
- return ERR_PTR(status);
+ dprintk("NFS reply create: %d\n", status);
+ return status;
}
static int
@@ -540,28 +523,30 @@ nfs3_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
}
static int
-nfs3_proc_mkdir(struct inode *dir, struct qstr *name, struct iattr *sattr,
- struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
{
- struct nfs_fattr dir_attr;
+ struct nfs_fh fhandle;
+ struct nfs_fattr fattr, dir_attr;
struct nfs3_mkdirargs arg = {
.fh = NFS_FH(dir),
- .name = name->name,
- .len = name->len,
+ .name = dentry->d_name.name,
+ .len = dentry->d_name.len,
.sattr = sattr
};
struct nfs3_diropres res = {
.dir_attr = &dir_attr,
- .fh = fhandle,
- .fattr = fattr
+ .fh = &fhandle,
+ .fattr = &fattr
};
int status;
- dprintk("NFS call mkdir %s\n", name->name);
+ dprintk("NFS call mkdir %s\n", dentry->d_name.name);
dir_attr.valid = 0;
- fattr->valid = 0;
+ fattr.valid = 0;
status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, 0);
nfs_refresh_inode(dir, &dir_attr);
+ if (status == 0)
+ status = nfs_instantiate(dentry, &fhandle, &fattr);
dprintk("NFS reply mkdir: %d\n", status);
return status;
}
@@ -639,23 +624,24 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
}
static int
-nfs3_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr,
- dev_t rdev, struct nfs_fh *fh, struct nfs_fattr *fattr)
+nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
+ dev_t rdev)
{
- struct nfs_fattr dir_attr;
+ struct nfs_fh fh;
+ struct nfs_fattr fattr, dir_attr;
struct nfs3_mknodargs arg = {
.fh = NFS_FH(dir),
- .name = name->name,
- .len = name->len,
+ .name = dentry->d_name.name,
+ .len = dentry->d_name.len,
.sattr = sattr,
.rdev = rdev
};
struct nfs3_diropres res = {
.dir_attr = &dir_attr,
- .fh = fh,
- .fattr = fattr
+ .fh = &fh,
+ .fattr = &fattr
};
- int status;
+ int status;
switch (sattr->ia_mode & S_IFMT) {
case S_IFBLK: arg.type = NF3BLK; break;
@@ -665,12 +651,14 @@ nfs3_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr,
default: return -EINVAL;
}
- dprintk("NFS call mknod %s %u:%u\n", name->name,
+ dprintk("NFS call mknod %s %u:%u\n", dentry->d_name.name,
MAJOR(rdev), MINOR(rdev));
dir_attr.valid = 0;
- fattr->valid = 0;
+ fattr.valid = 0;
status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, 0);
nfs_refresh_inode(dir, &dir_attr);
+ if (status == 0)
+ status = nfs_instantiate(dentry, &fh, &fattr);
dprintk("NFS reply mknod: %d\n", status);
return status;
}
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 7d56ca4d63b7..1d5cb3e80c3e 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -37,6 +37,7 @@
#include <linux/mm.h>
#include <linux/utsname.h>
+#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/sunrpc/clnt.h>
@@ -57,16 +58,17 @@
static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
static int nfs4_async_handle_error(struct rpc_task *, struct nfs_server *);
static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry);
+static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus);
extern struct rpc_procinfo nfs4_procedures[];
extern nfs4_stateid zero_stateid;
/* Prevent leaks of NFSv4 errors into userland */
-static inline int nfs4_map_errors(int err)
+int nfs4_map_errors(int err)
{
if (err < -1000) {
- printk(KERN_WARNING "%s could not handle NFSv4 error %d\n",
+ dprintk("%s could not handle NFSv4 error %d\n",
__FUNCTION__, -err);
return -EIO;
}
@@ -188,6 +190,23 @@ static void update_changeattr(struct inode *inode, struct nfs4_change_info *cinf
nfsi->change_attr = cinfo->after;
}
+static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags)
+{
+ struct inode *inode = state->inode;
+
+ open_flags &= (FMODE_READ|FMODE_WRITE);
+ /* Protect against nfs4_find_state() */
+ spin_lock(&inode->i_lock);
+ state->state |= open_flags;
+ /* NB! List reordering - see the reclaim code for why. */
+ if ((open_flags & FMODE_WRITE) && 0 == state->nwriters++)
+ list_move(&state->open_states, &state->owner->so_states);
+ if (open_flags & FMODE_READ)
+ state->nreaders++;
+ memcpy(&state->stateid, stateid, sizeof(state->stateid));
+ spin_unlock(&inode->i_lock);
+}
+
/*
* OPEN_RECLAIM:
* reclaim state on the server after a reboot.
@@ -244,7 +263,7 @@ static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *st
return status;
}
-int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
+static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
{
struct nfs_server *server = NFS_SERVER(state->inode);
struct nfs4_exception exception = { };
@@ -332,7 +351,7 @@ int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
return err;
}
-static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid)
+static inline int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid)
{
struct nfs_open_confirmargs arg = {
.fh = fh,
@@ -355,11 +374,49 @@ static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *f
return status;
}
-static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
+static int _nfs4_proc_open(struct inode *dir, struct nfs4_state_owner *sp, struct nfs_openargs *o_arg, struct nfs_openres *o_res)
+{
+ struct nfs_server *server = NFS_SERVER(dir);
+ struct rpc_message msg = {
+ .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN],
+ .rpc_argp = o_arg,
+ .rpc_resp = o_res,
+ .rpc_cred = sp->so_cred,
+ };
+ int status;
+
+ /* Update sequence id. The caller must serialize! */
+ o_arg->seqid = sp->so_seqid;
+ o_arg->id = sp->so_id;
+ o_arg->clientid = sp->so_client->cl_clientid;
+
+ status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
+ nfs4_increment_seqid(status, sp);
+ if (status != 0)
+ goto out;
+ update_changeattr(dir, &o_res->cinfo);
+ if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
+ status = _nfs4_proc_open_confirm(server->client, &o_res->fh,
+ sp, &o_res->stateid);
+ if (status != 0)
+ goto out;
+ }
+ if (!(o_res->f_attr->valid & NFS_ATTR_FATTR))
+ status = server->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr);
+out:
+ return status;
+}
+
+static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags)
{
struct nfs_access_entry cache;
+ int mask = 0;
int status;
+ if (openflags & FMODE_READ)
+ mask |= MAY_READ;
+ if (openflags & FMODE_WRITE)
+ mask |= MAY_WRITE;
status = nfs_access_get_cached(inode, cred, &cache);
if (status == 0)
goto out;
@@ -379,9 +436,103 @@ out:
}
/*
+ * OPEN_EXPIRED:
+ * reclaim state on the server after a network partition.
+ * Assumes caller holds the appropriate lock
+ */
+static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
+{
+ struct dentry *parent = dget_parent(dentry);
+ struct inode *dir = parent->d_inode;
+ struct inode *inode = state->inode;
+ struct nfs_server *server = NFS_SERVER(dir);
+ struct nfs_delegation *delegation = NFS_I(inode)->delegation;
+ struct nfs_fattr f_attr = {
+ .valid = 0,
+ };
+ struct nfs_openargs o_arg = {
+ .fh = NFS_FH(dir),
+ .open_flags = state->state,
+ .name = &dentry->d_name,
+ .bitmask = server->attr_bitmask,
+ .claim = NFS4_OPEN_CLAIM_NULL,
+ };
+ struct nfs_openres o_res = {
+ .f_attr = &f_attr,
+ .server = server,
+ };
+ int status = 0;
+
+ if (delegation != NULL && !(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) {
+ status = _nfs4_do_access(inode, sp->so_cred, state->state);
+ if (status < 0)
+ goto out;
+ memcpy(&state->stateid, &delegation->stateid, sizeof(state->stateid));
+ set_bit(NFS_DELEGATED_STATE, &state->flags);
+ goto out;
+ }
+ status = _nfs4_proc_open(dir, sp, &o_arg, &o_res);
+ if (status != 0)
+ goto out_nodeleg;
+ /* Check if files differ */
+ if ((f_attr.mode & S_IFMT) != (inode->i_mode & S_IFMT))
+ goto out_stale;
+ /* Has the file handle changed? */
+ if (nfs_compare_fh(&o_res.fh, NFS_FH(inode)) != 0) {
+ /* Verify if the change attributes are the same */
+ if (f_attr.change_attr != NFS_I(inode)->change_attr)
+ goto out_stale;
+ if (nfs_size_to_loff_t(f_attr.size) != inode->i_size)
+ goto out_stale;
+ /* Lets just pretend that this is the same file */
+ nfs_copy_fh(NFS_FH(inode), &o_res.fh);
+ NFS_I(inode)->fileid = f_attr.fileid;
+ }
+ memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid));
+ if (o_res.delegation_type != 0) {
+ if (!(delegation->flags & NFS_DELEGATION_NEED_RECLAIM))
+ nfs_inode_set_delegation(inode, sp->so_cred, &o_res);
+ else
+ nfs_inode_reclaim_delegation(inode, sp->so_cred, &o_res);
+ }
+out_nodeleg:
+ clear_bit(NFS_DELEGATED_STATE, &state->flags);
+out:
+ dput(parent);
+ return status;
+out_stale:
+ status = -ESTALE;
+ /* Invalidate the state owner so we don't ever use it again */
+ nfs4_drop_state_owner(sp);
+ d_drop(dentry);
+ /* Should we be trying to close that stateid? */
+ goto out_nodeleg;
+}
+
+static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
+{
+ struct nfs_inode *nfsi = NFS_I(state->inode);
+ struct nfs_open_context *ctx;
+ int status;
+
+ spin_lock(&state->inode->i_lock);
+ list_for_each_entry(ctx, &nfsi->open_files, list) {
+ if (ctx->state != state)
+ continue;
+ get_nfs_open_context(ctx);
+ spin_unlock(&state->inode->i_lock);
+ status = _nfs4_open_expired(sp, state, ctx->dentry);
+ put_nfs_open_context(ctx);
+ return status;
+ }
+ spin_unlock(&state->inode->i_lock);
+ return -ENOENT;
+}
+
+/*
* Returns an nfs4_state + an extra reference to the inode
*/
-int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred, struct nfs4_state **res)
+static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred, struct nfs4_state **res)
{
struct nfs_delegation *delegation;
struct nfs_server *server = NFS_SERVER(inode);
@@ -390,7 +541,6 @@ int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred,
struct nfs4_state_owner *sp = NULL;
struct nfs4_state *state = NULL;
int open_flags = flags & (FMODE_READ|FMODE_WRITE);
- int mask = 0;
int err;
/* Protect against reboot recovery - NOTE ORDER! */
@@ -424,20 +574,12 @@ int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred,
goto out_err;
lock_kernel();
- err = _nfs4_do_access(inode, cred, mask);
+ err = _nfs4_do_access(inode, cred, open_flags);
unlock_kernel();
if (err != 0)
goto out_err;
- spin_lock(&inode->i_lock);
- memcpy(state->stateid.data, delegation->stateid.data,
- sizeof(state->stateid.data));
- state->state |= open_flags;
- if (open_flags & FMODE_READ)
- state->nreaders++;
- if (open_flags & FMODE_WRITE)
- state->nwriters++;
set_bit(NFS_DELEGATED_STATE, &state->flags);
- spin_unlock(&inode->i_lock);
+ update_open_stateid(state, &delegation->stateid, open_flags);
out_ok:
up(&sp->so_sema);
nfs4_put_state_owner(sp);
@@ -500,12 +642,6 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st
.f_attr = &f_attr,
.server = server,
};
- struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN],
- .rpc_argp = &o_arg,
- .rpc_resp = &o_res,
- .rpc_cred = cred,
- };
/* Protect against reboot recovery conflicts */
down_read(&clp->cl_sem);
@@ -522,26 +658,10 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st
o_arg.u.attrs = sattr;
/* Serialization for the sequence id */
down(&sp->so_sema);
- o_arg.seqid = sp->so_seqid;
- o_arg.id = sp->so_id;
- o_arg.clientid = clp->cl_clientid,
- status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
- nfs4_increment_seqid(status, sp);
- if (status)
+ status = _nfs4_proc_open(dir, sp, &o_arg, &o_res);
+ if (status != 0)
goto out_err;
- update_changeattr(dir, &o_res.cinfo);
- if(o_res.rflags & NFS4_OPEN_RESULT_CONFIRM) {
- status = _nfs4_proc_open_confirm(server->client, &o_res.fh,
- sp, &o_res.stateid);
- if (status != 0)
- goto out_err;
- }
- if (!(f_attr.valid & NFS_ATTR_FATTR)) {
- status = server->rpc_ops->getattr(server, &o_res.fh, &f_attr);
- if (status < 0)
- goto out_err;
- }
status = -ENOMEM;
inode = nfs_fhget(dir->i_sb, &o_res.fh, &f_attr);
@@ -550,14 +670,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st
state = nfs4_get_open_state(inode, sp);
if (!state)
goto out_err;
- memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid));
- spin_lock(&inode->i_lock);
- if (flags & FMODE_READ)
- state->nreaders++;
- if (flags & FMODE_WRITE)
- state->nwriters++;
- state->state |= flags & (FMODE_READ|FMODE_WRITE);
- spin_unlock(&inode->i_lock);
+ update_open_stateid(state, &o_res.stateid, flags);
if (o_res.delegation_type != 0)
nfs_inode_set_delegation(inode, cred, &o_res);
up(&sp->so_sema);
@@ -581,7 +694,7 @@ out_err:
}
-struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, struct iattr *sattr, struct rpc_cred *cred)
+static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, struct iattr *sattr, struct rpc_cred *cred)
{
struct nfs4_exception exception = { };
struct nfs4_state *res;
@@ -645,7 +758,7 @@ static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
return rpc_call_sync(server->client, &msg, 0);
}
-int nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
+static int nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
struct nfs_fh *fhandle, struct iattr *sattr,
struct nfs4_state *state)
{
@@ -680,7 +793,6 @@ static void nfs4_close_done(struct rpc_task *task)
nfs4_increment_seqid(task->tk_status, sp);
switch (task->tk_status) {
case 0:
- state->state = calldata->arg.open_flags;
memcpy(&state->stateid, &calldata->res.stateid,
sizeof(state->stateid));
break;
@@ -695,6 +807,7 @@ static void nfs4_close_done(struct rpc_task *task)
return;
}
}
+ state->state = calldata->arg.open_flags;
nfs4_put_open_state(state);
up(&sp->so_sema);
nfs4_put_state_owner(sp);
@@ -774,6 +887,8 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
}
cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
+ if (IS_ERR(cred))
+ return (struct inode *)cred;
state = nfs4_do_open(dir, dentry, nd->intent.open.flags, &attr, cred);
put_rpccred(cred);
if (IS_ERR(state))
@@ -789,6 +904,8 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags)
struct inode *inode;
cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
+ if (IS_ERR(cred))
+ return PTR_ERR(cred);
state = nfs4_open_delegated(dentry->d_inode, openflags, cred);
if (IS_ERR(state))
state = nfs4_do_open(dir, dentry, openflags, NULL, cred);
@@ -1009,6 +1126,8 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
if (size_change) {
struct rpc_cred *cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
+ if (IS_ERR(cred))
+ return PTR_ERR(cred);
state = nfs4_find_state(inode, cred, FMODE_WRITE);
if (state == NULL) {
state = nfs4_open_delegated(dentry->d_inode,
@@ -1315,33 +1434,37 @@ static int nfs4_proc_commit(struct nfs_write_data *cdata)
* opens the file O_RDONLY. This will all be resolved with the VFS changes.
*/
-static struct inode *
+static int
nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
int flags)
{
- struct inode *inode;
- struct nfs4_state *state = NULL;
+ struct nfs4_state *state;
struct rpc_cred *cred;
+ int status = 0;
cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
+ if (IS_ERR(cred)) {
+ status = PTR_ERR(cred);
+ goto out;
+ }
state = nfs4_do_open(dir, dentry, flags, sattr, cred);
put_rpccred(cred);
- if (!IS_ERR(state)) {
- inode = state->inode;
- if (flags & O_EXCL) {
- struct nfs_fattr fattr;
- int status;
- status = nfs4_do_setattr(NFS_SERVER(dir), &fattr,
- NFS_FH(inode), sattr, state);
- if (status != 0) {
- nfs4_close_state(state, flags);
- iput(inode);
- inode = ERR_PTR(status);
- }
- }
- } else
- inode = (struct inode *)state;
- return inode;
+ if (IS_ERR(state)) {
+ status = PTR_ERR(state);
+ goto out;
+ }
+ d_instantiate(dentry, state->inode);
+ if (flags & O_EXCL) {
+ struct nfs_fattr fattr;
+ status = nfs4_do_setattr(NFS_SERVER(dir), &fattr,
+ NFS_FH(state->inode), sattr, state);
+ if (status == 0)
+ goto out;
+ } else if (flags != 0)
+ goto out;
+ nfs4_close_state(state, flags);
+out:
+ return status;
}
static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
@@ -1539,23 +1662,24 @@ static int nfs4_proc_symlink(struct inode *dir, struct qstr *name,
return err;
}
-static int _nfs4_proc_mkdir(struct inode *dir, struct qstr *name,
- struct iattr *sattr, struct nfs_fh *fhandle,
- struct nfs_fattr *fattr)
+static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
+ struct iattr *sattr)
{
struct nfs_server *server = NFS_SERVER(dir);
+ struct nfs_fh fhandle;
+ struct nfs_fattr fattr;
struct nfs4_create_arg arg = {
.dir_fh = NFS_FH(dir),
.server = server,
- .name = name,
+ .name = &dentry->d_name,
.attrs = sattr,
.ftype = NF4DIR,
.bitmask = server->attr_bitmask,
};
struct nfs4_create_res res = {
.server = server,
- .fh = fhandle,
- .fattr = fattr,
+ .fh = &fhandle,
+ .fattr = &fattr,
};
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
@@ -1564,24 +1688,24 @@ static int _nfs4_proc_mkdir(struct inode *dir, struct qstr *name,
};
int status;
- fattr->valid = 0;
+ fattr.valid = 0;
status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
- if (!status)
+ if (!status) {
update_changeattr(dir, &res.dir_cinfo);
+ status = nfs_instantiate(dentry, &fhandle, &fattr);
+ }
return status;
}
-static int nfs4_proc_mkdir(struct inode *dir, struct qstr *name,
- struct iattr *sattr, struct nfs_fh *fhandle,
- struct nfs_fattr *fattr)
+static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
+ struct iattr *sattr)
{
struct nfs4_exception exception = { };
int err;
do {
err = nfs4_handle_exception(NFS_SERVER(dir),
- _nfs4_proc_mkdir(dir, name, sattr,
- fhandle, fattr),
+ _nfs4_proc_mkdir(dir, dentry, sattr),
&exception);
} while (exception.retry);
return err;
@@ -1596,6 +1720,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
.pages = &page,
.pgbase = 0,
.count = count,
+ .bitmask = NFS_SERVER(dentry->d_inode)->attr_bitmask,
};
struct nfs4_readdir_res res;
struct rpc_message msg = {
@@ -1630,22 +1755,23 @@ static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
return err;
}
-static int _nfs4_proc_mknod(struct inode *dir, struct qstr *name,
- struct iattr *sattr, dev_t rdev, struct nfs_fh *fh,
- struct nfs_fattr *fattr)
+static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
+ struct iattr *sattr, dev_t rdev)
{
struct nfs_server *server = NFS_SERVER(dir);
+ struct nfs_fh fh;
+ struct nfs_fattr fattr;
struct nfs4_create_arg arg = {
.dir_fh = NFS_FH(dir),
.server = server,
- .name = name,
+ .name = &dentry->d_name,
.attrs = sattr,
.bitmask = server->attr_bitmask,
};
struct nfs4_create_res res = {
.server = server,
- .fh = fh,
- .fattr = fattr,
+ .fh = &fh,
+ .fattr = &fattr,
};
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
@@ -1655,7 +1781,7 @@ static int _nfs4_proc_mknod(struct inode *dir, struct qstr *name,
int status;
int mode = sattr->ia_mode;
- fattr->valid = 0;
+ fattr.valid = 0;
BUG_ON(!(sattr->ia_valid & ATTR_MODE));
BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode));
@@ -1675,21 +1801,21 @@ static int _nfs4_proc_mknod(struct inode *dir, struct qstr *name,
arg.ftype = NF4SOCK;
status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
- if (!status)
+ if (status == 0) {
update_changeattr(dir, &res.dir_cinfo);
+ status = nfs_instantiate(dentry, &fh, &fattr);
+ }
return status;
}
-static int nfs4_proc_mknod(struct inode *dir, struct qstr *name,
- struct iattr *sattr, dev_t rdev, struct nfs_fh *fh,
- struct nfs_fattr *fattr)
+static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
+ struct iattr *sattr, dev_t rdev)
{
struct nfs4_exception exception = { };
int err;
do {
err = nfs4_handle_exception(NFS_SERVER(dir),
- _nfs4_proc_mknod(dir, name, sattr, rdev,
- fh, fattr),
+ _nfs4_proc_mknod(dir, dentry, sattr, rdev),
&exception);
} while (exception.retry);
return err;
@@ -2001,8 +2127,8 @@ nfs4_proc_file_open(struct inode *inode, struct file *filp)
/* Find our open stateid */
cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
- if (unlikely(cred == NULL))
- return -ENOMEM;
+ if (IS_ERR(cred))
+ return PTR_ERR(cred);
ctx = alloc_nfs_open_context(dentry, cred);
put_rpccred(cred);
if (unlikely(ctx == NULL))
@@ -2067,7 +2193,7 @@ nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server)
return 0;
}
-int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp)
+static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp)
{
DEFINE_WAIT(wait);
sigset_t oldset;
@@ -2151,9 +2277,7 @@ int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_
int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short port)
{
- static nfs4_verifier sc_verifier;
- static int initialized;
-
+ nfs4_verifier sc_verifier;
struct nfs4_setclientid setclientid = {
.sc_verifier = &sc_verifier,
.sc_prog = program,
@@ -2164,27 +2288,38 @@ int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short p
.rpc_resp = clp,
.rpc_cred = clp->cl_cred,
};
+ u32 *p;
+ int loop = 0;
+ int status;
- if (!initialized) {
- struct timespec boot_time;
- u32 *p;
-
- initialized = 1;
- boot_time = CURRENT_TIME;
- p = (u32*)sc_verifier.data;
- *p++ = htonl((u32)boot_time.tv_sec);
- *p = htonl((u32)boot_time.tv_nsec);
+ p = (u32*)sc_verifier.data;
+ *p++ = htonl((u32)clp->cl_boot_time.tv_sec);
+ *p = htonl((u32)clp->cl_boot_time.tv_nsec);
+
+ for(;;) {
+ setclientid.sc_name_len = scnprintf(setclientid.sc_name,
+ sizeof(setclientid.sc_name), "%s/%u.%u.%u.%u %s %u",
+ clp->cl_ipaddr, NIPQUAD(clp->cl_addr.s_addr),
+ clp->cl_cred->cr_ops->cr_name,
+ clp->cl_id_uniquifier);
+ setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
+ sizeof(setclientid.sc_netid), "tcp");
+ setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr,
+ sizeof(setclientid.sc_uaddr), "%s.%d.%d",
+ clp->cl_ipaddr, port >> 8, port & 255);
+
+ status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+ if (status != -NFS4ERR_CLID_INUSE)
+ break;
+ if (signalled())
+ break;
+ if (loop++ & 1)
+ ssleep(clp->cl_lease_time + 1);
+ else
+ if (++clp->cl_id_uniquifier == 0)
+ break;
}
- setclientid.sc_name_len = scnprintf(setclientid.sc_name,
- sizeof(setclientid.sc_name), "%s/%u.%u.%u.%u",
- clp->cl_ipaddr, NIPQUAD(clp->cl_addr.s_addr));
- setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
- sizeof(setclientid.sc_netid), "tcp");
- setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr,
- sizeof(setclientid.sc_uaddr), "%s.%d.%d",
- clp->cl_ipaddr, port >> 8, port & 255);
-
- return rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+ return status;
}
int
@@ -2361,6 +2496,25 @@ static int nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *
return err;
}
+static int do_vfs_lock(struct file *file, struct file_lock *fl)
+{
+ int res = 0;
+ switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) {
+ case FL_POSIX:
+ res = posix_lock_file_wait(file, fl);
+ break;
+ case FL_FLOCK:
+ res = flock_lock_file_wait(file, fl);
+ break;
+ default:
+ BUG();
+ }
+ if (res < 0)
+ printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
+ __FUNCTION__);
+ return res;
+}
+
static int _nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
{
struct inode *inode = state->inode;
@@ -2408,7 +2562,7 @@ static int _nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock
out:
up(&state->lock_sema);
if (status == 0)
- posix_lock_file(request->fl_file, request);
+ do_vfs_lock(request->fl_file, request);
up_read(&clp->cl_sem);
return status;
}
@@ -2500,11 +2654,16 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *r
return status;
}
-int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
+static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
{
return _nfs4_do_setlk(state, F_SETLK, request, 1);
}
+static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request)
+{
+ return _nfs4_do_setlk(state, F_SETLK, request, 0);
+}
+
static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
{
struct nfs4_client *clp = state->owner->so_client;
@@ -2517,7 +2676,7 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock
if (status == 0) {
/* Note: we always want to sleep here! */
request->fl_flags |= FL_SLEEP;
- if (posix_lock_file_wait(request->fl_file, request) < 0)
+ if (do_vfs_lock(request->fl_file, request) < 0)
printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__);
}
up_read(&clp->cl_sem);
@@ -2574,6 +2733,16 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
return status;
}
+struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = {
+ .recover_open = nfs4_open_reclaim,
+ .recover_lock = nfs4_lock_reclaim,
+};
+
+struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops = {
+ .recover_open = nfs4_open_expired,
+ .recover_lock = nfs4_lock_expired,
+};
+
struct nfs_rpc_ops nfs_v4_clientops = {
.version = 4, /* protocol version */
.dentry_ops = &nfs4_dentry_operations,
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 67b0f4898490..231cebce3c87 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -116,6 +116,7 @@ nfs4_alloc_client(struct in_addr *addr)
INIT_LIST_HEAD(&clp->cl_superblocks);
init_waitqueue_head(&clp->cl_waitq);
rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client");
+ clp->cl_boot_time = CURRENT_TIME;
clp->cl_state = 1 << NFS4CLNT_OK;
return clp;
}
@@ -205,7 +206,7 @@ nfs4_put_client(struct nfs4_client *clp)
nfs4_free_client(clp);
}
-int nfs4_init_client(struct nfs4_client *clp)
+static int __nfs4_init_client(struct nfs4_client *clp)
{
int status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, nfs_callback_tcpport);
if (status == 0)
@@ -215,6 +216,11 @@ int nfs4_init_client(struct nfs4_client *clp)
return status;
}
+int nfs4_init_client(struct nfs4_client *clp)
+{
+ return nfs4_map_errors(__nfs4_init_client(clp));
+}
+
u32
nfs4_alloc_lockowner_id(struct nfs4_client *clp)
{
@@ -274,8 +280,8 @@ nfs4_alloc_state_owner(void)
return sp;
}
-static void
-nfs4_unhash_state_owner(struct nfs4_state_owner *sp)
+void
+nfs4_drop_state_owner(struct nfs4_state_owner *sp)
{
struct nfs4_client *clp = sp->so_client;
spin_lock(&clp->cl_lock);
@@ -441,7 +447,9 @@ nfs4_get_open_state(struct inode *inode, struct nfs4_state_owner *owner)
if (state == NULL && new != NULL) {
state = new;
/* Caller *must* be holding owner->so_sem */
- list_add(&state->open_states, &owner->so_states);
+ /* Note: The reclaim code dictates that we add stateless
+ * and read-only stateids to the end of the list */
+ list_add_tail(&state->open_states, &owner->so_states);
state->owner = owner;
atomic_inc(&owner->so_count);
list_add(&state->inode_states, &nfsi->open_states);
@@ -497,8 +505,12 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode)
state->nreaders--;
if (mode & FMODE_WRITE)
state->nwriters--;
- if (state->nwriters == 0 && state->nreaders == 0)
- list_del_init(&state->inode_states);
+ if (state->nwriters == 0) {
+ if (state->nreaders == 0)
+ list_del_init(&state->inode_states);
+ /* See reclaim code */
+ list_move_tail(&state->open_states, &owner->so_states);
+ }
spin_unlock(&inode->i_lock);
newstate = 0;
if (state->state != 0) {
@@ -708,7 +720,7 @@ void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp)
sp->so_seqid++;
/* If the server returns BAD_SEQID, unhash state_owner here */
if (status == -NFS4ERR_BAD_SEQID)
- nfs4_unhash_state_owner(sp);
+ nfs4_drop_state_owner(sp);
}
static int reclaimer(void *);
@@ -753,7 +765,7 @@ nfs4_schedule_state_recovery(struct nfs4_client *clp)
schedule_work(&clp->cl_recoverd);
}
-static int nfs4_reclaim_locks(struct nfs4_state *state)
+static int nfs4_reclaim_locks(struct nfs4_state_recovery_ops *ops, struct nfs4_state *state)
{
struct inode *inode = state->inode;
struct file_lock *fl;
@@ -764,7 +776,7 @@ static int nfs4_reclaim_locks(struct nfs4_state *state)
continue;
if (((struct nfs_open_context *)fl->fl_file->private_data)->state != state)
continue;
- status = nfs4_lock_reclaim(state, fl);
+ status = ops->recover_lock(state, fl);
if (status >= 0)
continue;
switch (status) {
@@ -786,20 +798,28 @@ out_err:
return status;
}
-static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp)
+static int nfs4_reclaim_open_state(struct nfs4_state_recovery_ops *ops, struct nfs4_state_owner *sp)
{
struct nfs4_state *state;
struct nfs4_lock_state *lock;
int status = 0;
+ /* Note: we rely on the sp->so_states list being ordered
+ * so that we always reclaim open(O_RDWR) and/or open(O_WRITE)
+ * states first.
+ * This is needed to ensure that the server won't give us any
+ * read delegations that we have to return if, say, we are
+ * recovering after a network partition or a reboot from a
+ * server that doesn't support a grace period.
+ */
list_for_each_entry(state, &sp->so_states, open_states) {
if (state->state == 0)
continue;
- status = nfs4_open_reclaim(sp, state);
+ status = ops->recover_open(sp, state);
list_for_each_entry(lock, &state->lock_states, ls_locks)
lock->ls_flags &= ~NFS_LOCK_INITIALIZED;
if (status >= 0) {
- status = nfs4_reclaim_locks(state);
+ status = nfs4_reclaim_locks(ops, state);
if (status < 0)
goto out_err;
list_for_each_entry(lock, &state->lock_states, ls_locks) {
@@ -813,8 +833,7 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp)
default:
printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n",
__FUNCTION__, status);
- case -NFS4ERR_EXPIRED:
- case -NFS4ERR_NO_GRACE:
+ case -ENOENT:
case -NFS4ERR_RECLAIM_BAD:
case -NFS4ERR_RECLAIM_CONFLICT:
/*
@@ -826,6 +845,8 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp)
/* Mark the file as being 'closed' */
state->state = 0;
break;
+ case -NFS4ERR_EXPIRED:
+ case -NFS4ERR_NO_GRACE:
case -NFS4ERR_STALE_CLIENTID:
goto out_err;
}
@@ -840,6 +861,7 @@ static int reclaimer(void *ptr)
struct reclaimer_args *args = (struct reclaimer_args *)ptr;
struct nfs4_client *clp = args->clp;
struct nfs4_state_owner *sp;
+ struct nfs4_state_recovery_ops *ops;
int status = 0;
daemonize("%u.%u.%u.%u-reclaim", NIPQUAD(clp->cl_addr));
@@ -856,20 +878,34 @@ static int reclaimer(void *ptr)
goto out;
restart_loop:
status = nfs4_proc_renew(clp);
- if (status == 0 || status == -NFS4ERR_CB_PATH_DOWN)
- goto out;
- status = nfs4_init_client(clp);
+ switch (status) {
+ case 0:
+ case -NFS4ERR_CB_PATH_DOWN:
+ goto out;
+ case -NFS4ERR_STALE_CLIENTID:
+ case -NFS4ERR_LEASE_MOVED:
+ ops = &nfs4_reboot_recovery_ops;
+ break;
+ default:
+ ops = &nfs4_network_partition_recovery_ops;
+ };
+ status = __nfs4_init_client(clp);
if (status)
goto out_error;
- /* Mark all delagations for reclaim */
+ /* Mark all delegations for reclaim */
nfs_delegation_mark_reclaim(clp);
/* Note: list is protected by exclusive lock on cl->cl_sem */
list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
- status = nfs4_reclaim_open_state(sp);
+ status = nfs4_reclaim_open_state(ops, sp);
if (status < 0) {
+ if (status == -NFS4ERR_NO_GRACE) {
+ ops = &nfs4_network_partition_recovery_ops;
+ status = nfs4_reclaim_open_state(ops, sp);
+ }
if (status == -NFS4ERR_STALE_CLIENTID)
goto restart_loop;
- goto out_error;
+ if (status == -NFS4ERR_EXPIRED)
+ goto restart_loop;
}
}
nfs_delegation_reap_unclaimed(clp);
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 481cb039626f..5f4de05763c9 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -1010,8 +1010,13 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
WRITE32(readdir->count >> 1); /* We're not doing readdirplus */
WRITE32(readdir->count);
WRITE32(2);
- WRITE32(FATTR4_WORD0_FILEID);
- WRITE32(0);
+ if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID) {
+ WRITE32(0);
+ WRITE32(FATTR4_WORD1_MOUNTED_ON_FILEID);
+ } else {
+ WRITE32(FATTR4_WORD0_FILEID);
+ WRITE32(0);
+ }
/* set up reply kvec
* toplevel_status + taglen + rescount + OP_PUTFH + status
@@ -3175,7 +3180,7 @@ static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_client *clp)
READ_BUF(4);
READ32(len);
READ_BUF(len);
- return -EEXIST;
+ return -NFSERR_CLID_INUSE;
} else
return -nfs_stat_to_errno(nfserr);
@@ -3857,7 +3862,7 @@ static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, uint32_t *p, void *d
uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus)
{
- uint32_t bitmap[1] = {0};
+ uint32_t bitmap[2] = {0};
uint32_t len;
if (!*p++) {
@@ -3881,13 +3886,18 @@ uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus)
entry->ino = 1;
len = ntohl(*p++); /* bitmap length */
- if (len > 0) {
- bitmap[0] = ntohl(*p);
- p += len;
+ if (len-- > 0) {
+ bitmap[0] = ntohl(*p++);
+ if (len-- > 0) {
+ bitmap[1] = ntohl(*p++);
+ p += len;
+ }
}
len = XDR_QUADLEN(ntohl(*p++)); /* attribute buffer length */
if (len > 0) {
- if (bitmap[0] == FATTR4_WORD0_FILEID)
+ if (bitmap[0] == 0 && bitmap[1] == FATTR4_WORD1_MOUNTED_ON_FILEID)
+ xdr_decode_hyper(p, &entry->ino);
+ else if (bitmap[0] == FATTR4_WORD0_FILEID)
xdr_decode_hyper(p, &entry->ino);
p += len;
}
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index 864615916862..fd5bc596fe8a 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -124,7 +124,6 @@ enum {
Opt_soft, Opt_hard, Opt_intr,
Opt_nointr, Opt_posix, Opt_noposix, Opt_cto, Opt_nocto, Opt_ac,
Opt_noac, Opt_lock, Opt_nolock, Opt_v2, Opt_v3, Opt_udp, Opt_tcp,
- Opt_broken_suid,
/* Error token */
Opt_err
};
@@ -159,7 +158,6 @@ static match_table_t __initdata tokens = {
{Opt_udp, "udp"},
{Opt_tcp, "proto=tcp"},
{Opt_tcp, "tcp"},
- {Opt_broken_suid, "broken_suid"},
{Opt_err, NULL}
};
@@ -268,9 +266,6 @@ static int __init root_nfs_parse(char *name, char *buf)
case Opt_tcp:
nfs_data.flags |= NFS_MOUNT_TCP;
break;
- case Opt_broken_suid:
- nfs_data.flags |= NFS_MOUNT_BROKEN_SUID;
- break;
default :
return 0;
}
@@ -351,7 +346,7 @@ static void __init root_nfs_print(void)
#endif
-int __init root_nfs_init(void)
+static int __init root_nfs_init(void)
{
#ifdef NFSROOT_DEBUG
nfs_debug |= NFSDBG_ROOT;
@@ -379,15 +374,15 @@ int __init root_nfs_init(void)
* Parse NFS server and directory information passed on the kernel
* command line.
*/
-int __init nfs_root_setup(char *line)
+static int __init nfs_root_setup(char *line)
{
ROOT_DEV = Root_NFS;
if (line[0] == '/' || line[0] == ',' || (line[0] >= '0' && line[0] <= '9')) {
strlcpy(nfs_root_name, line, sizeof(nfs_root_name));
} else {
- int n = strlen(line) + strlen(NFS_ROOT);
+ int n = strlen(line) + sizeof(NFS_ROOT) - 1;
if (n >= sizeof(nfs_root_name))
- line[sizeof(nfs_root_name) - strlen(NFS_ROOT) - 1] = '\0';
+ line[sizeof(nfs_root_name) - sizeof(NFS_ROOT) - 2] = '\0';
sprintf(nfs_root_name, NFS_ROOT, line);
}
root_server_addr = root_nfs_parse_addr(nfs_root_name);
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 3ddaaa1e9374..d31b4d6e5a5e 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -212,7 +212,7 @@ static int nfs_proc_write(struct nfs_write_data *wdata)
return status < 0? status : wdata->res.count;
}
-static struct inode *
+static int
nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
int flags)
{
@@ -233,37 +233,34 @@ nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
fattr.valid = 0;
dprintk("NFS call create %s\n", dentry->d_name.name);
status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0);
+ if (status == 0)
+ status = nfs_instantiate(dentry, &fhandle, &fattr);
dprintk("NFS reply create: %d\n", status);
- if (status == 0) {
- struct inode *inode;
- inode = nfs_fhget(dir->i_sb, &fhandle, &fattr);
- if (inode)
- return inode;
- status = -ENOMEM;
- }
- return ERR_PTR(status);
+ return status;
}
/*
* In NFSv2, mknod is grafted onto the create call.
*/
static int
-nfs_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr,
- dev_t rdev, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
+ dev_t rdev)
{
+ struct nfs_fh fhandle;
+ struct nfs_fattr fattr;
struct nfs_createargs arg = {
.fh = NFS_FH(dir),
- .name = name->name,
- .len = name->len,
+ .name = dentry->d_name.name,
+ .len = dentry->d_name.len,
.sattr = sattr
};
struct nfs_diropok res = {
- .fh = fhandle,
- .fattr = fattr
+ .fh = &fhandle,
+ .fattr = &fattr
};
- int status, mode;
+ int status, mode;
- dprintk("NFS call mknod %s\n", name->name);
+ dprintk("NFS call mknod %s\n", dentry->d_name.name);
mode = sattr->ia_mode;
if (S_ISFIFO(mode)) {
@@ -274,14 +271,16 @@ nfs_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr,
sattr->ia_size = new_encode_dev(rdev);/* get out your barf bag */
}
- fattr->valid = 0;
+ fattr.valid = 0;
status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0);
if (status == -EINVAL && S_ISFIFO(mode)) {
sattr->ia_mode = mode;
- fattr->valid = 0;
+ fattr.valid = 0;
status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0);
}
+ if (status == 0)
+ status = nfs_instantiate(dentry, &fhandle, &fattr);
dprintk("NFS reply mknod: %d\n", status);
return status;
}
@@ -398,24 +397,27 @@ nfs_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
}
static int
-nfs_proc_mkdir(struct inode *dir, struct qstr *name, struct iattr *sattr,
- struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
{
+ struct nfs_fh fhandle;
+ struct nfs_fattr fattr;
struct nfs_createargs arg = {
.fh = NFS_FH(dir),
- .name = name->name,
- .len = name->len,
+ .name = dentry->d_name.name,
+ .len = dentry->d_name.len,
.sattr = sattr
};
struct nfs_diropok res = {
- .fh = fhandle,
- .fattr = fattr
+ .fh = &fhandle,
+ .fattr = &fattr
};
int status;
- dprintk("NFS call mkdir %s\n", name->name);
- fattr->valid = 0;
+ dprintk("NFS call mkdir %s\n", dentry->d_name.name);
+ fattr.valid = 0;
status = rpc_call(NFS_CLIENT(dir), NFSPROC_MKDIR, &arg, &res, 0);
+ if (status == 0)
+ status = nfs_instantiate(dentry, &fhandle, &fattr);
dprintk("NFS reply mkdir: %d\n", status);
return status;
}
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index cb6f7bfe373b..a0042fb58634 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -370,7 +370,7 @@ out_bad:
return -ENOMEM;
}
-int
+static int
nfs_pagein_list(struct list_head *head, int rpages)
{
LIST_HEAD(one_request);
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 2b0a0cc642aa..f732541a3332 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -167,6 +167,11 @@ nfs_async_unlink(struct dentry *dentry)
goto out;
memset(data, 0, sizeof(*data));
+ data->cred = rpcauth_lookupcred(clnt->cl_auth, 0);
+ if (IS_ERR(data->cred)) {
+ status = PTR_ERR(data->cred);
+ goto out_free;
+ }
data->dir = dget(dir);
data->dentry = dentry;
@@ -183,12 +188,14 @@ nfs_async_unlink(struct dentry *dentry)
spin_lock(&dentry->d_lock);
dentry->d_flags |= DCACHE_NFSFS_RENAMED;
spin_unlock(&dentry->d_lock);
- data->cred = rpcauth_lookupcred(clnt->cl_auth, 0);
rpc_sleep_on(&nfs_delete_queue, task, NULL, NULL);
status = 0;
out:
return status;
+out_free:
+ kfree(data);
+ return status;
}
/**
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index ad7eb9bdff46..6f7a4af3bc46 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -80,14 +80,31 @@ static void nfs_writeback_done_partial(struct nfs_write_data *, int);
static void nfs_writeback_done_full(struct nfs_write_data *, int);
static int nfs_wait_on_write_congestion(struct address_space *, int);
static int nfs_wait_on_requests(struct inode *, unsigned long, unsigned int);
+static int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
+ unsigned int npages, int how);
static kmem_cache_t *nfs_wdata_cachep;
mempool_t *nfs_wdata_mempool;
-mempool_t *nfs_commit_mempool;
+static mempool_t *nfs_commit_mempool;
static DECLARE_WAIT_QUEUE_HEAD(nfs_write_congestion);
-void nfs_writedata_release(struct rpc_task *task)
+static inline struct nfs_write_data *nfs_commit_alloc(void)
+{
+ struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, SLAB_NOFS);
+ if (p) {
+ memset(p, 0, sizeof(*p));
+ INIT_LIST_HEAD(&p->pages);
+ }
+ return p;
+}
+
+static inline void nfs_commit_free(struct nfs_write_data *p)
+{
+ mempool_free(p, nfs_commit_mempool);
+}
+
+static void nfs_writedata_release(struct rpc_task *task)
{
struct nfs_write_data *wdata = (struct nfs_write_data *)task->tk_calldata;
nfs_writedata_free(wdata);
@@ -990,7 +1007,7 @@ static int nfs_flush_one(struct list_head *head, struct inode *inode, int how)
return -ENOMEM;
}
-int
+static int
nfs_flush_list(struct list_head *head, int wpages, int how)
{
LIST_HEAD(one_request);
@@ -1240,7 +1257,7 @@ static void nfs_commit_rpcsetup(struct list_head *head,
/*
* Commit dirty pages
*/
-int
+static int
nfs_commit_list(struct list_head *head, int how)
{
struct nfs_write_data *data;
@@ -1314,8 +1331,8 @@ nfs_commit_done(struct rpc_task *task)
}
#endif
-int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
- unsigned int npages, int how)
+static int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
+ unsigned int npages, int how)
{
struct nfs_inode *nfsi = NFS_I(inode);
LIST_HEAD(head);
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 3f5a0df497da..271c231e7ba4 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -446,7 +446,7 @@ nfsd4_probe_callback(struct nfs4_client *clp)
atomic_inc(&clp->cl_count);
msg.rpc_cred = nfsd4_lookupcred(clp,0);
- if (msg.rpc_cred == NULL)
+ if (IS_ERR(msg.rpc_cred))
goto out_rpciod;
status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, nfs4_cb_null, NULL);
put_rpccred(msg.rpc_cred);
@@ -512,7 +512,7 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
return;
msg.rpc_cred = nfsd4_lookupcred(clp, 0);
- if (msg.rpc_cred == NULL)
+ if (IS_ERR(msg.rpc_cred))
goto out;
cbr->cbr_trunc = 0; /* XXX need to implement truncate optimization */
diff --git a/include/asm-arm/arch-s3c2410/debug-macro.S b/include/asm-arm/arch-s3c2410/debug-macro.S
index eab2d12ed4f4..abfbe45cd17c 100644
--- a/include/asm-arm/arch-s3c2410/debug-macro.S
+++ b/include/asm-arm/arch-s3c2410/debug-macro.S
@@ -11,6 +11,8 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
+ * Modifications:
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*/
#include <asm/arch/map.h>
@@ -24,7 +26,7 @@
mrc p15, 0, \rx, c1, c0
tst \rx, #1
ldreq \rx, = S3C2410_PA_UART
- ldrne \rx, = S3C2410_VA_UART
+ ldrne \rx, = S3C24XX_VA_UART
#if CONFIG_DEBUG_S3C2410_UART != 0
add \rx, \rx, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C2410_UART)
#endif
@@ -43,7 +45,7 @@
mrc p15, 0, \rd, c1, c0
tst \rd, #1
addeq \rd, \rx, #(S3C2410_PA_GPIO - S3C2410_PA_UART)
- addne \rd, \rx, #(S3C2410_VA_GPIO - S3C2410_VA_UART)
+ addne \rd, \rx, #(S3C24XX_VA_GPIO - S3C24XX_VA_UART)
bic \rd, \rd, #0xff000
ldr \rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ]
and \rd, \rd, #0x00ff0000
@@ -74,7 +76,7 @@
mrc p15, 0, \rd, c1, c0
tst \rd, #1
addeq \rd, \rx, #(S3C2410_PA_GPIO - S3C2410_PA_UART)
- addne \rd, \rx, #(S3C2410_VA_GPIO - S3C2410_VA_UART)
+ addne \rd, \rx, #(S3C24XX_VA_GPIO - S3C24XX_VA_UART)
bic \rd, \rd, #0xff000
ldr \rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ]
and \rd, \rd, #0x00ff0000
diff --git a/include/asm-arm/arch-s3c2410/entry-macro.S b/include/asm-arm/arch-s3c2410/entry-macro.S
index 4cc886ed1dbb..b7d4d7f4422d 100644
--- a/include/asm-arm/arch-s3c2410/entry-macro.S
+++ b/include/asm-arm/arch-s3c2410/entry-macro.S
@@ -6,12 +6,15 @@
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
+
+ * Modifications:
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*/
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
- mov \tmp, #S3C2410_VA_IRQ
+ mov \tmp, #S3C24XX_VA_IRQ
ldr \irqnr, [ \tmp, #0x14 ] @ get irq no
30000:
teq \irqnr, #4
@@ -45,7 +48,7 @@
.align 4
20004:
mov r1, #1
- mov \tmp, #S3C2410_VA_IRQ
+ mov \tmp, #S3C24XX_VA_IRQ
ldmfd r13!, { r0 - r4 , r8-r12, r14 }
#endif
@@ -83,7 +86,7 @@
@ we get here from no main or external interrupts pending
1002:
- add \tmp, \tmp, #S3C2410_VA_GPIO - S3C2410_VA_IRQ
+ add \tmp, \tmp, #S3C24XX_VA_GPIO - S3C24XX_VA_IRQ
ldr \irqstat, [ \tmp, # 0xa8 ] @ EXTINTPEND
ldr \irqnr, [ \tmp, # 0xa4 ] @ EXTINTMASK
diff --git a/include/asm-arm/arch-s3c2410/io.h b/include/asm-arm/arch-s3c2410/io.h
index 291b862e3f56..4d5c08b6e198 100644
--- a/include/asm-arm/arch-s3c2410/io.h
+++ b/include/asm-arm/arch-s3c2410/io.h
@@ -8,6 +8,7 @@
* Modifications:
* 06-Dec-1997 RMK Created.
* 02-Sep-2003 BJD Modified for S3C2410
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*
*/
@@ -26,10 +27,10 @@
#define __PORT_PCIO(x) ((x) < (1<<28))
-#define PCIO_BASE (S3C2410_VA_ISA_WORD)
-#define PCIO_BASE_b (S3C2410_VA_ISA_BYTE)
-#define PCIO_BASE_w (S3C2410_VA_ISA_WORD)
-#define PCIO_BASE_l (S3C2410_VA_ISA_WORD)
+#define PCIO_BASE (S3C24XX_VA_ISA_WORD)
+#define PCIO_BASE_b (S3C24XX_VA_ISA_BYTE)
+#define PCIO_BASE_w (S3C24XX_VA_ISA_WORD)
+#define PCIO_BASE_l (S3C24XX_VA_ISA_WORD)
/*
* Dynamic IO functions - let the compiler
* optimize the expressions
diff --git a/include/asm-arm/arch-s3c2410/map.h b/include/asm-arm/arch-s3c2410/map.h
index 17ea5fcdc38c..a6d03737603e 100644
--- a/include/asm-arm/arch-s3c2410/map.h
+++ b/include/asm-arm/arch-s3c2410/map.h
@@ -10,9 +10,10 @@
* published by the Free Software Foundation.
*
* Changelog:
- * 12-May-2003 BJD Created file
- * 06-Jan-2003 BJD Linux 2.6.0 version, moved bast specifics out
- * 10-Feb-2005 BJD Added CAMIF definition from guillaume.gourat@nexvision.tv
+ * 12-May-2003 BJD Created file
+ * 06-Jan-2003 BJD Linux 2.6.0 version, moved bast specifics out
+ * 10-Feb-2005 BJD Added CAMIF definition from guillaume.gourat@nexvision.tv
+ * 10-Mar-2005 LCVR Added support to S3C2400, changed {VA,SZ} names
*/
#ifndef __ASM_ARCH_MAP_H
@@ -30,100 +31,122 @@
*/
#define S3C2410_ADDR(x) (0xF0000000 + (x))
+#define S3C2400_ADDR(x) S3C2410_ADDR(x)
/* interrupt controller is the first thing we put in, to make
* the assembly code for the irq detection easier
*/
-#define S3C2410_VA_IRQ S3C2410_ADDR(0x00000000)
+#define S3C24XX_VA_IRQ S3C2410_ADDR(0x00000000)
+#define S3C2400_PA_IRQ (0x14400000)
#define S3C2410_PA_IRQ (0x4A000000)
-#define S3C2410_SZ_IRQ SZ_1M
+#define S3C24XX_SZ_IRQ SZ_1M
/* memory controller registers */
-#define S3C2410_VA_MEMCTRL S3C2410_ADDR(0x00100000)
+#define S3C24XX_VA_MEMCTRL S3C2410_ADDR(0x00100000)
+#define S3C2400_PA_MEMCTRL (0x14000000)
#define S3C2410_PA_MEMCTRL (0x48000000)
-#define S3C2410_SZ_MEMCTRL SZ_1M
+#define S3C24XX_SZ_MEMCTRL SZ_1M
/* USB host controller */
-#define S3C2410_VA_USBHOST S3C2410_ADDR(0x00200000)
+#define S3C24XX_VA_USBHOST S3C2410_ADDR(0x00200000)
+#define S3C2400_PA_USBHOST (0x14200000)
#define S3C2410_PA_USBHOST (0x49000000)
-#define S3C2410_SZ_USBHOST SZ_1M
+#define S3C24XX_SZ_USBHOST SZ_1M
/* DMA controller */
-#define S3C2410_VA_DMA S3C2410_ADDR(0x00300000)
+#define S3C24XX_VA_DMA S3C2410_ADDR(0x00300000)
+#define S3C2400_PA_DMA (0x14600000)
#define S3C2410_PA_DMA (0x4B000000)
-#define S3C2410_SZ_DMA SZ_1M
+#define S3C24XX_SZ_DMA SZ_1M
/* Clock and Power management */
-#define S3C2410_VA_CLKPWR S3C2410_ADDR(0x00400000)
+#define S3C24XX_VA_CLKPWR S3C2410_ADDR(0x00400000)
+#define S3C2400_PA_CLKPWR (0x14800000)
#define S3C2410_PA_CLKPWR (0x4C000000)
-#define S3C2410_SZ_CLKPWR SZ_1M
+#define S3C24XX_SZ_CLKPWR SZ_1M
/* LCD controller */
-#define S3C2410_VA_LCD S3C2410_ADDR(0x00600000)
+#define S3C24XX_VA_LCD S3C2410_ADDR(0x00600000)
+#define S3C2400_PA_LCD (0x14A00000)
#define S3C2410_PA_LCD (0x4D000000)
-#define S3C2410_SZ_LCD SZ_1M
+#define S3C24XX_SZ_LCD SZ_1M
/* NAND flash controller */
-#define S3C2410_VA_NAND S3C2410_ADDR(0x00700000)
+#define S3C24XX_VA_NAND S3C2410_ADDR(0x00700000)
#define S3C2410_PA_NAND (0x4E000000)
-#define S3C2410_SZ_NAND SZ_1M
+#define S3C24XX_SZ_NAND SZ_1M
+
+/* MMC controller - available on the S3C2400 */
+#define S3C2400_VA_MMC S3C2400_ADDR(0x00700000)
+#define S3C2400_PA_MMC (0x15A00000)
+#define S3C2400_SZ_MMC SZ_1M
/* UARTs */
-#define S3C2410_VA_UART S3C2410_ADDR(0x00800000)
+#define S3C24XX_VA_UART S3C2410_ADDR(0x00800000)
+#define S3C2400_PA_UART (0x15000000)
#define S3C2410_PA_UART (0x50000000)
-#define S3C2410_SZ_UART SZ_1M
+#define S3C24XX_SZ_UART SZ_1M
/* Timers */
-#define S3C2410_VA_TIMER S3C2410_ADDR(0x00900000)
+#define S3C24XX_VA_TIMER S3C2410_ADDR(0x00900000)
+#define S3C2400_PA_TIMER (0x15100000)
#define S3C2410_PA_TIMER (0x51000000)
-#define S3C2410_SZ_TIMER SZ_1M
+#define S3C24XX_SZ_TIMER SZ_1M
/* USB Device port */
-#define S3C2410_VA_USBDEV S3C2410_ADDR(0x00A00000)
+#define S3C24XX_VA_USBDEV S3C2410_ADDR(0x00A00000)
+#define S3C2400_PA_USBDEV (0x15200140)
#define S3C2410_PA_USBDEV (0x52000000)
-#define S3C2410_SZ_USBDEV SZ_1M
+#define S3C24XX_SZ_USBDEV SZ_1M
/* Watchdog */
-#define S3C2410_VA_WATCHDOG S3C2410_ADDR(0x00B00000)
+#define S3C24XX_VA_WATCHDOG S3C2410_ADDR(0x00B00000)
+#define S3C2400_PA_WATCHDOG (0x15300000)
#define S3C2410_PA_WATCHDOG (0x53000000)
-#define S3C2410_SZ_WATCHDOG SZ_1M
+#define S3C24XX_SZ_WATCHDOG SZ_1M
/* IIC hardware controller */
-#define S3C2410_VA_IIC S3C2410_ADDR(0x00C00000)
+#define S3C24XX_VA_IIC S3C2410_ADDR(0x00C00000)
+#define S3C2400_PA_IIC (0x15400000)
#define S3C2410_PA_IIC (0x54000000)
-#define S3C2410_SZ_IIC SZ_1M
+#define S3C24XX_SZ_IIC SZ_1M
-#define VA_IIC_BASE (S3C2410_VA_IIC)
+#define VA_IIC_BASE (S3C24XX_VA_IIC)
/* IIS controller */
-#define S3C2410_VA_IIS S3C2410_ADDR(0x00D00000)
+#define S3C24XX_VA_IIS S3C2410_ADDR(0x00D00000)
+#define S3C2400_PA_IIS (0x15508000)
#define S3C2410_PA_IIS (0x55000000)
-#define S3C2410_SZ_IIS SZ_1M
+#define S3C24XX_SZ_IIS SZ_1M
/* GPIO ports */
-#define S3C2410_VA_GPIO S3C2410_ADDR(0x00E00000)
+#define S3C24XX_VA_GPIO S3C2410_ADDR(0x00E00000)
+#define S3C2400_PA_GPIO (0x15600000)
#define S3C2410_PA_GPIO (0x56000000)
-#define S3C2410_SZ_GPIO SZ_1M
+#define S3C24XX_SZ_GPIO SZ_1M
/* RTC */
-#define S3C2410_VA_RTC S3C2410_ADDR(0x00F00000)
+#define S3C24XX_VA_RTC S3C2410_ADDR(0x00F00000)
+#define S3C2400_PA_RTC (0x15700040)
#define S3C2410_PA_RTC (0x57000000)
-#define S3C2410_SZ_RTC SZ_1M
+#define S3C24XX_SZ_RTC SZ_1M
/* ADC */
-#define S3C2410_VA_ADC S3C2410_ADDR(0x01000000)
+#define S3C24XX_VA_ADC S3C2410_ADDR(0x01000000)
+#define S3C2400_PA_ADC (0x15800000)
#define S3C2410_PA_ADC (0x58000000)
-#define S3C2410_SZ_ADC SZ_1M
+#define S3C24XX_SZ_ADC SZ_1M
/* SPI */
-#define S3C2410_VA_SPI S3C2410_ADDR(0x01100000)
+#define S3C24XX_VA_SPI S3C2410_ADDR(0x01100000)
+#define S3C2400_PA_SPI (0x15900000)
#define S3C2410_PA_SPI (0x59000000)
-#define S3C2410_SZ_SPI SZ_1M
+#define S3C24XX_SZ_SPI SZ_1M
/* SDI */
-#define S3C2410_VA_SDI S3C2410_ADDR(0x01200000)
+#define S3C24XX_VA_SDI S3C2410_ADDR(0x01200000)
#define S3C2410_PA_SDI (0x5A000000)
-#define S3C2410_SZ_SDI SZ_1M
+#define S3C24XX_SZ_SDI SZ_1M
/* CAMIF */
#define S3C2440_PA_CAMIF (0x4F000000)
@@ -133,8 +156,8 @@
* implements it. We reserve two 16M regions for ISA.
*/
-#define S3C2410_VA_ISA_WORD S3C2410_ADDR(0x02000000)
-#define S3C2410_VA_ISA_BYTE S3C2410_ADDR(0x03000000)
+#define S3C24XX_VA_ISA_WORD S3C2410_ADDR(0x02000000)
+#define S3C24XX_VA_ISA_BYTE S3C2410_ADDR(0x03000000)
/* physical addresses of all the chip-select areas */
@@ -149,5 +172,16 @@
#define S3C2410_SDRAM_PA (S3C2410_CS6)
+#define S3C2400_CS0 (0x00000000)
+#define S3C2400_CS1 (0x02000000)
+#define S3C2400_CS2 (0x04000000)
+#define S3C2400_CS3 (0x06000000)
+#define S3C2400_CS4 (0x08000000)
+#define S3C2400_CS5 (0x0A000000)
+#define S3C2400_CS6 (0x0C000000)
+#define S3C2400_CS7 (0x0E000000)
+
+#define S3C2400_SDRAM_PA (S3C2400_CS6)
+
#endif /* __ASM_ARCH_MAP_H */
diff --git a/include/asm-arm/arch-s3c2410/regs-clock.h b/include/asm-arm/arch-s3c2410/regs-clock.h
index a6281f464d81..e5e938b79acc 100644
--- a/include/asm-arm/arch-s3c2410/regs-clock.h
+++ b/include/asm-arm/arch-s3c2410/regs-clock.h
@@ -10,18 +10,19 @@
* S3C2410 clock register definitions
*
* Changelog:
- * 18-Aug-2004 Ben Dooks Added 2440 definitions
- * 08-Aug-2004 Herbert Pötzl Added CLKCON definitions
- * 19-06-2003 Ben Dooks Created file
- * 12-03-2004 Ben Dooks Updated include protection
- * 29-Sep-2004 Ben Dooks Fixed usage for assembly inclusion
- * 10-Feb-2005 Ben Dooks Fixed CAMDIVN address (Guillaume Gourat)
+ * 18-Aug-2004 Ben Dooks Added 2440 definitions
+ * 08-Aug-2004 Herbert Pötzl Added CLKCON definitions
+ * 19-06-2003 Ben Dooks Created file
+ * 12-03-2004 Ben Dooks Updated include protection
+ * 29-Sep-2004 Ben Dooks Fixed usage for assembly inclusion
+ * 10-Feb-2005 Ben Dooks Fixed CAMDIVN address (Guillaume Gourat)
+ * 10-Mar-2005 Lucas Villa Real Changed S3C2410_VA to S3C24XX_VA
*/
#ifndef __ASM_ARM_REGS_CLOCK
#define __ASM_ARM_REGS_CLOCK "$Id: clock.h,v 1.4 2003/04/30 14:50:51 ben Exp $"
-#define S3C2410_CLKREG(x) ((x) + S3C2410_VA_CLKPWR)
+#define S3C2410_CLKREG(x) ((x) + S3C24XX_VA_CLKPWR)
#define S3C2410_PLLVAL(_m,_p,_s) ((_m) << 12 | ((_p) << 4) | ((_s)))
diff --git a/include/asm-arm/arch-s3c2410/regs-gpio.h b/include/asm-arm/arch-s3c2410/regs-gpio.h
index 07c17f95a92b..8ca8c0c922f5 100644
--- a/include/asm-arm/arch-s3c2410/regs-gpio.h
+++ b/include/asm-arm/arch-s3c2410/regs-gpio.h
@@ -18,6 +18,7 @@
* 17-10-2004 BJD Added GSTATUS1 register definitions
* 18-11-2004 BJD Fixed definitions of GPE3, GPE4, GPE5 and GPE6
* 18-11-2004 BJD Added S3C2440 AC97 controls
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*/
@@ -35,7 +36,7 @@
#define S3C2410_GPIO_BANKG (32*6)
#define S3C2410_GPIO_BANKH (32*7)
-#define S3C2410_GPIO_BASE(pin) ((((pin) & ~31) >> 1) + S3C2410_VA_GPIO)
+#define S3C2410_GPIO_BASE(pin) ((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO)
#define S3C2410_GPIO_OFFSET(pin) ((pin) & 31)
/* general configuration options */
@@ -44,7 +45,7 @@
/* configure GPIO ports A..G */
-#define S3C2410_GPIOREG(x) ((x) + S3C2410_VA_GPIO)
+#define S3C2410_GPIOREG(x) ((x) + S3C24XX_VA_GPIO)
/* port A - 22bits, zero in bit X makes pin X output
* 1 makes port special function, this is default
diff --git a/include/asm-arm/arch-s3c2410/regs-iis.h b/include/asm-arm/arch-s3c2410/regs-iis.h
index a3fde605f5c8..7ae8e1f45bc1 100644
--- a/include/asm-arm/arch-s3c2410/regs-iis.h
+++ b/include/asm-arm/arch-s3c2410/regs-iis.h
@@ -13,6 +13,7 @@
* 19-06-2003 BJD Created file
* 26-06-2003 BJD Finished off definitions for register addresses
* 12-03-2004 BJD Updated include protection
+ * 07-03-2005 BJD Added FIFO size flags and S3C2440 MPLL
*/
#ifndef __ASM_ARCH_REGS_IIS_H
@@ -20,6 +21,7 @@
#define S3C2410_IISCON (0x00)
+#define S3C2440_IISCON_MPLL (1<<9)
#define S3C2410_IISCON_LRINDEX (1<<8)
#define S3C2410_IISCON_TXFIFORDY (1<<7)
#define S3C2410_IISCON_RXFIFORDY (1<<6)
@@ -42,6 +44,7 @@
#define S3C2410_IISMOD_MSB (1<<4)
#define S3C2410_IISMOD_8BIT (0<<3)
#define S3C2410_IISMOD_16BIT (1<<3)
+#define S3C2410_IISMOD_BITMASK (1<<3)
#define S3C2410_IISMOD_256FS (0<<1)
#define S3C2410_IISMOD_384FS (1<<1)
#define S3C2410_IISMOD_16FS (0<<0)
@@ -50,7 +53,7 @@
#define S3C2410_IISPSR (0x08)
#define S3C2410_IISPSR_INTMASK (31<<5)
-#define S3C2410_IISPSR_INTSHFIT (5)
+#define S3C2410_IISPSR_INTSHIFT (5)
#define S3C2410_IISPSR_EXTMASK (31<<0)
#define S3C2410_IISPSR_EXTSHFIT (0)
@@ -60,8 +63,10 @@
#define S3C2410_IISFCON_RXDMA (1<<14)
#define S3C2410_IISFCON_TXENABLE (1<<13)
#define S3C2410_IISFCON_RXENABLE (1<<12)
+#define S3C2410_IISFCON_TXMASK (0x3f << 6)
+#define S3C2410_IISFCON_TXSHIFT (6)
+#define S3C2410_IISFCON_RXMASK (0x3f)
+#define S3C2410_IISFCON_RXSHIFT (0)
#define S3C2410_IISFIFO (0x10)
-
#endif /* __ASM_ARCH_REGS_IIS_H */
-
diff --git a/include/asm-arm/arch-s3c2410/regs-irq.h b/include/asm-arm/arch-s3c2410/regs-irq.h
index 87edb61ede09..24b7292df79e 100644
--- a/include/asm-arm/arch-s3c2410/regs-irq.h
+++ b/include/asm-arm/arch-s3c2410/regs-irq.h
@@ -12,6 +12,7 @@
* Changelog:
* 19-06-2003 BJD Created file
* 12-03-2004 BJD Updated include protection
+ * 10-03-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*/
@@ -20,8 +21,8 @@
/* interrupt controller */
-#define S3C2410_IRQREG(x) ((x) + S3C2410_VA_IRQ)
-#define S3C2410_EINTREG(x) ((x) + S3C2410_VA_GPIO)
+#define S3C2410_IRQREG(x) ((x) + S3C24XX_VA_IRQ)
+#define S3C2410_EINTREG(x) ((x) + S3C24XX_VA_GPIO)
#define S3C2410_SRCPND S3C2410_IRQREG(0x000)
#define S3C2410_INTMOD S3C2410_IRQREG(0x004)
diff --git a/include/asm-arm/arch-s3c2410/regs-lcd.h b/include/asm-arm/arch-s3c2410/regs-lcd.h
index eda2a7b9bf16..7f882ea92b2a 100644
--- a/include/asm-arm/arch-s3c2410/regs-lcd.h
+++ b/include/asm-arm/arch-s3c2410/regs-lcd.h
@@ -13,13 +13,14 @@
* 12-06-2003 BJD Created file
* 26-06-2003 BJD Updated LCDCON register definitions
* 12-03-2004 BJD Updated include protection
+ * 10-03-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*/
#ifndef ___ASM_ARCH_REGS_LCD_H
#define ___ASM_ARCH_REGS_LCD_H "$Id: lcd.h,v 1.3 2003/06/26 13:25:06 ben Exp $"
-#define S3C2410_LCDREG(x) ((x) + S3C2410_VA_LCD)
+#define S3C2410_LCDREG(x) ((x) + S3C24XX_VA_LCD)
/* LCD control registers */
#define S3C2410_LCDCON1 S3C2410_LCDREG(0x00)
diff --git a/include/asm-arm/arch-s3c2410/regs-mem.h b/include/asm-arm/arch-s3c2410/regs-mem.h
index 400fbd77d605..29aa625336e1 100644
--- a/include/asm-arm/arch-s3c2410/regs-mem.h
+++ b/include/asm-arm/arch-s3c2410/regs-mem.h
@@ -11,6 +11,7 @@
*
* Changelog:
* 29-Sep-2004 BJD Initial include for Linux
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*
*/
@@ -18,7 +19,7 @@
#define __ASM_ARM_MEMREGS_H "$Id: regs.h,v 1.8 2003/05/01 15:55:41 ben Exp $"
#ifndef S3C2410_MEMREG
-#define S3C2410_MEMREG(x) (S3C2410_VA_MEMCTRL + (x))
+#define S3C2410_MEMREG(x) (S3C24XX_VA_MEMCTRL + (x))
#endif
/* bus width, and wait state control */
diff --git a/include/asm-arm/arch-s3c2410/regs-rtc.h b/include/asm-arm/arch-s3c2410/regs-rtc.h
index 408cf04266e8..228983f89bc8 100644
--- a/include/asm-arm/arch-s3c2410/regs-rtc.h
+++ b/include/asm-arm/arch-s3c2410/regs-rtc.h
@@ -12,12 +12,13 @@
* Changelog:
* 19-06-2003 BJD Created file
* 12-03-2004 BJD Updated include protection
+ * 15-01-2005 LCVR Changed S3C2410_VA to S3C24XX_VA (s3c2400 support)
*/
#ifndef __ASM_ARCH_REGS_RTC_H
#define __ASM_ARCH_REGS_RTC_H __FILE__
-#define S3C2410_RTCREG(x) ((x) + S3C2410_VA_RTC)
+#define S3C2410_RTCREG(x) ((x) + S3C24XX_VA_RTC)
#define S3C2410_RTCCON S3C2410_RTCREG(0x40)
#define S3C2410_RTCCON_RTCEN (1<<0)
diff --git a/include/asm-arm/arch-s3c2410/regs-serial.h b/include/asm-arm/arch-s3c2410/regs-serial.h
index 782ce5f5d24d..ce1bbbaad6d3 100644
--- a/include/asm-arm/arch-s3c2410/regs-serial.h
+++ b/include/asm-arm/arch-s3c2410/regs-serial.h
@@ -27,14 +27,17 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Modifications:
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA (s3c2400 support)
*/
#ifndef __ASM_ARM_REGS_SERIAL_H
#define __ASM_ARM_REGS_SERIAL_H
-#define S3C2410_VA_UART0 (S3C2410_VA_UART)
-#define S3C2410_VA_UART1 (S3C2410_VA_UART + 0x4000 )
-#define S3C2410_VA_UART2 (S3C2410_VA_UART + 0x8000 )
+#define S3C24XX_VA_UART0 (S3C24XX_VA_UART)
+#define S3C24XX_VA_UART1 (S3C24XX_VA_UART + 0x4000 )
+#define S3C24XX_VA_UART2 (S3C24XX_VA_UART + 0x8000 )
#define S3C2410_PA_UART0 (S3C2410_PA_UART)
#define S3C2410_PA_UART1 (S3C2410_PA_UART + 0x4000 )
diff --git a/include/asm-arm/arch-s3c2410/regs-timer.h b/include/asm-arm/arch-s3c2410/regs-timer.h
index d93c35d7f690..169064e27520 100644
--- a/include/asm-arm/arch-s3c2410/regs-timer.h
+++ b/include/asm-arm/arch-s3c2410/regs-timer.h
@@ -14,13 +14,14 @@
* 26-06-2003 BJD Added more timer definitions to mux / control
* 12-03-2004 BJD Updated include protection
* 10-02-2005 BJD Added S3C2410_TCFG1_MUX4_SHIFT (Guillaume Gourat)
+ * 10-03-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*/
#ifndef __ASM_ARCH_REGS_TIMER_H
#define __ASM_ARCH_REGS_TIMER_H "$Id: timer.h,v 1.4 2003/05/06 19:30:50 ben Exp $"
-#define S3C2410_TIMERREG(x) (S3C2410_VA_TIMER + (x))
+#define S3C2410_TIMERREG(x) (S3C24XX_VA_TIMER + (x))
#define S3C2410_TIMERREG2(tmr,reg) S3C2410_TIMERREG((reg)+0x0c+((tmr)*0x0c))
#define S3C2410_TCFG0 S3C2410_TIMERREG(0x00)
diff --git a/include/asm-arm/arch-s3c2410/regs-udc.h b/include/asm-arm/arch-s3c2410/regs-udc.h
index ad550bbf7285..bf315b763252 100644
--- a/include/asm-arm/arch-s3c2410/regs-udc.h
+++ b/include/asm-arm/arch-s3c2410/regs-udc.h
@@ -11,13 +11,14 @@
* 01-08-2004 Initial creation
* 12-09-2004 Cleanup for submission
* 24-10-2004 Fixed S3C2410_UDC_MAXP_REG definition
+ * 10-03-2005 Changed S3C2410_VA to S3C24XX_VA
*/
#ifndef __ASM_ARCH_REGS_UDC_H
#define __ASM_ARCH_REGS_UDC_H
-#define S3C2410_USBDREG(x) ((x) + S3C2410_VA_USBDEV)
+#define S3C2410_USBDREG(x) ((x) + S3C24XX_VA_USBDEV)
#define S3C2410_UDC_FUNC_ADDR_REG S3C2410_USBDREG(0x0140)
#define S3C2410_UDC_PWR_REG S3C2410_USBDREG(0x0144)
diff --git a/include/asm-arm/arch-s3c2410/regs-watchdog.h b/include/asm-arm/arch-s3c2410/regs-watchdog.h
index b09d5107a1eb..d199ca6aff22 100644
--- a/include/asm-arm/arch-s3c2410/regs-watchdog.h
+++ b/include/asm-arm/arch-s3c2410/regs-watchdog.h
@@ -12,13 +12,14 @@
* Changelog:
* 21-06-2003 BJD Created file
* 12-03-2004 BJD Updated include protection
+ * 10-03-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*/
#ifndef __ASM_ARCH_REGS_WATCHDOG_H
#define __ASM_ARCH_REGS_WATCHDOG_H "$Id: watchdog.h,v 1.2 2003/04/29 13:31:09 ben Exp $"
-#define S3C2410_WDOGREG(x) ((x) + S3C2410_VA_WATCHDOG)
+#define S3C2410_WDOGREG(x) ((x) + S3C24XX_VA_WATCHDOG)
#define S3C2410_WTCON S3C2410_WDOGREG(0x00)
#define S3C2410_WTDAT S3C2410_WDOGREG(0x04)
diff --git a/include/asm-ppc/uninorth.h b/include/asm-ppc/uninorth.h
index 57daf7add022..f737732c3861 100644
--- a/include/asm-ppc/uninorth.h
+++ b/include/asm-ppc/uninorth.h
@@ -27,13 +27,18 @@
#define UNI_N_CFG_AGP_BASE 0x90
#define UNI_N_CFG_GART_CTRL 0x94
#define UNI_N_CFG_INTERNAL_STATUS 0x98
+#define UNI_N_CFG_GART_DUMMY_PAGE 0xa4
/* UNI_N_CFG_GART_CTRL bits definitions */
-/* Not U3 */
#define UNI_N_CFG_GART_INVAL 0x00000001
#define UNI_N_CFG_GART_ENABLE 0x00000100
#define UNI_N_CFG_GART_2xRESET 0x00010000
#define UNI_N_CFG_GART_DISSBADET 0x00020000
+/* The following seems to only be used only on U3 <j.glisse@gmail.com> */
+#define U3_N_CFG_GART_SYNCMODE 0x00040000
+#define U3_N_CFG_GART_PERFRD 0x00080000
+#define U3_N_CFG_GART_B2BGNT 0x00200000
+#define U3_N_CFG_GART_FASTDDR 0x00400000
/* My understanding of UniNorth AGP as of UniNorth rev 1.0x,
* revision 1.5 (x4 AGP) may need further changes.
diff --git a/include/asm-ppc64/agp.h b/include/asm-ppc64/agp.h
new file mode 100644
index 000000000000..be27cfa8c5b0
--- /dev/null
+++ b/include/asm-ppc64/agp.h
@@ -0,0 +1,13 @@
+#ifndef AGP_H
+#define AGP_H 1
+
+#include <asm/io.h>
+
+/* nothing much needed here */
+
+#define map_page_into_agp(page)
+#define unmap_page_from_agp(page)
+#define flush_agp_mappings()
+#define flush_agp_cache() mb()
+
+#endif
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index 5a173a673fc9..0d9d22578212 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -42,7 +42,6 @@ struct nlm_host {
struct rpc_clnt * h_rpcclnt; /* RPC client to talk to peer */
char h_name[20]; /* remote hostname */
u32 h_version; /* interface version */
- rpc_authflavor_t h_authflavor; /* RPC authentication type */
unsigned short h_proto; /* transport proto */
unsigned short h_reclaiming : 1,
h_server : 1, /* server side, not client side */
@@ -143,8 +142,6 @@ extern unsigned long nlmsvc_timeout;
* Lockd client functions
*/
struct nlm_rqst * nlmclnt_alloc_call(void);
-int nlmclnt_call(struct nlm_rqst *, u32);
-int nlmclnt_async_call(struct nlm_rqst *, u32, rpc_action);
int nlmclnt_block(struct nlm_host *, struct file_lock *, u32 *);
int nlmclnt_cancel(struct nlm_host *, struct file_lock *);
u32 nlmclnt_grant(struct nlm_lock *);
diff --git a/include/linux/namei.h b/include/linux/namei.h
index 1bbfa296e11f..7db67b008cac 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -39,12 +39,14 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
* - ending slashes ok even for nonexistent files
* - internal "there are more path compnents" flag
* - locked when lookup done with dcache_lock held
+ * - dentry cache is untrusted; force a real lookup
*/
#define LOOKUP_FOLLOW 1
#define LOOKUP_DIRECTORY 2
#define LOOKUP_CONTINUE 4
#define LOOKUP_PARENT 16
#define LOOKUP_NOALT 32
+#define LOOKUP_REVAL 64
/*
* Intent data
*/
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 12c46442cc86..dbac7f363e5d 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -345,17 +345,14 @@ extern struct inode_operations nfs_dir_inode_operations;
extern struct file_operations nfs_dir_operations;
extern struct dentry_operations nfs_dentry_operations;
+extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr);
+
/*
* linux/fs/nfs/symlink.c
*/
extern struct inode_operations nfs_symlink_inode_operations;
/*
- * linux/fs/nfs/locks.c
- */
-extern int nfs_lock(struct file *, int, struct file_lock *);
-
-/*
* linux/fs/nfs/unlink.c
*/
extern int nfs_async_unlink(struct dentry *);
@@ -379,11 +376,8 @@ extern void nfs_commit_done(struct rpc_task *);
* return value!)
*/
extern int nfs_sync_inode(struct inode *, unsigned long, unsigned int, int);
-extern int nfs_flush_inode(struct inode *, unsigned long, unsigned int, int);
-extern int nfs_flush_list(struct list_head *, int, int);
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
extern int nfs_commit_inode(struct inode *, unsigned long, unsigned int, int);
-extern int nfs_commit_list(struct list_head *, int);
#else
static inline int
nfs_commit_inode(struct inode *inode, unsigned long idx_start, unsigned int npages, int how)
@@ -424,7 +418,6 @@ static inline int nfs_wb_page(struct inode *inode, struct page* page)
* Allocate and free nfs_write_data structures
*/
extern mempool_t *nfs_wdata_mempool;
-extern mempool_t *nfs_commit_mempool;
static inline struct nfs_write_data *nfs_writedata_alloc(void)
{
@@ -441,23 +434,6 @@ static inline void nfs_writedata_free(struct nfs_write_data *p)
mempool_free(p, nfs_wdata_mempool);
}
-extern void nfs_writedata_release(struct rpc_task *task);
-
-static inline struct nfs_write_data *nfs_commit_alloc(void)
-{
- struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, SLAB_NOFS);
- if (p) {
- memset(p, 0, sizeof(*p));
- INIT_LIST_HEAD(&p->pages);
- }
- return p;
-}
-
-static inline void nfs_commit_free(struct nfs_write_data *p)
-{
- mempool_free(p, nfs_commit_mempool);
-}
-
/* Hack for future NFS swap support */
#ifndef IS_SWAPFILE
# define IS_SWAPFILE(inode) (0)
@@ -469,7 +445,6 @@ static inline void nfs_commit_free(struct nfs_write_data *p)
extern int nfs_readpage(struct file *, struct page *);
extern int nfs_readpages(struct file *, struct address_space *,
struct list_head *, unsigned);
-extern int nfs_pagein_list(struct list_head *, int);
extern void nfs_readpage_result(struct rpc_task *);
/*
@@ -610,6 +585,9 @@ struct nfs4_client {
wait_queue_head_t cl_waitq;
struct rpc_wait_queue cl_rpcwaitq;
+ /* used for the setclientid verifier */
+ struct timespec cl_boot_time;
+
/* idmapper */
struct idmap * cl_idmap;
@@ -617,6 +595,7 @@ struct nfs4_client {
* This is used to generate the clientid, and the callback address.
*/
char cl_ipaddr[16];
+ unsigned char cl_id_uniquifier;
};
/*
@@ -696,21 +675,26 @@ struct nfs4_exception {
int retry;
};
+struct nfs4_state_recovery_ops {
+ int (*recover_open)(struct nfs4_state_owner *, struct nfs4_state *);
+ int (*recover_lock)(struct nfs4_state *, struct file_lock *);
+};
+
extern struct dentry_operations nfs4_dentry_operations;
extern struct inode_operations nfs4_dir_inode_operations;
/* nfs4proc.c */
+extern int nfs4_map_errors(int err);
extern int nfs4_proc_setclientid(struct nfs4_client *, u32, unsigned short);
extern int nfs4_proc_setclientid_confirm(struct nfs4_client *);
-extern int nfs4_open_reclaim(struct nfs4_state_owner *, struct nfs4_state *);
extern int nfs4_proc_async_renew(struct nfs4_client *);
extern int nfs4_proc_renew(struct nfs4_client *);
extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode);
-extern int nfs4_wait_clnt_recover(struct rpc_clnt *, struct nfs4_client *);
extern struct inode *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
extern int nfs4_open_revalidate(struct inode *, struct dentry *, int);
-extern int nfs4_handle_exception(struct nfs_server *, int, struct nfs4_exception *);
-extern int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request);
+
+extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
+extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops;
/* nfs4renewd.c */
extern void nfs4_schedule_state_renewal(struct nfs4_client *);
@@ -728,6 +712,7 @@ extern u32 nfs4_alloc_lockowner_id(struct nfs4_client *);
extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *);
extern void nfs4_put_state_owner(struct nfs4_state_owner *);
+extern void nfs4_drop_state_owner(struct nfs4_state_owner *);
extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
extern void nfs4_put_open_state(struct nfs4_state *);
extern void nfs4_close_state(struct nfs4_state *, mode_t);
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index a43a38607982..fc51645d61ee 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -53,5 +53,6 @@ struct nfs_server {
#define NFS_CAP_HARDLINKS (1U << 1)
#define NFS_CAP_SYMLINKS (1U << 2)
#define NFS_CAP_ACLS (1U << 3)
+#define NFS_CAP_ATOMIC_OPEN (1U << 4)
#endif
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index a73f8a990b24..47037d9521cb 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -563,6 +563,7 @@ struct nfs4_readdir_arg {
u32 count;
struct page ** pages; /* zero-copy data */
unsigned int pgbase; /* zero-copy data */
+ const u32 * bitmask;
};
struct nfs4_readdir_res {
@@ -681,7 +682,7 @@ struct nfs_rpc_ops {
int (*read) (struct nfs_read_data *);
int (*write) (struct nfs_write_data *);
int (*commit) (struct nfs_write_data *);
- struct inode * (*create) (struct inode *, struct dentry *,
+ int (*create) (struct inode *, struct dentry *,
struct iattr *, int);
int (*remove) (struct inode *, struct qstr *);
int (*unlink_setup) (struct rpc_message *,
@@ -693,13 +694,12 @@ struct nfs_rpc_ops {
int (*symlink) (struct inode *, struct qstr *, struct qstr *,
struct iattr *, struct nfs_fh *,
struct nfs_fattr *);
- int (*mkdir) (struct inode *, struct qstr *, struct iattr *,
- struct nfs_fh *, struct nfs_fattr *);
+ int (*mkdir) (struct inode *, struct dentry *, struct iattr *);
int (*rmdir) (struct inode *, struct qstr *);
int (*readdir) (struct dentry *, struct rpc_cred *,
u64, struct page *, unsigned int, int);
- int (*mknod) (struct inode *, struct qstr *, struct iattr *,
- dev_t, struct nfs_fh *, struct nfs_fattr *);
+ int (*mknod) (struct inode *, struct dentry *, struct iattr *,
+ dev_t);
int (*statfs) (struct nfs_server *, struct nfs_fh *,
struct nfs_fsstat *);
int (*fsinfo) (struct nfs_server *, struct nfs_fh *,
@@ -731,7 +731,5 @@ extern struct nfs_rpc_ops nfs_v4_clientops;
extern struct rpc_version nfs_version2;
extern struct rpc_version nfs_version3;
extern struct rpc_version nfs_version4;
-extern struct rpc_program nfs_program;
-extern struct rpc_stat nfs_rpcstat;
#endif
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 2fe68378fbad..1274cdac9cbb 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -876,10 +876,13 @@
#define PCI_DEVICE_ID_APPLE_IPID_ATA100 0x003b
#define PCI_DEVICE_ID_APPLE_KEYLARGO_I 0x003e
#define PCI_DEVICE_ID_APPLE_K2_ATA100 0x0043
+#define PCI_DEVICE_ID_APPLE_U3_AGP 0x004b
#define PCI_DEVICE_ID_APPLE_K2_GMAC 0x004c
#define PCI_DEVICE_ID_APPLE_SH_ATA 0x0050
#define PCI_DEVICE_ID_APPLE_SH_SUNGEM 0x0051
#define PCI_DEVICE_ID_APPLE_SH_FW 0x0052
+#define PCI_DEVICE_ID_APPLE_U3L_AGP 0x0058
+#define PCI_DEVICE_ID_APPLE_U3H_AGP 0x0059
#define PCI_DEVICE_ID_APPLE_TIGON3 0x1645
#define PCI_VENDOR_ID_YAMAHA 0x1073
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index f6d27720962e..04ebc24db348 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -35,8 +35,7 @@ struct auth_cred {
* Client user credentials
*/
struct rpc_cred {
- struct list_head cr_hash; /* hash chain */
- struct rpc_auth * cr_auth;
+ struct hlist_node cr_hash; /* hash chain */
struct rpc_credops * cr_ops;
unsigned long cr_expire; /* when to gc */
atomic_t cr_count; /* ref count */
@@ -59,10 +58,13 @@ struct rpc_cred {
*/
#define RPC_CREDCACHE_NR 8
#define RPC_CREDCACHE_MASK (RPC_CREDCACHE_NR - 1)
+struct rpc_cred_cache {
+ struct hlist_head hashtable[RPC_CREDCACHE_NR];
+ unsigned long nextgc; /* next garbage collection */
+ unsigned long expire; /* cache expiry interval */
+};
+
struct rpc_auth {
- struct list_head au_credcache[RPC_CREDCACHE_NR];
- unsigned long au_expire; /* cache expiry interval */
- unsigned long au_nextgc; /* next garbage collection */
unsigned int au_cslack; /* call cred size estimate */
unsigned int au_rslack; /* reply verf size guess */
unsigned int au_flags; /* various flags */
@@ -73,6 +75,7 @@ struct rpc_auth {
* case) */
atomic_t au_count; /* Reference counter */
+ struct rpc_cred_cache * au_credcache;
/* per-flavor data */
};
#define RPC_AUTH_PROC_CREDS 0x0010 /* process creds (including
@@ -91,14 +94,16 @@ struct rpc_authops {
struct rpc_auth * (*create)(struct rpc_clnt *, rpc_authflavor_t);
void (*destroy)(struct rpc_auth *);
+ struct rpc_cred * (*lookup_cred)(struct rpc_auth *, struct auth_cred *, int);
struct rpc_cred * (*crcreate)(struct rpc_auth*, struct auth_cred *, int);
};
struct rpc_credops {
+ const char * cr_name; /* Name of the auth flavour */
void (*crdestroy)(struct rpc_cred *);
int (*crmatch)(struct auth_cred *, struct rpc_cred *, int);
- u32 * (*crmarshal)(struct rpc_task *, u32 *, int);
+ u32 * (*crmarshal)(struct rpc_task *, u32 *);
int (*crrefresh)(struct rpc_task *);
u32 * (*crvalidate)(struct rpc_task *, u32 *);
int (*crwrap_req)(struct rpc_task *, kxdrproc_t,
@@ -130,7 +135,7 @@ int rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp,
int rpcauth_refreshcred(struct rpc_task *);
void rpcauth_invalcred(struct rpc_task *);
int rpcauth_uptodatecred(struct rpc_task *);
-void rpcauth_init_credcache(struct rpc_auth *);
+int rpcauth_init_credcache(struct rpc_auth *, unsigned long);
void rpcauth_free_credcache(struct rpc_auth *);
static inline
diff --git a/include/linux/sunrpc/auth_gss.h b/include/linux/sunrpc/auth_gss.h
index 5bff5a1d45f7..03084dc4bb6a 100644
--- a/include/linux/sunrpc/auth_gss.h
+++ b/include/linux/sunrpc/auth_gss.h
@@ -68,18 +68,21 @@ struct rpc_gss_init_res {
struct gss_cl_ctx {
atomic_t count;
- u32 gc_proc;
+ enum rpc_gss_proc gc_proc;
u32 gc_seq;
spinlock_t gc_seq_lock;
struct gss_ctx *gc_gss_ctx;
struct xdr_netobj gc_wire_ctx;
u32 gc_win;
+ unsigned long gc_expiry;
};
+struct gss_upcall_msg;
struct gss_cred {
struct rpc_cred gc_base;
- u32 gc_flavor;
+ enum rpc_gss_svc gc_service;
struct gss_cl_ctx *gc_ctx;
+ struct gss_upcall_msg *gc_upcall;
};
#define gc_uid gc_base.cr_uid
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 917ec29d789b..2709caf4d128 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -51,7 +51,6 @@ struct rpc_clnt {
cl_intr : 1,/* interruptible */
cl_chatty : 1,/* be verbose */
cl_autobind : 1,/* use getport() */
- cl_droppriv : 1,/* enable NFS suid hack */
cl_oneshot : 1,/* dispose after use */
cl_dead : 1;/* abandoned */
@@ -129,6 +128,7 @@ void rpc_restart_call(struct rpc_task *);
void rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset);
void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset);
void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
+size_t rpc_max_payload(struct rpc_clnt *);
static __inline__
int rpc_call(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h
index 629957d710a0..689262f63059 100644
--- a/include/linux/sunrpc/gss_api.h
+++ b/include/linux/sunrpc/gss_api.h
@@ -33,8 +33,9 @@ struct gss_ctx {
/* gss-api prototypes; note that these are somewhat simplified versions of
* the prototypes specified in RFC 2744. */
-u32 gss_import_sec_context(
- struct xdr_netobj *input_token,
+int gss_import_sec_context(
+ const void* input_token,
+ size_t bufsize,
struct gss_api_mech *mech,
struct gss_ctx **ctx_id);
u32 gss_get_mic(
@@ -50,8 +51,6 @@ u32 gss_verify_mic(
u32 gss_delete_sec_context(
struct gss_ctx **ctx_id);
-struct gss_api_mech * gss_mech_get_by_name(char *name);
-struct gss_api_mech * gss_mech_get_by_pseudoflavor(u32 pseudoflavor);
u32 gss_pseudoflavor_to_service(struct gss_api_mech *, u32 pseudoflavor);
char *gss_service_to_auth_domain_name(struct gss_api_mech *, u32 service);
@@ -80,8 +79,9 @@ struct gss_api_mech {
/* and must provide the following operations: */
struct gss_api_ops {
- u32 (*gss_import_sec_context)(
- struct xdr_netobj *input_token,
+ int (*gss_import_sec_context)(
+ const void *input_token,
+ size_t bufsize,
struct gss_ctx *ctx_id);
u32 (*gss_get_mic)(
struct gss_ctx *ctx_id,
@@ -105,7 +105,7 @@ void gss_mech_unregister(struct gss_api_mech *);
struct gss_api_mech * gss_mech_get_by_OID(struct xdr_netobj *);
/* Returns a reference to a mechanism, given a name like "krb5" etc. */
-struct gss_api_mech *gss_mech_get_by_name(char *);
+struct gss_api_mech *gss_mech_get_by_name(const char *);
/* Similar, but get by pseudoflavor. */
struct gss_api_mech *gss_mech_get_by_pseudoflavor(u32);
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 933eeb005f09..99d17ed7cebb 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -53,9 +53,8 @@ struct rpc_task {
struct rpc_message tk_msg; /* RPC call info */
__u32 * tk_buffer; /* XDR buffer */
size_t tk_bufsize;
- __u8 tk_garb_retry,
- tk_cred_retry,
- tk_suid_retry;
+ __u8 tk_garb_retry;
+ __u8 tk_cred_retry;
unsigned long tk_cookie; /* Cookie for batching tasks */
@@ -118,9 +117,7 @@ typedef void (*rpc_action)(struct rpc_task *);
*/
#define RPC_TASK_ASYNC 0x0001 /* is an async task */
#define RPC_TASK_SWAPPER 0x0002 /* is swapping in/out */
-#define RPC_TASK_SETUID 0x0004 /* is setuid process */
#define RPC_TASK_CHILD 0x0008 /* is child of other task */
-#define RPC_CALL_REALUID 0x0010 /* try using real uid */
#define RPC_CALL_MAJORSEEN 0x0020 /* major timeout seen */
#define RPC_TASK_ROOTCREDS 0x0040 /* force root creds */
#define RPC_TASK_DYNAMIC 0x0080 /* task was kmalloc'ed */
@@ -129,7 +126,6 @@ typedef void (*rpc_action)(struct rpc_task *);
#define RPC_TASK_NOINTR 0x0400 /* uninterruptible task */
#define RPC_IS_ASYNC(t) ((t)->tk_flags & RPC_TASK_ASYNC)
-#define RPC_IS_SETUID(t) ((t)->tk_flags & RPC_TASK_SETUID)
#define RPC_IS_CHILD(t) ((t)->tk_flags & RPC_TASK_CHILD)
#define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER)
#define RPC_DO_ROOTOVERRIDE(t) ((t)->tk_flags & RPC_TASK_ROOTCREDS)
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 78dbc7bedd7b..e618c1649814 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -140,6 +140,9 @@ struct rpc_xprt {
unsigned int rcvsize, /* socket receive buffer size */
sndsize; /* socket send buffer size */
+ size_t max_payload; /* largest RPC payload size,
+ in bytes */
+
struct rpc_wait_queue sending; /* requests waiting to send */
struct rpc_wait_queue resend; /* requests waiting to resend */
struct rpc_wait_queue pending; /* requests in flight */
diff --git a/kernel/printk.c b/kernel/printk.c
index 7e36204db952..f5dc23584ff7 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -579,6 +579,7 @@ asmlinkage int vprintk(const char *fmt, va_list args)
p[1] <= '7' && p[2] == '>') {
loglev_char = p[1];
p += 3;
+ printed_len += 3;
} else {
loglev_char = default_message_loglevel
+ '0';
@@ -591,8 +592,9 @@ asmlinkage int vprintk(const char *fmt, va_list args)
(unsigned long)t,
nanosec_rem/1000);
- for (tp = tbuf; tp< tbuf + tlen; tp++)
- emit_log_char (*tp);
+ for (tp = tbuf; tp < tbuf + tlen; tp++)
+ emit_log_char(*tp);
+ printed_len += tlen - 3;
} else {
if (p[0] != '<' || p[1] < '0' ||
p[1] > '7' || p[2] != '>') {
@@ -601,8 +603,11 @@ asmlinkage int vprintk(const char *fmt, va_list args)
+ '0');
emit_log_char('>');
}
+ printed_len += 3;
}
log_level_unknown = 0;
+ if (!*p)
+ break;
}
emit_log_char(*p);
if (*p == '\n')
diff --git a/lib/extable.c b/lib/extable.c
index e8e77527946e..3f677a8f0c3c 100644
--- a/lib/extable.c
+++ b/lib/extable.c
@@ -29,7 +29,13 @@ extern struct exception_table_entry __stop___ex_table[];
static int cmp_ex(const void *a, const void *b)
{
const struct exception_table_entry *x = a, *y = b;
- return x->insn - y->insn;
+
+ /* avoid overflow */
+ if (x->insn > y->insn)
+ return 1;
+ if (x->insn < y->insn)
+ return -1;
+ return 0;
}
void sort_extable(struct exception_table_entry *start,
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 7176c6d37190..9bcec9b927b9 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -67,12 +67,9 @@ rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt)
if (flavor >= RPC_AUTH_MAXFLAVOR || !(ops = auth_flavors[flavor]))
return NULL;
- if (!try_module_get(ops->owner))
- return NULL;
auth = ops->create(clnt, pseudoflavor);
if (!auth)
return NULL;
- atomic_set(&auth->au_count, 1);
if (clnt->cl_auth)
rpcauth_destroy(clnt->cl_auth);
clnt->cl_auth = auth;
@@ -85,8 +82,6 @@ rpcauth_destroy(struct rpc_auth *auth)
if (!atomic_dec_and_test(&auth->au_count))
return;
auth->au_ops->destroy(auth);
- module_put(auth->au_ops->owner);
- kfree(auth);
}
static DEFINE_SPINLOCK(rpc_credcache_lock);
@@ -94,42 +89,35 @@ static DEFINE_SPINLOCK(rpc_credcache_lock);
/*
* Initialize RPC credential cache
*/
-void
-rpcauth_init_credcache(struct rpc_auth *auth)
+int
+rpcauth_init_credcache(struct rpc_auth *auth, unsigned long expire)
{
+ struct rpc_cred_cache *new;
int i;
- for (i = 0; i < RPC_CREDCACHE_NR; i++)
- INIT_LIST_HEAD(&auth->au_credcache[i]);
- auth->au_nextgc = jiffies + (auth->au_expire >> 1);
-}
-/*
- * Destroy an unreferenced credential
- */
-static inline void
-rpcauth_crdestroy(struct rpc_cred *cred)
-{
-#ifdef RPC_DEBUG
- BUG_ON(cred->cr_magic != RPCAUTH_CRED_MAGIC ||
- atomic_read(&cred->cr_count) ||
- !list_empty(&cred->cr_hash));
- cred->cr_magic = 0;
-#endif
- cred->cr_ops->crdestroy(cred);
+ new = (struct rpc_cred_cache *)kmalloc(sizeof(*new), GFP_KERNEL);
+ if (!new)
+ return -ENOMEM;
+ for (i = 0; i < RPC_CREDCACHE_NR; i++)
+ INIT_HLIST_HEAD(&new->hashtable[i]);
+ new->expire = expire;
+ new->nextgc = jiffies + (expire >> 1);
+ auth->au_credcache = new;
+ return 0;
}
/*
* Destroy a list of credentials
*/
static inline
-void rpcauth_destroy_credlist(struct list_head *head)
+void rpcauth_destroy_credlist(struct hlist_head *head)
{
struct rpc_cred *cred;
- while (!list_empty(head)) {
- cred = list_entry(head->next, struct rpc_cred, cr_hash);
- list_del_init(&cred->cr_hash);
- rpcauth_crdestroy(cred);
+ while (!hlist_empty(head)) {
+ cred = hlist_entry(head->first, struct rpc_cred, cr_hash);
+ hlist_del_init(&cred->cr_hash);
+ put_rpccred(cred);
}
}
@@ -140,56 +128,56 @@ void rpcauth_destroy_credlist(struct list_head *head)
void
rpcauth_free_credcache(struct rpc_auth *auth)
{
- LIST_HEAD(free);
- struct list_head *pos, *next;
+ struct rpc_cred_cache *cache = auth->au_credcache;
+ HLIST_HEAD(free);
+ struct hlist_node *pos, *next;
struct rpc_cred *cred;
int i;
spin_lock(&rpc_credcache_lock);
for (i = 0; i < RPC_CREDCACHE_NR; i++) {
- list_for_each_safe(pos, next, &auth->au_credcache[i]) {
- cred = list_entry(pos, struct rpc_cred, cr_hash);
- cred->cr_auth = NULL;
- list_del_init(&cred->cr_hash);
- if (atomic_read(&cred->cr_count) == 0)
- list_add(&cred->cr_hash, &free);
+ hlist_for_each_safe(pos, next, &cache->hashtable[i]) {
+ cred = hlist_entry(pos, struct rpc_cred, cr_hash);
+ __hlist_del(&cred->cr_hash);
+ hlist_add_head(&cred->cr_hash, &free);
}
}
spin_unlock(&rpc_credcache_lock);
rpcauth_destroy_credlist(&free);
}
-static inline int
-rpcauth_prune_expired(struct rpc_cred *cred, struct list_head *free)
+static void
+rpcauth_prune_expired(struct rpc_auth *auth, struct rpc_cred *cred, struct hlist_head *free)
{
- if (atomic_read(&cred->cr_count) != 0)
- return 0;
- if (time_before(jiffies, cred->cr_expire))
- return 0;
- cred->cr_auth = NULL;
- list_del(&cred->cr_hash);
- list_add(&cred->cr_hash, free);
- return 1;
+ if (atomic_read(&cred->cr_count) != 1)
+ return;
+ if (time_after(jiffies, cred->cr_expire + auth->au_credcache->expire))
+ cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+ if (!(cred->cr_flags & RPCAUTH_CRED_UPTODATE)) {
+ __hlist_del(&cred->cr_hash);
+ hlist_add_head(&cred->cr_hash, free);
+ }
}
/*
* Remove stale credentials. Avoid sleeping inside the loop.
*/
static void
-rpcauth_gc_credcache(struct rpc_auth *auth, struct list_head *free)
+rpcauth_gc_credcache(struct rpc_auth *auth, struct hlist_head *free)
{
- struct list_head *pos, *next;
+ struct rpc_cred_cache *cache = auth->au_credcache;
+ struct hlist_node *pos, *next;
struct rpc_cred *cred;
int i;
dprintk("RPC: gc'ing RPC credentials for auth %p\n", auth);
for (i = 0; i < RPC_CREDCACHE_NR; i++) {
- list_for_each_safe(pos, next, &auth->au_credcache[i]) {
- cred = list_entry(pos, struct rpc_cred, cr_hash);
- rpcauth_prune_expired(cred, free);
+ hlist_for_each_safe(pos, next, &cache->hashtable[i]) {
+ cred = hlist_entry(pos, struct rpc_cred, cr_hash);
+ rpcauth_prune_expired(auth, cred, free);
}
}
- auth->au_nextgc = jiffies + auth->au_expire;
+ cache->nextgc = jiffies + cache->expire;
}
/*
@@ -199,8 +187,9 @@ struct rpc_cred *
rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
int taskflags)
{
- LIST_HEAD(free);
- struct list_head *pos, *next;
+ struct rpc_cred_cache *cache = auth->au_credcache;
+ HLIST_HEAD(free);
+ struct hlist_node *pos, *next;
struct rpc_cred *new = NULL,
*cred = NULL;
int nr = 0;
@@ -209,28 +198,26 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
nr = acred->uid & RPC_CREDCACHE_MASK;
retry:
spin_lock(&rpc_credcache_lock);
- if (time_before(auth->au_nextgc, jiffies))
+ if (time_before(cache->nextgc, jiffies))
rpcauth_gc_credcache(auth, &free);
- list_for_each_safe(pos, next, &auth->au_credcache[nr]) {
+ hlist_for_each_safe(pos, next, &cache->hashtable[nr]) {
struct rpc_cred *entry;
- entry = list_entry(pos, struct rpc_cred, cr_hash);
- if (rpcauth_prune_expired(entry, &free))
- continue;
+ entry = hlist_entry(pos, struct rpc_cred, cr_hash);
if (entry->cr_ops->crmatch(acred, entry, taskflags)) {
- list_del(&entry->cr_hash);
+ hlist_del(&entry->cr_hash);
cred = entry;
break;
}
+ rpcauth_prune_expired(auth, entry, &free);
}
if (new) {
if (cred)
- list_add(&new->cr_hash, &free);
+ hlist_add_head(&new->cr_hash, &free);
else
cred = new;
}
if (cred) {
- list_add(&cred->cr_hash, &auth->au_credcache[nr]);
- cred->cr_auth = auth;
+ hlist_add_head(&cred->cr_hash, &cache->hashtable[nr]);
get_rpccred(cred);
}
spin_unlock(&rpc_credcache_lock);
@@ -239,12 +226,13 @@ retry:
if (!cred) {
new = auth->au_ops->crcreate(auth, acred, taskflags);
- if (new) {
+ if (!IS_ERR(new)) {
#ifdef RPC_DEBUG
new->cr_magic = RPCAUTH_CRED_MAGIC;
#endif
goto retry;
- }
+ } else
+ cred = new;
}
return (struct rpc_cred *) cred;
@@ -253,18 +241,18 @@ retry:
struct rpc_cred *
rpcauth_lookupcred(struct rpc_auth *auth, int taskflags)
{
- struct auth_cred acred;
+ struct auth_cred acred = {
+ .uid = current->fsuid,
+ .gid = current->fsgid,
+ .group_info = current->group_info,
+ };
struct rpc_cred *ret;
- get_group_info(current->group_info);
- acred.uid = current->fsuid;
- acred.gid = current->fsgid;
- acred.group_info = current->group_info;
-
dprintk("RPC: looking up %s cred\n",
auth->au_ops->au_name);
- ret = rpcauth_lookup_credcache(auth, &acred, taskflags);
- put_group_info(current->group_info);
+ get_group_info(acred.group_info);
+ ret = auth->au_ops->lookup_cred(auth, &acred, taskflags);
+ put_group_info(acred.group_info);
return ret;
}
@@ -272,21 +260,22 @@ struct rpc_cred *
rpcauth_bindcred(struct rpc_task *task)
{
struct rpc_auth *auth = task->tk_auth;
- struct auth_cred acred;
+ struct auth_cred acred = {
+ .uid = current->fsuid,
+ .gid = current->fsgid,
+ .group_info = current->group_info,
+ };
struct rpc_cred *ret;
- get_group_info(current->group_info);
- acred.uid = current->fsuid;
- acred.gid = current->fsgid;
- acred.group_info = current->group_info;
-
dprintk("RPC: %4d looking up %s cred\n",
task->tk_pid, task->tk_auth->au_ops->au_name);
- task->tk_msg.rpc_cred = rpcauth_lookup_credcache(auth, &acred, task->tk_flags);
- if (task->tk_msg.rpc_cred == 0)
- task->tk_status = -ENOMEM;
- ret = task->tk_msg.rpc_cred;
- put_group_info(current->group_info);
+ get_group_info(acred.group_info);
+ ret = auth->au_ops->lookup_cred(auth, &acred, task->tk_flags);
+ if (!IS_ERR(ret))
+ task->tk_msg.rpc_cred = ret;
+ else
+ task->tk_status = PTR_ERR(ret);
+ put_group_info(acred.group_info);
return ret;
}
@@ -302,16 +291,10 @@ rpcauth_holdcred(struct rpc_task *task)
void
put_rpccred(struct rpc_cred *cred)
{
- if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock))
- return;
-
- if (list_empty(&cred->cr_hash)) {
- spin_unlock(&rpc_credcache_lock);
- rpcauth_crdestroy(cred);
+ cred->cr_expire = jiffies;
+ if (!atomic_dec_and_test(&cred->cr_count))
return;
- }
- cred->cr_expire = jiffies + cred->cr_auth->au_expire;
- spin_unlock(&rpc_credcache_lock);
+ cred->cr_ops->crdestroy(cred);
}
void
@@ -335,8 +318,7 @@ rpcauth_marshcred(struct rpc_task *task, u32 *p)
dprintk("RPC: %4d marshaling %s cred %p\n",
task->tk_pid, auth->au_ops->au_name, cred);
- return cred->cr_ops->crmarshal(task, p,
- task->tk_flags & RPC_CALL_REALUID);
+ return cred->cr_ops->crmarshal(task, p);
}
u32 *
@@ -357,7 +339,7 @@ rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp,
struct rpc_cred *cred = task->tk_msg.rpc_cred;
dprintk("RPC: %4d using %s cred %p to wrap rpc data\n",
- task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
+ task->tk_pid, cred->cr_ops->cr_name, cred);
if (cred->cr_ops->crwrap_req)
return cred->cr_ops->crwrap_req(task, encode, rqstp, data, obj);
/* By default, we encode the arguments normally. */
@@ -371,7 +353,7 @@ rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp,
struct rpc_cred *cred = task->tk_msg.rpc_cred;
dprintk("RPC: %4d using %s cred %p to unwrap rpc data\n",
- task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
+ task->tk_pid, cred->cr_ops->cr_name, cred);
if (cred->cr_ops->crunwrap_resp)
return cred->cr_ops->crunwrap_resp(task, decode, rqstp,
data, obj);
@@ -384,11 +366,14 @@ rpcauth_refreshcred(struct rpc_task *task)
{
struct rpc_auth *auth = task->tk_auth;
struct rpc_cred *cred = task->tk_msg.rpc_cred;
+ int err;
dprintk("RPC: %4d refreshing %s cred %p\n",
task->tk_pid, auth->au_ops->au_name, cred);
- task->tk_status = cred->cr_ops->crrefresh(task);
- return task->tk_status;
+ err = cred->cr_ops->crrefresh(task);
+ if (err < 0)
+ task->tk_status = err;
+ return err;
}
void
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 62960a5603e8..a33b627cbef4 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -85,7 +85,9 @@ static DEFINE_RWLOCK(gss_ctx_lock);
struct gss_auth {
struct rpc_auth rpc_auth;
struct gss_api_mech *mech;
+ enum rpc_gss_svc service;
struct list_head upcalls;
+ struct rpc_clnt *client;
struct dentry *dentry;
char path[48];
spinlock_t lock;
@@ -175,42 +177,34 @@ gss_cred_is_uptodate_ctx(struct rpc_cred *cred)
return res;
}
-static inline int
-simple_get_bytes(char **ptr, const char *end, void *res, int len)
+static const void *
+simple_get_bytes(const void *p, const void *end, void *res, size_t len)
{
- char *p, *q;
- p = *ptr;
- q = p + len;
- if (q > end || q < p)
- return -1;
+ const void *q = (const void *)((const char *)p + len);
+ if (unlikely(q > end || q < p))
+ return ERR_PTR(-EFAULT);
memcpy(res, p, len);
- *ptr = q;
- return 0;
-}
-
-static inline int
-simple_get_netobj(char **ptr, const char *end, struct xdr_netobj *res)
-{
- char *p, *q;
- p = *ptr;
- if (simple_get_bytes(&p, end, &res->len, sizeof(res->len)))
- return -1;
- q = p + res->len;
- if (q > end || q < p)
- return -1;
- res->data = p;
- *ptr = q;
- return 0;
+ return q;
}
-static int
-dup_netobj(struct xdr_netobj *source, struct xdr_netobj *dest)
+static inline const void *
+simple_get_netobj(const void *p, const void *end, struct xdr_netobj *dest)
{
- dest->len = source->len;
- if (!(dest->data = kmalloc(dest->len, GFP_KERNEL)))
- return -1;
- memcpy(dest->data, source->data, dest->len);
- return 0;
+ const void *q;
+ unsigned int len;
+
+ p = simple_get_bytes(p, end, &len, sizeof(len));
+ if (IS_ERR(p))
+ return p;
+ q = (const void *)((const char *)p + len);
+ if (unlikely(q > end || q < p))
+ return ERR_PTR(-EFAULT);
+ dest->data = kmalloc(len, GFP_KERNEL);
+ if (unlikely(dest->data == NULL))
+ return ERR_PTR(-ENOMEM);
+ dest->len = len;
+ memcpy(dest->data, p, len);
+ return q;
}
static struct gss_cl_ctx *
@@ -226,74 +220,84 @@ gss_cred_get_ctx(struct rpc_cred *cred)
return ctx;
}
-static int
-gss_parse_init_downcall(struct gss_api_mech *gm, struct xdr_netobj *buf,
- struct gss_cl_ctx **gc, uid_t *uid, int *gss_err)
+static struct gss_cl_ctx *
+gss_alloc_context(void)
{
- char *end = buf->data + buf->len;
- char *p = buf->data;
struct gss_cl_ctx *ctx;
- struct xdr_netobj tmp_buf;
+
+ ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+ if (ctx != NULL) {
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->gc_proc = RPC_GSS_PROC_DATA;
+ ctx->gc_seq = 1; /* NetApp 6.4R1 doesn't accept seq. no. 0 */
+ spin_lock_init(&ctx->gc_seq_lock);
+ atomic_set(&ctx->count,1);
+ }
+ return ctx;
+}
+
+#define GSSD_MIN_TIMEOUT (60 * 60)
+static const void *
+gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct gss_api_mech *gm)
+{
+ const void *q;
+ unsigned int seclen;
unsigned int timeout;
- int err = -EIO;
+ u32 window_size;
+ int ret;
- if (!(ctx = kmalloc(sizeof(*ctx), GFP_KERNEL))) {
- err = -ENOMEM;
+ /* First unsigned int gives the lifetime (in seconds) of the cred */
+ p = simple_get_bytes(p, end, &timeout, sizeof(timeout));
+ if (IS_ERR(p))
goto err;
- }
- ctx->gc_proc = RPC_GSS_PROC_DATA;
- ctx->gc_seq = 1; /* NetApp 6.4R1 doesn't accept seq. no. 0 */
- spin_lock_init(&ctx->gc_seq_lock);
- atomic_set(&ctx->count,1);
-
- if (simple_get_bytes(&p, end, uid, sizeof(*uid)))
- goto err_free_ctx;
- /* FIXME: discarded timeout for now */
- if (simple_get_bytes(&p, end, &timeout, sizeof(timeout)))
- goto err_free_ctx;
- *gss_err = 0;
- if (simple_get_bytes(&p, end, &ctx->gc_win, sizeof(ctx->gc_win)))
- goto err_free_ctx;
+ if (timeout == 0)
+ timeout = GSSD_MIN_TIMEOUT;
+ ctx->gc_expiry = jiffies + (unsigned long)timeout * HZ * 3 / 4;
+ /* Sequence number window. Determines the maximum number of simultaneous requests */
+ p = simple_get_bytes(p, end, &window_size, sizeof(window_size));
+ if (IS_ERR(p))
+ goto err;
+ ctx->gc_win = window_size;
/* gssd signals an error by passing ctx->gc_win = 0: */
- if (!ctx->gc_win) {
- /* in which case the next int is an error code: */
- if (simple_get_bytes(&p, end, gss_err, sizeof(*gss_err)))
- goto err_free_ctx;
- err = 0;
- goto err_free_ctx;
+ if (ctx->gc_win == 0) {
+ /* in which case, p points to an error code which we ignore */
+ p = ERR_PTR(-EACCES);
+ goto err;
}
- if (simple_get_netobj(&p, end, &tmp_buf))
- goto err_free_ctx;
- if (dup_netobj(&tmp_buf, &ctx->gc_wire_ctx)) {
- err = -ENOMEM;
- goto err_free_ctx;
+ /* copy the opaque wire context */
+ p = simple_get_netobj(p, end, &ctx->gc_wire_ctx);
+ if (IS_ERR(p))
+ goto err;
+ /* import the opaque security context */
+ p = simple_get_bytes(p, end, &seclen, sizeof(seclen));
+ if (IS_ERR(p))
+ goto err;
+ q = (const void *)((const char *)p + seclen);
+ if (unlikely(q > end || q < p)) {
+ p = ERR_PTR(-EFAULT);
+ goto err;
}
- if (simple_get_netobj(&p, end, &tmp_buf))
- goto err_free_wire_ctx;
- if (p != end)
- goto err_free_wire_ctx;
- if (gss_import_sec_context(&tmp_buf, gm, &ctx->gc_gss_ctx))
- goto err_free_wire_ctx;
- *gc = ctx;
- return 0;
-err_free_wire_ctx:
- kfree(ctx->gc_wire_ctx.data);
-err_free_ctx:
- kfree(ctx);
+ ret = gss_import_sec_context(p, seclen, gm, &ctx->gc_gss_ctx);
+ if (ret < 0) {
+ p = ERR_PTR(ret);
+ goto err;
+ }
+ return q;
err:
- *gc = NULL;
- dprintk("RPC: gss_parse_init_downcall returning %d\n", err);
- return err;
+ dprintk("RPC: gss_fill_context returning %ld\n", -PTR_ERR(p));
+ return p;
}
struct gss_upcall_msg {
+ atomic_t count;
+ uid_t uid;
struct rpc_pipe_msg msg;
struct list_head list;
struct gss_auth *auth;
- struct rpc_wait_queue waitq;
- uid_t uid;
- atomic_t count;
+ struct rpc_wait_queue rpc_waitqueue;
+ wait_queue_head_t waitqueue;
+ struct gss_cl_ctx *ctx;
};
static void
@@ -302,6 +306,8 @@ gss_release_msg(struct gss_upcall_msg *gss_msg)
if (!atomic_dec_and_test(&gss_msg->count))
return;
BUG_ON(!list_empty(&gss_msg->list));
+ if (gss_msg->ctx != NULL)
+ gss_put_ctx(gss_msg->ctx);
kfree(gss_msg);
}
@@ -320,16 +326,34 @@ __gss_find_upcall(struct gss_auth *gss_auth, uid_t uid)
return NULL;
}
+/* Try to add a upcall to the pipefs queue.
+ * If an upcall owned by our uid already exists, then we return a reference
+ * to that upcall instead of adding the new upcall.
+ */
+static inline struct gss_upcall_msg *
+gss_add_msg(struct gss_auth *gss_auth, struct gss_upcall_msg *gss_msg)
+{
+ struct gss_upcall_msg *old;
+
+ spin_lock(&gss_auth->lock);
+ old = __gss_find_upcall(gss_auth, gss_msg->uid);
+ if (old == NULL) {
+ atomic_inc(&gss_msg->count);
+ list_add(&gss_msg->list, &gss_auth->upcalls);
+ } else
+ gss_msg = old;
+ spin_unlock(&gss_auth->lock);
+ return gss_msg;
+}
+
static void
__gss_unhash_msg(struct gss_upcall_msg *gss_msg)
{
if (list_empty(&gss_msg->list))
return;
list_del_init(&gss_msg->list);
- if (gss_msg->msg.errno < 0)
- rpc_wake_up_status(&gss_msg->waitq, gss_msg->msg.errno);
- else
- rpc_wake_up(&gss_msg->waitq);
+ rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
+ wake_up_all(&gss_msg->waitqueue);
atomic_dec(&gss_msg->count);
}
@@ -343,76 +367,139 @@ gss_unhash_msg(struct gss_upcall_msg *gss_msg)
spin_unlock(&gss_auth->lock);
}
-static int
-gss_upcall(struct rpc_clnt *clnt, struct rpc_task *task, struct rpc_cred *cred)
+static void
+gss_upcall_callback(struct rpc_task *task)
{
- struct gss_auth *gss_auth = container_of(clnt->cl_auth,
- struct gss_auth, rpc_auth);
- struct gss_upcall_msg *gss_msg, *gss_new = NULL;
- struct rpc_pipe_msg *msg;
- struct dentry *dentry = gss_auth->dentry;
- uid_t uid = cred->cr_uid;
- int res = 0;
+ struct gss_cred *gss_cred = container_of(task->tk_msg.rpc_cred,
+ struct gss_cred, gc_base);
+ struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall;
- dprintk("RPC: %4u gss_upcall for uid %u\n", task->tk_pid, uid);
+ BUG_ON(gss_msg == NULL);
+ if (gss_msg->ctx)
+ gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_get_ctx(gss_msg->ctx));
+ else
+ task->tk_status = gss_msg->msg.errno;
+ spin_lock(&gss_msg->auth->lock);
+ gss_cred->gc_upcall = NULL;
+ rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
+ spin_unlock(&gss_msg->auth->lock);
+ gss_release_msg(gss_msg);
+}
-retry:
- spin_lock(&gss_auth->lock);
- gss_msg = __gss_find_upcall(gss_auth, uid);
- if (gss_msg)
- goto out_sleep;
- if (gss_new == NULL) {
- spin_unlock(&gss_auth->lock);
- gss_new = kmalloc(sizeof(*gss_new), GFP_KERNEL);
- if (!gss_new) {
- dprintk("RPC: %4u gss_upcall -ENOMEM\n", task->tk_pid);
- return -ENOMEM;
+static inline struct gss_upcall_msg *
+gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid)
+{
+ struct gss_upcall_msg *gss_msg;
+
+ gss_msg = kmalloc(sizeof(*gss_msg), GFP_KERNEL);
+ if (gss_msg != NULL) {
+ memset(gss_msg, 0, sizeof(*gss_msg));
+ INIT_LIST_HEAD(&gss_msg->list);
+ rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
+ init_waitqueue_head(&gss_msg->waitqueue);
+ atomic_set(&gss_msg->count, 1);
+ gss_msg->msg.data = &gss_msg->uid;
+ gss_msg->msg.len = sizeof(gss_msg->uid);
+ gss_msg->uid = uid;
+ gss_msg->auth = gss_auth;
+ }
+ return gss_msg;
+}
+
+static struct gss_upcall_msg *
+gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cred *cred)
+{
+ struct gss_upcall_msg *gss_new, *gss_msg;
+
+ gss_new = gss_alloc_msg(gss_auth, cred->cr_uid);
+ if (gss_new == NULL)
+ return ERR_PTR(-ENOMEM);
+ gss_msg = gss_add_msg(gss_auth, gss_new);
+ if (gss_msg == gss_new) {
+ int res = rpc_queue_upcall(gss_auth->dentry->d_inode, &gss_new->msg);
+ if (res) {
+ gss_unhash_msg(gss_new);
+ gss_msg = ERR_PTR(res);
}
- goto retry;
+ } else
+ gss_release_msg(gss_new);
+ return gss_msg;
+}
+
+static inline int
+gss_refresh_upcall(struct rpc_task *task)
+{
+ struct rpc_cred *cred = task->tk_msg.rpc_cred;
+ struct gss_auth *gss_auth = container_of(task->tk_client->cl_auth,
+ struct gss_auth, rpc_auth);
+ struct gss_cred *gss_cred = container_of(cred,
+ struct gss_cred, gc_base);
+ struct gss_upcall_msg *gss_msg;
+ int err = 0;
+
+ dprintk("RPC: %4u gss_refresh_upcall for uid %u\n", task->tk_pid, cred->cr_uid);
+ gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred);
+ if (IS_ERR(gss_msg)) {
+ err = PTR_ERR(gss_msg);
+ goto out;
}
- gss_msg = gss_new;
- memset(gss_new, 0, sizeof(*gss_new));
- INIT_LIST_HEAD(&gss_new->list);
- rpc_init_wait_queue(&gss_new->waitq, "RPCSEC_GSS upcall waitq");
- atomic_set(&gss_new->count, 2);
- msg = &gss_new->msg;
- msg->data = &gss_new->uid;
- msg->len = sizeof(gss_new->uid);
- gss_new->uid = uid;
- gss_new->auth = gss_auth;
- list_add(&gss_new->list, &gss_auth->upcalls);
- gss_new = NULL;
- /* Has someone updated the credential behind our back? */
- if (!gss_cred_is_uptodate_ctx(cred)) {
- /* No, so do upcall and sleep */
+ spin_lock(&gss_auth->lock);
+ if (gss_cred->gc_upcall != NULL)
+ rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL, NULL);
+ else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) {
task->tk_timeout = 0;
- rpc_sleep_on(&gss_msg->waitq, task, NULL, NULL);
- spin_unlock(&gss_auth->lock);
- res = rpc_queue_upcall(dentry->d_inode, msg);
- if (res)
- gss_unhash_msg(gss_msg);
- } else {
- /* Yes, so cancel upcall */
- __gss_unhash_msg(gss_msg);
+ gss_cred->gc_upcall = gss_msg;
+ /* gss_upcall_callback will release the reference to gss_upcall_msg */
+ atomic_inc(&gss_msg->count);
+ rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback, NULL);
+ } else
+ err = gss_msg->msg.errno;
+ spin_unlock(&gss_auth->lock);
+ gss_release_msg(gss_msg);
+out:
+ dprintk("RPC: %4u gss_refresh_upcall for uid %u result %d\n", task->tk_pid,
+ cred->cr_uid, err);
+ return err;
+}
+
+static inline int
+gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
+{
+ struct rpc_cred *cred = &gss_cred->gc_base;
+ struct gss_upcall_msg *gss_msg;
+ DEFINE_WAIT(wait);
+ int err = 0;
+
+ dprintk("RPC: gss_upcall for uid %u\n", cred->cr_uid);
+ gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred);
+ if (IS_ERR(gss_msg)) {
+ err = PTR_ERR(gss_msg);
+ goto out;
+ }
+ for (;;) {
+ prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_INTERRUPTIBLE);
+ spin_lock(&gss_auth->lock);
+ if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) {
+ spin_unlock(&gss_auth->lock);
+ break;
+ }
spin_unlock(&gss_auth->lock);
+ if (signalled()) {
+ err = -ERESTARTSYS;
+ goto out_intr;
+ }
+ schedule();
}
+ if (gss_msg->ctx)
+ gss_cred_set_ctx(cred, gss_get_ctx(gss_msg->ctx));
+ else
+ err = gss_msg->msg.errno;
+out_intr:
+ finish_wait(&gss_msg->waitqueue, &wait);
gss_release_msg(gss_msg);
- dprintk("RPC: %4u gss_upcall for uid %u result %d\n", task->tk_pid,
- uid, res);
- return res;
-out_sleep:
- task->tk_timeout = 0;
- rpc_sleep_on(&gss_msg->waitq, task, NULL, NULL);
- spin_unlock(&gss_auth->lock);
- dprintk("RPC: %4u gss_upcall sleeping\n", task->tk_pid);
- if (gss_new)
- kfree(gss_new);
- /* Note: we drop the reference here: we are automatically removed
- * from the queue when we're woken up, and we should in any case
- * have no further responsabilities w.r.t. the upcall.
- */
- gss_release_msg(gss_msg);
- return 0;
+out:
+ dprintk("RPC: gss_create_upcall for uid %u result %d\n", cred->cr_uid, err);
+ return err;
}
static ssize_t
@@ -441,68 +528,75 @@ gss_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg,
static ssize_t
gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
{
- struct xdr_netobj obj = {
- .len = mlen,
- };
- struct inode *inode = filp->f_dentry->d_inode;
- struct rpc_inode *rpci = RPC_I(inode);
+ const void *p, *end;
+ void *buf;
struct rpc_clnt *clnt;
- struct rpc_auth *auth;
struct gss_auth *gss_auth;
- struct gss_api_mech *mech;
- struct auth_cred acred = { 0 };
struct rpc_cred *cred;
struct gss_upcall_msg *gss_msg;
- struct gss_cl_ctx *ctx = NULL;
- ssize_t left;
- int err;
- int gss_err;
+ struct gss_cl_ctx *ctx;
+ uid_t uid;
+ int err = -EFBIG;
if (mlen > MSG_BUF_MAXSIZE)
- return -EFBIG;
- obj.data = kmalloc(mlen, GFP_KERNEL);
- if (!obj.data)
- return -ENOMEM;
- left = copy_from_user(obj.data, src, mlen);
- if (left) {
- err = -EFAULT;
goto out;
- }
- clnt = rpci->private;
- atomic_inc(&clnt->cl_users);
- auth = clnt->cl_auth;
- gss_auth = container_of(auth, struct gss_auth, rpc_auth);
- mech = gss_auth->mech;
- err = gss_parse_init_downcall(mech, &obj, &ctx, &acred.uid, &gss_err);
- if (err)
+ err = -ENOMEM;
+ buf = kmalloc(mlen, GFP_KERNEL);
+ if (!buf)
+ goto out;
+
+ clnt = RPC_I(filp->f_dentry->d_inode)->private;
+ err = -EFAULT;
+ if (copy_from_user(buf, src, mlen))
goto err;
- cred = rpcauth_lookup_credcache(auth, &acred, 0);
- if (!cred)
+
+ end = (const void *)((char *)buf + mlen);
+ p = simple_get_bytes(buf, end, &uid, sizeof(uid));
+ if (IS_ERR(p)) {
+ err = PTR_ERR(p);
goto err;
- if (gss_err)
- cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
- else
- gss_cred_set_ctx(cred, ctx);
+ }
+
+ err = -ENOMEM;
+ ctx = gss_alloc_context();
+ if (ctx == NULL)
+ goto err;
+ err = 0;
+ gss_auth = container_of(clnt->cl_auth, struct gss_auth, rpc_auth);
+ p = gss_fill_context(p, end, ctx, gss_auth->mech);
+ if (IS_ERR(p)) {
+ err = PTR_ERR(p);
+ if (err != -EACCES)
+ goto err_put_ctx;
+ }
spin_lock(&gss_auth->lock);
- gss_msg = __gss_find_upcall(gss_auth, acred.uid);
+ gss_msg = __gss_find_upcall(gss_auth, uid);
if (gss_msg) {
- if (gss_err)
- gss_msg->msg.errno = -EACCES;
+ if (err == 0 && gss_msg->ctx == NULL)
+ gss_msg->ctx = gss_get_ctx(ctx);
+ gss_msg->msg.errno = err;
__gss_unhash_msg(gss_msg);
spin_unlock(&gss_auth->lock);
gss_release_msg(gss_msg);
- } else
+ } else {
+ struct auth_cred acred = { .uid = uid };
spin_unlock(&gss_auth->lock);
- rpc_release_client(clnt);
- kfree(obj.data);
+ cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, 0);
+ if (IS_ERR(cred)) {
+ err = PTR_ERR(cred);
+ goto err_put_ctx;
+ }
+ gss_cred_set_ctx(cred, gss_get_ctx(ctx));
+ }
+ gss_put_ctx(ctx);
+ kfree(buf);
dprintk("RPC: gss_pipe_downcall returning length %Zu\n", mlen);
return mlen;
+err_put_ctx:
+ gss_put_ctx(ctx);
err:
- if (ctx)
- gss_destroy_ctx(ctx);
- rpc_release_client(clnt);
+ kfree(buf);
out:
- kfree(obj.data);
dprintk("RPC: gss_pipe_downcall returning %d\n", err);
return err;
}
@@ -569,24 +663,32 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
dprintk("RPC: creating GSS authenticator for client %p\n",clnt);
+ if (!try_module_get(THIS_MODULE))
+ return NULL;
if (!(gss_auth = kmalloc(sizeof(*gss_auth), GFP_KERNEL)))
goto out_dec;
+ gss_auth->client = clnt;
gss_auth->mech = gss_mech_get_by_pseudoflavor(flavor);
if (!gss_auth->mech) {
printk(KERN_WARNING "%s: Pseudoflavor %d not found!",
__FUNCTION__, flavor);
goto err_free;
}
+ gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor);
+ /* FIXME: Will go away once privacy support is merged in */
+ if (gss_auth->service == RPC_GSS_SVC_PRIVACY)
+ gss_auth->service = RPC_GSS_SVC_INTEGRITY;
INIT_LIST_HEAD(&gss_auth->upcalls);
spin_lock_init(&gss_auth->lock);
auth = &gss_auth->rpc_auth;
auth->au_cslack = GSS_CRED_SLACK >> 2;
auth->au_rslack = GSS_VERF_SLACK >> 2;
- auth->au_expire = GSS_CRED_EXPIRE;
auth->au_ops = &authgss_ops;
auth->au_flavor = flavor;
+ atomic_set(&auth->au_count, 1);
- rpcauth_init_credcache(auth);
+ if (rpcauth_init_credcache(auth, GSS_CRED_EXPIRE) < 0)
+ goto err_put_mech;
snprintf(gss_auth->path, sizeof(gss_auth->path), "%s/%s",
clnt->cl_pathname,
@@ -601,6 +703,7 @@ err_put_mech:
err_free:
kfree(gss_auth);
out_dec:
+ module_put(THIS_MODULE);
return NULL;
}
@@ -617,6 +720,8 @@ gss_destroy(struct rpc_auth *auth)
gss_mech_put(gss_auth->mech);
rpcauth_free_credcache(auth);
+ kfree(gss_auth);
+ module_put(THIS_MODULE);
}
/* gss_destroy_cred (and gss_destroy_ctx) are used to clean up after failure
@@ -630,19 +735,14 @@ gss_destroy_ctx(struct gss_cl_ctx *ctx)
if (ctx->gc_gss_ctx)
gss_delete_sec_context(&ctx->gc_gss_ctx);
- if (ctx->gc_wire_ctx.len > 0) {
- kfree(ctx->gc_wire_ctx.data);
- ctx->gc_wire_ctx.len = 0;
- }
-
+ kfree(ctx->gc_wire_ctx.data);
kfree(ctx);
-
}
static void
gss_destroy_cred(struct rpc_cred *rc)
{
- struct gss_cred *cred = (struct gss_cred *)rc;
+ struct gss_cred *cred = container_of(rc, struct gss_cred, gc_base);
dprintk("RPC: gss_destroy_cred \n");
@@ -651,10 +751,21 @@ gss_destroy_cred(struct rpc_cred *rc)
kfree(cred);
}
+/*
+ * Lookup RPCSEC_GSS cred for the current process
+ */
+static struct rpc_cred *
+gss_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags)
+{
+ return rpcauth_lookup_credcache(auth, acred, taskflags);
+}
+
static struct rpc_cred *
gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags)
{
+ struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth);
struct gss_cred *cred = NULL;
+ int err = -ENOMEM;
dprintk("RPC: gss_create_cred for uid %d, flavor %d\n",
acred->uid, auth->au_flavor);
@@ -663,7 +774,7 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags)
goto out_err;
memset(cred, 0, sizeof(*cred));
- atomic_set(&cred->gc_count, 0);
+ atomic_set(&cred->gc_count, 1);
cred->gc_uid = acred->uid;
/*
* Note: in order to force a call to call_refresh(), we deliberately
@@ -671,19 +782,27 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags)
*/
cred->gc_flags = 0;
cred->gc_base.cr_ops = &gss_credops;
- cred->gc_flavor = auth->au_flavor;
+ cred->gc_service = gss_auth->service;
+ err = gss_create_upcall(gss_auth, cred);
+ if (err < 0)
+ goto out_err;
- return (struct rpc_cred *) cred;
+ return &cred->gc_base;
out_err:
- dprintk("RPC: gss_create_cred failed\n");
- if (cred) gss_destroy_cred((struct rpc_cred *)cred);
- return NULL;
+ dprintk("RPC: gss_create_cred failed with error %d\n", err);
+ if (cred) gss_destroy_cred(&cred->gc_base);
+ return ERR_PTR(err);
}
static int
gss_match(struct auth_cred *acred, struct rpc_cred *rc, int taskflags)
{
+ struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base);
+
+ /* Don't match with creds that have expired. */
+ if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry))
+ return 0;
return (rc->cr_uid == acred->uid);
}
@@ -692,7 +811,7 @@ gss_match(struct auth_cred *acred, struct rpc_cred *rc, int taskflags)
* Maybe we should keep a cached credential for performance reasons.
*/
static u32 *
-gss_marshal(struct rpc_task *task, u32 *p, int ruid)
+gss_marshal(struct rpc_task *task, u32 *p)
{
struct rpc_cred *cred = task->tk_msg.rpc_cred;
struct gss_cred *gss_cred = container_of(cred, struct gss_cred,
@@ -704,20 +823,12 @@ gss_marshal(struct rpc_task *task, u32 *p, int ruid)
struct xdr_netobj mic;
struct kvec iov;
struct xdr_buf verf_buf;
- u32 service;
dprintk("RPC: %4u gss_marshal\n", task->tk_pid);
*p++ = htonl(RPC_AUTH_GSS);
cred_len = p++;
- service = gss_pseudoflavor_to_service(ctx->gc_gss_ctx->mech_type,
- gss_cred->gc_flavor);
- if (service == 0) {
- dprintk("RPC: %4u Bad pseudoflavor %d in gss_marshal\n",
- task->tk_pid, gss_cred->gc_flavor);
- goto out_put_ctx;
- }
spin_lock(&ctx->gc_seq_lock);
req->rq_seqno = ctx->gc_seq++;
spin_unlock(&ctx->gc_seq_lock);
@@ -725,7 +836,7 @@ gss_marshal(struct rpc_task *task, u32 *p, int ruid)
*p++ = htonl((u32) RPC_GSS_VERSION);
*p++ = htonl((u32) ctx->gc_proc);
*p++ = htonl((u32) req->rq_seqno);
- *p++ = htonl((u32) service);
+ *p++ = htonl((u32) gss_cred->gc_service);
p = xdr_encode_netobj(p, &ctx->gc_wire_ctx);
*cred_len = htonl((p - (cred_len + 1)) << 2);
@@ -765,11 +876,9 @@ out_put_ctx:
static int
gss_refresh(struct rpc_task *task)
{
- struct rpc_clnt *clnt = task->tk_client;
- struct rpc_cred *cred = task->tk_msg.rpc_cred;
- if (!gss_cred_is_uptodate_ctx(cred))
- return gss_upcall(clnt, task, cred);
+ if (!gss_cred_is_uptodate_ctx(task->tk_msg.rpc_cred))
+ return gss_refresh_upcall(task);
return 0;
}
@@ -785,7 +894,6 @@ gss_validate(struct rpc_task *task, u32 *p)
struct xdr_buf verf_buf;
struct xdr_netobj mic;
u32 flav,len;
- u32 service;
u32 maj_stat;
dprintk("RPC: %4u gss_validate\n", task->tk_pid);
@@ -807,9 +915,7 @@ gss_validate(struct rpc_task *task, u32 *p)
cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
if (maj_stat)
goto out_bad;
- service = gss_pseudoflavor_to_service(ctx->gc_gss_ctx->mech_type,
- gss_cred->gc_flavor);
- switch (service) {
+ switch (gss_cred->gc_service) {
case RPC_GSS_SVC_NONE:
/* verifier data, flavor, length: */
task->tk_auth->au_rslack = XDR_QUADLEN(len) + 2;
@@ -818,7 +924,7 @@ gss_validate(struct rpc_task *task, u32 *p)
/* verifier data, flavor, length, length, sequence number: */
task->tk_auth->au_rslack = XDR_QUADLEN(len) + 4;
break;
- default:
+ case RPC_GSS_SVC_PRIVACY:
goto out_bad;
}
gss_put_ctx(ctx);
@@ -889,7 +995,6 @@ gss_wrap_req(struct rpc_task *task,
gc_base);
struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
int status = -EIO;
- u32 service;
dprintk("RPC: %4u gss_wrap_req\n", task->tk_pid);
if (ctx->gc_proc != RPC_GSS_PROC_DATA) {
@@ -899,19 +1004,16 @@ gss_wrap_req(struct rpc_task *task,
status = encode(rqstp, p, obj);
goto out;
}
- service = gss_pseudoflavor_to_service(ctx->gc_gss_ctx->mech_type,
- gss_cred->gc_flavor);
- switch (service) {
+ switch (gss_cred->gc_service) {
case RPC_GSS_SVC_NONE:
status = encode(rqstp, p, obj);
- goto out;
+ break;
case RPC_GSS_SVC_INTEGRITY:
status = gss_wrap_req_integ(cred, ctx, encode,
rqstp, p, obj);
- goto out;
- case RPC_GSS_SVC_PRIVACY:
- default:
- goto out;
+ break;
+ case RPC_GSS_SVC_PRIVACY:
+ break;
}
out:
gss_put_ctx(ctx);
@@ -966,23 +1068,19 @@ gss_unwrap_resp(struct rpc_task *task,
gc_base);
struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
int status = -EIO;
- u32 service;
if (ctx->gc_proc != RPC_GSS_PROC_DATA)
goto out_decode;
- service = gss_pseudoflavor_to_service(ctx->gc_gss_ctx->mech_type,
- gss_cred->gc_flavor);
- switch (service) {
+ switch (gss_cred->gc_service) {
case RPC_GSS_SVC_NONE:
- goto out_decode;
+ break;
case RPC_GSS_SVC_INTEGRITY:
status = gss_unwrap_resp_integ(cred, ctx, rqstp, &p);
if (status)
goto out;
break;
- case RPC_GSS_SVC_PRIVACY:
- default:
- goto out;
+ case RPC_GSS_SVC_PRIVACY:
+ break;
}
out_decode:
status = decode(rqstp, p, obj);
@@ -1001,10 +1099,12 @@ static struct rpc_authops authgss_ops = {
#endif
.create = gss_create,
.destroy = gss_destroy,
+ .lookup_cred = gss_lookup_cred,
.crcreate = gss_create_cred
};
static struct rpc_credops gss_credops = {
+ .cr_name = "AUTH_GSS",
.crdestroy = gss_destroy_cred,
.crmatch = gss_match,
.crmarshal = gss_marshal,
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index a734dd869518..cf726510df8e 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -48,46 +48,48 @@
# define RPCDBG_FACILITY RPCDBG_AUTH
#endif
-static inline int
-get_bytes(char **ptr, const char *end, void *res, int len)
+static const void *
+simple_get_bytes(const void *p, const void *end, void *res, int len)
{
- char *p, *q;
- p = *ptr;
- q = p + len;
- if (q > end || q < p)
- return -1;
+ const void *q = (const void *)((const char *)p + len);
+ if (unlikely(q > end || q < p))
+ return ERR_PTR(-EFAULT);
memcpy(res, p, len);
- *ptr = q;
- return 0;
+ return q;
}
-static inline int
-get_netobj(char **ptr, const char *end, struct xdr_netobj *res)
+static const void *
+simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)
{
- char *p, *q;
- p = *ptr;
- if (get_bytes(&p, end, &res->len, sizeof(res->len)))
- return -1;
- q = p + res->len;
- if (q > end || q < p)
- return -1;
- if (!(res->data = kmalloc(res->len, GFP_KERNEL)))
- return -1;
- memcpy(res->data, p, res->len);
- *ptr = q;
- return 0;
+ const void *q;
+ unsigned int len;
+
+ p = simple_get_bytes(p, end, &len, sizeof(len));
+ if (IS_ERR(p))
+ return p;
+ q = (const void *)((const char *)p + len);
+ if (unlikely(q > end || q < p))
+ return ERR_PTR(-EFAULT);
+ res->data = kmalloc(len, GFP_KERNEL);
+ if (unlikely(res->data == NULL))
+ return ERR_PTR(-ENOMEM);
+ memcpy(res->data, p, len);
+ res->len = len;
+ return q;
}
-static inline int
-get_key(char **p, char *end, struct crypto_tfm **res)
+static inline const void *
+get_key(const void *p, const void *end, struct crypto_tfm **res)
{
struct xdr_netobj key;
int alg, alg_mode;
char *alg_name;
- if (get_bytes(p, end, &alg, sizeof(alg)))
+ p = simple_get_bytes(p, end, &alg, sizeof(alg));
+ if (IS_ERR(p))
goto out_err;
- if ((get_netobj(p, end, &key)))
+ p = simple_get_netobj(p, end, &key);
+ if (IS_ERR(p))
goto out_err;
switch (alg) {
@@ -105,50 +107,63 @@ get_key(char **p, char *end, struct crypto_tfm **res)
goto out_err_free_tfm;
kfree(key.data);
- return 0;
+ return p;
out_err_free_tfm:
crypto_free_tfm(*res);
out_err_free_key:
kfree(key.data);
+ p = ERR_PTR(-EINVAL);
out_err:
- return -1;
+ return p;
}
-static u32
-gss_import_sec_context_kerberos(struct xdr_netobj *inbuf,
+static int
+gss_import_sec_context_kerberos(const void *p,
+ size_t len,
struct gss_ctx *ctx_id)
{
- char *p = inbuf->data;
- char *end = inbuf->data + inbuf->len;
+ const void *end = (const void *)((const char *)p + len);
struct krb5_ctx *ctx;
if (!(ctx = kmalloc(sizeof(*ctx), GFP_KERNEL)))
goto out_err;
memset(ctx, 0, sizeof(*ctx));
- if (get_bytes(&p, end, &ctx->initiate, sizeof(ctx->initiate)))
+ p = simple_get_bytes(p, end, &ctx->initiate, sizeof(ctx->initiate));
+ if (IS_ERR(p))
goto out_err_free_ctx;
- if (get_bytes(&p, end, &ctx->seed_init, sizeof(ctx->seed_init)))
+ p = simple_get_bytes(p, end, &ctx->seed_init, sizeof(ctx->seed_init));
+ if (IS_ERR(p))
goto out_err_free_ctx;
- if (get_bytes(&p, end, ctx->seed, sizeof(ctx->seed)))
+ p = simple_get_bytes(p, end, ctx->seed, sizeof(ctx->seed));
+ if (IS_ERR(p))
goto out_err_free_ctx;
- if (get_bytes(&p, end, &ctx->signalg, sizeof(ctx->signalg)))
+ p = simple_get_bytes(p, end, &ctx->signalg, sizeof(ctx->signalg));
+ if (IS_ERR(p))
goto out_err_free_ctx;
- if (get_bytes(&p, end, &ctx->sealalg, sizeof(ctx->sealalg)))
+ p = simple_get_bytes(p, end, &ctx->sealalg, sizeof(ctx->sealalg));
+ if (IS_ERR(p))
goto out_err_free_ctx;
- if (get_bytes(&p, end, &ctx->endtime, sizeof(ctx->endtime)))
+ p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime));
+ if (IS_ERR(p))
goto out_err_free_ctx;
- if (get_bytes(&p, end, &ctx->seq_send, sizeof(ctx->seq_send)))
+ p = simple_get_bytes(p, end, &ctx->seq_send, sizeof(ctx->seq_send));
+ if (IS_ERR(p))
goto out_err_free_ctx;
- if (get_netobj(&p, end, &ctx->mech_used))
+ p = simple_get_netobj(p, end, &ctx->mech_used);
+ if (IS_ERR(p))
goto out_err_free_ctx;
- if (get_key(&p, end, &ctx->enc))
+ p = get_key(p, end, &ctx->enc);
+ if (IS_ERR(p))
goto out_err_free_mech;
- if (get_key(&p, end, &ctx->seq))
+ p = get_key(p, end, &ctx->seq);
+ if (IS_ERR(p))
goto out_err_free_key1;
- if (p != end)
+ if (p != end) {
+ p = ERR_PTR(-EFAULT);
goto out_err_free_key2;
+ }
ctx_id->internal_ctx_id = ctx;
dprintk("RPC: Succesfully imported new context.\n");
@@ -163,7 +178,7 @@ out_err_free_mech:
out_err_free_ctx:
kfree(ctx);
out_err:
- return GSS_S_FAILURE;
+ return PTR_ERR(p);
}
static void
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
index a0db9f5004f1..9dfb68377d69 100644
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -143,7 +143,7 @@ gss_mech_get(struct gss_api_mech *gm)
EXPORT_SYMBOL(gss_mech_get);
struct gss_api_mech *
-gss_mech_get_by_name(char *name)
+gss_mech_get_by_name(const char *name)
{
struct gss_api_mech *pos, *gm = NULL;
@@ -233,8 +233,8 @@ EXPORT_SYMBOL(gss_mech_put);
/* The mech could probably be determined from the token instead, but it's just
* as easy for now to pass it in. */
-u32
-gss_import_sec_context(struct xdr_netobj *input_token,
+int
+gss_import_sec_context(const void *input_token, size_t bufsize,
struct gss_api_mech *mech,
struct gss_ctx **ctx_id)
{
@@ -244,7 +244,7 @@ gss_import_sec_context(struct xdr_netobj *input_token,
(*ctx_id)->mech_type = gss_mech_get(mech);
return mech->gm_ops
- ->gss_import_sec_context(input_token, *ctx_id);
+ ->gss_import_sec_context(input_token, bufsize, *ctx_id);
}
/* gss_get_mic: compute a mic over message and return mic_token. */
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c
index fd213dc36093..dad05994c3eb 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_mech.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c
@@ -49,52 +49,51 @@
# define RPCDBG_FACILITY RPCDBG_AUTH
#endif
-static inline int
-get_bytes(char **ptr, const char *end, void *res, int len)
+static const void *
+simple_get_bytes(const void *p, const void *end, void *res, int len)
{
- char *p, *q;
- p = *ptr;
- q = p + len;
- if (q > end || q < p)
- return -1;
+ const void *q = (const void *)((const char *)p + len);
+ if (unlikely(q > end || q < p))
+ return ERR_PTR(-EFAULT);
memcpy(res, p, len);
- *ptr = q;
- return 0;
+ return q;
}
-static inline int
-get_netobj(char **ptr, const char *end, struct xdr_netobj *res)
+static const void *
+simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)
{
- char *p, *q;
- p = *ptr;
- if (get_bytes(&p, end, &res->len, sizeof(res->len)))
- return -1;
- q = p + res->len;
- if(res->len == 0)
- goto out_nocopy;
- if (q > end || q < p)
- return -1;
- if (!(res->data = kmalloc(res->len, GFP_KERNEL)))
- return -1;
- memcpy(res->data, p, res->len);
-out_nocopy:
- *ptr = q;
- return 0;
+ const void *q;
+ unsigned int len;
+ p = simple_get_bytes(p, end, &len, sizeof(len));
+ if (IS_ERR(p))
+ return p;
+ res->len = len;
+ if (len == 0) {
+ res->data = NULL;
+ return p;
+ }
+ q = (const void *)((const char *)p + len);
+ if (unlikely(q > end || q < p))
+ return ERR_PTR(-EFAULT);
+ res->data = kmalloc(len, GFP_KERNEL);
+ if (unlikely(res->data == NULL))
+ return ERR_PTR(-ENOMEM);
+ memcpy(res->data, p, len);
+ return q;
}
-static inline int
-get_key(char **p, char *end, struct crypto_tfm **res, int *resalg)
+static inline const void *
+get_key(const void *p, const void *end, struct crypto_tfm **res, int *resalg)
{
- struct xdr_netobj key = {
- .len = 0,
- .data = NULL,
- };
+ struct xdr_netobj key = { 0 };
int alg_mode,setkey = 0;
char *alg_name;
- if (get_bytes(p, end, resalg, sizeof(int)))
+ p = simple_get_bytes(p, end, resalg, sizeof(*resalg));
+ if (IS_ERR(p))
goto out_err;
- if ((get_netobj(p, end, &key)))
+ p = simple_get_netobj(p, end, &key);
+ if (IS_ERR(p))
goto out_err;
switch (*resalg) {
@@ -111,10 +110,6 @@ get_key(char **p, char *end, struct crypto_tfm **res, int *resalg)
alg_mode = 0;
setkey = 0;
break;
- case NID_cast5_cbc:
- dprintk("RPC: SPKM3 get_key: case cast5_cbc, UNSUPPORTED \n");
- goto out_err;
- break;
default:
dprintk("RPC: SPKM3 get_key: unsupported algorithm %d", *resalg);
goto out_err_free_key;
@@ -128,69 +123,81 @@ get_key(char **p, char *end, struct crypto_tfm **res, int *resalg)
if(key.len > 0)
kfree(key.data);
- return 0;
+ return p;
out_err_free_tfm:
crypto_free_tfm(*res);
out_err_free_key:
if(key.len > 0)
kfree(key.data);
+ p = ERR_PTR(-EINVAL);
out_err:
- return -1;
+ return p;
}
-static u32
-gss_import_sec_context_spkm3(struct xdr_netobj *inbuf,
+static int
+gss_import_sec_context_spkm3(const void *p, size_t len,
struct gss_ctx *ctx_id)
{
- char *p = inbuf->data;
- char *end = inbuf->data + inbuf->len;
+ const void *end = (const void *)((const char *)p + len);
struct spkm3_ctx *ctx;
if (!(ctx = kmalloc(sizeof(*ctx), GFP_KERNEL)))
goto out_err;
memset(ctx, 0, sizeof(*ctx));
- if (get_netobj(&p, end, &ctx->ctx_id))
+ p = simple_get_netobj(p, end, &ctx->ctx_id);
+ if (IS_ERR(p))
goto out_err_free_ctx;
- if (get_bytes(&p, end, &ctx->qop, sizeof(ctx->qop)))
+ p = simple_get_bytes(p, end, &ctx->qop, sizeof(ctx->qop));
+ if (IS_ERR(p))
goto out_err_free_ctx_id;
- if (get_netobj(&p, end, &ctx->mech_used))
+ p = simple_get_netobj(p, end, &ctx->mech_used);
+ if (IS_ERR(p))
goto out_err_free_mech;
- if (get_bytes(&p, end, &ctx->ret_flags, sizeof(ctx->ret_flags)))
+ p = simple_get_bytes(p, end, &ctx->ret_flags, sizeof(ctx->ret_flags));
+ if (IS_ERR(p))
goto out_err_free_mech;
- if (get_bytes(&p, end, &ctx->req_flags, sizeof(ctx->req_flags)))
+ p = simple_get_bytes(p, end, &ctx->req_flags, sizeof(ctx->req_flags));
+ if (IS_ERR(p))
goto out_err_free_mech;
- if (get_netobj(&p, end, &ctx->share_key))
+ p = simple_get_netobj(p, end, &ctx->share_key);
+ if (IS_ERR(p))
goto out_err_free_s_key;
- if (get_key(&p, end, &ctx->derived_conf_key, &ctx->conf_alg)) {
- dprintk("RPC: SPKM3 confidentiality key will be NULL\n");
- }
+ p = get_key(p, end, &ctx->derived_conf_key, &ctx->conf_alg);
+ if (IS_ERR(p))
+ goto out_err_free_s_key;
- if (get_key(&p, end, &ctx->derived_integ_key, &ctx->intg_alg)) {
- dprintk("RPC: SPKM3 integrity key will be NULL\n");
- }
+ p = get_key(p, end, &ctx->derived_integ_key, &ctx->intg_alg);
+ if (IS_ERR(p))
+ goto out_err_free_key1;
- if (get_bytes(&p, end, &ctx->owf_alg, sizeof(ctx->owf_alg)))
- goto out_err_free_s_key;
+ p = simple_get_bytes(p, end, &ctx->keyestb_alg, sizeof(ctx->keyestb_alg));
+ if (IS_ERR(p))
+ goto out_err_free_key2;
- if (get_bytes(&p, end, &ctx->owf_alg, sizeof(ctx->owf_alg)))
- goto out_err_free_s_key;
+ p = simple_get_bytes(p, end, &ctx->owf_alg, sizeof(ctx->owf_alg));
+ if (IS_ERR(p))
+ goto out_err_free_key2;
if (p != end)
- goto out_err_free_s_key;
+ goto out_err_free_key2;
ctx_id->internal_ctx_id = ctx;
dprintk("Succesfully imported new spkm context.\n");
return 0;
+out_err_free_key2:
+ crypto_free_tfm(ctx->derived_integ_key);
+out_err_free_key1:
+ crypto_free_tfm(ctx->derived_conf_key);
out_err_free_s_key:
kfree(ctx->share_key.data);
out_err_free_mech:
@@ -200,7 +207,7 @@ out_err_free_ctx_id:
out_err_free_ctx:
kfree(ctx);
out_err:
- return GSS_S_FAILURE;
+ return PTR_ERR(p);
}
static void
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index d806bafe106c..5c8fe3bfc494 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -381,7 +381,6 @@ static int rsc_parse(struct cache_detail *cd,
else {
int N, i;
struct gss_api_mech *gm;
- struct xdr_netobj tmp_buf;
/* gid */
if (get_int(&mesg, &rsci.cred.cr_gid))
@@ -420,9 +419,7 @@ static int rsc_parse(struct cache_detail *cd,
gss_mech_put(gm);
goto out;
}
- tmp_buf.len = len;
- tmp_buf.data = buf;
- if (gss_import_sec_context(&tmp_buf, gm, &rsci.mechctx)) {
+ if (gss_import_sec_context(buf, len, gm, &rsci.mechctx)) {
gss_mech_put(gm);
goto out;
}
diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c
index f112f63e3705..aa3dd1098f38 100644
--- a/net/sunrpc/auth_null.c
+++ b/net/sunrpc/auth_null.c
@@ -18,48 +18,29 @@
# define RPCDBG_FACILITY RPCDBG_AUTH
#endif
-static struct rpc_credops null_credops;
+static struct rpc_auth null_auth;
+static struct rpc_cred null_cred;
static struct rpc_auth *
nul_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
{
- struct rpc_auth *auth;
-
- dprintk("RPC: creating NULL authenticator for client %p\n", clnt);
- if (!(auth = (struct rpc_auth *) kmalloc(sizeof(*auth),GFP_KERNEL)))
- return NULL;
- auth->au_cslack = 4;
- auth->au_rslack = 2;
- auth->au_ops = &authnull_ops;
- auth->au_expire = 1800 * HZ;
- rpcauth_init_credcache(auth);
-
- return (struct rpc_auth *) auth;
+ atomic_inc(&null_auth.au_count);
+ return &null_auth;
}
static void
nul_destroy(struct rpc_auth *auth)
{
- dprintk("RPC: destroying NULL authenticator %p\n", auth);
- rpcauth_free_credcache(auth);
+ atomic_dec(&null_auth.au_count);
}
/*
- * Create NULL creds for current process
+ * Lookup NULL creds for current process
*/
static struct rpc_cred *
-nul_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
+nul_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
{
- struct rpc_cred *cred;
-
- if (!(cred = (struct rpc_cred *) kmalloc(sizeof(*cred),GFP_KERNEL)))
- return NULL;
- atomic_set(&cred->cr_count, 0);
- cred->cr_flags = RPCAUTH_CRED_UPTODATE;
- cred->cr_uid = acred->uid;
- cred->cr_ops = &null_credops;
-
- return cred;
+ return get_rpccred(&null_cred);
}
/*
@@ -68,7 +49,6 @@ nul_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
static void
nul_destroy_cred(struct rpc_cred *cred)
{
- kfree(cred);
}
/*
@@ -84,7 +64,7 @@ nul_match(struct auth_cred *acred, struct rpc_cred *cred, int taskflags)
* Marshal credential.
*/
static u32 *
-nul_marshal(struct rpc_task *task, u32 *p, int ruid)
+nul_marshal(struct rpc_task *task, u32 *p)
{
*p++ = htonl(RPC_AUTH_NULL);
*p++ = 0;
@@ -125,7 +105,7 @@ nul_validate(struct rpc_task *task, u32 *p)
return p;
}
-struct rpc_authops authnull_ops = {
+struct rpc_authops authnull_ops = {
.owner = THIS_MODULE,
.au_flavor = RPC_AUTH_NULL,
#ifdef RPC_DEBUG
@@ -133,14 +113,32 @@ struct rpc_authops authnull_ops = {
#endif
.create = nul_create,
.destroy = nul_destroy,
- .crcreate = nul_create_cred,
+ .lookup_cred = nul_lookup_cred,
+};
+
+static
+struct rpc_auth null_auth = {
+ .au_cslack = 4,
+ .au_rslack = 2,
+ .au_ops = &authnull_ops,
};
static
struct rpc_credops null_credops = {
+ .cr_name = "AUTH_NULL",
.crdestroy = nul_destroy_cred,
.crmatch = nul_match,
.crmarshal = nul_marshal,
.crrefresh = nul_refresh,
.crvalidate = nul_validate,
};
+
+static
+struct rpc_cred null_cred = {
+ .cr_ops = &null_credops,
+ .cr_count = ATOMIC_INIT(1),
+ .cr_flags = RPCAUTH_CRED_UPTODATE,
+#ifdef RPC_DEBUG
+ .cr_magic = RPCAUTH_CRED_MAGIC,
+#endif
+};
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c
index f49ed17fe3fb..4ff297a9b15b 100644
--- a/net/sunrpc/auth_unix.c
+++ b/net/sunrpc/auth_unix.c
@@ -19,8 +19,6 @@
struct unx_cred {
struct rpc_cred uc_base;
gid_t uc_gid;
- uid_t uc_puid; /* process uid */
- gid_t uc_pgid; /* process gid */
gid_t uc_gids[NFS_NGROUPS];
};
#define uc_uid uc_base.cr_uid
@@ -36,24 +34,17 @@ struct unx_cred {
# define RPCDBG_FACILITY RPCDBG_AUTH
#endif
+static struct rpc_auth unix_auth;
+static struct rpc_cred_cache unix_cred_cache;
static struct rpc_credops unix_credops;
static struct rpc_auth *
unx_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
{
- struct rpc_auth *auth;
-
dprintk("RPC: creating UNIX authenticator for client %p\n", clnt);
- if (!(auth = (struct rpc_auth *) kmalloc(sizeof(*auth), GFP_KERNEL)))
- return NULL;
- auth->au_cslack = UNX_WRITESLACK;
- auth->au_rslack = 2; /* assume AUTH_NULL verf */
- auth->au_expire = UNX_CRED_EXPIRE;
- auth->au_ops = &authunix_ops;
-
- rpcauth_init_credcache(auth);
-
- return auth;
+ if (atomic_inc_return(&unix_auth.au_count) == 0)
+ unix_cred_cache.nextgc = jiffies + (unix_cred_cache.expire >> 1);
+ return &unix_auth;
}
static void
@@ -63,6 +54,15 @@ unx_destroy(struct rpc_auth *auth)
rpcauth_free_credcache(auth);
}
+/*
+ * Lookup AUTH_UNIX creds for current process
+ */
+static struct rpc_cred *
+unx_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
+{
+ return rpcauth_lookup_credcache(auth, acred, flags);
+}
+
static struct rpc_cred *
unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
{
@@ -73,13 +73,13 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
acred->uid, acred->gid);
if (!(cred = (struct unx_cred *) kmalloc(sizeof(*cred), GFP_KERNEL)))
- return NULL;
+ return ERR_PTR(-ENOMEM);
- atomic_set(&cred->uc_count, 0);
+ atomic_set(&cred->uc_count, 1);
cred->uc_flags = RPCAUTH_CRED_UPTODATE;
if (flags & RPC_TASK_ROOTCREDS) {
- cred->uc_uid = cred->uc_puid = 0;
- cred->uc_gid = cred->uc_pgid = 0;
+ cred->uc_uid = 0;
+ cred->uc_gid = 0;
cred->uc_gids[0] = NOGROUP;
} else {
int groups = acred->group_info->ngroups;
@@ -88,8 +88,6 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
cred->uc_uid = acred->uid;
cred->uc_gid = acred->gid;
- cred->uc_puid = current->uid;
- cred->uc_pgid = current->gid;
for (i = 0; i < groups; i++)
cred->uc_gids[i] = GROUP_AT(acred->group_info, i);
if (i < NFS_NGROUPS)
@@ -121,9 +119,7 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int taskflags)
int groups;
if (cred->uc_uid != acred->uid
- || cred->uc_gid != acred->gid
- || cred->uc_puid != current->uid
- || cred->uc_pgid != current->gid)
+ || cred->uc_gid != acred->gid)
return 0;
groups = acred->group_info->ngroups;
@@ -134,8 +130,8 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int taskflags)
return 0;
return 1;
}
- return (cred->uc_uid == 0 && cred->uc_puid == 0
- && cred->uc_gid == 0 && cred->uc_pgid == 0
+ return (cred->uc_uid == 0
+ && cred->uc_gid == 0
&& cred->uc_gids[0] == (gid_t) NOGROUP);
}
@@ -144,7 +140,7 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int taskflags)
* Maybe we should keep a cached credential for performance reasons.
*/
static u32 *
-unx_marshal(struct rpc_task *task, u32 *p, int ruid)
+unx_marshal(struct rpc_task *task, u32 *p)
{
struct rpc_clnt *clnt = task->tk_client;
struct unx_cred *cred = (struct unx_cred *) task->tk_msg.rpc_cred;
@@ -160,14 +156,8 @@ unx_marshal(struct rpc_task *task, u32 *p, int ruid)
*/
p = xdr_encode_array(p, clnt->cl_nodename, clnt->cl_nodelen);
- /* Note: we don't use real uid if it involves raising privilege */
- if (ruid && cred->uc_puid != 0 && cred->uc_pgid != 0) {
- *p++ = htonl((u32) cred->uc_puid);
- *p++ = htonl((u32) cred->uc_pgid);
- } else {
- *p++ = htonl((u32) cred->uc_uid);
- *p++ = htonl((u32) cred->uc_gid);
- }
+ *p++ = htonl((u32) cred->uc_uid);
+ *p++ = htonl((u32) cred->uc_gid);
hold = p++;
for (i = 0; i < 16 && cred->uc_gids[i] != (gid_t) NOGROUP; i++)
*p++ = htonl((u32) cred->uc_gids[i]);
@@ -223,11 +213,27 @@ struct rpc_authops authunix_ops = {
#endif
.create = unx_create,
.destroy = unx_destroy,
+ .lookup_cred = unx_lookup_cred,
.crcreate = unx_create_cred,
};
static
+struct rpc_cred_cache unix_cred_cache = {
+ .expire = UNX_CRED_EXPIRE,
+};
+
+static
+struct rpc_auth unix_auth = {
+ .au_cslack = UNX_WRITESLACK,
+ .au_rslack = 2, /* assume AUTH_NULL verf */
+ .au_ops = &authunix_ops,
+ .au_count = ATOMIC_INIT(0),
+ .au_credcache = &unix_cred_cache,
+};
+
+static
struct rpc_credops unix_credops = {
+ .cr_name = "AUTH_UNIX",
.crdestroy = unx_destroy_cred,
.crmatch = unx_match,
.crmarshal = unx_marshal,
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 50d58e877b9a..02bc029d46fe 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -23,6 +23,7 @@
#include <asm/system.h>
+#include <linux/module.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/slab.h>
@@ -406,12 +407,11 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
rpc_call_setup(task, msg, 0);
/* Set up the call info struct and execute the task */
- if (task->tk_status == 0)
- status = rpc_execute(task);
- else {
- status = task->tk_status;
+ status = task->tk_status;
+ if (status == 0)
+ rpc_execute(task);
+ else
rpc_release_task(task);
- }
out:
rpc_clnt_sigunmask(clnt, &oldset);
@@ -426,9 +426,9 @@ rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags)
task->tk_msg = *msg;
task->tk_flags |= flags;
/* Bind the user cred */
- if (task->tk_msg.rpc_cred != NULL) {
+ if (task->tk_msg.rpc_cred != NULL)
rpcauth_holdcred(task);
- } else
+ else
rpcauth_bindcred(task);
if (task->tk_status == 0)
@@ -453,6 +453,20 @@ rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize
}
/*
+ * Return size of largest payload RPC client can support, in bytes
+ *
+ * For stream transports, this is one RPC record fragment (see RFC
+ * 1831), as we don't support multi-record requests yet. For datagram
+ * transports, this is the size of an IP packet minus the IP, UDP, and
+ * RPC header sizes.
+ */
+size_t rpc_max_payload(struct rpc_clnt *clnt)
+{
+ return clnt->cl_xprt->max_payload;
+}
+EXPORT_SYMBOL(rpc_max_payload);
+
+/*
* Restart an (async) RPC call. Usually called from within the
* exit handler.
*/
@@ -871,21 +885,6 @@ call_decode(struct rpc_task *task)
goto out_retry;
}
- /*
- * The following is an NFS-specific hack to cater for setuid
- * processes whose uid is mapped to nobody on the server.
- */
- if (task->tk_client->cl_droppriv &&
- (ntohl(*p) == NFSERR_ACCES || ntohl(*p) == NFSERR_PERM)) {
- if (RPC_IS_SETUID(task) && task->tk_suid_retry) {
- dprintk("RPC: %4d retry squashed uid\n", task->tk_pid);
- task->tk_flags ^= RPC_CALL_REALUID;
- task->tk_action = call_bind;
- task->tk_suid_retry--;
- goto out_retry;
- }
- }
-
task->tk_action = NULL;
if (decode)
diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
index 2a5d319eda09..d0b1d2c34a4d 100644
--- a/net/sunrpc/pmap_clnt.c
+++ b/net/sunrpc/pmap_clnt.c
@@ -3,9 +3,6 @@
*
* Portmapper client.
*
- * FIXME: In a secure environment, we may want to use an authentication
- * flavor other than AUTH_NULL.
- *
* Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
*/
@@ -212,7 +209,7 @@ pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto)
/* printk("pmap: create clnt\n"); */
clnt = rpc_create_client(xprt, hostname,
&pmap_program, RPC_PMAP_VERSION,
- RPC_AUTH_NULL);
+ RPC_AUTH_UNIX);
if (IS_ERR(clnt)) {
xprt_destroy(xprt);
} else {
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index be26e4c5b1a7..c06614d0e31d 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -132,9 +132,11 @@ __rpc_add_timer(struct rpc_task *task, rpc_action timer)
* Delete any timer for the current task. Because we use del_timer_sync(),
* this function should never be called while holding queue->lock.
*/
-static inline void
+static void
rpc_delete_timer(struct rpc_task *task)
{
+ if (RPC_IS_QUEUED(task))
+ return;
if (test_and_clear_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate)) {
del_singleshot_timer_sync(&task->tk_timer);
dprintk("RPC: %4d deleting timer\n", task->tk_pid);
@@ -747,13 +749,10 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, rpc_action call
task->tk_client = clnt;
task->tk_flags = flags;
task->tk_exit = callback;
- if (current->uid != current->fsuid || current->gid != current->fsgid)
- task->tk_flags |= RPC_TASK_SETUID;
/* Initialize retry counters */
task->tk_garb_retry = 2;
task->tk_cred_retry = 2;
- task->tk_suid_retry = 1;
task->tk_priority = RPC_PRIORITY_NORMAL;
task->tk_cookie = (unsigned long)current;
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index ed2a19c762e0..a24a29bfdebd 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -1460,8 +1460,11 @@ xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to)
if (xprt->stream) {
xprt->cwnd = RPC_MAXCWND(xprt);
xprt->nocong = 1;
- } else
+ xprt->max_payload = (1U << 31) - 1;
+ } else {
xprt->cwnd = RPC_INITCWND;
+ xprt->max_payload = (1U << 16) - (MAX_HEADER << 3);
+ }
spin_lock_init(&xprt->sock_lock);
spin_lock_init(&xprt->xprt_lock);
init_waitqueue_head(&xprt->cong_wait);