From 880dd4b9f5b433c1fd13def9d618eb51a848883f Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 22 Jun 2005 12:37:50 -0700 Subject: [PATCH] --- yaml --- r: 2824 b: refs/heads/master c: 5d927eb0101eb791fb2d4f72b49a2da5faf01941 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/arch/arm/common/dmabounce.c | 18 +- trunk/arch/arm/common/sa1111.c | 13 +- trunk/arch/arm/kernel/setup.c | 25 +- trunk/arch/arm/kernel/signal.c | 29 +- trunk/arch/arm/kernel/signal.h | 12 - trunk/arch/arm/kernel/traps.c | 9 - trunk/arch/arm/mach-clps7500/core.c | 2 - trunk/arch/arm/mach-rpc/riscpc.c | 7 +- trunk/arch/arm/mm/init.c | 19 +- trunk/arch/ia64/Kconfig | 2 +- trunk/arch/ia64/configs/tiger_defconfig | 19 +- trunk/arch/ia64/defconfig | 138 ++---- trunk/arch/ia64/kernel/entry.h | 2 +- trunk/arch/ia64/kernel/ivt.S | 13 +- trunk/arch/ia64/kernel/ptrace.c | 15 +- trunk/arch/ia64/kernel/signal.c | 5 +- trunk/arch/ia64/kernel/smp.c | 2 +- trunk/arch/ia64/pci/pci.c | 20 + .../ppc/platforms/85xx/mpc85xx_cds_common.c | 1 - trunk/fs/Kconfig | 35 -- trunk/fs/Makefile | 1 - trunk/fs/lockd/clntlock.c | 113 +++-- trunk/fs/lockd/clntproc.c | 40 +- trunk/fs/lockd/host.c | 8 +- trunk/fs/lockd/mon.c | 7 +- trunk/fs/locks.c | 6 - trunk/fs/nfs/Makefile | 1 - trunk/fs/nfs/callback.c | 1 - trunk/fs/nfs/callback_proc.c | 1 - trunk/fs/nfs/callback_xdr.c | 2 +- trunk/fs/nfs/delegation.c | 1 - trunk/fs/nfs/dir.c | 160 ++----- trunk/fs/nfs/direct.c | 2 +- trunk/fs/nfs/file.c | 48 +- trunk/fs/nfs/idmap.c | 1 - trunk/fs/nfs/inode.c | 427 +++++++---------- trunk/fs/nfs/mount_clnt.c | 4 +- trunk/fs/nfs/nfs3acl.c | 403 ---------------- trunk/fs/nfs/nfs3proc.c | 43 +- trunk/fs/nfs/nfs3xdr.c | 147 ------ trunk/fs/nfs/nfs4_fs.h | 253 ----------- trunk/fs/nfs/nfs4proc.c | 429 ++++-------------- trunk/fs/nfs/nfs4renewd.c | 1 - trunk/fs/nfs/nfs4state.c | 193 ++++---- trunk/fs/nfs/nfs4xdr.c | 241 +--------- trunk/fs/nfs/nfsroot.c | 9 - trunk/fs/nfs/pagelist.c | 142 ++---- trunk/fs/nfs/proc.c | 1 - trunk/fs/nfs/read.c | 3 + trunk/fs/nfs/write.c | 108 ++--- trunk/fs/nfs_common/Makefile | 7 - trunk/fs/nfs_common/nfsacl.c | 257 ----------- trunk/fs/nfsd/Makefile | 2 - trunk/fs/nfsd/nfs2acl.c | 336 -------------- trunk/fs/nfsd/nfs3acl.c | 267 ----------- trunk/fs/nfsd/nfs3xdr.c | 13 - trunk/fs/nfsd/nfs4callback.c | 4 +- trunk/fs/nfsd/nfsproc.c | 1 - trunk/fs/nfsd/nfssvc.c | 28 -- trunk/fs/nfsd/nfsxdr.c | 11 - trunk/fs/nfsd/vfs.c | 107 +---- trunk/include/asm-arm/pgalloc.h | 24 +- trunk/include/linux/efi.h | 2 +- trunk/include/linux/fs.h | 1 - trunk/include/linux/lockd/lockd.h | 7 +- trunk/include/linux/nfs4.h | 2 - trunk/include/linux/nfs_fs.h | 306 ++++++++++--- trunk/include/linux/nfs_fs_i.h | 5 - trunk/include/linux/nfs_fs_sb.h | 1 - trunk/include/linux/nfs_mount.h | 1 - trunk/include/linux/nfs_page.h | 30 +- trunk/include/linux/nfs_xdr.h | 43 -- trunk/include/linux/nfsacl.h | 58 --- trunk/include/linux/nfsd/nfsd.h | 16 - trunk/include/linux/nfsd/xdr.h | 4 - trunk/include/linux/nfsd/xdr3.h | 26 -- trunk/include/linux/sunrpc/clnt.h | 6 - trunk/include/linux/sunrpc/sched.h | 1 + trunk/include/linux/sunrpc/svc.h | 14 +- trunk/include/linux/sunrpc/xdr.h | 21 +- trunk/mm/page_alloc.c | 11 +- trunk/net/ipv4/netfilter/ipt_CLUSTERIP.c | 2 +- trunk/net/sunrpc/auth.c | 6 +- trunk/net/sunrpc/auth_gss/auth_gss.c | 18 +- trunk/net/sunrpc/clnt.c | 205 ++------- trunk/net/sunrpc/pmap_clnt.c | 9 +- trunk/net/sunrpc/sched.c | 84 ++-- trunk/net/sunrpc/sunrpc_syms.c | 6 +- trunk/net/sunrpc/svc.c | 36 +- trunk/net/sunrpc/xdr.c | 298 +----------- trunk/net/sunrpc/xprt.c | 71 +-- 92 files changed, 1171 insertions(+), 4360 deletions(-) delete mode 100644 trunk/arch/arm/kernel/signal.h delete mode 100644 trunk/fs/nfs/nfs3acl.c delete mode 100644 trunk/fs/nfs/nfs4_fs.h delete mode 100644 trunk/fs/nfs_common/Makefile delete mode 100644 trunk/fs/nfs_common/nfsacl.c delete mode 100644 trunk/fs/nfsd/nfs2acl.c delete mode 100644 trunk/fs/nfsd/nfs3acl.c delete mode 100644 trunk/include/linux/nfsacl.h diff --git a/[refs] b/[refs] index 61bb9271443a..5cf6b19fe510 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: b7c84c6ada2be942eca6722edb2cfaad412cd5de +refs/heads/master: 5d927eb0101eb791fb2d4f72b49a2da5faf01941 diff --git a/trunk/arch/arm/common/dmabounce.c b/trunk/arch/arm/common/dmabounce.c index cbf2165476b0..9d63a01214eb 100644 --- a/trunk/arch/arm/common/dmabounce.c +++ b/trunk/arch/arm/common/dmabounce.c @@ -93,12 +93,15 @@ static void print_alloc_stats(struct dmabounce_device_info *device_info) static inline struct dmabounce_device_info * find_dmabounce_dev(struct device *dev) { - struct dmabounce_device_info *d; + struct list_head *entry; + + list_for_each(entry, &dmabounce_devs) { + struct dmabounce_device_info *d = + list_entry(entry, struct dmabounce_device_info, node); - list_for_each_entry(d, &dmabounce_devs, node) if (d->dev == dev) return d; - + } return NULL; } @@ -169,11 +172,15 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr, static inline struct safe_buffer * find_safe_buffer(struct dmabounce_device_info *device_info, dma_addr_t safe_dma_addr) { - struct safe_buffer *b; + struct list_head *entry; + + list_for_each(entry, &device_info->safe_buffers) { + struct safe_buffer *b = + list_entry(entry, struct safe_buffer, node); - list_for_each_entry(b, &device_info->safe_buffers, node) if (b->safe_dma_addr == safe_dma_addr) return b; + } return NULL; } @@ -294,6 +301,7 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, __func__, buf->ptr, (void *) virt_to_dma(dev, buf->ptr), buf->safe, (void *) buf->safe_dma_addr); + DO_STATS ( device_info->bounce_count++ ); if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) { diff --git a/trunk/arch/arm/common/sa1111.c b/trunk/arch/arm/common/sa1111.c index 38c2eb667eb9..21fce3414ed1 100644 --- a/trunk/arch/arm/common/sa1111.c +++ b/trunk/arch/arm/common/sa1111.c @@ -721,17 +721,16 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq) return ret; } -static int sa1111_remove_one(struct device *dev, void *data) -{ - device_unregister(dev); - return 0; -} - static void __sa1111_remove(struct sa1111 *sachip) { + struct list_head *l, *n; void __iomem *irqbase = sachip->base + SA1111_INTC; - device_for_each_child(sachip->dev, NULL, sa1111_remove_one); + list_for_each_safe(l, n, &sachip->dev->children) { + struct device *d = list_to_dev(l); + + device_unregister(d); + } /* disable all IRQs */ sa1111_writel(0, irqbase + SA1111_INTEN0); diff --git a/trunk/arch/arm/kernel/setup.c b/trunk/arch/arm/kernel/setup.c index 8cf733daa800..9fed5fa194d9 100644 --- a/trunk/arch/arm/kernel/setup.c +++ b/trunk/arch/arm/kernel/setup.c @@ -395,20 +395,6 @@ static void __init early_initrd(char **p) } __early_param("initrd=", early_initrd); -static void __init add_memory(unsigned long start, unsigned long size) -{ - /* - * Ensure that start/size are aligned to a page boundary. - * Size is appropriately rounded down, start is rounded up. - */ - size -= start & ~PAGE_MASK; - - meminfo.bank[meminfo.nr_banks].start = PAGE_ALIGN(start); - meminfo.bank[meminfo.nr_banks].size = size & PAGE_MASK; - meminfo.bank[meminfo.nr_banks].node = PHYS_TO_NID(start); - meminfo.nr_banks += 1; -} - /* * Pick out the memory size. We look for mem=size@start, * where start and size are "size[KkMm]" @@ -433,7 +419,10 @@ static void __init early_mem(char **p) if (**p == '@') start = memparse(*p + 1, p); - add_memory(start, size); + meminfo.bank[meminfo.nr_banks].start = start; + meminfo.bank[meminfo.nr_banks].size = size; + meminfo.bank[meminfo.nr_banks].node = PHYS_TO_NID(start); + meminfo.nr_banks += 1; } __early_param("mem=", early_mem); @@ -575,7 +564,11 @@ static int __init parse_tag_mem32(const struct tag *tag) tag->u.mem.start, tag->u.mem.size / 1024); return -EINVAL; } - add_memory(tag->u.mem.start, tag->u.mem.size); + meminfo.bank[meminfo.nr_banks].start = tag->u.mem.start; + meminfo.bank[meminfo.nr_banks].size = tag->u.mem.size; + meminfo.bank[meminfo.nr_banks].node = PHYS_TO_NID(tag->u.mem.start); + meminfo.nr_banks += 1; + return 0; } diff --git a/trunk/arch/arm/kernel/signal.c b/trunk/arch/arm/kernel/signal.c index 07ddeed61766..931919fd5121 100644 --- a/trunk/arch/arm/kernel/signal.c +++ b/trunk/arch/arm/kernel/signal.c @@ -19,7 +19,6 @@ #include #include "ptrace.h" -#include "signal.h" #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) @@ -36,7 +35,7 @@ #define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_sigreturn - __NR_SYSCALL_BASE)) #define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE)) -const unsigned long sigreturn_codes[4] = { +static const unsigned long retcodes[4] = { SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN }; @@ -501,25 +500,17 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka, if (ka->sa.sa_flags & SA_SIGINFO) idx += 2; - if (__put_user(sigreturn_codes[idx], rc)) + if (__put_user(retcodes[idx], rc)) return 1; - if (cpsr & MODE32_BIT) { - /* - * 32-bit code can use the new high-page - * signal return code support. - */ - retcode = KERN_SIGRETURN_CODE + (idx << 2) + thumb; - } else { - /* - * Ensure that the instruction cache sees - * the return code written onto the stack. - */ - flush_icache_range((unsigned long)rc, - (unsigned long)(rc + 1)); - - retcode = ((unsigned long)rc) + thumb; - } + /* + * Ensure that the instruction cache sees + * the return code written onto the stack. + */ + flush_icache_range((unsigned long)rc, + (unsigned long)(rc + 1)); + + retcode = ((unsigned long)rc) + thumb; } regs->ARM_r0 = usig; diff --git a/trunk/arch/arm/kernel/signal.h b/trunk/arch/arm/kernel/signal.h deleted file mode 100644 index 91d26faca62b..000000000000 --- a/trunk/arch/arm/kernel/signal.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * linux/arch/arm/kernel/signal.h - * - * Copyright (C) 2005 Russell King. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#define KERN_SIGRETURN_CODE 0xffff0500 - -extern const unsigned long sigreturn_codes[4]; diff --git a/trunk/arch/arm/kernel/traps.c b/trunk/arch/arm/kernel/traps.c index 2fb0a4cfb37a..45d2a032d890 100644 --- a/trunk/arch/arm/kernel/traps.c +++ b/trunk/arch/arm/kernel/traps.c @@ -30,7 +30,6 @@ #include #include "ptrace.h" -#include "signal.h" const char *processor_modes[]= { "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , @@ -684,14 +683,6 @@ void __init trap_init(void) memcpy((void *)0xffff0000, __vectors_start, __vectors_end - __vectors_start); memcpy((void *)0xffff0200, __stubs_start, __stubs_end - __stubs_start); memcpy((void *)0xffff1000 - kuser_sz, __kuser_helper_start, kuser_sz); - - /* - * Copy signal return handlers into the vector page, and - * set sigreturn to be a pointer to these. - */ - memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes, - sizeof(sigreturn_codes)); - flush_icache_range(0xffff0000, 0xffff0000 + PAGE_SIZE); modify_domain(DOMAIN_USER, DOMAIN_CLIENT); } diff --git a/trunk/arch/arm/mach-clps7500/core.c b/trunk/arch/arm/mach-clps7500/core.c index 0bc7da488612..fdfededfd96f 100644 --- a/trunk/arch/arm/mach-clps7500/core.c +++ b/trunk/arch/arm/mach-clps7500/core.c @@ -26,8 +26,6 @@ #include #include -unsigned int vram_size; - static void cl7500_ack_irq_a(unsigned int irq) { unsigned int val, mask; diff --git a/trunk/arch/arm/mach-rpc/riscpc.c b/trunk/arch/arm/mach-rpc/riscpc.c index 437106881436..815c53225cd8 100644 --- a/trunk/arch/arm/mach-rpc/riscpc.c +++ b/trunk/arch/arm/mach-rpc/riscpc.c @@ -32,7 +32,10 @@ extern void rpc_init_irq(void); -unsigned int vram_size; +extern unsigned int vram_size; + +#if 0 + unsigned int memc_ctrl_reg; unsigned int number_mfm_drives; @@ -60,6 +63,8 @@ static int __init parse_tag_acorn(const struct tag *tag) __tagtable(ATAG_ACORN, parse_tag_acorn); +#endif + static struct map_desc rpc_io_desc[] __initdata = { { SCREEN_BASE, SCREEN_START, 2*1048576, MT_DEVICE }, /* VRAM */ { (u32)IO_BASE, IO_START, IO_SIZE , MT_DEVICE }, /* IO space */ diff --git a/trunk/arch/arm/mm/init.c b/trunk/arch/arm/mm/init.c index c08710b1ff02..72a2b8cee319 100644 --- a/trunk/arch/arm/mm/init.c +++ b/trunk/arch/arm/mm/init.c @@ -93,7 +93,14 @@ struct node_info { }; #define O_PFN_DOWN(x) ((x) >> PAGE_SHIFT) +#define V_PFN_DOWN(x) O_PFN_DOWN(__pa(x)) + #define O_PFN_UP(x) (PAGE_ALIGN(x) >> PAGE_SHIFT) +#define V_PFN_UP(x) O_PFN_UP(__pa(x)) + +#define PFN_SIZE(x) ((x) >> PAGE_SHIFT) +#define PFN_RANGE(s,e) PFN_SIZE(PAGE_ALIGN((unsigned long)(e)) - \ + (((unsigned long)(s)) & PAGE_MASK)) /* * FIXME: We really want to avoid allocating the bootmap bitmap @@ -106,7 +113,7 @@ find_bootmap_pfn(int node, struct meminfo *mi, unsigned int bootmap_pages) { unsigned int start_pfn, bank, bootmap_pfn; - start_pfn = O_PFN_UP(__pa(&_end)); + start_pfn = V_PFN_UP(&_end); bootmap_pfn = 0; for (bank = 0; bank < mi->nr_banks; bank ++) { @@ -115,9 +122,9 @@ find_bootmap_pfn(int node, struct meminfo *mi, unsigned int bootmap_pages) if (mi->bank[bank].node != node) continue; - start = mi->bank[bank].start >> PAGE_SHIFT; - end = (mi->bank[bank].size + - mi->bank[bank].start) >> PAGE_SHIFT; + start = O_PFN_UP(mi->bank[bank].start); + end = O_PFN_DOWN(mi->bank[bank].size + + mi->bank[bank].start); if (end < start_pfn) continue; @@ -184,8 +191,8 @@ find_memend_and_nodes(struct meminfo *mi, struct node_info *np) /* * Get the start and end pfns for this bank */ - start = mi->bank[i].start >> PAGE_SHIFT; - end = (mi->bank[i].start + mi->bank[i].size) >> PAGE_SHIFT; + start = O_PFN_UP(mi->bank[i].start); + end = O_PFN_DOWN(mi->bank[i].start + mi->bank[i].size); if (np[node].start > start) np[node].start = start; diff --git a/trunk/arch/ia64/Kconfig b/trunk/arch/ia64/Kconfig index ce4dfa8b834d..34e603cc1716 100644 --- a/trunk/arch/ia64/Kconfig +++ b/trunk/arch/ia64/Kconfig @@ -220,7 +220,7 @@ config IOSAPIC config IA64_SGI_SN_SIM bool "SGI Medusa Simulator Support" - depends on IA64_SGI_SN2 || IA64_GENERIC + depends on IA64_SGI_SN2 help If you are compiling a kernel that will run under SGI's IA-64 simulator (Medusa) then say Y, otherwise say N. diff --git a/trunk/arch/ia64/configs/tiger_defconfig b/trunk/arch/ia64/configs/tiger_defconfig index 47f45341ac62..9086b789f6ac 100644 --- a/trunk/arch/ia64/configs/tiger_defconfig +++ b/trunk/arch/ia64/configs/tiger_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.12-20050621 -# Tue Jun 21 14:03:24 2005 +# Linux kernel version: 2.6.12-rc3 +# Tue May 3 15:55:04 2005 # # @@ -67,7 +67,6 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_TIME_INTERPOLATION=y CONFIG_EFI=y CONFIG_GENERIC_IOMAP=y -CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y # CONFIG_IA64_GENERIC is not set CONFIG_IA64_DIG=y # CONFIG_IA64_HP_ZX1 is not set @@ -286,7 +285,6 @@ CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=m # CONFIG_BLK_DEV_SR_VENDOR is not set CONFIG_CHR_DEV_SG=m -# CONFIG_CHR_DEV_SCH is not set # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs @@ -315,8 +313,11 @@ CONFIG_SCSI_FC_ATTRS=y # CONFIG_MEGARAID_NEWGEN is not set # CONFIG_MEGARAID_LEGACY is not set # CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_IPS is not set # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set @@ -365,10 +366,8 @@ CONFIG_DM_ZERO=m # Fusion MPT device support # CONFIG_FUSION=y -CONFIG_FUSION_SPI=y -CONFIG_FUSION_FC=y -CONFIG_FUSION_MAX_SGE=128 -CONFIG_FUSION_CTL=y +CONFIG_FUSION_MAX_SGE=40 +# CONFIG_FUSION_CTL is not set # # IEEE 1394 (FireWire) support @@ -507,11 +506,9 @@ CONFIG_E1000=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SKGE is not set # CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set CONFIG_TIGON3=y -# CONFIG_BNX2 is not set # # Ethernet (10000 Mbit) @@ -601,6 +598,7 @@ CONFIG_GAMEPORT=m # CONFIG_GAMEPORT_VORTEX is not set # CONFIG_GAMEPORT_FM801 is not set # CONFIG_GAMEPORT_CS461X is not set +CONFIG_SOUND_GAMEPORT=m # # Character devices @@ -613,6 +611,7 @@ CONFIG_SERIAL_NONSTANDARD=y # CONFIG_CYCLADES is not set # CONFIG_MOXA_SMARTIO is not set # CONFIG_ISI is not set +# CONFIG_SYNCLINK is not set # CONFIG_SYNCLINKMP is not set # CONFIG_N_HDLC is not set # CONFIG_SPECIALIX is not set diff --git a/trunk/arch/ia64/defconfig b/trunk/arch/ia64/defconfig index 7be8096e0561..9997ef45ab23 100644 --- a/trunk/arch/ia64/defconfig +++ b/trunk/arch/ia64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.12 -# Tue Jun 21 11:30:42 2005 +# Linux kernel version: 2.6.10 +# Thu Jan 6 11:13:13 2005 # # @@ -10,7 +10,6 @@ CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y CONFIG_LOCK_KERNEL=y -CONFIG_INIT_ENV_ARG_LIMIT=32 # # General setup @@ -22,27 +21,24 @@ CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set +CONFIG_LOG_BUF_SHIFT=20 CONFIG_HOTPLUG=y CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y -# CONFIG_CPUSETS is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y # CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SHMEM=y CONFIG_CC_ALIGN_FUNCTIONS=0 CONFIG_CC_ALIGN_LABELS=0 CONFIG_CC_ALIGN_LOOPS=0 CONFIG_CC_ALIGN_JUMPS=0 # CONFIG_TINY_SHMEM is not set -CONFIG_BASE_SMALL=0 # # Loadable module support @@ -67,11 +63,9 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_TIME_INTERPOLATION=y CONFIG_EFI=y CONFIG_GENERIC_IOMAP=y -CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_IA64_GENERIC=y # CONFIG_IA64_DIG is not set # CONFIG_IA64_HP_ZX1 is not set -# CONFIG_IA64_HP_ZX1_SWIOTLB is not set # CONFIG_IA64_SGI_SN2 is not set # CONFIG_IA64_HP_SIM is not set # CONFIG_ITANIUM is not set @@ -83,7 +77,6 @@ CONFIG_IA64_PAGE_SIZE_16KB=y CONFIG_IA64_L1_CACHE_SHIFT=7 CONFIG_NUMA=y CONFIG_VIRTUAL_MEM_MAP=y -CONFIG_HOLES_IN_ZONE=y CONFIG_DISCONTIGMEM=y CONFIG_IA64_CYCLONE=y CONFIG_IOSAPIC=y @@ -91,7 +84,6 @@ CONFIG_FORCE_MAX_ZONEORDER=18 CONFIG_SMP=y CONFIG_NR_CPUS=512 CONFIG_HOTPLUG_CPU=y -# CONFIG_SCHED_SMT is not set # CONFIG_PREEMPT is not set CONFIG_HAVE_DEC_LOCK=y CONFIG_IA32_SUPPORT=y @@ -143,7 +135,6 @@ CONFIG_PCI_DOMAINS=y # CONFIG_PCI_MSI is not set CONFIG_PCI_LEGACY_PROC=y CONFIG_PCI_NAMES=y -# CONFIG_PCI_DEBUG is not set # # PCI Hotplug Support @@ -153,6 +144,7 @@ CONFIG_HOTPLUG_PCI=m CONFIG_HOTPLUG_PCI_ACPI=m # CONFIG_HOTPLUG_PCI_ACPI_IBM is not set # CONFIG_HOTPLUG_PCI_CPCI is not set +# CONFIG_HOTPLUG_PCI_PCIE is not set # CONFIG_HOTPLUG_PCI_SHPC is not set # @@ -160,6 +152,10 @@ CONFIG_HOTPLUG_PCI_ACPI=m # # CONFIG_PCCARD is not set +# +# PC-card bridges +# + # # Device Drivers # @@ -194,7 +190,6 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_COW_COMMON is not set CONFIG_BLK_DEV_LOOP=m CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_NBD=m @@ -214,7 +209,6 @@ CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y CONFIG_IOSCHED_CFQ=y -# CONFIG_ATA_OVER_ETH is not set # # ATA/ATAPI/MFM/RLL support @@ -289,7 +283,6 @@ CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=m # CONFIG_BLK_DEV_SR_VENDOR is not set CONFIG_CHR_DEV_SG=m -# CONFIG_CHR_DEV_SCH is not set # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs @@ -317,21 +310,13 @@ CONFIG_SCSI_FC_ATTRS=y # CONFIG_SCSI_AIC79XX is not set # CONFIG_MEGARAID_NEWGEN is not set # CONFIG_MEGARAID_LEGACY is not set -CONFIG_SCSI_SATA=y -# CONFIG_SCSI_SATA_AHCI is not set -# CONFIG_SCSI_SATA_SVW is not set -# CONFIG_SCSI_ATA_PIIX is not set -# CONFIG_SCSI_SATA_NV is not set -# CONFIG_SCSI_SATA_PROMISE is not set -# CONFIG_SCSI_SATA_QSTOR is not set -# CONFIG_SCSI_SATA_SX4 is not set -# CONFIG_SCSI_SATA_SIL is not set -# CONFIG_SCSI_SATA_SIS is not set -# CONFIG_SCSI_SATA_ULI is not set -# CONFIG_SCSI_SATA_VIA is not set -CONFIG_SCSI_SATA_VITESSE=y +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_IPS is not set # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set @@ -341,6 +326,7 @@ CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set # CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_ISP is not set CONFIG_SCSI_QLOGIC_FC=y # CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set CONFIG_SCSI_QLOGIC_1280=y @@ -351,7 +337,6 @@ CONFIG_SCSI_QLA22XX=m CONFIG_SCSI_QLA2300=m CONFIG_SCSI_QLA2322=m # CONFIG_SCSI_QLA6312 is not set -# CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_DEBUG is not set @@ -374,16 +359,12 @@ CONFIG_DM_CRYPT=m CONFIG_DM_SNAPSHOT=m CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m -CONFIG_DM_MULTIPATH=m -# CONFIG_DM_MULTIPATH_EMC is not set # # Fusion MPT device support # CONFIG_FUSION=y -CONFIG_FUSION_SPI=y -CONFIG_FUSION_FC=m -CONFIG_FUSION_MAX_SGE=128 +CONFIG_FUSION_MAX_SGE=40 # CONFIG_FUSION_CTL is not set # @@ -406,6 +387,7 @@ CONFIG_NET=y # CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y @@ -465,6 +447,7 @@ CONFIG_DUMMY=m # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set # # ARCnet devices @@ -501,7 +484,9 @@ CONFIG_NET_PCI=y # CONFIG_FORCEDETH is not set # CONFIG_DGRS is not set CONFIG_EEPRO100=m +# CONFIG_EEPRO100_PIO is not set CONFIG_E100=m +# CONFIG_E100_NAPI is not set # CONFIG_FEALNX is not set # CONFIG_NATSEMI is not set # CONFIG_NE2K_PCI is not set @@ -523,11 +508,9 @@ CONFIG_E1000=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SKGE is not set # CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set CONFIG_TIGON3=y -# CONFIG_BNX2 is not set # # Ethernet (10000 Mbit) @@ -584,6 +567,25 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_EVDEV is not set # CONFIG_INPUT_EVBUG is not set +# +# Input I/O drivers +# +CONFIG_GAMEPORT=m +CONFIG_SOUND_GAMEPORT=m +# CONFIG_GAMEPORT_NS558 is not set +# CONFIG_GAMEPORT_L4 is not set +# CONFIG_GAMEPORT_EMU10K1 is not set +# CONFIG_GAMEPORT_VORTEX is not set +# CONFIG_GAMEPORT_FM801 is not set +# CONFIG_GAMEPORT_CS461x is not set +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set + # # Input Device Drivers # @@ -601,23 +603,6 @@ CONFIG_MOUSE_PS2=y # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set -# -# Hardware I/O ports -# -CONFIG_SERIO=y -CONFIG_SERIO_I8042=y -# CONFIG_SERIO_SERPORT is not set -# CONFIG_SERIO_PCIPS2 is not set -CONFIG_SERIO_LIBPS2=y -# CONFIG_SERIO_RAW is not set -CONFIG_GAMEPORT=m -# CONFIG_GAMEPORT_NS558 is not set -# CONFIG_GAMEPORT_L4 is not set -# CONFIG_GAMEPORT_EMU10K1 is not set -# CONFIG_GAMEPORT_VORTEX is not set -# CONFIG_GAMEPORT_FM801 is not set -# CONFIG_GAMEPORT_CS461X is not set - # # Character devices # @@ -628,15 +613,11 @@ CONFIG_SERIAL_NONSTANDARD=y # CONFIG_ROCKETPORT is not set # CONFIG_CYCLADES is not set # CONFIG_MOXA_SMARTIO is not set -# CONFIG_ISI is not set +# CONFIG_SYNCLINK is not set # CONFIG_SYNCLINKMP is not set # CONFIG_N_HDLC is not set -# CONFIG_SPECIALIX is not set -# CONFIG_SX is not set # CONFIG_STALDRV is not set CONFIG_SGI_SNSC=y -CONFIG_SGI_TIOCX=y -CONFIG_SGI_MBCS=m # # Serial drivers @@ -658,7 +639,6 @@ CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_SERIAL_SGI_L1_CONSOLE=y CONFIG_SERIAL_SGI_IOC4=y -# CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -684,7 +664,6 @@ CONFIG_EFI_RTC=y CONFIG_AGP=m CONFIG_AGP_I460=m CONFIG_AGP_HP_ZX1=m -CONFIG_AGP_SGI_TIOCA=m CONFIG_DRM=m CONFIG_DRM_TDFX=m CONFIG_DRM_R128=m @@ -696,14 +675,8 @@ CONFIG_HPET=y # CONFIG_HPET_RTC_IRQ is not set CONFIG_HPET_MMAP=y CONFIG_MAX_RAW_DEVS=256 -# CONFIG_HANGCHECK_TIMER is not set CONFIG_MMTIMER=y -# -# TPM devices -# -# CONFIG_TCG_TPM is not set - # # I2C support # @@ -788,8 +761,6 @@ CONFIG_SND_CS46XX=m CONFIG_SND_CS46XX_NEW_DSP=y CONFIG_SND_CS4281=m CONFIG_SND_EMU10K1=m -# CONFIG_SND_EMU10K1X is not set -# CONFIG_SND_CA0106 is not set # CONFIG_SND_KORG1212 is not set # CONFIG_SND_MIXART is not set # CONFIG_SND_NM256 is not set @@ -814,14 +785,13 @@ CONFIG_SND_FM801=m # CONFIG_SND_INTEL8X0M is not set # CONFIG_SND_SONICVIBES is not set # CONFIG_SND_VIA82XX is not set -# CONFIG_SND_VIA82XX_MODEM is not set # CONFIG_SND_VX222 is not set -# CONFIG_SND_HDA_INTEL is not set # # USB devices # # CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_USX2Y is not set # # Open Sound System @@ -831,8 +801,6 @@ CONFIG_SND_FM801=m # # USB support # -CONFIG_USB_ARCH_HAS_HCD=y -CONFIG_USB_ARCH_HAS_OHCI=y CONFIG_USB=m # CONFIG_USB_DEBUG is not set @@ -844,6 +812,8 @@ CONFIG_USB_DEVICEFS=y # CONFIG_USB_DYNAMIC_MINORS is not set # CONFIG_USB_SUSPEND is not set # CONFIG_USB_OTG is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Host Controller Drivers @@ -852,8 +822,6 @@ CONFIG_USB_EHCI_HCD=m # CONFIG_USB_EHCI_SPLIT_ISO is not set # CONFIG_USB_EHCI_ROOT_HUB_TT is not set CONFIG_USB_OHCI_HCD=m -# CONFIG_USB_OHCI_BIG_ENDIAN is not set -CONFIG_USB_OHCI_LITTLE_ENDIAN=y CONFIG_USB_UHCI_HCD=m # CONFIG_USB_SL811_HCD is not set @@ -871,11 +839,12 @@ CONFIG_USB_UHCI_HCD=m # CONFIG_USB_STORAGE=m # CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_RW_DETECT is not set # CONFIG_USB_STORAGE_DATAFAB is not set # CONFIG_USB_STORAGE_FREECOM is not set # CONFIG_USB_STORAGE_ISD200 is not set # CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_HP8200e is not set # CONFIG_USB_STORAGE_SDDR09 is not set # CONFIG_USB_STORAGE_SDDR55 is not set # CONFIG_USB_STORAGE_JUMPSHOT is not set @@ -925,7 +894,6 @@ CONFIG_USB_HIDINPUT=y # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set # CONFIG_USB_USBNET is not set -CONFIG_USB_MON=m # # USB port drivers @@ -941,6 +909,7 @@ CONFIG_USB_MON=m # # CONFIG_USB_EMI62 is not set # CONFIG_USB_EMI26 is not set +# CONFIG_USB_TIGL is not set # CONFIG_USB_AUERSWALD is not set # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set @@ -949,8 +918,6 @@ CONFIG_USB_MON=m # CONFIG_USB_CYTHERM is not set # CONFIG_USB_PHIDGETKIT is not set # CONFIG_USB_PHIDGETSERVO is not set -# CONFIG_USB_IDMOUSE is not set -# CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_TEST is not set # @@ -1003,12 +970,7 @@ CONFIG_REISERFS_FS_POSIX_ACL=y CONFIG_REISERFS_FS_SECURITY=y # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y - -# -# XFS support -# CONFIG_XFS_FS=y -CONFIG_XFS_EXPORT=y # CONFIG_XFS_RT is not set # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_SECURITY is not set @@ -1086,7 +1048,7 @@ CONFIG_NFSD_V4=y CONFIG_NFSD_TCP=y CONFIG_LOCKD=m CONFIG_LOCKD_V4=y -CONFIG_EXPORTFS=y +CONFIG_EXPORTFS=m CONFIG_SUNRPC=m CONFIG_SUNRPC_GSS=m CONFIG_RPCSEC_GSS_KRB5=m @@ -1172,8 +1134,6 @@ CONFIG_NLS_UTF8=m # CONFIG_CRC_CCITT is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set -CONFIG_GENERIC_HARDIRQS=y -CONFIG_GENERIC_IRQ_PROBE=y # # HP Simulator drivers @@ -1190,17 +1150,14 @@ CONFIG_GENERIC_IRQ_PROBE=y # # Kernel hacking # -# CONFIG_PRINTK_TIME is not set CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y -CONFIG_LOG_BUF_SHIFT=20 # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_FS is not set CONFIG_IA64_GRANULE_16MB=y # CONFIG_IA64_GRANULE_64MB is not set # CONFIG_IA64_PRINT_HAZARDS is not set @@ -1227,7 +1184,6 @@ CONFIG_CRYPTO_MD5=m # CONFIG_CRYPTO_SHA256 is not set # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_WP512 is not set -# CONFIG_CRYPTO_TGR192 is not set CONFIG_CRYPTO_DES=m # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_TWOFISH is not set diff --git a/trunk/arch/ia64/kernel/entry.h b/trunk/arch/ia64/kernel/entry.h index 78eeb0793419..6d4ecec989b5 100644 --- a/trunk/arch/ia64/kernel/entry.h +++ b/trunk/arch/ia64/kernel/entry.h @@ -60,7 +60,7 @@ .spillsp @priunat,SW(AR_UNAT)+16+(off); \ .spillsp ar.rnat,SW(AR_RNAT)+16+(off); \ .spillsp ar.bspstore,SW(AR_BSPSTORE)+16+(off); \ - .spillsp pr,SW(PR)+16+(off) + .spillsp pr,SW(PR)+16+(off)) #define DO_SAVE_SWITCH_STACK \ movl r28=1f; \ diff --git a/trunk/arch/ia64/kernel/ivt.S b/trunk/arch/ia64/kernel/ivt.S index 2bc085a73e30..d9c05d53435b 100644 --- a/trunk/arch/ia64/kernel/ivt.S +++ b/trunk/arch/ia64/kernel/ivt.S @@ -405,22 +405,17 @@ ENTRY(nested_dtlb_miss) * r30: continuation address * r31: saved pr * - * Clobbered: b0, r18, r19, r21, r22, psr.dt (cleared) + * Clobbered: b0, r18, r19, r21, psr.dt (cleared) */ rsm psr.dt // switch to using physical data addressing mov r19=IA64_KR(PT_BASE) // get the page table base address shl r21=r16,3 // shift bit 60 into sign bit - mov r18=cr.itir ;; shr.u r17=r16,61 // get the region number into r17 - extr.u r18=r18,2,6 // get the faulting page size ;; cmp.eq p6,p7=5,r17 // is faulting address in region 5? - add r22=-PAGE_SHIFT,r18 // adjustment for hugetlb address - add r18=PGDIR_SHIFT-PAGE_SHIFT,r18 + shr.u r18=r16,PGDIR_SHIFT // get bits 33-63 of faulting address ;; - shr.u r22=r16,r22 - shr.u r18=r16,r18 (p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place srlz.d @@ -433,7 +428,7 @@ ENTRY(nested_dtlb_miss) (p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=PTA + IFA(33,42)*8 (p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8) cmp.eq p7,p6=0,r21 // unused address bits all zeroes? - shr.u r18=r22,PMD_SHIFT // shift L2 index into position + shr.u r18=r16,PMD_SHIFT // shift L2 index into position ;; ld8 r17=[r17] // fetch the L1 entry (may be 0) ;; @@ -441,7 +436,7 @@ ENTRY(nested_dtlb_miss) dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L2 page table entry ;; (p7) ld8 r17=[r17] // fetch the L2 entry (may be 0) - shr.u r19=r22,PAGE_SHIFT // shift L3 index into position + shr.u r19=r16,PAGE_SHIFT // shift L3 index into position ;; (p7) cmp.eq.or.andcm p6,p7=r17,r0 // was L2 entry NULL? dep r17=r19,r17,3,(PAGE_SHIFT-3) // compute address of L3 page table entry diff --git a/trunk/arch/ia64/kernel/ptrace.c b/trunk/arch/ia64/kernel/ptrace.c index 6d57aebad485..575a8f657b31 100644 --- a/trunk/arch/ia64/kernel/ptrace.c +++ b/trunk/arch/ia64/kernel/ptrace.c @@ -945,13 +945,6 @@ access_uarea (struct task_struct *child, unsigned long addr, *data = (pt->cr_ipsr & IPSR_MASK); return 0; - case PT_AR_RSC: - if (write_access) - pt->ar_rsc = *data | (3 << 2); /* force PL3 */ - else - *data = pt->ar_rsc; - return 0; - case PT_AR_RNAT: urbs_end = ia64_get_user_rbs_end(child, pt, NULL); rnat_addr = (long) ia64_rse_rnat_addr((long *) @@ -1003,6 +996,9 @@ access_uarea (struct task_struct *child, unsigned long addr, case PT_AR_BSPSTORE: ptr = pt_reg_addr(pt, ar_bspstore); break; + case PT_AR_RSC: + ptr = pt_reg_addr(pt, ar_rsc); + break; case PT_AR_UNAT: ptr = pt_reg_addr(pt, ar_unat); break; @@ -1238,7 +1234,7 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs __user *ppr) static long ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr) { - unsigned long psr, rsc, ec, lc, rnat, bsp, cfm, nat_bits, val = 0; + unsigned long psr, ec, lc, rnat, bsp, cfm, nat_bits, val = 0; struct unw_frame_info info; struct switch_stack *sw; struct ia64_fpreg fpval; @@ -1271,7 +1267,7 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr) /* app regs */ retval |= __get_user(pt->ar_pfs, &ppr->ar[PT_AUR_PFS]); - retval |= __get_user(rsc, &ppr->ar[PT_AUR_RSC]); + retval |= __get_user(pt->ar_rsc, &ppr->ar[PT_AUR_RSC]); retval |= __get_user(pt->ar_bspstore, &ppr->ar[PT_AUR_BSPSTORE]); retval |= __get_user(pt->ar_unat, &ppr->ar[PT_AUR_UNAT]); retval |= __get_user(pt->ar_ccv, &ppr->ar[PT_AUR_CCV]); @@ -1369,7 +1365,6 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr) retval |= __get_user(nat_bits, &ppr->nat); retval |= access_uarea(child, PT_CR_IPSR, &psr, 1); - retval |= access_uarea(child, PT_AR_RSC, &rsc, 1); retval |= access_uarea(child, PT_AR_EC, &ec, 1); retval |= access_uarea(child, PT_AR_LC, &lc, 1); retval |= access_uarea(child, PT_AR_RNAT, &rnat, 1); diff --git a/trunk/arch/ia64/kernel/signal.c b/trunk/arch/ia64/kernel/signal.c index edd9f07860b2..499b7e5317cf 100644 --- a/trunk/arch/ia64/kernel/signal.c +++ b/trunk/arch/ia64/kernel/signal.c @@ -94,7 +94,7 @@ sys_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, long arg2, static long restore_sigcontext (struct sigcontext __user *sc, struct sigscratch *scr) { - unsigned long ip, flags, nat, um, cfm, rsc; + unsigned long ip, flags, nat, um, cfm; long err; /* Always make any pending restarted system calls return -EINTR */ @@ -106,7 +106,7 @@ restore_sigcontext (struct sigcontext __user *sc, struct sigscratch *scr) err |= __get_user(ip, &sc->sc_ip); /* instruction pointer */ err |= __get_user(cfm, &sc->sc_cfm); err |= __get_user(um, &sc->sc_um); /* user mask */ - err |= __get_user(rsc, &sc->sc_ar_rsc); + err |= __get_user(scr->pt.ar_rsc, &sc->sc_ar_rsc); err |= __get_user(scr->pt.ar_unat, &sc->sc_ar_unat); err |= __get_user(scr->pt.ar_fpsr, &sc->sc_ar_fpsr); err |= __get_user(scr->pt.ar_pfs, &sc->sc_ar_pfs); @@ -119,7 +119,6 @@ restore_sigcontext (struct sigcontext __user *sc, struct sigscratch *scr) err |= __copy_from_user(&scr->pt.r15, &sc->sc_gr[15], 8); /* r15 */ scr->pt.cr_ifs = cfm | (1UL << 63); - scr->pt.ar_rsc = rsc | (3 << 2); /* force PL3 */ /* establish new instruction pointer: */ scr->pt.cr_iip = ip & ~0x3UL; diff --git a/trunk/arch/ia64/kernel/smp.c b/trunk/arch/ia64/kernel/smp.c index b49d4ddaab93..953095e2ce15 100644 --- a/trunk/arch/ia64/kernel/smp.c +++ b/trunk/arch/ia64/kernel/smp.c @@ -269,7 +269,7 @@ smp_call_function_single (int cpuid, void (*func) (void *info), void *info, int int me = get_cpu(); /* prevent preemption and reschedule on another processor */ if (cpuid == me) { - printk(KERN_INFO "%s: trying to call self\n", __FUNCTION__); + printk("%s: trying to call self\n", __FUNCTION__); put_cpu(); return -EBUSY; } diff --git a/trunk/arch/ia64/pci/pci.c b/trunk/arch/ia64/pci/pci.c index e3fc4edea113..88641e5095b5 100644 --- a/trunk/arch/ia64/pci/pci.c +++ b/trunk/arch/ia64/pci/pci.c @@ -33,6 +33,8 @@ #include +static int pci_routeirq; + /* * Low-level SAL-based PCI configuration access functions. Note that SAL * calls are already serialized (via sal_lock), so we don't need another @@ -137,8 +139,24 @@ static void acpi_map_iosapics(void) static int __init pci_acpi_init (void) { + struct pci_dev *dev = NULL; + + printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n"); + acpi_map_iosapics(); + if (pci_routeirq) { + /* + * PCI IRQ routing is set up by pci_enable_device(), but we + * also do it here in case there are still broken drivers that + * don't use pci_enable_device(). + */ + printk(KERN_INFO "PCI: Routing interrupts for all devices because \"pci=routeirq\" specified\n"); + for_each_pci_dev(dev) + acpi_pci_irq_enable(dev); + } else + printk(KERN_INFO "PCI: If a device doesn't work, try \"pci=routeirq\". If it helps, post a report\n"); + return 0; } @@ -482,6 +500,8 @@ pcibios_align_resource (void *data, struct resource *res, char * __init pcibios_setup (char *str) { + if (!strcmp(str, "routeirq")) + pci_routeirq = 1; return NULL; } diff --git a/trunk/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/trunk/arch/ppc/platforms/85xx/mpc85xx_cds_common.c index b52c4317fefd..203b2ca61df8 100644 --- a/trunk/arch/ppc/platforms/85xx/mpc85xx_cds_common.c +++ b/trunk/arch/ppc/platforms/85xx/mpc85xx_cds_common.c @@ -149,7 +149,6 @@ void __init mpc85xx_cds_init_IRQ(void) { bd_t *binfo = (bd_t *) __res; - int i; /* Determine the Physical Address of the OpenPIC regs */ phys_addr_t OpenPIC_PAddr = binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET; diff --git a/trunk/fs/Kconfig b/trunk/fs/Kconfig index a7c0cc3203cb..178e27494b74 100644 --- a/trunk/fs/Kconfig +++ b/trunk/fs/Kconfig @@ -1268,7 +1268,6 @@ config NFS_FS depends on INET select LOCKD select SUNRPC - select NFS_ACL_SUPPORT if NFS_V3_ACL help If you are connected to some other (usually local) Unix computer (using SLIP, PLIP, PPP or Ethernet) and want to mount files residing @@ -1311,16 +1310,6 @@ config NFS_V3 If unsure, say Y. -config NFS_V3_ACL - bool "Provide client support for the NFSv3 ACL protocol extension" - depends on NFS_V3 - help - Implement the NFSv3 ACL protocol extension for manipulating POSIX - Access Control Lists. The server should also be compiled with - the NFSv3 ACL protocol extension; see the CONFIG_NFSD_V3_ACL option. - - If unsure, say N. - config NFS_V4 bool "Provide NFSv4 client support (EXPERIMENTAL)" depends on NFS_FS && EXPERIMENTAL @@ -1364,7 +1353,6 @@ config NFSD select LOCKD select SUNRPC select EXPORTFS - select NFS_ACL_SUPPORT if NFSD_V3_ACL || NFSD_V2_ACL help If you want your Linux box to act as an NFS *server*, so that other computers on your local network which support NFS can access certain @@ -1388,10 +1376,6 @@ config NFSD To compile the NFS server support as a module, choose M here: the module will be called nfsd. If unsure, say N. -config NFSD_V2_ACL - bool - depends on NFSD - config NFSD_V3 bool "Provide NFSv3 server support" depends on NFSD @@ -1399,16 +1383,6 @@ config NFSD_V3 If you would like to include the NFSv3 server as well as the NFSv2 server, say Y here. If unsure, say Y. -config NFSD_V3_ACL - bool "Provide server support for the NFSv3 ACL protocol extension" - depends on NFSD_V3 - select NFSD_V2_ACL - help - Implement the NFSv3 ACL protocol extension for manipulating POSIX - Access Control Lists on exported file systems. NFS clients should - be compiled with the NFSv3 ACL protocol extension; see the - CONFIG_NFS_V3_ACL option. If unsure, say N. - config NFSD_V4 bool "Provide NFSv4 server support (EXPERIMENTAL)" depends on NFSD_V3 && EXPERIMENTAL @@ -1453,15 +1427,6 @@ config LOCKD_V4 config EXPORTFS tristate -config NFS_ACL_SUPPORT - tristate - select FS_POSIX_ACL - -config NFS_COMMON - bool - depends on NFSD || NFS_FS - default y - config SUNRPC tristate diff --git a/trunk/fs/Makefile b/trunk/fs/Makefile index fc92e59e9faf..443f2bc56ccf 100644 --- a/trunk/fs/Makefile +++ b/trunk/fs/Makefile @@ -31,7 +31,6 @@ obj-$(CONFIG_BINFMT_FLAT) += binfmt_flat.o obj-$(CONFIG_FS_MBCACHE) += mbcache.o obj-$(CONFIG_FS_POSIX_ACL) += posix_acl.o xattr_acl.o -obj-$(CONFIG_NFS_COMMON) += nfs_common/ obj-$(CONFIG_QUOTA) += dquot.o obj-$(CONFIG_QFMT_V1) += quota_v1.o diff --git a/trunk/fs/lockd/clntlock.c b/trunk/fs/lockd/clntlock.c index 006bb9e14579..ef7103b8c5bd 100644 --- a/trunk/fs/lockd/clntlock.c +++ b/trunk/fs/lockd/clntlock.c @@ -31,7 +31,7 @@ static int reclaimer(void *ptr); * This is the representation of a blocked client lock. */ struct nlm_wait { - struct list_head b_list; /* linked list */ + struct nlm_wait * b_next; /* linked list */ wait_queue_head_t b_wait; /* where to wait on */ struct nlm_host * b_host; struct file_lock * b_lock; /* local file lock */ @@ -39,54 +39,27 @@ struct nlm_wait { u32 b_status; /* grant callback status */ }; -static LIST_HEAD(nlm_blocked); - -/* - * Queue up a lock for blocking so that the GRANTED request can see it - */ -int nlmclnt_prepare_block(struct nlm_rqst *req, struct nlm_host *host, struct file_lock *fl) -{ - struct nlm_wait *block; - - BUG_ON(req->a_block != NULL); - block = kmalloc(sizeof(*block), GFP_KERNEL); - if (block == NULL) - return -ENOMEM; - block->b_host = host; - block->b_lock = fl; - init_waitqueue_head(&block->b_wait); - block->b_status = NLM_LCK_BLOCKED; - - list_add(&block->b_list, &nlm_blocked); - req->a_block = block; - - return 0; -} - -void nlmclnt_finish_block(struct nlm_rqst *req) -{ - struct nlm_wait *block = req->a_block; - - if (block == NULL) - return; - req->a_block = NULL; - list_del(&block->b_list); - kfree(block); -} +static struct nlm_wait * nlm_blocked; /* * Block on a lock */ -long nlmclnt_block(struct nlm_rqst *req, long timeout) +int +nlmclnt_block(struct nlm_host *host, struct file_lock *fl, u32 *statp) { - struct nlm_wait *block = req->a_block; - long ret; + struct nlm_wait block, **head; + int err; + u32 pstate; - /* A borken server might ask us to block even if we didn't - * request it. Just say no! - */ - if (!req->a_args.block) - return -EAGAIN; + block.b_host = host; + block.b_lock = fl; + init_waitqueue_head(&block.b_wait); + block.b_status = NLM_LCK_BLOCKED; + block.b_next = nlm_blocked; + nlm_blocked = █ + + /* Remember pseudo nsm state */ + pstate = host->h_state; /* Go to sleep waiting for GRANT callback. Some servers seem * to lose callbacks, however, so we're going to poll from @@ -96,16 +69,28 @@ long nlmclnt_block(struct nlm_rqst *req, long timeout) * a 1 minute timeout would do. See the comment before * nlmclnt_lock for an explanation. */ - ret = wait_event_interruptible_timeout(block->b_wait, - block->b_status != NLM_LCK_BLOCKED, - timeout); + sleep_on_timeout(&block.b_wait, 30*HZ); + + for (head = &nlm_blocked; *head; head = &(*head)->b_next) { + if (*head == &block) { + *head = block.b_next; + break; + } + } - if (block->b_status != NLM_LCK_BLOCKED) { - req->a_res.status = block->b_status; - block->b_status = NLM_LCK_BLOCKED; + if (!signalled()) { + *statp = block.b_status; + return 0; } - return ret; + /* Okay, we were interrupted. Cancel the pending request + * unless the server has rebooted. + */ + if (pstate == host->h_state && (err = nlmclnt_cancel(host, fl)) < 0) + printk(KERN_NOTICE + "lockd: CANCEL call failed (errno %d)\n", -err); + + return -ERESTARTSYS; } /* @@ -115,23 +100,27 @@ u32 nlmclnt_grant(struct nlm_lock *lock) { struct nlm_wait *block; - u32 res = nlm_lck_denied; /* * Look up blocked request based on arguments. * Warning: must not use cookie to match it! */ - list_for_each_entry(block, &nlm_blocked, b_list) { - if (nlm_compare_locks(block->b_lock, &lock->fl)) { - /* Alright, we found a lock. Set the return status - * and wake up the caller - */ - block->b_status = NLM_LCK_GRANTED; - wake_up(&block->b_wait); - res = nlm_granted; - } + for (block = nlm_blocked; block; block = block->b_next) { + if (nlm_compare_locks(block->b_lock, &lock->fl)) + break; } - return res; + + /* Ooops, no blocked request found. */ + if (block == NULL) + return nlm_lck_denied; + + /* Alright, we found the lock. Set the return status and + * wake up the caller. + */ + block->b_status = NLM_LCK_GRANTED; + wake_up(&block->b_wait); + + return nlm_granted; } /* @@ -241,7 +230,7 @@ reclaimer(void *ptr) host->h_reclaiming = 0; /* Now, wake up all processes that sleep on a blocked lock */ - list_for_each_entry(block, &nlm_blocked, b_list) { + for (block = nlm_blocked; block; block = block->b_next) { if (block->b_host == host) { block->b_status = NLM_LCK_DENIED_GRACE_PERIOD; wake_up(&block->b_wait); diff --git a/trunk/fs/lockd/clntproc.c b/trunk/fs/lockd/clntproc.c index fd77ed1d710d..a4407619b1f1 100644 --- a/trunk/fs/lockd/clntproc.c +++ b/trunk/fs/lockd/clntproc.c @@ -21,7 +21,6 @@ #define NLMDBG_FACILITY NLMDBG_CLIENT #define NLMCLNT_GRACE_WAIT (5*HZ) -#define NLMCLNT_POLL_TIMEOUT (30*HZ) static int nlmclnt_test(struct nlm_rqst *, struct file_lock *); static int nlmclnt_lock(struct nlm_rqst *, struct file_lock *); @@ -554,8 +553,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) { struct nlm_host *host = req->a_host; struct nlm_res *resp = &req->a_res; - long timeout; - int status; + int status; if (!host->h_monitored && nsm_monitor(host) < 0) { printk(KERN_NOTICE "lockd: failed to monitor %s\n", @@ -564,32 +562,15 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) goto out; } - if (req->a_args.block) { - status = nlmclnt_prepare_block(req, host, fl); + do { + if ((status = nlmclnt_call(req, NLMPROC_LOCK)) >= 0) { + if (resp->status != NLM_LCK_BLOCKED) + break; + status = nlmclnt_block(host, fl, &resp->status); + } if (status < 0) goto out; - } - for(;;) { - status = nlmclnt_call(req, NLMPROC_LOCK); - if (status < 0) - goto out_unblock; - if (resp->status != NLM_LCK_BLOCKED) - break; - /* Wait on an NLM blocking lock */ - timeout = nlmclnt_block(req, NLMCLNT_POLL_TIMEOUT); - /* Did a reclaimer thread notify us of a server reboot? */ - if (resp->status == NLM_LCK_DENIED_GRACE_PERIOD) - continue; - if (resp->status != NLM_LCK_BLOCKED) - break; - if (timeout >= 0) - continue; - /* We were interrupted. Send a CANCEL request to the server - * and exit - */ - status = (int)timeout; - goto out_unblock; - } + } while (resp->status == NLM_LCK_BLOCKED && req->a_args.block); if (resp->status == NLM_LCK_GRANTED) { fl->fl_u.nfs_fl.state = host->h_state; @@ -598,11 +579,6 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) do_vfs_lock(fl); } status = nlm_stat_to_errno(resp->status); -out_unblock: - nlmclnt_finish_block(req); - /* Cancel the blocked request if it is still pending */ - if (resp->status == NLM_LCK_BLOCKED) - nlmclnt_cancel(host, fl); out: nlmclnt_release_lockargs(req); return status; diff --git a/trunk/fs/lockd/host.c b/trunk/fs/lockd/host.c index 82c77df81c5f..52707c5ad6ea 100644 --- a/trunk/fs/lockd/host.c +++ b/trunk/fs/lockd/host.c @@ -189,15 +189,17 @@ nlm_bind_host(struct nlm_host *host) goto forgetit; xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout); - xprt->nocong = 1; /* No congestion control for NLM */ - xprt->resvport = 1; /* NLM requires a reserved port */ /* Existing NLM servers accept AUTH_UNIX only */ clnt = rpc_create_client(xprt, host->h_name, &nlm_program, host->h_version, RPC_AUTH_UNIX); - if (IS_ERR(clnt)) + if (IS_ERR(clnt)) { + xprt_destroy(xprt); goto forgetit; + } clnt->cl_autobind = 1; /* turn on pmap queries */ + xprt->nocong = 1; /* No congestion control for NLM */ + xprt->resvport = 1; /* NLM requires a reserved port */ host->h_rpcclnt = clnt; } diff --git a/trunk/fs/lockd/mon.c b/trunk/fs/lockd/mon.c index 2d144abe84ad..6fc1bebeec1d 100644 --- a/trunk/fs/lockd/mon.c +++ b/trunk/fs/lockd/mon.c @@ -115,19 +115,20 @@ nsm_create(void) xprt = xprt_create_proto(IPPROTO_UDP, &sin, NULL); if (IS_ERR(xprt)) return (struct rpc_clnt *)xprt; - xprt->resvport = 1; /* NSM requires a reserved port */ clnt = rpc_create_client(xprt, "localhost", &nsm_program, SM_VERSION, RPC_AUTH_NULL); if (IS_ERR(clnt)) - goto out_err; + goto out_destroy; clnt->cl_softrtry = 1; clnt->cl_chatty = 1; clnt->cl_oneshot = 1; + xprt->resvport = 1; /* NSM requires a reserved port */ return clnt; -out_err: +out_destroy: + xprt_destroy(xprt); return clnt; } diff --git a/trunk/fs/locks.c b/trunk/fs/locks.c index a0bc03495bd4..3fa6a7ce57a7 100644 --- a/trunk/fs/locks.c +++ b/trunk/fs/locks.c @@ -1548,8 +1548,6 @@ int fcntl_getlk(struct file *filp, struct flock __user *l) if (filp->f_op && filp->f_op->lock) { error = filp->f_op->lock(filp, F_GETLK, &file_lock); - if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private) - file_lock.fl_ops->fl_release_private(&file_lock); if (error < 0) goto out; else @@ -1692,8 +1690,6 @@ int fcntl_getlk64(struct file *filp, struct flock64 __user *l) if (filp->f_op && filp->f_op->lock) { error = filp->f_op->lock(filp, F_GETLK, &file_lock); - if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private) - file_lock.fl_ops->fl_release_private(&file_lock); if (error < 0) goto out; else @@ -1877,8 +1873,6 @@ void locks_remove_flock(struct file *filp) .fl_end = OFFSET_MAX, }; filp->f_op->flock(filp, F_SETLKW, &fl); - if (fl.fl_ops && fl.fl_ops->fl_release_private) - fl.fl_ops->fl_release_private(&fl); } lock_kernel(); diff --git a/trunk/fs/nfs/Makefile b/trunk/fs/nfs/Makefile index 8b3bb715d177..b4baa031edf4 100644 --- a/trunk/fs/nfs/Makefile +++ b/trunk/fs/nfs/Makefile @@ -8,7 +8,6 @@ nfs-y := dir.o file.o inode.o nfs2xdr.o pagelist.o \ proc.o read.o symlink.o unlink.o write.o nfs-$(CONFIG_ROOT_NFS) += nfsroot.o mount_clnt.o nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o -nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \ delegation.o idmap.o \ callback.o callback_xdr.o callback_proc.o diff --git a/trunk/fs/nfs/callback.c b/trunk/fs/nfs/callback.c index f2ca782aba33..560d6175dd58 100644 --- a/trunk/fs/nfs/callback.c +++ b/trunk/fs/nfs/callback.c @@ -14,7 +14,6 @@ #include #include #include -#include "nfs4_fs.h" #include "callback.h" #define NFSDBG_FACILITY NFSDBG_CALLBACK diff --git a/trunk/fs/nfs/callback_proc.c b/trunk/fs/nfs/callback_proc.c index 65f1e19e4d19..ece27e42b93b 100644 --- a/trunk/fs/nfs/callback_proc.c +++ b/trunk/fs/nfs/callback_proc.c @@ -8,7 +8,6 @@ #include #include #include -#include "nfs4_fs.h" #include "callback.h" #include "delegation.h" diff --git a/trunk/fs/nfs/callback_xdr.c b/trunk/fs/nfs/callback_xdr.c index 7c33b9a81a94..d271df9df2b2 100644 --- a/trunk/fs/nfs/callback_xdr.c +++ b/trunk/fs/nfs/callback_xdr.c @@ -10,7 +10,6 @@ #include #include #include -#include "nfs4_fs.h" #include "callback.h" #define CB_OP_TAGLEN_MAXSZ (512) @@ -411,6 +410,7 @@ static int nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *resp xdr_init_decode(&xdr_in, &rqstp->rq_arg, rqstp->rq_arg.head[0].iov_base); p = (uint32_t*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len); + rqstp->rq_res.head[0].iov_len = PAGE_SIZE; xdr_init_encode(&xdr_out, &rqstp->rq_res, p); decode_compound_hdr_arg(&xdr_in, &hdr_arg); diff --git a/trunk/fs/nfs/delegation.c b/trunk/fs/nfs/delegation.c index d7f7eb669d03..5b9c60f97791 100644 --- a/trunk/fs/nfs/delegation.c +++ b/trunk/fs/nfs/delegation.c @@ -16,7 +16,6 @@ #include #include -#include "nfs4_fs.h" #include "delegation.h" static struct nfs_delegation *nfs_alloc_delegation(void) diff --git a/trunk/fs/nfs/dir.c b/trunk/fs/nfs/dir.c index b38a57e78a63..ff6155f5e8d9 100644 --- a/trunk/fs/nfs/dir.c +++ b/trunk/fs/nfs/dir.c @@ -32,7 +32,6 @@ #include #include -#include "nfs4_fs.h" #include "delegation.h" #define NFS_PARANOIA 1 @@ -51,10 +50,8 @@ static int nfs_mknod(struct inode *, struct dentry *, int, dev_t); static int nfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); static int nfs_fsync_dir(struct file *, struct dentry *, int); -static loff_t nfs_llseek_dir(struct file *, loff_t, int); struct file_operations nfs_dir_operations = { - .llseek = nfs_llseek_dir, .read = generic_read_dir, .readdir = nfs_readdir, .open = nfs_opendir, @@ -77,27 +74,6 @@ struct inode_operations nfs_dir_inode_operations = { .setattr = nfs_setattr, }; -#ifdef CONFIG_NFS_V3 -struct inode_operations nfs3_dir_inode_operations = { - .create = nfs_create, - .lookup = nfs_lookup, - .link = nfs_link, - .unlink = nfs_unlink, - .symlink = nfs_symlink, - .mkdir = nfs_mkdir, - .rmdir = nfs_rmdir, - .mknod = nfs_mknod, - .rename = nfs_rename, - .permission = nfs_permission, - .getattr = nfs_getattr, - .setattr = nfs_setattr, - .listxattr = nfs3_listxattr, - .getxattr = nfs3_getxattr, - .setxattr = nfs3_setxattr, - .removexattr = nfs3_removexattr, -}; -#endif /* CONFIG_NFS_V3 */ - #ifdef CONFIG_NFS_V4 static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *); @@ -114,9 +90,6 @@ struct inode_operations nfs4_dir_inode_operations = { .permission = nfs_permission, .getattr = nfs_getattr, .setattr = nfs_setattr, - .getxattr = nfs4_getxattr, - .setxattr = nfs4_setxattr, - .listxattr = nfs4_listxattr, }; #endif /* CONFIG_NFS_V4 */ @@ -143,8 +116,7 @@ typedef struct { struct page *page; unsigned long page_index; u32 *ptr; - u64 *dir_cookie; - loff_t current_index; + u64 target; struct nfs_entry *entry; decode_dirent_t decode; int plus; @@ -192,10 +164,12 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) NFS_FLAGS(inode) |= NFS_INO_INVALID_ATIME; /* Ensure consistent page alignment of the data. * Note: assumes we have exclusive access to this mapping either - * through inode->i_sem or some other mechanism. + * throught inode->i_sem or some other mechanism. */ - if (page->index == 0) - invalidate_inode_pages2_range(inode->i_mapping, PAGE_CACHE_SIZE, -1); + if (page->index == 0) { + invalidate_inode_pages(inode->i_mapping); + NFS_I(inode)->readdir_timestamp = timestamp; + } unlock_page(page); return 0; error: @@ -228,22 +202,22 @@ void dir_page_release(nfs_readdir_descriptor_t *desc) /* * Given a pointer to a buffer that has already been filled by a call - * to readdir, find the next entry with cookie '*desc->dir_cookie'. + * to readdir, find the next entry. * * If the end of the buffer has been reached, return -EAGAIN, if not, * return the offset within the buffer of the next entry to be * read. */ static inline -int find_dirent(nfs_readdir_descriptor_t *desc) +int find_dirent(nfs_readdir_descriptor_t *desc, struct page *page) { struct nfs_entry *entry = desc->entry; int loop_count = 0, status; while((status = dir_decode(desc)) == 0) { - dfprintk(VFS, "NFS: found cookie %Lu\n", (unsigned long long)entry->cookie); - if (entry->prev_cookie == *desc->dir_cookie) + dfprintk(VFS, "NFS: found cookie %Lu\n", (long long)entry->cookie); + if (entry->prev_cookie == desc->target) break; if (loop_count++ > 200) { loop_count = 0; @@ -255,44 +229,8 @@ int find_dirent(nfs_readdir_descriptor_t *desc) } /* - * Given a pointer to a buffer that has already been filled by a call - * to readdir, find the entry at offset 'desc->file->f_pos'. - * - * If the end of the buffer has been reached, return -EAGAIN, if not, - * return the offset within the buffer of the next entry to be - * read. - */ -static inline -int find_dirent_index(nfs_readdir_descriptor_t *desc) -{ - struct nfs_entry *entry = desc->entry; - int loop_count = 0, - status; - - for(;;) { - status = dir_decode(desc); - if (status) - break; - - dfprintk(VFS, "NFS: found cookie %Lu at index %Ld\n", (unsigned long long)entry->cookie, desc->current_index); - - if (desc->file->f_pos == desc->current_index) { - *desc->dir_cookie = entry->cookie; - break; - } - desc->current_index++; - if (loop_count++ > 200) { - loop_count = 0; - schedule(); - } - } - dfprintk(VFS, "NFS: find_dirent_index() returns %d\n", status); - return status; -} - -/* - * Find the given page, and call find_dirent() or find_dirent_index in - * order to try to return the next entry. + * Find the given page, and call find_dirent() in order to try to + * return the next entry. */ static inline int find_dirent_page(nfs_readdir_descriptor_t *desc) @@ -315,10 +253,7 @@ int find_dirent_page(nfs_readdir_descriptor_t *desc) /* NOTE: Someone else may have changed the READDIRPLUS flag */ desc->page = page; desc->ptr = kmap(page); /* matching kunmap in nfs_do_filldir */ - if (*desc->dir_cookie != 0) - status = find_dirent(desc); - else - status = find_dirent_index(desc); + status = find_dirent(desc, page); if (status < 0) dir_page_release(desc); out: @@ -333,8 +268,7 @@ int find_dirent_page(nfs_readdir_descriptor_t *desc) * Recurse through the page cache pages, and return a * filled nfs_entry structure of the next directory entry if possible. * - * The target for the search is '*desc->dir_cookie' if non-0, - * 'desc->file->f_pos' otherwise + * The target for the search is 'desc->target'. */ static inline int readdir_search_pagecache(nfs_readdir_descriptor_t *desc) @@ -342,16 +276,7 @@ int readdir_search_pagecache(nfs_readdir_descriptor_t *desc) int loop_count = 0; int res; - /* Always search-by-index from the beginning of the cache */ - if (*desc->dir_cookie == 0) { - dfprintk(VFS, "NFS: readdir_search_pagecache() searching for offset %Ld\n", (long long)desc->file->f_pos); - desc->page_index = 0; - desc->entry->cookie = desc->entry->prev_cookie = 0; - desc->entry->eof = 0; - desc->current_index = 0; - } else - dfprintk(VFS, "NFS: readdir_search_pagecache() searching for cookie %Lu\n", (unsigned long long)*desc->dir_cookie); - + dfprintk(VFS, "NFS: readdir_search_pagecache() searching for cookie %Lu\n", (long long)desc->target); for (;;) { res = find_dirent_page(desc); if (res != -EAGAIN) @@ -388,7 +313,7 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, int loop_count = 0, res; - dfprintk(VFS, "NFS: nfs_do_filldir() filling starting @ cookie %Lu\n", (long long)entry->cookie); + dfprintk(VFS, "NFS: nfs_do_filldir() filling starting @ cookie %Lu\n", (long long)desc->target); for(;;) { unsigned d_type = DT_UNKNOWN; @@ -408,11 +333,10 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, } res = filldir(dirent, entry->name, entry->len, - file->f_pos, fileid, d_type); + entry->prev_cookie, fileid, d_type); if (res < 0) break; - file->f_pos++; - *desc->dir_cookie = entry->cookie; + file->f_pos = desc->target = entry->cookie; if (dir_decode(desc) != 0) { desc->page_index ++; break; @@ -425,7 +349,7 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, dir_page_release(desc); if (dentry != NULL) dput(dentry); - dfprintk(VFS, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", (unsigned long long)*desc->dir_cookie, res); + dfprintk(VFS, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", (long long)desc->target, res); return res; } @@ -451,14 +375,14 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, struct page *page = NULL; int status; - dfprintk(VFS, "NFS: uncached_readdir() searching for cookie %Lu\n", (unsigned long long)*desc->dir_cookie); + dfprintk(VFS, "NFS: uncached_readdir() searching for cookie %Lu\n", (long long)desc->target); page = alloc_page(GFP_HIGHUSER); if (!page) { status = -ENOMEM; goto out; } - desc->error = NFS_PROTO(inode)->readdir(file->f_dentry, cred, *desc->dir_cookie, + desc->error = NFS_PROTO(inode)->readdir(file->f_dentry, cred, desc->target, page, NFS_SERVER(inode)->dtsize, desc->plus); @@ -467,7 +391,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, desc->ptr = kmap(page); /* matching kunmap in nfs_do_filldir */ if (desc->error >= 0) { if ((status = dir_decode(desc)) == 0) - desc->entry->prev_cookie = *desc->dir_cookie; + desc->entry->prev_cookie = desc->target; } else status = -EIO; if (status < 0) @@ -488,9 +412,8 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, goto out; } -/* The file offset position represents the dirent entry number. A - last cookie cache takes care of the common case of reading the - whole directory. +/* The file offset position is now represented as a true offset into the + * page cache as is the case in most of the other filesystems. */ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) { @@ -512,15 +435,15 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) } /* - * filp->f_pos points to the dirent entry number. - * *desc->dir_cookie has the cookie for the next entry. We have - * to either find the entry with the appropriate number or - * revalidate the cookie. + * filp->f_pos points to the file offset in the page cache. + * but if the cache has meanwhile been zapped, we need to + * read from the last dirent to revalidate f_pos + * itself. */ memset(desc, 0, sizeof(*desc)); desc->file = filp; - desc->dir_cookie = &((struct nfs_open_context *)filp->private_data)->dir_cookie; + desc->target = filp->f_pos; desc->decode = NFS_PROTO(inode)->decode_dirent; desc->plus = NFS_USE_READDIRPLUS(inode); @@ -532,10 +455,9 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) while(!desc->entry->eof) { res = readdir_search_pagecache(desc); - if (res == -EBADCOOKIE) { /* This means either end of directory */ - if (*desc->dir_cookie && desc->entry->cookie != *desc->dir_cookie) { + if (desc->entry->cookie != desc->target) { /* Or that the server has 'lost' a cookie */ res = uncached_readdir(desc, dirent, filldir); if (res >= 0) @@ -568,28 +490,6 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) return 0; } -loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin) -{ - down(&filp->f_dentry->d_inode->i_sem); - switch (origin) { - case 1: - offset += filp->f_pos; - case 0: - if (offset >= 0) - break; - default: - offset = -EINVAL; - goto out; - } - if (offset != filp->f_pos) { - filp->f_pos = offset; - ((struct nfs_open_context *)filp->private_data)->dir_cookie = 0; - } -out: - up(&filp->f_dentry->d_inode->i_sem); - return offset; -} - /* * All directory operations under NFS are synchronous, so fsync() * is a dummy operation. diff --git a/trunk/fs/nfs/direct.c b/trunk/fs/nfs/direct.c index d6a30c844de3..68df803f27ca 100644 --- a/trunk/fs/nfs/direct.c +++ b/trunk/fs/nfs/direct.c @@ -517,7 +517,7 @@ static ssize_t nfs_direct_write_seg(struct inode *inode, result = tot_bytes; out: - nfs_end_data_update(inode); + nfs_end_data_update_defer(inode); nfs_writedata_free(wdata); return result; diff --git a/trunk/fs/nfs/file.c b/trunk/fs/nfs/file.c index 5621ba9885f4..55c907592490 100644 --- a/trunk/fs/nfs/file.c +++ b/trunk/fs/nfs/file.c @@ -71,18 +71,6 @@ struct inode_operations nfs_file_inode_operations = { .setattr = nfs_setattr, }; -#ifdef CONFIG_NFS_V3 -struct inode_operations nfs3_file_inode_operations = { - .permission = nfs_permission, - .getattr = nfs_getattr, - .setattr = nfs_setattr, - .listxattr = nfs3_listxattr, - .getxattr = nfs3_getxattr, - .setxattr = nfs3_setxattr, - .removexattr = nfs3_removexattr, -}; -#endif /* CONFIG_NFS_v3 */ - /* Hack for future NFS swap support */ #ifndef IS_SWAPFILE # define IS_SWAPFILE(inode) (0) @@ -127,21 +115,6 @@ nfs_file_release(struct inode *inode, struct file *filp) return NFS_PROTO(inode)->file_release(inode, filp); } -/** - * nfs_revalidate_file - Revalidate the page cache & related metadata - * @inode - pointer to inode struct - * @file - pointer to file - */ -static int nfs_revalidate_file(struct inode *inode, struct file *filp) -{ - int retval = 0; - - if ((NFS_FLAGS(inode) & NFS_INO_REVAL_PAGECACHE) || nfs_attribute_timeout(inode)) - retval = __nfs_revalidate_inode(NFS_SERVER(inode), inode); - nfs_revalidate_mapping(inode, filp->f_mapping); - return 0; -} - /** * nfs_revalidate_size - Revalidate the file size * @inode - pointer to inode struct @@ -164,8 +137,7 @@ static int nfs_revalidate_file_size(struct inode *inode, struct file *filp) goto force_reval; if (nfsi->npages != 0) return 0; - if (!(NFS_FLAGS(inode) & NFS_INO_REVAL_PAGECACHE) && !nfs_attribute_timeout(inode)) - return 0; + return nfs_revalidate_inode(server, inode); force_reval: return __nfs_revalidate_inode(server, inode); } @@ -226,7 +198,7 @@ nfs_file_read(struct kiocb *iocb, char __user * buf, size_t count, loff_t pos) dentry->d_parent->d_name.name, dentry->d_name.name, (unsigned long) count, (unsigned long) pos); - result = nfs_revalidate_file(inode, iocb->ki_filp); + result = nfs_revalidate_inode(NFS_SERVER(inode), inode); if (!result) result = generic_file_aio_read(iocb, buf, count, pos); return result; @@ -244,7 +216,7 @@ nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count, dentry->d_parent->d_name.name, dentry->d_name.name, (unsigned long) count, (unsigned long long) *ppos); - res = nfs_revalidate_file(inode, filp); + res = nfs_revalidate_inode(NFS_SERVER(inode), inode); if (!res) res = generic_file_sendfile(filp, ppos, count, actor, target); return res; @@ -260,7 +232,7 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma) dfprintk(VFS, "nfs: mmap(%s/%s)\n", dentry->d_parent->d_name.name, dentry->d_name.name); - status = nfs_revalidate_file(inode, file); + status = nfs_revalidate_inode(NFS_SERVER(inode), inode); if (!status) status = generic_file_mmap(file, vma); return status; @@ -349,15 +321,9 @@ nfs_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t result = -EBUSY; if (IS_SWAPFILE(inode)) goto out_swapfile; - /* - * O_APPEND implies that we must revalidate the file length. - */ - if (iocb->ki_filp->f_flags & O_APPEND) { - result = nfs_revalidate_file_size(inode, iocb->ki_filp); - if (result) - goto out; - } - nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping); + result = nfs_revalidate_inode(NFS_SERVER(inode), inode); + if (result) + goto out; result = count; if (!count) diff --git a/trunk/fs/nfs/idmap.c b/trunk/fs/nfs/idmap.c index ffb8df91dc34..87f4f9aeac86 100644 --- a/trunk/fs/nfs/idmap.c +++ b/trunk/fs/nfs/idmap.c @@ -50,7 +50,6 @@ #include #include -#include "nfs4_fs.h" #define IDMAP_HASH_SZ 128 diff --git a/trunk/fs/nfs/inode.c b/trunk/fs/nfs/inode.c index 4845911f1c63..f2317f3e29f9 100644 --- a/trunk/fs/nfs/inode.c +++ b/trunk/fs/nfs/inode.c @@ -39,7 +39,6 @@ #include #include -#include "nfs4_fs.h" #include "delegation.h" #define NFSDBG_FACILITY NFSDBG_VFS @@ -64,7 +63,6 @@ static void nfs_clear_inode(struct inode *); 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 void nfs_zap_acl_cache(struct inode *); static struct rpc_program nfs_program; @@ -108,21 +106,6 @@ static struct rpc_program nfs_program = { .pipe_dir_name = "/nfs", }; -#ifdef CONFIG_NFS_V3_ACL -static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program }; -static struct rpc_version * nfsacl_version[] = { - [3] = &nfsacl_version3, -}; - -struct rpc_program nfsacl_program = { - .name = "nfsacl", - .number = NFS_ACL_PROGRAM, - .nrvers = sizeof(nfsacl_version) / sizeof(nfsacl_version[0]), - .version = nfsacl_version, - .stats = &nfsacl_rpcstat, -}; -#endif /* CONFIG_NFS_V3_ACL */ - static inline unsigned long nfs_fattr_to_ino_t(struct nfs_fattr *fattr) { @@ -135,7 +118,7 @@ nfs_write_inode(struct inode *inode, int sync) int flags = sync ? FLUSH_WAIT : 0; int ret; - ret = nfs_commit_inode(inode, flags); + ret = nfs_commit_inode(inode, 0, 0, flags); if (ret < 0) return ret; return 0; @@ -157,6 +140,10 @@ nfs_delete_inode(struct inode * inode) clear_inode(inode); } +/* + * For the moment, the only task for the NFS clear_inode method is to + * release the mmap credential + */ static void nfs_clear_inode(struct inode *inode) { @@ -165,7 +152,6 @@ nfs_clear_inode(struct inode *inode) nfs_wb_all(inode); BUG_ON (!list_empty(&nfsi->open_files)); - nfs_zap_acl_cache(inode); cred = nfsi->cache_access.cred; if (cred) put_rpccred(cred); @@ -175,13 +161,11 @@ nfs_clear_inode(struct inode *inode) void nfs_umount_begin(struct super_block *sb) { - struct rpc_clnt *rpc = NFS_SB(sb)->client; + struct nfs_server *server = NFS_SB(sb); + struct rpc_clnt *rpc; /* -EIO all pending I/O */ - if (!IS_ERR(rpc)) - rpc_killall_tasks(rpc); - rpc = NFS_SB(sb)->client_acl; - if (!IS_ERR(rpc)) + if ((rpc = server->client) != NULL) rpc_killall_tasks(rpc); } @@ -382,15 +366,13 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data) xprt = xprt_create_proto(tcp ? IPPROTO_TCP : IPPROTO_UDP, &server->addr, &timeparms); if (IS_ERR(xprt)) { - dprintk("%s: cannot create RPC transport. Error = %ld\n", - __FUNCTION__, PTR_ERR(xprt)); + printk(KERN_WARNING "NFS: cannot create RPC transport.\n"); return (struct rpc_clnt *)xprt; } clnt = rpc_create_client(xprt, server->hostname, &nfs_program, server->rpc_ops->version, data->pseudoflavor); if (IS_ERR(clnt)) { - dprintk("%s: cannot create RPC client. Error = %ld\n", - __FUNCTION__, PTR_ERR(xprt)); + printk(KERN_WARNING "NFS: cannot create RPC client.\n"); goto out_fail; } @@ -401,6 +383,7 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data) return clnt; out_fail: + xprt_destroy(xprt); return clnt; } @@ -444,16 +427,21 @@ nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent) /* Check NFS protocol revision and initialize RPC op vector * and file handle pool. */ -#ifdef CONFIG_NFS_V3 if (server->flags & NFS_MOUNT_VER3) { +#ifdef CONFIG_NFS_V3 server->rpc_ops = &nfs_v3_clientops; server->caps |= NFS_CAP_READDIRPLUS; + if (data->version < 4) { + printk(KERN_NOTICE "NFS: NFSv3 not supported by mount program.\n"); + return -EIO; + } +#else + printk(KERN_NOTICE "NFS: NFSv3 not supported.\n"); + return -EIO; +#endif } else { server->rpc_ops = &nfs_v2_clientops; } -#else - server->rpc_ops = &nfs_v2_clientops; -#endif /* Fill in pseudoflavor for mount version < 5 */ if (!(data->flags & NFS_MOUNT_SECFLAVOUR)) @@ -467,34 +455,17 @@ nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent) return PTR_ERR(server->client); /* RFC 2623, sec 2.3.2 */ if (authflavor != RPC_AUTH_UNIX) { - struct rpc_auth *auth; - server->client_sys = rpc_clone_client(server->client); if (IS_ERR(server->client_sys)) return PTR_ERR(server->client_sys); - auth = rpcauth_create(RPC_AUTH_UNIX, server->client_sys); - if (IS_ERR(auth)) - return PTR_ERR(auth); + if (!rpcauth_create(RPC_AUTH_UNIX, server->client_sys)) + return -ENOMEM; } else { atomic_inc(&server->client->cl_count); server->client_sys = server->client; } + if (server->flags & NFS_MOUNT_VER3) { -#ifdef CONFIG_NFS_V3_ACL - if (!(server->flags & NFS_MOUNT_NOACL)) { - server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3); - /* No errors! Assume that Sun nfsacls are supported */ - if (!IS_ERR(server->client_acl)) - server->caps |= NFS_CAP_ACLS; - } -#else - server->flags &= ~NFS_MOUNT_NOACL; -#endif /* CONFIG_NFS_V3_ACL */ - /* - * The VFS shouldn't apply the umask to mode bits. We will - * do so ourselves when necessary. - */ - sb->s_flags |= MS_POSIXACL; if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN) server->namelen = NFS3_MAXNAMLEN; sb->s_time_gran = 1; @@ -578,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_NOACL, ",noacl", "" }, { 0, NULL, NULL } }; struct proc_nfs_info *nfs_infop; @@ -620,19 +590,9 @@ nfs_zap_caches(struct inode *inode) memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode))); if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) - nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; + nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS; else - nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; -} - -static void nfs_zap_acl_cache(struct inode *inode) -{ - void (*clear_acl_cache)(struct inode *); - - clear_acl_cache = NFS_PROTO(inode)->clear_acl_cache; - if (clear_acl_cache != NULL) - clear_acl_cache(inode); - NFS_I(inode)->flags &= ~NFS_INO_INVALID_ACL; + nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS; } /* @@ -729,7 +689,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) /* Why so? Because we want revalidate for devices/FIFOs, and * that's precisely what we have in nfs_file_inode_operations. */ - inode->i_op = NFS_SB(sb)->rpc_ops->file_inode_ops; + inode->i_op = &nfs_file_inode_operations; if (S_ISREG(inode->i_mode)) { inode->i_fop = &nfs_file_operations; inode->i_data.a_ops = &nfs_file_aops; @@ -832,7 +792,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) } } if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) - NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; + NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS; nfs_end_data_update(inode); unlock_kernel(); return error; @@ -891,7 +851,7 @@ struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rp ctx->state = NULL; ctx->lockowner = current->files; ctx->error = 0; - ctx->dir_cookie = 0; + init_waitqueue_head(&ctx->waitq); } return ctx; } @@ -1055,7 +1015,6 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) goto out; } flags = nfsi->flags; - nfsi->flags &= ~NFS_INO_REVAL_PAGECACHE; /* * We may need to keep the attributes marked as invalid if * we raced with nfs_end_attr_update(). @@ -1063,9 +1022,21 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) if (verifier == nfsi->cache_change_attribute) nfsi->flags &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); /* Do the page cache invalidation */ - nfs_revalidate_mapping(inode, inode->i_mapping); - if (flags & NFS_INO_INVALID_ACL) - nfs_zap_acl_cache(inode); + if (flags & NFS_INO_INVALID_DATA) { + if (S_ISREG(inode->i_mode)) { + if (filemap_fdatawrite(inode->i_mapping) == 0) + filemap_fdatawait(inode->i_mapping); + nfs_wb_all(inode); + } + nfsi->flags &= ~NFS_INO_INVALID_DATA; + invalidate_inode_pages2(inode->i_mapping); + memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode))); + dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n", + inode->i_sb->s_id, + (long long)NFS_FILEID(inode)); + /* This ensures we revalidate dentries */ + nfsi->cache_change_attribute++; + } dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n", inode->i_sb->s_id, (long long)NFS_FILEID(inode)); @@ -1102,34 +1073,6 @@ int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) return __nfs_revalidate_inode(server, inode); } -/** - * nfs_revalidate_mapping - Revalidate the pagecache - * @inode - pointer to host inode - * @mapping - pointer to mapping - */ -void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) -{ - struct nfs_inode *nfsi = NFS_I(inode); - - if (nfsi->flags & NFS_INO_INVALID_DATA) { - if (S_ISREG(inode->i_mode)) { - if (filemap_fdatawrite(mapping) == 0) - filemap_fdatawait(mapping); - nfs_wb_all(inode); - } - invalidate_inode_pages2(mapping); - nfsi->flags &= ~NFS_INO_INVALID_DATA; - if (S_ISDIR(inode->i_mode)) { - memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); - /* This ensures we revalidate child dentries */ - nfsi->cache_change_attribute++; - } - dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n", - inode->i_sb->s_id, - (long long)NFS_FILEID(inode)); - } -} - /** * nfs_begin_data_update * @inode - pointer to inode @@ -1162,6 +1105,27 @@ void nfs_end_data_update(struct inode *inode) atomic_dec(&nfsi->data_updates); } +/** + * nfs_end_data_update_defer + * @inode - pointer to inode + * Declare end of the operations that will update file data + * This will defer marking the inode as needing revalidation + * unless there are no other pending updates. + */ +void nfs_end_data_update_defer(struct inode *inode) +{ + struct nfs_inode *nfsi = NFS_I(inode); + + if (atomic_dec_and_test(&nfsi->data_updates)) { + /* Mark the attribute cache for revalidation */ + nfsi->flags |= NFS_INO_INVALID_ATTR; + /* Directories and symlinks: invalidate page cache too */ + if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) + nfsi->flags |= NFS_INO_INVALID_DATA; + nfsi->cache_change_attribute ++; + } +} + /** * nfs_refresh_inode - verify consistency of the inode attribute cache * @inode - pointer to inode @@ -1188,11 +1152,8 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) if ((fattr->valid & NFS_ATTR_PRE_CHANGE) != 0 && nfsi->change_attr == fattr->pre_change_attr) nfsi->change_attr = fattr->change_attr; - if (nfsi->change_attr != fattr->change_attr) { + if (!data_unstable && nfsi->change_attr != fattr->change_attr) nfsi->flags |= NFS_INO_INVALID_ATTR; - if (!data_unstable) - nfsi->flags |= NFS_INO_REVAL_PAGECACHE; - } } if ((fattr->valid & NFS_ATTR_FATTR) == 0) @@ -1215,22 +1176,18 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) } /* Verify a few of the more important attributes */ - if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { - nfsi->flags |= NFS_INO_INVALID_ATTR; - if (!data_unstable) - nfsi->flags |= NFS_INO_REVAL_PAGECACHE; - } - if (cur_size != new_isize) { - nfsi->flags |= NFS_INO_INVALID_ATTR; - if (nfsi->npages == 0) - nfsi->flags |= NFS_INO_REVAL_PAGECACHE; - } + if (!data_unstable) { + if (!timespec_equal(&inode->i_mtime, &fattr->mtime) + || cur_size != new_isize) + nfsi->flags |= NFS_INO_INVALID_ATTR; + } else if (S_ISREG(inode->i_mode) && new_isize > cur_size) + nfsi->flags |= NFS_INO_INVALID_ATTR; /* Have any file permissions changed? */ if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) || inode->i_uid != fattr->uid || inode->i_gid != fattr->gid) - nfsi->flags |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; + nfsi->flags |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS; /* Has the link count changed? */ if (inode->i_nlink != fattr->nlink) @@ -1258,8 +1215,10 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsigned long verifier) { struct nfs_inode *nfsi = NFS_I(inode); - loff_t cur_isize, new_isize; + __u64 new_size; + loff_t new_isize; unsigned int invalid = 0; + loff_t cur_isize; int data_unstable; dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n", @@ -1292,56 +1251,61 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign /* Are we racing with known updates of the metadata on the server? */ data_unstable = ! nfs_verify_change_attribute(inode, verifier); - /* Check if our cached file size is stale */ + /* Check if the file size agrees */ + new_size = fattr->size; new_isize = nfs_size_to_loff_t(fattr->size); cur_isize = i_size_read(inode); - if (new_isize != cur_isize) { - /* Do we perhaps have any outstanding writes? */ - if (nfsi->npages == 0) { - /* No, but did we race with nfs_end_data_update()? */ - if (verifier == nfsi->cache_change_attribute) { + if (cur_isize != new_size) { +#ifdef NFS_DEBUG_VERBOSE + printk(KERN_DEBUG "NFS: isize change on %s/%ld\n", inode->i_sb->s_id, inode->i_ino); +#endif + /* + * If we have pending writebacks, things can get + * messy. + */ + if (S_ISREG(inode->i_mode) && data_unstable) { + if (new_isize > cur_isize) { inode->i_size = new_isize; - invalid |= NFS_INO_INVALID_DATA; + invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; } - invalid |= NFS_INO_INVALID_ATTR; - } else if (new_isize > cur_isize) { + } else { inode->i_size = new_isize; invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; } - dprintk("NFS: isize change on server for file %s/%ld\n", - inode->i_sb->s_id, inode->i_ino); } - /* Check if the mtime agrees */ + /* + * Note: we don't check inode->i_mtime since pipes etc. + * can change this value in VFS without requiring a + * cache revalidation. + */ if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); - dprintk("NFS: mtime change on server for file %s/%ld\n", - inode->i_sb->s_id, inode->i_ino); +#ifdef NFS_DEBUG_VERBOSE + printk(KERN_DEBUG "NFS: mtime change on %s/%ld\n", inode->i_sb->s_id, inode->i_ino); +#endif if (!data_unstable) invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; } if ((fattr->valid & NFS_ATTR_FATTR_V4) && nfsi->change_attr != fattr->change_attr) { - dprintk("NFS: change_attr change on server for file %s/%ld\n", +#ifdef NFS_DEBUG_VERBOSE + printk(KERN_DEBUG "NFS: change_attr change on %s/%ld\n", inode->i_sb->s_id, inode->i_ino); +#endif nfsi->change_attr = fattr->change_attr; if (!data_unstable) - invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; + invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS; } - /* If ctime has changed we should definitely clear access+acl caches */ - if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) { - if (!data_unstable) - invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; - memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); - } + memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) || inode->i_uid != fattr->uid || inode->i_gid != fattr->gid) - invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; + invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS; inode->i_mode = fattr->mode; inode->i_nlink = fattr->nlink; @@ -1421,96 +1385,75 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data) { int error; - struct nfs_server *server = NULL; + struct nfs_server *server; struct super_block *s; struct nfs_fh *root; struct nfs_mount_data *data = raw_data; - s = ERR_PTR(-EINVAL); - if (data == NULL) { - dprintk("%s: missing data argument\n", __FUNCTION__); - goto out_err; - } - if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) { - dprintk("%s: bad mount version\n", __FUNCTION__); - goto out_err; - } - switch (data->version) { - case 1: - data->namlen = 0; - case 2: - data->bsize = 0; - case 3: - if (data->flags & NFS_MOUNT_VER3) { - dprintk("%s: mount structure version %d does not support NFSv3\n", - __FUNCTION__, - data->version); - goto out_err; - } - data->root.size = NFS2_FHSIZE; - memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE); - case 4: - if (data->flags & NFS_MOUNT_SECFLAVOUR) { - dprintk("%s: mount structure version %d does not support strong security\n", - __FUNCTION__, - data->version); - goto out_err; - } - case 5: - memset(data->context, 0, sizeof(data->context)); - } -#ifndef CONFIG_NFS_V3 - /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */ - s = ERR_PTR(-EPROTONOSUPPORT); - if (data->flags & NFS_MOUNT_VER3) { - dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__); - goto out_err; + if (!data) { + printk("nfs_read_super: missing data argument\n"); + return ERR_PTR(-EINVAL); } -#endif /* CONFIG_NFS_V3 */ - s = ERR_PTR(-ENOMEM); server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL); if (!server) - goto out_err; + return ERR_PTR(-ENOMEM); memset(server, 0, sizeof(struct nfs_server)); /* Zero out the NFS state stuff */ init_nfsv4_state(server); - server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); + + if (data->version != NFS_MOUNT_VERSION) { + printk("nfs warning: mount version %s than kernel\n", + data->version < NFS_MOUNT_VERSION ? "older" : "newer"); + if (data->version < 2) + data->namlen = 0; + if (data->version < 3) + data->bsize = 0; + if (data->version < 4) { + data->flags &= ~NFS_MOUNT_VER3; + data->root.size = NFS2_FHSIZE; + memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE); + } + if (data->version < 5) + data->flags &= ~NFS_MOUNT_SECFLAVOUR; + } root = &server->fh; if (data->flags & NFS_MOUNT_VER3) root->size = data->root.size; else root->size = NFS2_FHSIZE; - s = ERR_PTR(-EINVAL); if (root->size > sizeof(root->data)) { - dprintk("%s: invalid root filehandle\n", __FUNCTION__); - goto out_err; + printk("nfs_get_sb: invalid root filehandle\n"); + kfree(server); + return ERR_PTR(-EINVAL); } memcpy(root->data, data->root.data, root->size); /* We now require that the mount process passes the remote address */ memcpy(&server->addr, &data->addr, sizeof(server->addr)); if (server->addr.sin_addr.s_addr == INADDR_ANY) { - dprintk("%s: mount program didn't pass remote address!\n", - __FUNCTION__); - goto out_err; - } - - /* Fire up rpciod if not yet running */ - s = ERR_PTR(rpciod_up()); - if (IS_ERR(s)) { - dprintk("%s: couldn't start rpciod! Error = %ld\n", - __FUNCTION__, PTR_ERR(s)); - goto out_err; + printk("NFS: mount program didn't pass remote address!\n"); + kfree(server); + return ERR_PTR(-EINVAL); } s = sget(fs_type, nfs_compare_super, nfs_set_super, server); - if (IS_ERR(s) || s->s_root) - goto out_rpciod_down; + + if (IS_ERR(s) || s->s_root) { + kfree(server); + return s; + } s->s_flags = flags; + /* Fire up rpciod if not yet running */ + if (rpciod_up() != 0) { + printk(KERN_WARNING "NFS: couldn't start rpciod!\n"); + kfree(server); + return ERR_PTR(-EIO); + } + error = nfs_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); if (error) { up_write(&s->s_umount); @@ -1519,11 +1462,6 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, } s->s_flags |= MS_ACTIVE; return s; -out_rpciod_down: - rpciod_down(); -out_err: - kfree(server); - return s; } static void nfs_kill_super(struct super_block *s) @@ -1532,12 +1470,10 @@ static void nfs_kill_super(struct super_block *s) kill_anon_super(s); - if (!IS_ERR(server->client)) + if (server->client != NULL && !IS_ERR(server->client)) rpc_shutdown_client(server->client); - if (!IS_ERR(server->client_sys)) + if (server->client_sys != NULL && !IS_ERR(server->client_sys)) rpc_shutdown_client(server->client_sys); - if (!IS_ERR(server->client_acl)) - rpc_shutdown_client(server->client_acl); if (!(server->flags & NFS_MOUNT_NONLM)) lockd_down(); /* release rpc.lockd */ @@ -1658,19 +1594,15 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, clp = nfs4_get_client(&server->addr.sin_addr); if (!clp) { - dprintk("%s: failed to create NFS4 client.\n", __FUNCTION__); + printk(KERN_WARNING "NFS: failed to create NFS4 client.\n"); return -EIO; } /* Now create transport and client */ authflavour = RPC_AUTH_UNIX; if (data->auth_flavourlen != 0) { - if (data->auth_flavourlen != 1) { - dprintk("%s: Invalid number of RPC auth flavours %d.\n", - __FUNCTION__, data->auth_flavourlen); - err = -EINVAL; - goto out_fail; - } + if (data->auth_flavourlen > 1) + printk(KERN_INFO "NFS: cannot yet deal with multiple auth flavours.\n"); if (copy_from_user(&authflavour, data->auth_flavours, sizeof(authflavour))) { err = -EFAULT; goto out_fail; @@ -1678,22 +1610,21 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, } down_write(&clp->cl_sem); - if (IS_ERR(clp->cl_rpcclient)) { + if (clp->cl_rpcclient == NULL) { xprt = xprt_create_proto(proto, &server->addr, &timeparms); if (IS_ERR(xprt)) { up_write(&clp->cl_sem); + printk(KERN_WARNING "NFS: cannot create RPC transport.\n"); err = PTR_ERR(xprt); - dprintk("%s: cannot create RPC transport. Error = %d\n", - __FUNCTION__, err); goto out_fail; } clnt = rpc_create_client(xprt, server->hostname, &nfs_program, server->rpc_ops->version, authflavour); if (IS_ERR(clnt)) { up_write(&clp->cl_sem); + printk(KERN_WARNING "NFS: cannot create RPC client.\n"); + xprt_destroy(xprt); err = PTR_ERR(clnt); - dprintk("%s: cannot create RPC client. Error = %d\n", - __FUNCTION__, err); goto out_fail; } clnt->cl_intr = 1; @@ -1725,26 +1656,21 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, clp = NULL; if (IS_ERR(clnt)) { - err = PTR_ERR(clnt); - dprintk("%s: cannot create RPC client. Error = %d\n", - __FUNCTION__, err); - return err; + printk(KERN_WARNING "NFS: cannot create RPC client.\n"); + return PTR_ERR(clnt); } server->client = clnt; if (server->nfs4_state->cl_idmap == NULL) { - dprintk("%s: failed to create idmapper.\n", __FUNCTION__); + printk(KERN_WARNING "NFS: failed to create idmapper.\n"); return -ENOMEM; } if (clnt->cl_auth->au_flavor != authflavour) { - struct rpc_auth *auth; - - auth = rpcauth_create(authflavour, clnt); - if (IS_ERR(auth)) { - dprintk("%s: couldn't create credcache!\n", __FUNCTION__); - return PTR_ERR(auth); + if (rpcauth_create(authflavour, clnt) == NULL) { + printk(KERN_WARNING "NFS: couldn't create credcache!\n"); + return -ENOMEM; } } @@ -1804,12 +1730,8 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, struct nfs4_mount_data *data = raw_data; void *p; - if (data == NULL) { - dprintk("%s: missing data argument\n", __FUNCTION__); - return ERR_PTR(-EINVAL); - } - if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) { - dprintk("%s: bad mount version\n", __FUNCTION__); + if (!data) { + printk("nfs_read_super: missing data argument\n"); return ERR_PTR(-EINVAL); } @@ -1819,7 +1741,11 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, memset(server, 0, sizeof(struct nfs_server)); /* Zero out the NFS state stuff */ init_nfsv4_state(server); - server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); + + if (data->version != NFS4_MOUNT_VERSION) { + printk("nfs warning: mount version %s than kernel\n", + data->version < NFS4_MOUNT_VERSION ? "older" : "newer"); + } p = nfs_copy_user_string(NULL, &data->hostname, 256); if (IS_ERR(p)) @@ -1847,20 +1773,11 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, } if (server->addr.sin_family != AF_INET || server->addr.sin_addr.s_addr == INADDR_ANY) { - dprintk("%s: mount program didn't pass remote IP address!\n", - __FUNCTION__); + printk("NFS: mount program didn't pass remote IP address!\n"); s = ERR_PTR(-EINVAL); goto out_free; } - /* Fire up rpciod if not yet running */ - s = ERR_PTR(rpciod_up()); - if (IS_ERR(s)) { - dprintk("%s: couldn't start rpciod! Error = %ld\n", - __FUNCTION__, PTR_ERR(s)); - goto out_free; - } - s = sget(fs_type, nfs4_compare_super, nfs_set_super, server); if (IS_ERR(s) || s->s_root) @@ -1868,6 +1785,13 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, s->s_flags = flags; + /* Fire up rpciod if not yet running */ + if (rpciod_up() != 0) { + printk(KERN_WARNING "NFS: couldn't start rpciod!\n"); + s = ERR_PTR(-EIO); + goto out_free; + } + error = nfs4_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); if (error) { up_write(&s->s_umount); @@ -1951,13 +1875,6 @@ static struct inode *nfs_alloc_inode(struct super_block *sb) if (!nfsi) return NULL; nfsi->flags = 0; -#ifdef CONFIG_NFS_V3_ACL - nfsi->acl_access = ERR_PTR(-EAGAIN); - nfsi->acl_default = ERR_PTR(-EAGAIN); -#endif -#ifdef CONFIG_NFS_V4 - nfsi->nfs4_acl = NULL; -#endif /* CONFIG_NFS_V4 */ return &nfsi->vfs_inode; } diff --git a/trunk/fs/nfs/mount_clnt.c b/trunk/fs/nfs/mount_clnt.c index 0e82617f2de0..9d3ddad96d9e 100644 --- a/trunk/fs/nfs/mount_clnt.c +++ b/trunk/fs/nfs/mount_clnt.c @@ -80,7 +80,9 @@ mnt_create(char *hostname, struct sockaddr_in *srvaddr, int version, clnt = rpc_create_client(xprt, hostname, &mnt_program, version, RPC_AUTH_UNIX); - if (!IS_ERR(clnt)) { + if (IS_ERR(clnt)) { + xprt_destroy(xprt); + } else { clnt->cl_softrtry = 1; clnt->cl_chatty = 1; clnt->cl_oneshot = 1; diff --git a/trunk/fs/nfs/nfs3acl.c b/trunk/fs/nfs/nfs3acl.c deleted file mode 100644 index ee3536fc84a3..000000000000 --- a/trunk/fs/nfs/nfs3acl.c +++ /dev/null @@ -1,403 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#define NFSDBG_FACILITY NFSDBG_PROC - -ssize_t nfs3_listxattr(struct dentry *dentry, char *buffer, size_t size) -{ - struct inode *inode = dentry->d_inode; - struct posix_acl *acl; - int pos=0, len=0; - -# define output(s) do { \ - if (pos + sizeof(s) <= size) { \ - memcpy(buffer + pos, s, sizeof(s)); \ - pos += sizeof(s); \ - } \ - len += sizeof(s); \ - } while(0) - - acl = nfs3_proc_getacl(inode, ACL_TYPE_ACCESS); - if (IS_ERR(acl)) - return PTR_ERR(acl); - if (acl) { - output("system.posix_acl_access"); - posix_acl_release(acl); - } - - if (S_ISDIR(inode->i_mode)) { - acl = nfs3_proc_getacl(inode, ACL_TYPE_DEFAULT); - if (IS_ERR(acl)) - return PTR_ERR(acl); - if (acl) { - output("system.posix_acl_default"); - posix_acl_release(acl); - } - } - -# undef output - - if (!buffer || len <= size) - return len; - return -ERANGE; -} - -ssize_t nfs3_getxattr(struct dentry *dentry, const char *name, - void *buffer, size_t size) -{ - struct inode *inode = dentry->d_inode; - struct posix_acl *acl; - int type, error = 0; - - if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0) - type = ACL_TYPE_ACCESS; - else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0) - type = ACL_TYPE_DEFAULT; - else - return -EOPNOTSUPP; - - acl = nfs3_proc_getacl(inode, type); - if (IS_ERR(acl)) - return PTR_ERR(acl); - else if (acl) { - if (type == ACL_TYPE_ACCESS && acl->a_count == 0) - error = -ENODATA; - else - error = posix_acl_to_xattr(acl, buffer, size); - posix_acl_release(acl); - } else - error = -ENODATA; - - return error; -} - -int nfs3_setxattr(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags) -{ - struct inode *inode = dentry->d_inode; - struct posix_acl *acl; - int type, error; - - if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0) - type = ACL_TYPE_ACCESS; - else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0) - type = ACL_TYPE_DEFAULT; - else - return -EOPNOTSUPP; - - acl = posix_acl_from_xattr(value, size); - if (IS_ERR(acl)) - return PTR_ERR(acl); - error = nfs3_proc_setacl(inode, type, acl); - posix_acl_release(acl); - - return error; -} - -int nfs3_removexattr(struct dentry *dentry, const char *name) -{ - struct inode *inode = dentry->d_inode; - int type; - - if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0) - type = ACL_TYPE_ACCESS; - else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0) - type = ACL_TYPE_DEFAULT; - else - return -EOPNOTSUPP; - - return nfs3_proc_setacl(inode, type, NULL); -} - -static void __nfs3_forget_cached_acls(struct nfs_inode *nfsi) -{ - if (!IS_ERR(nfsi->acl_access)) { - posix_acl_release(nfsi->acl_access); - nfsi->acl_access = ERR_PTR(-EAGAIN); - } - if (!IS_ERR(nfsi->acl_default)) { - posix_acl_release(nfsi->acl_default); - nfsi->acl_default = ERR_PTR(-EAGAIN); - } -} - -void nfs3_forget_cached_acls(struct inode *inode) -{ - dprintk("NFS: nfs3_forget_cached_acls(%s/%ld)\n", inode->i_sb->s_id, - inode->i_ino); - spin_lock(&inode->i_lock); - __nfs3_forget_cached_acls(NFS_I(inode)); - spin_unlock(&inode->i_lock); -} - -static struct posix_acl *nfs3_get_cached_acl(struct inode *inode, int type) -{ - struct nfs_inode *nfsi = NFS_I(inode); - struct posix_acl *acl = ERR_PTR(-EINVAL); - - spin_lock(&inode->i_lock); - switch(type) { - case ACL_TYPE_ACCESS: - acl = nfsi->acl_access; - break; - - case ACL_TYPE_DEFAULT: - acl = nfsi->acl_default; - break; - - default: - goto out; - } - if (IS_ERR(acl)) - acl = ERR_PTR(-EAGAIN); - else - acl = posix_acl_dup(acl); -out: - spin_unlock(&inode->i_lock); - dprintk("NFS: nfs3_get_cached_acl(%s/%ld, %d) = %p\n", inode->i_sb->s_id, - inode->i_ino, type, acl); - return acl; -} - -static void nfs3_cache_acls(struct inode *inode, struct posix_acl *acl, - struct posix_acl *dfacl) -{ - struct nfs_inode *nfsi = NFS_I(inode); - - dprintk("nfs3_cache_acls(%s/%ld, %p, %p)\n", inode->i_sb->s_id, - inode->i_ino, acl, dfacl); - spin_lock(&inode->i_lock); - __nfs3_forget_cached_acls(NFS_I(inode)); - nfsi->acl_access = posix_acl_dup(acl); - nfsi->acl_default = posix_acl_dup(dfacl); - spin_unlock(&inode->i_lock); -} - -struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type) -{ - struct nfs_server *server = NFS_SERVER(inode); - struct nfs_fattr fattr; - struct page *pages[NFSACL_MAXPAGES] = { }; - struct nfs3_getaclargs args = { - .fh = NFS_FH(inode), - /* The xdr layer may allocate pages here. */ - .pages = pages, - }; - struct nfs3_getaclres res = { - .fattr = &fattr, - }; - struct posix_acl *acl; - int status, count; - - if (!nfs_server_capable(inode, NFS_CAP_ACLS)) - return ERR_PTR(-EOPNOTSUPP); - - status = nfs_revalidate_inode(server, inode); - if (status < 0) - return ERR_PTR(status); - acl = nfs3_get_cached_acl(inode, type); - if (acl != ERR_PTR(-EAGAIN)) - return acl; - acl = NULL; - - /* - * Only get the access acl when explicitly requested: We don't - * need it for access decisions, and only some applications use - * it. Applications which request the access acl first are not - * penalized from this optimization. - */ - if (type == ACL_TYPE_ACCESS) - args.mask |= NFS_ACLCNT|NFS_ACL; - if (S_ISDIR(inode->i_mode)) - args.mask |= NFS_DFACLCNT|NFS_DFACL; - if (args.mask == 0) - return NULL; - - dprintk("NFS call getacl\n"); - status = rpc_call(server->client_acl, ACLPROC3_GETACL, - &args, &res, 0); - dprintk("NFS reply getacl: %d\n", status); - - /* pages may have been allocated at the xdr layer. */ - for (count = 0; count < NFSACL_MAXPAGES && args.pages[count]; count++) - __free_page(args.pages[count]); - - switch (status) { - case 0: - status = nfs_refresh_inode(inode, &fattr); - break; - case -EPFNOSUPPORT: - case -EPROTONOSUPPORT: - dprintk("NFS_V3_ACL extension not supported; disabling\n"); - server->caps &= ~NFS_CAP_ACLS; - case -ENOTSUPP: - status = -EOPNOTSUPP; - default: - goto getout; - } - if ((args.mask & res.mask) != args.mask) { - status = -EIO; - goto getout; - } - - if (res.acl_access != NULL) { - if (posix_acl_equiv_mode(res.acl_access, NULL) == 0) { - posix_acl_release(res.acl_access); - res.acl_access = NULL; - } - } - nfs3_cache_acls(inode, res.acl_access, res.acl_default); - - switch(type) { - case ACL_TYPE_ACCESS: - acl = res.acl_access; - res.acl_access = NULL; - break; - - case ACL_TYPE_DEFAULT: - acl = res.acl_default; - res.acl_default = NULL; - } - -getout: - posix_acl_release(res.acl_access); - posix_acl_release(res.acl_default); - - if (status != 0) { - posix_acl_release(acl); - acl = ERR_PTR(status); - } - return acl; -} - -static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, - struct posix_acl *dfacl) -{ - struct nfs_server *server = NFS_SERVER(inode); - struct nfs_fattr fattr; - struct page *pages[NFSACL_MAXPAGES] = { }; - struct nfs3_setaclargs args = { - .inode = inode, - .mask = NFS_ACL, - .acl_access = acl, - .pages = pages, - }; - int status, count; - - status = -EOPNOTSUPP; - if (!nfs_server_capable(inode, NFS_CAP_ACLS)) - goto out; - - /* We are doing this here, because XDR marshalling can only - return -ENOMEM. */ - status = -ENOSPC; - if (acl != NULL && acl->a_count > NFS_ACL_MAX_ENTRIES) - goto out; - if (dfacl != NULL && dfacl->a_count > NFS_ACL_MAX_ENTRIES) - goto out; - if (S_ISDIR(inode->i_mode)) { - args.mask |= NFS_DFACL; - args.acl_default = dfacl; - } - - dprintk("NFS call setacl\n"); - nfs_begin_data_update(inode); - status = rpc_call(server->client_acl, ACLPROC3_SETACL, - &args, &fattr, 0); - NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS; - nfs_end_data_update(inode); - dprintk("NFS reply setacl: %d\n", status); - - /* pages may have been allocated at the xdr layer. */ - for (count = 0; count < NFSACL_MAXPAGES && args.pages[count]; count++) - __free_page(args.pages[count]); - - switch (status) { - case 0: - status = nfs_refresh_inode(inode, &fattr); - break; - case -EPFNOSUPPORT: - case -EPROTONOSUPPORT: - dprintk("NFS_V3_ACL SETACL RPC not supported" - "(will not retry)\n"); - server->caps &= ~NFS_CAP_ACLS; - case -ENOTSUPP: - status = -EOPNOTSUPP; - } -out: - return status; -} - -int nfs3_proc_setacl(struct inode *inode, int type, struct posix_acl *acl) -{ - struct posix_acl *alloc = NULL, *dfacl = NULL; - int status; - - if (S_ISDIR(inode->i_mode)) { - switch(type) { - case ACL_TYPE_ACCESS: - alloc = dfacl = nfs3_proc_getacl(inode, - ACL_TYPE_DEFAULT); - if (IS_ERR(alloc)) - goto fail; - break; - - case ACL_TYPE_DEFAULT: - dfacl = acl; - alloc = acl = nfs3_proc_getacl(inode, - ACL_TYPE_ACCESS); - if (IS_ERR(alloc)) - goto fail; - break; - - default: - return -EINVAL; - } - } else if (type != ACL_TYPE_ACCESS) - return -EINVAL; - - if (acl == NULL) { - alloc = acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL); - if (IS_ERR(alloc)) - goto fail; - } - status = nfs3_proc_setacls(inode, acl, dfacl); - posix_acl_release(alloc); - return status; - -fail: - return PTR_ERR(alloc); -} - -int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode, - mode_t mode) -{ - struct posix_acl *dfacl, *acl; - int error = 0; - - dfacl = nfs3_proc_getacl(dir, ACL_TYPE_DEFAULT); - if (IS_ERR(dfacl)) { - error = PTR_ERR(dfacl); - return (error == -EOPNOTSUPP) ? 0 : error; - } - if (!dfacl) - return 0; - acl = posix_acl_clone(dfacl, GFP_KERNEL); - error = -ENOMEM; - if (!acl) - goto out_release_dfacl; - error = posix_acl_create_masq(acl, &mode); - if (error < 0) - goto out_release_acl; - error = nfs3_proc_setacls(inode, acl, S_ISDIR(inode->i_mode) ? - dfacl : NULL); -out_release_acl: - posix_acl_release(acl); -out_release_dfacl: - posix_acl_release(dfacl); - return error; -} diff --git a/trunk/fs/nfs/nfs3proc.c b/trunk/fs/nfs/nfs3proc.c index 7851569b31c6..3878494dfc2c 100644 --- a/trunk/fs/nfs/nfs3proc.c +++ b/trunk/fs/nfs/nfs3proc.c @@ -17,7 +17,6 @@ #include #include #include -#include #define NFSDBG_FACILITY NFSDBG_PROC @@ -46,7 +45,7 @@ static inline int nfs3_rpc_call_wrapper(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags) { struct rpc_message msg = { - .rpc_proc = &clnt->cl_procinfo[proc], + .rpc_proc = &nfs3_procedures[proc], .rpc_argp = argp, .rpc_resp = resp, }; @@ -314,8 +313,7 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, .fh = &fhandle, .fattr = &fattr }; - mode_t mode = sattr->ia_mode; - int status; + int status; dprintk("NFS call create %s\n", dentry->d_name.name); arg.createmode = NFS3_CREATE_UNCHECKED; @@ -325,8 +323,6 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, arg.verifier[1] = current->pid; } - sattr->ia_mode &= ~current->fs->umask; - again: dir_attr.valid = 0; fattr.valid = 0; @@ -373,9 +369,6 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, nfs_refresh_inode(dentry->d_inode, &fattr); dprintk("NFS reply setattr (post-create): %d\n", status); } - if (status != 0) - goto out; - status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode); out: dprintk("NFS reply create: %d\n", status); return status; @@ -545,24 +538,15 @@ nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) .fh = &fhandle, .fattr = &fattr }; - int mode = sattr->ia_mode; - int status; + int status; dprintk("NFS call mkdir %s\n", dentry->d_name.name); dir_attr.valid = 0; fattr.valid = 0; - - sattr->ia_mode &= ~current->fs->umask; - status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, 0); nfs_refresh_inode(dir, &dir_attr); - if (status != 0) - goto out; - status = nfs_instantiate(dentry, &fhandle, &fattr); - if (status != 0) - goto out; - status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode); -out: + if (status == 0) + status = nfs_instantiate(dentry, &fhandle, &fattr); dprintk("NFS reply mkdir: %d\n", status); return status; } @@ -657,7 +641,6 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, .fh = &fh, .fattr = &fattr }; - mode_t mode = sattr->ia_mode; int status; switch (sattr->ia_mode & S_IFMT) { @@ -670,20 +653,12 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, dprintk("NFS call mknod %s %u:%u\n", dentry->d_name.name, MAJOR(rdev), MINOR(rdev)); - - sattr->ia_mode &= ~current->fs->umask; - dir_attr.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) - goto out; - status = nfs_instantiate(dentry, &fh, &fattr); - if (status != 0) - goto out; - status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode); -out: + if (status == 0) + status = nfs_instantiate(dentry, &fh, &fattr); dprintk("NFS reply mknod: %d\n", status); return status; } @@ -850,8 +825,7 @@ nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl) struct nfs_rpc_ops nfs_v3_clientops = { .version = 3, /* protocol version */ .dentry_ops = &nfs_dentry_operations, - .dir_inode_ops = &nfs3_dir_inode_operations, - .file_inode_ops = &nfs3_file_inode_operations, + .dir_inode_ops = &nfs_dir_inode_operations, .getroot = nfs3_proc_get_root, .getattr = nfs3_proc_getattr, .setattr = nfs3_proc_setattr, @@ -882,5 +856,4 @@ struct nfs_rpc_ops nfs_v3_clientops = { .file_open = nfs_open, .file_release = nfs_release, .lock = nfs3_proc_lock, - .clear_acl_cache = nfs3_forget_cached_acls, }; diff --git a/trunk/fs/nfs/nfs3xdr.c b/trunk/fs/nfs/nfs3xdr.c index db4a904810a4..a3593d47e5ab 100644 --- a/trunk/fs/nfs/nfs3xdr.c +++ b/trunk/fs/nfs/nfs3xdr.c @@ -21,7 +21,6 @@ #include #include #include -#include #define NFSDBG_FACILITY NFSDBG_XDR @@ -80,11 +79,6 @@ extern int nfs_stat_to_errno(int); #define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6) #define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2) -#define ACL3_getaclargs_sz (NFS3_fh_sz+1) -#define ACL3_setaclargs_sz (NFS3_fh_sz+1+2*(2+5*3)) -#define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+2*(2+5*3)) -#define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz) - /* * Map file type to S_IFMT bits */ @@ -633,74 +627,6 @@ nfs3_xdr_commitargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args) return 0; } -#ifdef CONFIG_NFS_V3_ACL -/* - * Encode GETACL arguments - */ -static int -nfs3_xdr_getaclargs(struct rpc_rqst *req, u32 *p, - struct nfs3_getaclargs *args) -{ - struct rpc_auth *auth = req->rq_task->tk_auth; - unsigned int replen; - - p = xdr_encode_fhandle(p, args->fh); - *p++ = htonl(args->mask); - req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); - - if (args->mask & (NFS_ACL | NFS_DFACL)) { - /* Inline the page array */ - replen = (RPC_REPHDRSIZE + auth->au_rslack + - ACL3_getaclres_sz) << 2; - xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, - NFSACL_MAXPAGES << PAGE_SHIFT); - } - return 0; -} - -/* - * Encode SETACL arguments - */ -static int -nfs3_xdr_setaclargs(struct rpc_rqst *req, u32 *p, - struct nfs3_setaclargs *args) -{ - struct xdr_buf *buf = &req->rq_snd_buf; - unsigned int base, len_in_head, len = nfsacl_size( - (args->mask & NFS_ACL) ? args->acl_access : NULL, - (args->mask & NFS_DFACL) ? args->acl_default : NULL); - int count, err; - - p = xdr_encode_fhandle(p, NFS_FH(args->inode)); - *p++ = htonl(args->mask); - base = (char *)p - (char *)buf->head->iov_base; - /* put as much of the acls into head as possible. */ - len_in_head = min_t(unsigned int, buf->head->iov_len - base, len); - len -= len_in_head; - req->rq_slen = xdr_adjust_iovec(req->rq_svec, p + (len_in_head >> 2)); - - for (count = 0; (count << PAGE_SHIFT) < len; count++) { - args->pages[count] = alloc_page(GFP_KERNEL); - if (!args->pages[count]) { - while (count) - __free_page(args->pages[--count]); - return -ENOMEM; - } - } - xdr_encode_pages(buf, args->pages, 0, len); - - err = nfsacl_encode(buf, base, args->inode, - (args->mask & NFS_ACL) ? - args->acl_access : NULL, 1, 0); - if (err > 0) - err = nfsacl_encode(buf, base + err, args->inode, - (args->mask & NFS_DFACL) ? - args->acl_default : NULL, 1, - NFS_ACL_DEFAULT); - return (err > 0) ? 0 : err; -} -#endif /* CONFIG_NFS_V3_ACL */ - /* * NFS XDR decode functions */ @@ -1052,54 +978,6 @@ nfs3_xdr_commitres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res) return 0; } -#ifdef CONFIG_NFS_V3_ACL -/* - * Decode GETACL reply - */ -static int -nfs3_xdr_getaclres(struct rpc_rqst *req, u32 *p, - struct nfs3_getaclres *res) -{ - struct xdr_buf *buf = &req->rq_rcv_buf; - int status = ntohl(*p++); - struct posix_acl **acl; - unsigned int *aclcnt; - int err, base; - - if (status != 0) - return -nfs_stat_to_errno(status); - p = xdr_decode_post_op_attr(p, res->fattr); - res->mask = ntohl(*p++); - if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) - return -EINVAL; - base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base; - - acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL; - aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL; - err = nfsacl_decode(buf, base, aclcnt, acl); - - acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL; - aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL; - if (err > 0) - err = nfsacl_decode(buf, base + err, aclcnt, acl); - return (err > 0) ? 0 : err; -} - -/* - * Decode setacl reply. - */ -static int -nfs3_xdr_setaclres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr) -{ - int status = ntohl(*p++); - - if (status) - return -nfs_stat_to_errno(status); - xdr_decode_post_op_attr(p, fattr); - return 0; -} -#endif /* CONFIG_NFS_V3_ACL */ - #ifndef MAX # define MAX(a, b) (((a) > (b))? (a) : (b)) #endif @@ -1143,28 +1021,3 @@ struct rpc_version nfs_version3 = { .procs = nfs3_procedures }; -#ifdef CONFIG_NFS_V3_ACL -static struct rpc_procinfo nfs3_acl_procedures[] = { - [ACLPROC3_GETACL] = { - .p_proc = ACLPROC3_GETACL, - .p_encode = (kxdrproc_t) nfs3_xdr_getaclargs, - .p_decode = (kxdrproc_t) nfs3_xdr_getaclres, - .p_bufsiz = MAX(ACL3_getaclargs_sz, ACL3_getaclres_sz) << 2, - .p_timer = 1, - }, - [ACLPROC3_SETACL] = { - .p_proc = ACLPROC3_SETACL, - .p_encode = (kxdrproc_t) nfs3_xdr_setaclargs, - .p_decode = (kxdrproc_t) nfs3_xdr_setaclres, - .p_bufsiz = MAX(ACL3_setaclargs_sz, ACL3_setaclres_sz) << 2, - .p_timer = 0, - }, -}; - -struct rpc_version nfsacl_version3 = { - .number = 3, - .nrprocs = sizeof(nfs3_acl_procedures)/ - sizeof(nfs3_acl_procedures[0]), - .procs = nfs3_acl_procedures, -}; -#endif /* CONFIG_NFS_V3_ACL */ diff --git a/trunk/fs/nfs/nfs4_fs.h b/trunk/fs/nfs/nfs4_fs.h deleted file mode 100644 index ec1a22d7b876..000000000000 --- a/trunk/fs/nfs/nfs4_fs.h +++ /dev/null @@ -1,253 +0,0 @@ -/* - * linux/fs/nfs/nfs4_fs.h - * - * Copyright (C) 2005 Trond Myklebust - * - * NFSv4-specific filesystem definitions and declarations - */ - -#ifndef __LINUX_FS_NFS_NFS4_FS_H -#define __LINUX_FS_NFS_NFS4_FS_H - -#ifdef CONFIG_NFS_V4 - -struct idmap; - -/* - * In a seqid-mutating op, this macro controls which error return - * values trigger incrementation of the seqid. - * - * from rfc 3010: - * The client MUST monotonically increment the sequence number for the - * CLOSE, LOCK, LOCKU, OPEN, OPEN_CONFIRM, and OPEN_DOWNGRADE - * operations. This is true even in the event that the previous - * operation that used the sequence number received an error. The only - * exception to this rule is if the previous operation received one of - * the following errors: NFSERR_STALE_CLIENTID, NFSERR_STALE_STATEID, - * NFSERR_BAD_STATEID, NFSERR_BAD_SEQID, NFSERR_BADXDR, - * NFSERR_RESOURCE, NFSERR_NOFILEHANDLE. - * - */ -#define seqid_mutating_err(err) \ -(((err) != NFSERR_STALE_CLIENTID) && \ - ((err) != NFSERR_STALE_STATEID) && \ - ((err) != NFSERR_BAD_STATEID) && \ - ((err) != NFSERR_BAD_SEQID) && \ - ((err) != NFSERR_BAD_XDR) && \ - ((err) != NFSERR_RESOURCE) && \ - ((err) != NFSERR_NOFILEHANDLE)) - -enum nfs4_client_state { - NFS4CLNT_OK = 0, -}; - -/* - * The nfs4_client identifies our client state to the server. - */ -struct nfs4_client { - struct list_head cl_servers; /* Global list of servers */ - struct in_addr cl_addr; /* Server identifier */ - u64 cl_clientid; /* constant */ - nfs4_verifier cl_confirm; - unsigned long cl_state; - - u32 cl_lockowner_id; - - /* - * The following rwsem ensures exclusive access to the server - * while we recover the state following a lease expiration. - */ - struct rw_semaphore cl_sem; - - struct list_head cl_delegations; - struct list_head cl_state_owners; - struct list_head cl_unused; - int cl_nunused; - spinlock_t cl_lock; - atomic_t cl_count; - - struct rpc_clnt * cl_rpcclient; - struct rpc_cred * cl_cred; - - struct list_head cl_superblocks; /* List of nfs_server structs */ - - unsigned long cl_lease_time; - unsigned long cl_last_renewal; - struct work_struct cl_renewd; - struct work_struct cl_recoverd; - - 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; - - /* Our own IP address, as a null-terminated string. - * This is used to generate the clientid, and the callback address. - */ - char cl_ipaddr[16]; - unsigned char cl_id_uniquifier; -}; - -/* - * NFS4 state_owners and lock_owners are simply labels for ordered - * sequences of RPC calls. Their sole purpose is to provide once-only - * semantics by allowing the server to identify replayed requests. - * - * The ->so_sema is held during all state_owner seqid-mutating operations: - * OPEN, OPEN_DOWNGRADE, and CLOSE. Its purpose is to properly serialize - * so_seqid. - */ -struct nfs4_state_owner { - struct list_head so_list; /* per-clientid list of state_owners */ - struct nfs4_client *so_client; - u32 so_id; /* 32-bit identifier, unique */ - struct semaphore so_sema; - u32 so_seqid; /* protected by so_sema */ - atomic_t so_count; - - struct rpc_cred *so_cred; /* Associated cred */ - struct list_head so_states; - struct list_head so_delegations; -}; - -/* - * struct nfs4_state maintains the client-side state for a given - * (state_owner,inode) tuple (OPEN) or state_owner (LOCK). - * - * OPEN: - * In order to know when to OPEN_DOWNGRADE or CLOSE the state on the server, - * we need to know how many files are open for reading or writing on a - * given inode. This information too is stored here. - * - * LOCK: one nfs4_state (LOCK) to hold the lock stateid nfs4_state(OPEN) - */ - -struct nfs4_lock_state { - struct list_head ls_locks; /* Other lock stateids */ - struct nfs4_state * ls_state; /* Pointer to open state */ - fl_owner_t ls_owner; /* POSIX lock owner */ -#define NFS_LOCK_INITIALIZED 1 - int ls_flags; - u32 ls_seqid; - u32 ls_id; - nfs4_stateid ls_stateid; - atomic_t ls_count; -}; - -/* bits for nfs4_state->flags */ -enum { - LK_STATE_IN_USE, - NFS_DELEGATED_STATE, -}; - -struct nfs4_state { - struct list_head open_states; /* List of states for the same state_owner */ - struct list_head inode_states; /* List of states for the same inode */ - struct list_head lock_states; /* List of subservient lock stateids */ - - struct nfs4_state_owner *owner; /* Pointer to the open owner */ - struct inode *inode; /* Pointer to the inode */ - - unsigned long flags; /* Do we hold any locks? */ - struct semaphore lock_sema; /* Serializes file locking operations */ - spinlock_t state_lock; /* Protects the lock_states list */ - - nfs4_stateid stateid; - - unsigned int nreaders; - unsigned int nwriters; - int state; /* State on the server (R,W, or RW) */ - atomic_t count; -}; - - -struct nfs4_exception { - long timeout; - 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; - -/* inode.c */ -extern ssize_t nfs4_getxattr(struct dentry *, const char *, void *, size_t); -extern int nfs4_setxattr(struct dentry *, const char *, const void *, size_t, int); -extern ssize_t nfs4_listxattr(struct dentry *, char *, size_t); - - -/* 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_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 struct inode *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); -extern int nfs4_open_revalidate(struct inode *, struct dentry *, int); - -extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops; -extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops; - -extern const u32 nfs4_fattr_bitmap[2]; -extern const u32 nfs4_statfs_bitmap[2]; -extern const u32 nfs4_pathconf_bitmap[2]; -extern const u32 nfs4_fsinfo_bitmap[2]; - -/* nfs4renewd.c */ -extern void nfs4_schedule_state_renewal(struct nfs4_client *); -extern void nfs4_renewd_prepare_shutdown(struct nfs_server *); -extern void nfs4_kill_renewd(struct nfs4_client *); -extern void nfs4_renew_state(void *); - -/* nfs4state.c */ -extern void init_nfsv4_state(struct nfs_server *); -extern void destroy_nfsv4_state(struct nfs_server *); -extern struct nfs4_client *nfs4_get_client(struct in_addr *); -extern void nfs4_put_client(struct nfs4_client *clp); -extern int nfs4_init_client(struct nfs4_client *clp); -extern struct nfs4_client *nfs4_find_client(struct in_addr *); -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); -extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mode_t mode); -extern void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp); -extern void nfs4_schedule_state_recovery(struct nfs4_client *); -extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); -extern void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *ls); -extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t); - -extern const nfs4_stateid zero_stateid; - -/* nfs4xdr.c */ -extern uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus); -extern struct rpc_procinfo nfs4_procedures[]; - -struct nfs4_mount_data; - -/* callback_xdr.c */ -extern struct svc_version nfs4_callback_version1; - -#else - -#define init_nfsv4_state(server) do { } while (0) -#define destroy_nfsv4_state(server) do { } while (0) -#define nfs4_put_state_owner(inode, owner) do { } while (0) -#define nfs4_put_open_state(state) do { } while (0) -#define nfs4_close_state(a, b) do { } while (0) - -#endif /* CONFIG_NFS_V4 */ -#endif /* __LINUX_FS_NFS_NFS4_FS.H */ diff --git a/trunk/fs/nfs/nfs4proc.c b/trunk/fs/nfs/nfs4proc.c index 1b76f80aedb9..1d5cb3e80c3e 100644 --- a/trunk/fs/nfs/nfs4proc.c +++ b/trunk/fs/nfs/nfs4proc.c @@ -48,7 +48,6 @@ #include #include -#include "nfs4_fs.h" #include "delegation.h" #define NFSDBG_FACILITY NFSDBG_PROC @@ -63,6 +62,8 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc 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 */ int nfs4_map_errors(int err) { @@ -103,7 +104,7 @@ const u32 nfs4_statfs_bitmap[2] = { | FATTR4_WORD1_SPACE_TOTAL }; -const u32 nfs4_pathconf_bitmap[2] = { +u32 nfs4_pathconf_bitmap[2] = { FATTR4_WORD0_MAXLINK | FATTR4_WORD0_MAXNAME, 0 @@ -123,7 +124,7 @@ static void nfs4_setup_readdir(u64 cookie, u32 *verifier, struct dentry *dentry, BUG_ON(readdir->count < 80); if (cookie > 2) { - readdir->cookie = cookie; + readdir->cookie = (cookie > 2) ? cookie : 0; memcpy(&readdir->verifier, verifier, sizeof(readdir->verifier)); return; } @@ -269,9 +270,14 @@ static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *sta int err; do { err = _nfs4_open_reclaim(sp, state); - if (err != -NFS4ERR_DELAY) - break; - nfs4_handle_exception(server, err, &exception); + switch (err) { + case 0: + case -NFS4ERR_STALE_CLIENTID: + case -NFS4ERR_STALE_STATEID: + case -NFS4ERR_EXPIRED: + return err; + } + err = nfs4_handle_exception(server, err, &exception); } while (exception.retry); return err; } @@ -503,20 +509,6 @@ static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st goto out_nodeleg; } -static inline int nfs4_do_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry) -{ - struct nfs_server *server = NFS_SERVER(dentry->d_inode); - struct nfs4_exception exception = { }; - int err; - - do { - err = _nfs4_open_expired(sp, state, dentry); - if (err == -NFS4ERR_DELAY) - nfs4_handle_exception(server, err, &exception); - } while (exception.retry); - return err; -} - static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state) { struct nfs_inode *nfsi = NFS_I(state->inode); @@ -529,7 +521,7 @@ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *sta continue; get_nfs_open_context(ctx); spin_unlock(&state->inode->i_lock); - status = nfs4_do_open_expired(sp, state, ctx->dentry); + status = _nfs4_open_expired(sp, state, ctx->dentry); put_nfs_open_context(ctx); return status; } @@ -756,10 +748,11 @@ static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr, fattr->valid = 0; - if (state != NULL) { + if (state != NULL) msg.rpc_cred = state->owner->so_cred; - nfs4_copy_stateid(&arg.stateid, state, current->files); - } else + if (sattr->ia_valid & ATTR_SIZE) + nfs4_copy_stateid(&arg.stateid, state, NULL); + else memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); return rpc_call_sync(server->client, &msg, 0); @@ -1123,31 +1116,47 @@ static int nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, struct iattr *sattr) { - struct rpc_cred *cred; - struct inode *inode = dentry->d_inode; - struct nfs4_state *state; + struct inode * inode = dentry->d_inode; + int size_change = sattr->ia_valid & ATTR_SIZE; + struct nfs4_state *state = NULL; + int need_iput = 0; int status; fattr->valid = 0; - cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0); - if (IS_ERR(cred)) - return PTR_ERR(cred); - /* Search for an existing WRITE delegation first */ - state = nfs4_open_delegated(inode, FMODE_WRITE, cred); - if (!IS_ERR(state)) { - /* NB: nfs4_open_delegated() bumps the inode->i_count */ - iput(inode); - } else { - /* Search for an existing open(O_WRITE) stateid */ + 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, + FMODE_WRITE, cred); + if (IS_ERR(state)) + state = nfs4_do_open(dentry->d_parent->d_inode, + dentry, FMODE_WRITE, + NULL, cred); + need_iput = 1; + } + put_rpccred(cred); + if (IS_ERR(state)) + return PTR_ERR(state); + if (state->inode != inode) { + printk(KERN_WARNING "nfs: raced in setattr (%p != %p), returning -EIO\n", inode, state->inode); + status = -EIO; + goto out; + } + } status = nfs4_do_setattr(NFS_SERVER(inode), fattr, NFS_FH(inode), sattr, state); - if (state != NULL) +out: + if (state) { + inode = state->inode; nfs4_close_state(state, FMODE_WRITE); - put_rpccred(cred); + if (need_iput) + iput(inode); + } return status; } @@ -1722,10 +1731,6 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, }; int status; - dprintk("%s: dentry = %s/%s, cookie = %Lu\n", __FUNCTION__, - dentry->d_parent->d_name.name, - dentry->d_name.name, - (unsigned long long)cookie); lock_kernel(); nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args); res.pgbase = args.pgbase; @@ -1733,7 +1738,6 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, if (status == 0) memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); unlock_kernel(); - dprintk("%s: returns %d\n", __FUNCTION__, status); return status; } @@ -2159,193 +2163,6 @@ nfs4_proc_file_release(struct inode *inode, struct file *filp) return 0; } -static inline int nfs4_server_supports_acls(struct nfs_server *server) -{ - return (server->caps & NFS_CAP_ACLS) - && (server->acl_bitmask & ACL4_SUPPORT_ALLOW_ACL) - && (server->acl_bitmask & ACL4_SUPPORT_DENY_ACL); -} - -/* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_CACHE_SIZE, and that - * it's OK to put sizeof(void) * (XATTR_SIZE_MAX/PAGE_CACHE_SIZE) bytes on - * the stack. - */ -#define NFS4ACL_MAXPAGES (XATTR_SIZE_MAX >> PAGE_CACHE_SHIFT) - -static void buf_to_pages(const void *buf, size_t buflen, - struct page **pages, unsigned int *pgbase) -{ - const void *p = buf; - - *pgbase = offset_in_page(buf); - p -= *pgbase; - while (p < buf + buflen) { - *(pages++) = virt_to_page(p); - p += PAGE_CACHE_SIZE; - } -} - -struct nfs4_cached_acl { - int cached; - size_t len; - char data[0]; -}; - -static void nfs4_set_cached_acl(struct inode *inode, struct nfs4_cached_acl *acl) -{ - struct nfs_inode *nfsi = NFS_I(inode); - - spin_lock(&inode->i_lock); - kfree(nfsi->nfs4_acl); - nfsi->nfs4_acl = acl; - spin_unlock(&inode->i_lock); -} - -static void nfs4_zap_acl_attr(struct inode *inode) -{ - nfs4_set_cached_acl(inode, NULL); -} - -static inline ssize_t nfs4_read_cached_acl(struct inode *inode, char *buf, size_t buflen) -{ - struct nfs_inode *nfsi = NFS_I(inode); - struct nfs4_cached_acl *acl; - int ret = -ENOENT; - - spin_lock(&inode->i_lock); - acl = nfsi->nfs4_acl; - if (acl == NULL) - goto out; - if (buf == NULL) /* user is just asking for length */ - goto out_len; - if (acl->cached == 0) - goto out; - ret = -ERANGE; /* see getxattr(2) man page */ - if (acl->len > buflen) - goto out; - memcpy(buf, acl->data, acl->len); -out_len: - ret = acl->len; -out: - spin_unlock(&inode->i_lock); - return ret; -} - -static void nfs4_write_cached_acl(struct inode *inode, const char *buf, size_t acl_len) -{ - struct nfs4_cached_acl *acl; - - if (buf && acl_len <= PAGE_SIZE) { - acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL); - if (acl == NULL) - goto out; - acl->cached = 1; - memcpy(acl->data, buf, acl_len); - } else { - acl = kmalloc(sizeof(*acl), GFP_KERNEL); - if (acl == NULL) - goto out; - acl->cached = 0; - } - acl->len = acl_len; -out: - nfs4_set_cached_acl(inode, acl); -} - -static inline ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen) -{ - struct page *pages[NFS4ACL_MAXPAGES]; - struct nfs_getaclargs args = { - .fh = NFS_FH(inode), - .acl_pages = pages, - .acl_len = buflen, - }; - size_t resp_len = buflen; - void *resp_buf; - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL], - .rpc_argp = &args, - .rpc_resp = &resp_len, - }; - struct page *localpage = NULL; - int ret; - - if (buflen < PAGE_SIZE) { - /* As long as we're doing a round trip to the server anyway, - * let's be prepared for a page of acl data. */ - localpage = alloc_page(GFP_KERNEL); - resp_buf = page_address(localpage); - if (localpage == NULL) - return -ENOMEM; - args.acl_pages[0] = localpage; - args.acl_pgbase = 0; - args.acl_len = PAGE_SIZE; - } else { - resp_buf = buf; - buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase); - } - ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); - if (ret) - goto out_free; - if (resp_len > args.acl_len) - nfs4_write_cached_acl(inode, NULL, resp_len); - else - nfs4_write_cached_acl(inode, resp_buf, resp_len); - if (buf) { - ret = -ERANGE; - if (resp_len > buflen) - goto out_free; - if (localpage) - memcpy(buf, resp_buf, resp_len); - } - ret = resp_len; -out_free: - if (localpage) - __free_page(localpage); - return ret; -} - -static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen) -{ - struct nfs_server *server = NFS_SERVER(inode); - int ret; - - if (!nfs4_server_supports_acls(server)) - return -EOPNOTSUPP; - ret = nfs_revalidate_inode(server, inode); - if (ret < 0) - return ret; - ret = nfs4_read_cached_acl(inode, buf, buflen); - if (ret != -ENOENT) - return ret; - return nfs4_get_acl_uncached(inode, buf, buflen); -} - -static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen) -{ - struct nfs_server *server = NFS_SERVER(inode); - struct page *pages[NFS4ACL_MAXPAGES]; - struct nfs_setaclargs arg = { - .fh = NFS_FH(inode), - .acl_pages = pages, - .acl_len = buflen, - }; - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETACL], - .rpc_argp = &arg, - .rpc_resp = NULL, - }; - int ret; - - if (!nfs4_server_supports_acls(server)) - return -EOPNOTSUPP; - buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase); - ret = rpc_call_sync(NFS_SERVER(inode)->client, &msg, 0); - if (ret == 0) - nfs4_write_cached_acl(inode, buf, buflen); - return ret; -} - static int nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server) { @@ -2631,11 +2448,14 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock down_read(&clp->cl_sem); nlo.clientid = clp->cl_clientid; down(&state->lock_sema); - status = nfs4_set_lock_state(state, request); - if (status != 0) - goto out; - lsp = request->fl_u.nfs4_fl.owner; - nlo.id = lsp->ls_id; + lsp = nfs4_find_lock_state(state, request->fl_owner); + if (lsp) + nlo.id = lsp->ls_id; + else { + spin_lock(&clp->cl_lock); + nlo.id = nfs4_alloc_lockowner_id(clp); + spin_unlock(&clp->cl_lock); + } arg.u.lockt = &nlo; status = rpc_call_sync(server->client, &msg, 0); if (!status) { @@ -2656,7 +2476,8 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock request->fl_pid = 0; status = 0; } -out: + if (lsp) + nfs4_put_lock_state(lsp); up(&state->lock_sema); up_read(&clp->cl_sem); return status; @@ -2716,26 +2537,28 @@ static int _nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock }; struct nfs4_lock_state *lsp; struct nfs_locku_opargs luargs; - int status; + int status = 0; down_read(&clp->cl_sem); down(&state->lock_sema); - status = nfs4_set_lock_state(state, request); - if (status != 0) + lsp = nfs4_find_lock_state(state, request->fl_owner); + if (!lsp) goto out; - lsp = request->fl_u.nfs4_fl.owner; /* We might have lost the locks! */ - if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) - goto out; - luargs.seqid = lsp->ls_seqid; - memcpy(&luargs.stateid, &lsp->ls_stateid, sizeof(luargs.stateid)); - arg.u.locku = &luargs; - status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); - nfs4_increment_lock_seqid(status, lsp); + if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) { + luargs.seqid = lsp->ls_seqid; + memcpy(&luargs.stateid, &lsp->ls_stateid, sizeof(luargs.stateid)); + arg.u.locku = &luargs; + status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); + nfs4_increment_lock_seqid(status, lsp); + } - if (status == 0) + if (status == 0) { memcpy(&lsp->ls_stateid, &res.u.stateid, sizeof(lsp->ls_stateid)); + nfs4_notify_unlck(state, request, lsp); + } + nfs4_put_lock_state(lsp); out: up(&state->lock_sema); if (status == 0) @@ -2761,7 +2584,7 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *r { struct inode *inode = state->inode; struct nfs_server *server = NFS_SERVER(inode); - struct nfs4_lock_state *lsp = request->fl_u.nfs4_fl.owner; + struct nfs4_lock_state *lsp; struct nfs_lockargs arg = { .fh = NFS_FH(inode), .type = nfs4_lck_type(cmd, request), @@ -2783,6 +2606,9 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *r }; int status; + lsp = nfs4_get_lock_state(state, request->fl_owner); + if (lsp == NULL) + return -ENOMEM; if (!(lsp->ls_flags & NFS_LOCK_INITIALIZED)) { struct nfs4_state_owner *owner = state->owner; struct nfs_open_to_lock otl = { @@ -2804,57 +2630,38 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *r * seqid mutating errors */ nfs4_increment_seqid(status, owner); up(&owner->so_sema); - if (status == 0) { - lsp->ls_flags |= NFS_LOCK_INITIALIZED; - lsp->ls_seqid++; - } } else { struct nfs_exist_lock el = { .seqid = lsp->ls_seqid, }; memcpy(&el.stateid, &lsp->ls_stateid, sizeof(el.stateid)); largs.u.exist_lock = ⪙ + largs.new_lock_owner = 0; arg.u.lock = &largs; status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); - /* increment seqid on success, and * seqid mutating errors*/ - nfs4_increment_lock_seqid(status, lsp); } + /* increment seqid on success, and * seqid mutating errors*/ + nfs4_increment_lock_seqid(status, lsp); /* save the returned stateid. */ - if (status == 0) + if (status == 0) { memcpy(&lsp->ls_stateid, &res.u.stateid, sizeof(nfs4_stateid)); - else if (status == -NFS4ERR_DENIED) + lsp->ls_flags |= NFS_LOCK_INITIALIZED; + if (!reclaim) + nfs4_notify_setlk(state, request, lsp); + } else if (status == -NFS4ERR_DENIED) status = -EAGAIN; + nfs4_put_lock_state(lsp); return status; } static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request) { - struct nfs_server *server = NFS_SERVER(state->inode); - struct nfs4_exception exception = { }; - int err; - - do { - err = _nfs4_do_setlk(state, F_SETLK, request, 1); - if (err != -NFS4ERR_DELAY) - break; - nfs4_handle_exception(server, err, &exception); - } while (exception.retry); - return err; + return _nfs4_do_setlk(state, F_SETLK, request, 1); } static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request) { - struct nfs_server *server = NFS_SERVER(state->inode); - struct nfs4_exception exception = { }; - int err; - - do { - err = _nfs4_do_setlk(state, F_SETLK, request, 0); - if (err != -NFS4ERR_DELAY) - break; - nfs4_handle_exception(server, err, &exception); - } while (exception.retry); - return err; + return _nfs4_do_setlk(state, F_SETLK, request, 0); } static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request) @@ -2864,9 +2671,7 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock down_read(&clp->cl_sem); down(&state->lock_sema); - status = nfs4_set_lock_state(state, request); - if (status == 0) - status = _nfs4_do_setlk(state, cmd, request, 0); + status = _nfs4_do_setlk(state, cmd, request, 0); up(&state->lock_sema); if (status == 0) { /* Note: we always want to sleep here! */ @@ -2924,51 +2729,8 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request) if (signalled()) break; } while(status < 0); - return status; -} - - -#define XATTR_NAME_NFSV4_ACL "system.nfs4_acl" - -int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf, - size_t buflen, int flags) -{ - struct inode *inode = dentry->d_inode; - if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0) - return -EOPNOTSUPP; - - if (!S_ISREG(inode->i_mode) && - (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX)) - return -EPERM; - - return nfs4_proc_set_acl(inode, buf, buflen); -} - -/* The getxattr man page suggests returning -ENODATA for unknown attributes, - * and that's what we'll do for e.g. user attributes that haven't been set. - * But we'll follow ext2/ext3's lead by returning -EOPNOTSUPP for unsupported - * attributes in kernel-managed attribute namespaces. */ -ssize_t nfs4_getxattr(struct dentry *dentry, const char *key, void *buf, - size_t buflen) -{ - struct inode *inode = dentry->d_inode; - - if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0) - return -EOPNOTSUPP; - - return nfs4_proc_get_acl(inode, buf, buflen); -} - -ssize_t nfs4_listxattr(struct dentry *dentry, char *buf, size_t buflen) -{ - size_t len = strlen(XATTR_NAME_NFSV4_ACL) + 1; - - if (buf && buflen < len) - return -ERANGE; - if (buf) - memcpy(buf, XATTR_NAME_NFSV4_ACL, len); - return len; + return status; } struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = { @@ -2981,20 +2743,10 @@ struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops = { .recover_lock = nfs4_lock_expired, }; -static struct inode_operations nfs4_file_inode_operations = { - .permission = nfs_permission, - .getattr = nfs_getattr, - .setattr = nfs_setattr, - .getxattr = nfs4_getxattr, - .setxattr = nfs4_setxattr, - .listxattr = nfs4_listxattr, -}; - struct nfs_rpc_ops nfs_v4_clientops = { .version = 4, /* protocol version */ .dentry_ops = &nfs4_dentry_operations, .dir_inode_ops = &nfs4_dir_inode_operations, - .file_inode_ops = &nfs4_file_inode_operations, .getroot = nfs4_proc_get_root, .getattr = nfs4_proc_getattr, .setattr = nfs4_proc_setattr, @@ -3025,7 +2777,6 @@ struct nfs_rpc_ops nfs_v4_clientops = { .file_open = nfs4_proc_file_open, .file_release = nfs4_proc_file_release, .lock = nfs4_proc_lock, - .clear_acl_cache = nfs4_zap_acl_attr, }; /* diff --git a/trunk/fs/nfs/nfs4renewd.c b/trunk/fs/nfs/nfs4renewd.c index a3001628ad32..667e06f1c647 100644 --- a/trunk/fs/nfs/nfs4renewd.c +++ b/trunk/fs/nfs/nfs4renewd.c @@ -53,7 +53,6 @@ #include #include #include -#include "nfs4_fs.h" #define NFSDBG_FACILITY NFSDBG_PROC diff --git a/trunk/fs/nfs/nfs4state.c b/trunk/fs/nfs/nfs4state.c index afe587d82f1e..231cebce3c87 100644 --- a/trunk/fs/nfs/nfs4state.c +++ b/trunk/fs/nfs/nfs4state.c @@ -46,18 +46,24 @@ #include #include -#include "nfs4_fs.h" #include "callback.h" #include "delegation.h" #define OPENOWNER_POOL_SIZE 8 -const nfs4_stateid zero_stateid; - static DEFINE_SPINLOCK(state_spinlock); + +nfs4_stateid zero_stateid; + +#if 0 +nfs4_stateid one_stateid = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +#endif + static LIST_HEAD(nfs4_clientid_list); static void nfs4_recover_state(void *); +extern void nfs4_renew_state(void *); void init_nfsv4_state(struct nfs_server *server) @@ -110,7 +116,6 @@ 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_rpcclient = ERR_PTR(-EINVAL); clp->cl_boot_time = CURRENT_TIME; clp->cl_state = 1 << NFS4CLNT_OK; return clp; @@ -132,7 +137,7 @@ nfs4_free_client(struct nfs4_client *clp) if (clp->cl_cred) put_rpccred(clp->cl_cred); nfs_idmap_delete(clp); - if (!IS_ERR(clp->cl_rpcclient)) + if (clp->cl_rpcclient) rpc_shutdown_client(clp->cl_rpcclient); kfree(clp); nfs_callback_down(); @@ -360,7 +365,7 @@ nfs4_alloc_open_state(void) atomic_set(&state->count, 1); INIT_LIST_HEAD(&state->lock_states); init_MUTEX(&state->lock_sema); - spin_lock_init(&state->state_lock); + rwlock_init(&state->state_lock); return state; } @@ -542,6 +547,16 @@ __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) return NULL; } +struct nfs4_lock_state * +nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) +{ + struct nfs4_lock_state *lsp; + read_lock(&state->state_lock); + lsp = __nfs4_find_lock_state(state, fl_owner); + read_unlock(&state->state_lock); + return lsp; +} + /* * Return a compatible lock_state. If no initialized lock_state structure * exists, return an uninitialized one. @@ -558,13 +573,14 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f return NULL; lsp->ls_flags = 0; lsp->ls_seqid = 0; /* arbitrary */ + lsp->ls_id = -1; memset(lsp->ls_stateid.data, 0, sizeof(lsp->ls_stateid.data)); atomic_set(&lsp->ls_count, 1); lsp->ls_owner = fl_owner; + INIT_LIST_HEAD(&lsp->ls_locks); spin_lock(&clp->cl_lock); lsp->ls_id = nfs4_alloc_lockowner_id(clp); spin_unlock(&clp->cl_lock); - INIT_LIST_HEAD(&lsp->ls_locks); return lsp; } @@ -574,112 +590,121 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f * * The caller must be holding state->lock_sema and clp->cl_sem */ -static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner) +struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner) { - struct nfs4_lock_state *lsp, *new = NULL; + struct nfs4_lock_state * lsp; - for(;;) { - spin_lock(&state->state_lock); - lsp = __nfs4_find_lock_state(state, owner); - if (lsp != NULL) - break; - if (new != NULL) { - new->ls_state = state; - list_add(&new->ls_locks, &state->lock_states); - set_bit(LK_STATE_IN_USE, &state->flags); - lsp = new; - new = NULL; - break; - } - spin_unlock(&state->state_lock); - new = nfs4_alloc_lock_state(state, owner); - if (new == NULL) - return NULL; - } - spin_unlock(&state->state_lock); - kfree(new); + lsp = nfs4_find_lock_state(state, owner); + if (lsp == NULL) + lsp = nfs4_alloc_lock_state(state, owner); return lsp; } /* - * Release reference to lock_state, and free it if we see that - * it is no longer in use + * Byte-range lock aware utility to initialize the stateid of read/write + * requests. */ -static void nfs4_put_lock_state(struct nfs4_lock_state *lsp) -{ - struct nfs4_state *state; - - if (lsp == NULL) - return; - state = lsp->ls_state; - if (!atomic_dec_and_lock(&lsp->ls_count, &state->state_lock)) - return; - list_del(&lsp->ls_locks); - if (list_empty(&state->lock_states)) - clear_bit(LK_STATE_IN_USE, &state->flags); - spin_unlock(&state->state_lock); - kfree(lsp); -} - -static void nfs4_fl_copy_lock(struct file_lock *dst, struct file_lock *src) +void +nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner) { - struct nfs4_lock_state *lsp = src->fl_u.nfs4_fl.owner; + if (test_bit(LK_STATE_IN_USE, &state->flags)) { + struct nfs4_lock_state *lsp; - dst->fl_u.nfs4_fl.owner = lsp; - atomic_inc(&lsp->ls_count); + lsp = nfs4_find_lock_state(state, fl_owner); + if (lsp) { + memcpy(dst, &lsp->ls_stateid, sizeof(*dst)); + nfs4_put_lock_state(lsp); + return; + } + } + memcpy(dst, &state->stateid, sizeof(*dst)); } -static void nfs4_fl_release_lock(struct file_lock *fl) +/* +* Called with state->lock_sema and clp->cl_sem held. +*/ +void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *lsp) { - nfs4_put_lock_state(fl->fl_u.nfs4_fl.owner); + if (status == NFS_OK || seqid_mutating_err(-status)) + lsp->ls_seqid++; } -static struct file_lock_operations nfs4_fl_lock_ops = { - .fl_copy_lock = nfs4_fl_copy_lock, - .fl_release_private = nfs4_fl_release_lock, -}; +/* +* Check to see if the request lock (type FL_UNLK) effects the fl lock. +* +* fl and request must have the same posix owner +* +* return: +* 0 -> fl not effected by request +* 1 -> fl consumed by request +*/ -int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl) +static int +nfs4_check_unlock(struct file_lock *fl, struct file_lock *request) { - struct nfs4_lock_state *lsp; - - if (fl->fl_ops != NULL) - return 0; - lsp = nfs4_get_lock_state(state, fl->fl_owner); - if (lsp == NULL) - return -ENOMEM; - fl->fl_u.nfs4_fl.owner = lsp; - fl->fl_ops = &nfs4_fl_lock_ops; + if (fl->fl_start >= request->fl_start && fl->fl_end <= request->fl_end) + return 1; return 0; } /* - * Byte-range lock aware utility to initialize the stateid of read/write - * requests. + * Post an initialized lock_state on the state->lock_states list. */ -void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner) +void nfs4_notify_setlk(struct nfs4_state *state, struct file_lock *request, struct nfs4_lock_state *lsp) { - struct nfs4_lock_state *lsp; - - memcpy(dst, &state->stateid, sizeof(*dst)); - if (test_bit(LK_STATE_IN_USE, &state->flags) == 0) + if (!list_empty(&lsp->ls_locks)) return; + atomic_inc(&lsp->ls_count); + write_lock(&state->state_lock); + list_add(&lsp->ls_locks, &state->lock_states); + set_bit(LK_STATE_IN_USE, &state->flags); + write_unlock(&state->state_lock); +} - spin_lock(&state->state_lock); - lsp = __nfs4_find_lock_state(state, fl_owner); - if (lsp != NULL && (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) - memcpy(dst, &lsp->ls_stateid, sizeof(*dst)); - spin_unlock(&state->state_lock); +/* + * to decide to 'reap' lock state: + * 1) search i_flock for file_locks with fl.lock_state = to ls. + * 2) determine if unlock will consume found lock. + * if so, reap + * + * else, don't reap. + * + */ +void +nfs4_notify_unlck(struct nfs4_state *state, struct file_lock *request, struct nfs4_lock_state *lsp) +{ + struct inode *inode = state->inode; + struct file_lock *fl; + + for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { + if (!(fl->fl_flags & FL_POSIX)) + continue; + if (fl->fl_owner != lsp->ls_owner) + continue; + /* Exit if we find at least one lock which is not consumed */ + if (nfs4_check_unlock(fl,request) == 0) + return; + } + + write_lock(&state->state_lock); + list_del_init(&lsp->ls_locks); + if (list_empty(&state->lock_states)) + clear_bit(LK_STATE_IN_USE, &state->flags); + write_unlock(&state->state_lock); nfs4_put_lock_state(lsp); } /* -* Called with state->lock_sema and clp->cl_sem held. -*/ -void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *lsp) + * Release reference to lock_state, and free it if we see that + * it is no longer in use + */ +void +nfs4_put_lock_state(struct nfs4_lock_state *lsp) { - if (status == NFS_OK || seqid_mutating_err(-status)) - lsp->ls_seqid++; + if (!atomic_dec_and_test(&lsp->ls_count)) + return; + BUG_ON (!list_empty(&lsp->ls_locks)); + kfree(lsp); } /* diff --git a/trunk/fs/nfs/nfs4xdr.c b/trunk/fs/nfs/nfs4xdr.c index 6c564ef9489e..5f4de05763c9 100644 --- a/trunk/fs/nfs/nfs4xdr.c +++ b/trunk/fs/nfs/nfs4xdr.c @@ -51,7 +51,6 @@ #include #include #include -#include "nfs4_fs.h" #define NFSDBG_FACILITY NFSDBG_XDR @@ -83,16 +82,12 @@ static int nfs_stat_to_errno(int); #define encode_getfh_maxsz (op_encode_hdr_maxsz) #define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \ ((3+NFS4_FHSIZE) >> 2)) -#define nfs4_fattr_bitmap_maxsz 3 -#define encode_getattr_maxsz (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz) +#define encode_getattr_maxsz (op_encode_hdr_maxsz + 3) #define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2)) #define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2)) -/* This is based on getfattr, which uses the most attributes: */ -#define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \ - 3 + 3 + 3 + 2 * nfs4_name_maxsz)) -#define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \ - nfs4_fattr_value_maxsz) -#define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) +#define nfs4_fattr_bitmap_maxsz (36 + 2 * nfs4_name_maxsz) +#define decode_getattr_maxsz (op_decode_hdr_maxsz + 3 + \ + nfs4_fattr_bitmap_maxsz) #define encode_savefh_maxsz (op_encode_hdr_maxsz) #define decode_savefh_maxsz (op_decode_hdr_maxsz) #define encode_fsinfo_maxsz (op_encode_hdr_maxsz + 2) @@ -127,11 +122,11 @@ static int nfs_stat_to_errno(int); #define encode_symlink_maxsz (op_encode_hdr_maxsz + \ 1 + nfs4_name_maxsz + \ nfs4_path_maxsz + \ - nfs4_fattr_maxsz) + nfs4_fattr_bitmap_maxsz) #define decode_symlink_maxsz (op_decode_hdr_maxsz + 8) #define encode_create_maxsz (op_encode_hdr_maxsz + \ 2 + nfs4_name_maxsz + \ - nfs4_fattr_maxsz) + nfs4_fattr_bitmap_maxsz) #define decode_create_maxsz (op_decode_hdr_maxsz + 8) #define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4) #define decode_delegreturn_maxsz (op_decode_hdr_maxsz) @@ -210,7 +205,7 @@ static int nfs_stat_to_errno(int); #define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \ encode_putfh_maxsz + \ op_encode_hdr_maxsz + 4 + \ - nfs4_fattr_maxsz + \ + nfs4_fattr_bitmap_maxsz + \ encode_getattr_maxsz) #define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \ decode_putfh_maxsz + \ @@ -365,20 +360,6 @@ static int nfs_stat_to_errno(int); encode_delegreturn_maxsz) #define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \ decode_delegreturn_maxsz) -#define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \ - encode_putfh_maxsz + \ - encode_getattr_maxsz) -#define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \ - decode_putfh_maxsz + \ - op_decode_hdr_maxsz + \ - nfs4_fattr_bitmap_maxsz + 1) -#define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \ - encode_putfh_maxsz + \ - op_encode_hdr_maxsz + 4 + \ - nfs4_fattr_bitmap_maxsz + 1) -#define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \ - decode_putfh_maxsz + \ - op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz) static struct { unsigned int mode; @@ -478,7 +459,7 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s * In the worst-case, this would be * 12(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime) * = 36 bytes, plus any contribution from variable-length fields - * such as owner/group. + * such as owner/group/acl's. */ len = 16; @@ -679,6 +660,8 @@ static int encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1 static int encode_getfattr(struct xdr_stream *xdr, const u32* bitmask) { + extern u32 nfs4_fattr_bitmap[]; + return encode_getattr_two(xdr, bitmask[0] & nfs4_fattr_bitmap[0], bitmask[1] & nfs4_fattr_bitmap[1]); @@ -686,6 +669,8 @@ static int encode_getfattr(struct xdr_stream *xdr, const u32* bitmask) static int encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask) { + extern u32 nfs4_fsinfo_bitmap[]; + return encode_getattr_two(xdr, bitmask[0] & nfs4_fsinfo_bitmap[0], bitmask[1] & nfs4_fsinfo_bitmap[1]); } @@ -984,6 +969,7 @@ static int encode_putrootfh(struct xdr_stream *xdr) static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx) { + extern nfs4_stateid zero_stateid; nfs4_stateid stateid; uint32_t *p; @@ -1014,10 +1000,6 @@ static int encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args) static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req) { struct rpc_auth *auth = req->rq_task->tk_auth; - uint32_t attrs[2] = { - FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID, - FATTR4_WORD1_MOUNTED_ON_FILEID, - }; int replen; uint32_t *p; @@ -1028,20 +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); - /* Switch to mounted_on_fileid if the server supports it */ - if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID) - attrs[0] &= ~FATTR4_WORD0_FILEID; - else - attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID; - WRITE32(attrs[0] & readdir->bitmask[0]); - WRITE32(attrs[1] & readdir->bitmask[1]); - dprintk("%s: cookie = %Lu, verifier = 0x%x%x, bitmap = 0x%x%x\n", - __FUNCTION__, - (unsigned long long)readdir->cookie, - ((u32 *)readdir->verifier.data)[0], - ((u32 *)readdir->verifier.data)[1], - attrs[0] & readdir->bitmask[0], - attrs[1] & readdir->bitmask[1]); + 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 @@ -1050,9 +1025,6 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg replen = (RPC_REPHDRSIZE + auth->au_rslack + 9) << 2; xdr_inline_pages(&req->rq_rcv_buf, replen, readdir->pages, readdir->pgbase, readdir->count); - dprintk("%s: inlined page args = (%u, %p, %u, %u)\n", - __FUNCTION__, replen, readdir->pages, - readdir->pgbase, readdir->count); return 0; } @@ -1116,25 +1088,6 @@ static int encode_renew(struct xdr_stream *xdr, const struct nfs4_client *client return 0; } -static int -encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg) -{ - uint32_t *p; - - RESERVE_SPACE(4+sizeof(zero_stateid.data)); - WRITE32(OP_SETATTR); - WRITEMEM(zero_stateid.data, sizeof(zero_stateid.data)); - RESERVE_SPACE(2*4); - WRITE32(1); - WRITE32(FATTR4_WORD0_ACL); - if (arg->acl_len % 4) - return -EINVAL; - RESERVE_SPACE(4); - WRITE32(arg->acl_len); - xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len); - return 0; -} - static int encode_savefh(struct xdr_stream *xdr) { @@ -1678,34 +1631,6 @@ static int nfs4_xdr_enc_setattr(struct rpc_rqst *req, uint32_t *p, struct nfs_se return status; } -/* - * Encode a GETACL request - */ -static int -nfs4_xdr_enc_getacl(struct rpc_rqst *req, uint32_t *p, - struct nfs_getaclargs *args) -{ - struct xdr_stream xdr; - struct rpc_auth *auth = req->rq_task->tk_auth; - struct compound_hdr hdr = { - .nops = 2, - }; - int replen, status; - - xdr_init_encode(&xdr, &req->rq_snd_buf, p); - encode_compound_hdr(&xdr, &hdr); - status = encode_putfh(&xdr, args->fh); - if (status) - goto out; - status = encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0); - /* set up reply buffer: */ - replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_getacl_sz) << 2; - xdr_inline_pages(&req->rq_rcv_buf, replen, - args->acl_pages, args->acl_pgbase, args->acl_len); -out: - return status; -} - /* * Encode a WRITE request */ @@ -1772,6 +1697,7 @@ static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, uint32_t *p, struct nfs4_fs */ static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, uint32_t *p, const struct nfs4_pathconf_arg *args) { + extern u32 nfs4_pathconf_bitmap[2]; struct xdr_stream xdr; struct compound_hdr hdr = { .nops = 2, @@ -1792,6 +1718,7 @@ static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, uint32_t *p, const struct */ static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, uint32_t *p, const struct nfs4_statfs_arg *args) { + extern u32 nfs4_statfs_bitmap[]; struct xdr_stream xdr; struct compound_hdr hdr = { .nops = 2, @@ -3076,11 +3003,6 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n return status; READ_BUF(8); COPYMEM(readdir->verifier.data, 8); - dprintk("%s: verifier = 0x%x%x\n", - __FUNCTION__, - ((u32 *)readdir->verifier.data)[0], - ((u32 *)readdir->verifier.data)[1]); - hdrlen = (char *) p - (char *) iov->iov_base; recvd = rcvbuf->len - hdrlen; @@ -3095,14 +3017,12 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n for (nr = 0; *p++; nr++) { if (p + 3 > end) goto short_pkt; - dprintk("cookie = %Lu, ", *((unsigned long long *)p)); p += 2; /* cookie */ len = ntohl(*p++); /* filename length */ if (len > NFS4_MAXNAMLEN) { printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)\n", len); goto err_unmap; } - dprintk("filename = %*s\n", len, (char *)p); p += XDR_QUADLEN(len); if (p + 1 > end) goto short_pkt; @@ -3122,7 +3042,6 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n kunmap_atomic(kaddr, KM_USER0); return 0; short_pkt: - dprintk("%s: short packet at entry %d\n", __FUNCTION__, nr); entry[0] = entry[1] = 0; /* truncate listing ? */ if (!nr) { @@ -3208,47 +3127,6 @@ static int decode_renew(struct xdr_stream *xdr) return decode_op_hdr(xdr, OP_RENEW); } -static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, - size_t *acl_len) -{ - uint32_t *savep; - uint32_t attrlen, - bitmap[2] = {0}; - struct kvec *iov = req->rq_rcv_buf.head; - int status; - - *acl_len = 0; - if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) - goto out; - if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) - goto out; - if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) - goto out; - - if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U))) - return -EIO; - if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { - int hdrlen, recvd; - - /* We ignore &savep and don't do consistency checks on - * the attr length. Let userspace figure it out.... */ - hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base; - recvd = req->rq_rcv_buf.len - hdrlen; - if (attrlen > recvd) { - printk(KERN_WARNING "NFS: server cheating in getattr" - " acl reply: attrlen %u > recvd %u\n", - attrlen, recvd); - return -EINVAL; - } - if (attrlen <= *acl_len) - xdr_read_pages(xdr, attrlen); - *acl_len = attrlen; - } - -out: - return status; -} - static int decode_savefh(struct xdr_stream *xdr) { @@ -3540,71 +3418,6 @@ static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4 } -/* - * Encode an SETACL request - */ -static int -nfs4_xdr_enc_setacl(struct rpc_rqst *req, uint32_t *p, struct nfs_setaclargs *args) -{ - struct xdr_stream xdr; - struct compound_hdr hdr = { - .nops = 2, - }; - int status; - - xdr_init_encode(&xdr, &req->rq_snd_buf, p); - encode_compound_hdr(&xdr, &hdr); - status = encode_putfh(&xdr, args->fh); - if (status) - goto out; - status = encode_setacl(&xdr, args); -out: - return status; -} -/* - * Decode SETACL response - */ -static int -nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, uint32_t *p, void *res) -{ - struct xdr_stream xdr; - struct compound_hdr hdr; - int status; - - xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); - status = decode_compound_hdr(&xdr, &hdr); - if (status) - goto out; - status = decode_putfh(&xdr); - if (status) - goto out; - status = decode_setattr(&xdr, res); -out: - return status; -} - -/* - * Decode GETACL response - */ -static int -nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, uint32_t *p, size_t *acl_len) -{ - struct xdr_stream xdr; - struct compound_hdr hdr; - int status; - - xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); - status = decode_compound_hdr(&xdr, &hdr); - if (status) - goto out; - status = decode_putfh(&xdr); - if (status) - goto out; - status = decode_getacl(&xdr, rqstp, acl_len); - -out: - return status; -} /* * Decode CLOSE response @@ -4082,12 +3895,6 @@ uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus) } len = XDR_QUADLEN(ntohl(*p++)); /* attribute buffer length */ if (len > 0) { - if (bitmap[0] & FATTR4_WORD0_RDATTR_ERROR) { - bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR; - /* Ignore the return value of rdattr_error for now */ - p++; - len--; - } if (bitmap[0] == 0 && bitmap[1] == FATTR4_WORD1_MOUNTED_ON_FILEID) xdr_decode_hyper(p, &entry->ino); else if (bitmap[0] == FATTR4_WORD0_FILEID) @@ -4127,8 +3934,6 @@ static struct { { NFS4ERR_DQUOT, EDQUOT }, { NFS4ERR_STALE, ESTALE }, { NFS4ERR_BADHANDLE, EBADHANDLE }, - { NFS4ERR_BADOWNER, EINVAL }, - { NFS4ERR_BADNAME, EINVAL }, { NFS4ERR_BAD_COOKIE, EBADCOOKIE }, { NFS4ERR_NOTSUPP, ENOTSUPP }, { NFS4ERR_TOOSMALL, ETOOSMALL }, @@ -4214,8 +4019,6 @@ struct rpc_procinfo nfs4_procedures[] = { PROC(READDIR, enc_readdir, dec_readdir), PROC(SERVER_CAPS, enc_server_caps, dec_server_caps), PROC(DELEGRETURN, enc_delegreturn, dec_delegreturn), - PROC(GETACL, enc_getacl, dec_getacl), - PROC(SETACL, enc_setacl, dec_setacl), }; struct rpc_version nfs_version4 = { diff --git a/trunk/fs/nfs/nfsroot.c b/trunk/fs/nfs/nfsroot.c index 1b272a135a31..fd5bc596fe8a 100644 --- a/trunk/fs/nfs/nfsroot.c +++ b/trunk/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_acl, Opt_noacl, /* Error token */ Opt_err }; @@ -159,8 +158,6 @@ static match_table_t __initdata tokens = { {Opt_udp, "udp"}, {Opt_tcp, "proto=tcp"}, {Opt_tcp, "tcp"}, - {Opt_acl, "acl"}, - {Opt_noacl, "noacl"}, {Opt_err, NULL} }; @@ -269,12 +266,6 @@ static int __init root_nfs_parse(char *name, char *buf) case Opt_tcp: nfs_data.flags |= NFS_MOUNT_TCP; break; - case Opt_acl: - nfs_data.flags &= ~NFS_MOUNT_NOACL; - break; - case Opt_noacl: - nfs_data.flags |= NFS_MOUNT_NOACL; - break; default : return 0; } diff --git a/trunk/fs/nfs/pagelist.c b/trunk/fs/nfs/pagelist.c index d53857b148e2..4f1ba723848d 100644 --- a/trunk/fs/nfs/pagelist.c +++ b/trunk/fs/nfs/pagelist.c @@ -107,37 +107,10 @@ void nfs_unlock_request(struct nfs_page *req) smp_mb__before_clear_bit(); clear_bit(PG_BUSY, &req->wb_flags); smp_mb__after_clear_bit(); - wake_up_bit(&req->wb_flags, PG_BUSY); + wake_up_all(&req->wb_context->waitq); nfs_release_request(req); } -/** - * nfs_set_page_writeback_locked - Lock a request for writeback - * @req: - */ -int nfs_set_page_writeback_locked(struct nfs_page *req) -{ - struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode); - - if (!nfs_lock_request(req)) - return 0; - radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_WRITEBACK); - return 1; -} - -/** - * nfs_clear_page_writeback - Unlock request and wake up sleepers - */ -void nfs_clear_page_writeback(struct nfs_page *req) -{ - struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode); - - spin_lock(&nfsi->req_lock); - radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_WRITEBACK); - spin_unlock(&nfsi->req_lock); - nfs_unlock_request(req); -} - /** * nfs_clear_request - Free up all resources allocated to the request * @req: @@ -177,15 +150,34 @@ nfs_release_request(struct nfs_page *req) nfs_page_free(req); } -static int nfs_wait_bit_interruptible(void *word) +/** + * nfs_list_add_request - Insert a request into a sorted list + * @req: request + * @head: head of list into which to insert the request. + * + * Note that the wb_list is sorted by page index in order to facilitate + * coalescing of requests. + * We use an insertion sort that is optimized for the case of appended + * writes. + */ +void +nfs_list_add_request(struct nfs_page *req, struct list_head *head) { - int ret = 0; + struct list_head *pos; - if (signal_pending(current)) - ret = -ERESTARTSYS; - else - schedule(); - return ret; +#ifdef NFS_PARANOIA + if (!list_empty(&req->wb_list)) { + printk(KERN_ERR "NFS: Add to list failed!\n"); + BUG(); + } +#endif + list_for_each_prev(pos, head) { + struct nfs_page *p = nfs_list_entry(pos); + if (p->wb_index < req->wb_index) + break; + } + list_add(&req->wb_list, pos); + req->wb_list_head = head; } /** @@ -198,22 +190,12 @@ static int nfs_wait_bit_interruptible(void *word) int nfs_wait_on_request(struct nfs_page *req) { - struct rpc_clnt *clnt = NFS_CLIENT(req->wb_context->dentry->d_inode); - sigset_t oldmask; - int ret = 0; - - if (!test_bit(PG_BUSY, &req->wb_flags)) - goto out; - /* - * Note: the call to rpc_clnt_sigmask() suffices to ensure that we - * are not interrupted if intr flag is not set - */ - rpc_clnt_sigmask(clnt, &oldmask); - ret = out_of_line_wait_on_bit(&req->wb_flags, PG_BUSY, - nfs_wait_bit_interruptible, TASK_INTERRUPTIBLE); - rpc_clnt_sigunmask(clnt, &oldmask); -out: - return ret; + struct inode *inode = req->wb_context->dentry->d_inode; + struct rpc_clnt *clnt = NFS_CLIENT(inode); + + if (!NFS_WBACK_BUSY(req)) + return 0; + return nfs_wait_event(clnt, req->wb_context->waitq, !NFS_WBACK_BUSY(req)); } /** @@ -261,62 +243,6 @@ nfs_coalesce_requests(struct list_head *head, struct list_head *dst, return npages; } -#define NFS_SCAN_MAXENTRIES 16 -/** - * nfs_scan_lock_dirty - Scan the radix tree for dirty requests - * @nfsi: NFS inode - * @dst: Destination list - * @idx_start: lower bound of page->index to scan - * @npages: idx_start + npages sets the upper bound to scan. - * - * Moves elements from one of the inode request lists. - * If the number of requests is set to 0, the entire address_space - * starting at index idx_start, is scanned. - * The requests are *not* checked to ensure that they form a contiguous set. - * You must be holding the inode's req_lock when calling this function - */ -int -nfs_scan_lock_dirty(struct nfs_inode *nfsi, struct list_head *dst, - unsigned long idx_start, unsigned int npages) -{ - struct nfs_page *pgvec[NFS_SCAN_MAXENTRIES]; - struct nfs_page *req; - unsigned long idx_end; - int found, i; - int res; - - res = 0; - if (npages == 0) - idx_end = ~0; - else - idx_end = idx_start + npages - 1; - - for (;;) { - found = radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, - (void **)&pgvec[0], idx_start, NFS_SCAN_MAXENTRIES, - NFS_PAGE_TAG_DIRTY); - if (found <= 0) - break; - for (i = 0; i < found; i++) { - req = pgvec[i]; - if (req->wb_index > idx_end) - goto out; - - idx_start = req->wb_index + 1; - - if (nfs_set_page_writeback_locked(req)) { - radix_tree_tag_clear(&nfsi->nfs_page_tree, - req->wb_index, NFS_PAGE_TAG_DIRTY); - nfs_list_remove_request(req); - nfs_list_add_request(req, dst); - res++; - } - } - } -out: - return res; -} - /** * nfs_scan_list - Scan a list for matching requests * @head: One of the NFS inode request lists @@ -354,7 +280,7 @@ nfs_scan_list(struct list_head *head, struct list_head *dst, if (req->wb_index > idx_end) break; - if (!nfs_set_page_writeback_locked(req)) + if (!nfs_lock_request(req)) continue; nfs_list_remove_request(req); nfs_list_add_request(req, dst); diff --git a/trunk/fs/nfs/proc.c b/trunk/fs/nfs/proc.c index cedf636bcf3c..d31b4d6e5a5e 100644 --- a/trunk/fs/nfs/proc.c +++ b/trunk/fs/nfs/proc.c @@ -622,7 +622,6 @@ struct nfs_rpc_ops nfs_v2_clientops = { .version = 2, /* protocol version */ .dentry_ops = &nfs_dentry_operations, .dir_inode_ops = &nfs_dir_inode_operations, - .file_inode_ops = &nfs_file_inode_operations, .getroot = nfs_proc_get_root, .getattr = nfs_proc_getattr, .setattr = nfs_proc_setattr, diff --git a/trunk/fs/nfs/read.c b/trunk/fs/nfs/read.c index 6f866b8aa2d5..a0042fb58634 100644 --- a/trunk/fs/nfs/read.c +++ b/trunk/fs/nfs/read.c @@ -173,6 +173,7 @@ static int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, if (len < PAGE_CACHE_SIZE) memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len); + nfs_lock_request(new); nfs_list_add_request(new, &one_request); nfs_pagein_one(&one_request, inode); return 0; @@ -184,6 +185,7 @@ static void nfs_readpage_release(struct nfs_page *req) nfs_clear_request(req); nfs_release_request(req); + nfs_unlock_request(req); dprintk("NFS: read done (%s/%Ld %d@%Ld)\n", req->wb_context->dentry->d_inode->i_sb->s_id, @@ -551,6 +553,7 @@ readpage_async_filler(void *data, struct page *page) } if (len < PAGE_CACHE_SIZE) memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len); + nfs_lock_request(new); nfs_list_add_request(new, desc->head); return 0; } diff --git a/trunk/fs/nfs/write.c b/trunk/fs/nfs/write.c index 5130eda231d7..6f7a4af3bc46 100644 --- a/trunk/fs/nfs/write.c +++ b/trunk/fs/nfs/write.c @@ -220,7 +220,7 @@ static int nfs_writepage_sync(struct nfs_open_context *ctx, struct inode *inode, ClearPageError(page); io_error: - nfs_end_data_update(inode); + nfs_end_data_update_defer(inode); nfs_writedata_free(wdata); return written ? written : result; } @@ -352,7 +352,7 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) if (err < 0) goto out; } - err = nfs_commit_inode(inode, wb_priority(wbc)); + err = nfs_commit_inode(inode, 0, 0, wb_priority(wbc)); if (err > 0) { wbc->nr_to_write -= err; err = 0; @@ -401,7 +401,7 @@ static void nfs_inode_remove_request(struct nfs_page *req) nfsi->npages--; if (!nfsi->npages) { spin_unlock(&nfsi->req_lock); - nfs_end_data_update(inode); + nfs_end_data_update_defer(inode); iput(inode); } else spin_unlock(&nfsi->req_lock); @@ -446,8 +446,6 @@ nfs_mark_request_dirty(struct nfs_page *req) struct nfs_inode *nfsi = NFS_I(inode); spin_lock(&nfsi->req_lock); - radix_tree_tag_set(&nfsi->nfs_page_tree, - req->wb_index, NFS_PAGE_TAG_DIRTY); nfs_list_add_request(req, &nfsi->dirty); nfsi->ndirty++; spin_unlock(&nfsi->req_lock); @@ -505,12 +503,13 @@ nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, unsigned int spin_lock(&nfsi->req_lock); next = idx_start; - while (radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, (void **)&req, next, 1, NFS_PAGE_TAG_WRITEBACK)) { + while (radix_tree_gang_lookup(&nfsi->nfs_page_tree, (void **)&req, next, 1)) { if (req->wb_index > idx_end) break; next = req->wb_index + 1; - BUG_ON(!NFS_WBACK_BUSY(req)); + if (!NFS_WBACK_BUSY(req)) + continue; atomic_inc(&req->wb_count); spin_unlock(&nfsi->req_lock); @@ -539,15 +538,12 @@ static int nfs_scan_dirty(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages) { struct nfs_inode *nfsi = NFS_I(inode); - int res = 0; - - if (nfsi->ndirty != 0) { - res = nfs_scan_lock_dirty(nfsi, dst, idx_start, npages); - nfsi->ndirty -= res; - sub_page_state(nr_dirty,res); - if ((nfsi->ndirty == 0) != list_empty(&nfsi->dirty)) - printk(KERN_ERR "NFS: desynchronized value of nfs_i.ndirty.\n"); - } + int res; + res = nfs_scan_list(&nfsi->dirty, dst, idx_start, npages); + nfsi->ndirty -= res; + sub_page_state(nr_dirty,res); + if ((nfsi->ndirty == 0) != list_empty(&nfsi->dirty)) + printk(KERN_ERR "NFS: desynchronized value of nfs_i.ndirty.\n"); return res; } @@ -566,14 +562,11 @@ static int nfs_scan_commit(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages) { struct nfs_inode *nfsi = NFS_I(inode); - int res = 0; - - if (nfsi->ncommit != 0) { - res = nfs_scan_list(&nfsi->commit, dst, idx_start, npages); - nfsi->ncommit -= res; - if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit)) - printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n"); - } + int res; + res = nfs_scan_list(&nfsi->commit, dst, idx_start, npages); + nfsi->ncommit -= res; + if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit)) + printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n"); return res; } #endif @@ -757,7 +750,7 @@ int nfs_updatepage(struct file *file, struct page *page, * is entirely in cache, it may be more efficient to avoid * fragmenting write requests. */ - if (PageUptodate(page) && inode->i_flock == NULL && !(file->f_mode & O_SYNC)) { + if (PageUptodate(page) && inode->i_flock == NULL) { loff_t end_offs = i_size_read(inode) - 1; unsigned long end_index = end_offs >> PAGE_CACHE_SHIFT; @@ -828,7 +821,7 @@ static void nfs_writepage_release(struct nfs_page *req) #else nfs_inode_remove_request(req); #endif - nfs_clear_page_writeback(req); + nfs_unlock_request(req); } static inline int flush_task_priority(int how) @@ -959,7 +952,7 @@ static int nfs_flush_multi(struct list_head *head, struct inode *inode, int how) nfs_writedata_free(data); } nfs_mark_request_dirty(req); - nfs_clear_page_writeback(req); + nfs_unlock_request(req); return -ENOMEM; } @@ -1009,7 +1002,7 @@ static int nfs_flush_one(struct list_head *head, struct inode *inode, int how) struct nfs_page *req = nfs_list_entry(head->next); nfs_list_remove_request(req); nfs_mark_request_dirty(req); - nfs_clear_page_writeback(req); + nfs_unlock_request(req); } return -ENOMEM; } @@ -1036,7 +1029,7 @@ nfs_flush_list(struct list_head *head, int wpages, int how) req = nfs_list_entry(head->next); nfs_list_remove_request(req); nfs_mark_request_dirty(req); - nfs_clear_page_writeback(req); + nfs_unlock_request(req); } return error; } @@ -1128,7 +1121,7 @@ static void nfs_writeback_done_full(struct nfs_write_data *data, int status) nfs_inode_remove_request(req); #endif next: - nfs_clear_page_writeback(req); + nfs_unlock_request(req); } } @@ -1217,24 +1210,36 @@ static void nfs_commit_rpcsetup(struct list_head *head, struct nfs_write_data *data, int how) { struct rpc_task *task = &data->task; - struct nfs_page *first; + struct nfs_page *first, *last; struct inode *inode; + loff_t start, end, len; /* Set up the RPC argument and reply structs * NB: take care not to mess about with data->commit et al. */ list_splice_init(head, &data->pages); first = nfs_list_entry(data->pages.next); + last = nfs_list_entry(data->pages.prev); inode = first->wb_context->dentry->d_inode; + /* + * Determine the offset range of requests in the COMMIT call. + * We rely on the fact that data->pages is an ordered list... + */ + start = req_offset(first); + end = req_offset(last) + last->wb_bytes; + len = end - start; + /* If 'len' is not a 32-bit quantity, pass '0' in the COMMIT call */ + if (end >= i_size_read(inode) || len < 0 || len > (~((u32)0) >> 1)) + len = 0; + data->inode = inode; data->cred = first->wb_context->cred; data->args.fh = NFS_FH(data->inode); - /* Note: we always request a commit of the entire inode */ - data->args.offset = 0; - data->args.count = 0; - data->res.count = 0; + data->args.offset = start; + data->args.count = len; + data->res.count = len; data->res.fattr = &data->fattr; data->res.verf = &data->verf; @@ -1273,7 +1278,7 @@ nfs_commit_list(struct list_head *head, int how) req = nfs_list_entry(head->next); nfs_list_remove_request(req); nfs_mark_request_commit(req); - nfs_clear_page_writeback(req); + nfs_unlock_request(req); } return -ENOMEM; } @@ -1319,7 +1324,7 @@ nfs_commit_done(struct rpc_task *task) dprintk(" mismatch\n"); nfs_mark_request_dirty(req); next: - nfs_clear_page_writeback(req); + nfs_unlock_request(req); res++; } sub_page_state(nr_unstable,res); @@ -1337,23 +1342,16 @@ static int nfs_flush_inode(struct inode *inode, unsigned long idx_start, spin_lock(&nfsi->req_lock); res = nfs_scan_dirty(inode, &head, idx_start, npages); spin_unlock(&nfsi->req_lock); - if (res) { - struct nfs_server *server = NFS_SERVER(inode); - - /* For single writes, FLUSH_STABLE is more efficient */ - if (res == nfsi->npages && nfsi->npages <= server->wpages) { - if (res > 1 || nfs_list_entry(head.next)->wb_bytes <= server->wsize) - how |= FLUSH_STABLE; - } - error = nfs_flush_list(&head, server->wpages, how); - } + if (res) + error = nfs_flush_list(&head, NFS_SERVER(inode)->wpages, how); if (error < 0) return error; return res; } #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) -int nfs_commit_inode(struct inode *inode, int how) +int nfs_commit_inode(struct inode *inode, unsigned long idx_start, + unsigned int npages, int how) { struct nfs_inode *nfsi = NFS_I(inode); LIST_HEAD(head); @@ -1361,13 +1359,15 @@ int nfs_commit_inode(struct inode *inode, int how) error = 0; spin_lock(&nfsi->req_lock); - res = nfs_scan_commit(inode, &head, 0, 0); - spin_unlock(&nfsi->req_lock); + res = nfs_scan_commit(inode, &head, idx_start, npages); if (res) { + res += nfs_scan_commit(inode, &head, 0, 0); + spin_unlock(&nfsi->req_lock); error = nfs_commit_list(&head, how); - if (error < 0) - return error; - } + } else + spin_unlock(&nfsi->req_lock); + if (error < 0) + return error; return res; } #endif @@ -1389,7 +1389,7 @@ int nfs_sync_inode(struct inode *inode, unsigned long idx_start, error = nfs_flush_inode(inode, idx_start, npages, how); #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) if (error == 0) - error = nfs_commit_inode(inode, how); + error = nfs_commit_inode(inode, idx_start, npages, how); #endif } while (error > 0); return error; diff --git a/trunk/fs/nfs_common/Makefile b/trunk/fs/nfs_common/Makefile deleted file mode 100644 index f689ed82af3a..000000000000 --- a/trunk/fs/nfs_common/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# Makefile for Linux filesystem routines that are shared by client and server. -# - -obj-$(CONFIG_NFS_ACL_SUPPORT) += nfs_acl.o - -nfs_acl-objs := nfsacl.o diff --git a/trunk/fs/nfs_common/nfsacl.c b/trunk/fs/nfs_common/nfsacl.c deleted file mode 100644 index 18c58c32e326..000000000000 --- a/trunk/fs/nfs_common/nfsacl.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * fs/nfs_common/nfsacl.c - * - * Copyright (C) 2002-2003 Andreas Gruenbacher - */ - -/* - * The Solaris nfsacl protocol represents some ACLs slightly differently - * than POSIX 1003.1e draft 17 does (and we do): - * - * - Minimal ACLs always have an ACL_MASK entry, so they have - * four instead of three entries. - * - The ACL_MASK entry in such minimal ACLs always has the same - * permissions as the ACL_GROUP_OBJ entry. (In extended ACLs - * the ACL_MASK and ACL_GROUP_OBJ entries may differ.) - * - The identifier fields of the ACL_USER_OBJ and ACL_GROUP_OBJ - * entries contain the identifiers of the owner and owning group. - * (In POSIX ACLs we always set them to ACL_UNDEFINED_ID). - * - ACL entries in the kernel are kept sorted in ascending order - * of (e_tag, e_id). Solaris ACLs are unsorted. - */ - -#include -#include -#include -#include -#include -#include - -MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(nfsacl_encode); -EXPORT_SYMBOL(nfsacl_decode); - -struct nfsacl_encode_desc { - struct xdr_array2_desc desc; - unsigned int count; - struct posix_acl *acl; - int typeflag; - uid_t uid; - gid_t gid; -}; - -static int -xdr_nfsace_encode(struct xdr_array2_desc *desc, void *elem) -{ - struct nfsacl_encode_desc *nfsacl_desc = - (struct nfsacl_encode_desc *) desc; - u32 *p = (u32 *) elem; - - if (nfsacl_desc->count < nfsacl_desc->acl->a_count) { - struct posix_acl_entry *entry = - &nfsacl_desc->acl->a_entries[nfsacl_desc->count++]; - - *p++ = htonl(entry->e_tag | nfsacl_desc->typeflag); - switch(entry->e_tag) { - case ACL_USER_OBJ: - *p++ = htonl(nfsacl_desc->uid); - break; - case ACL_GROUP_OBJ: - *p++ = htonl(nfsacl_desc->gid); - break; - case ACL_USER: - case ACL_GROUP: - *p++ = htonl(entry->e_id); - break; - default: /* Solaris depends on that! */ - *p++ = 0; - break; - } - *p++ = htonl(entry->e_perm & S_IRWXO); - } else { - const struct posix_acl_entry *pa, *pe; - int group_obj_perm = ACL_READ|ACL_WRITE|ACL_EXECUTE; - - FOREACH_ACL_ENTRY(pa, nfsacl_desc->acl, pe) { - if (pa->e_tag == ACL_GROUP_OBJ) { - group_obj_perm = pa->e_perm & S_IRWXO; - break; - } - } - /* fake up ACL_MASK entry */ - *p++ = htonl(ACL_MASK | nfsacl_desc->typeflag); - *p++ = htonl(0); - *p++ = htonl(group_obj_perm); - } - - return 0; -} - -unsigned int -nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode, - struct posix_acl *acl, int encode_entries, int typeflag) -{ - int entries = (acl && acl->a_count) ? max_t(int, acl->a_count, 4) : 0; - struct nfsacl_encode_desc nfsacl_desc = { - .desc = { - .elem_size = 12, - .array_len = encode_entries ? entries : 0, - .xcode = xdr_nfsace_encode, - }, - .acl = acl, - .typeflag = typeflag, - .uid = inode->i_uid, - .gid = inode->i_gid, - }; - int err; - - if (entries > NFS_ACL_MAX_ENTRIES || - xdr_encode_word(buf, base, entries)) - return -EINVAL; - err = xdr_encode_array2(buf, base + 4, &nfsacl_desc.desc); - if (!err) - err = 8 + nfsacl_desc.desc.elem_size * - nfsacl_desc.desc.array_len; - return err; -} - -struct nfsacl_decode_desc { - struct xdr_array2_desc desc; - unsigned int count; - struct posix_acl *acl; -}; - -static int -xdr_nfsace_decode(struct xdr_array2_desc *desc, void *elem) -{ - struct nfsacl_decode_desc *nfsacl_desc = - (struct nfsacl_decode_desc *) desc; - u32 *p = (u32 *) elem; - struct posix_acl_entry *entry; - - if (!nfsacl_desc->acl) { - if (desc->array_len > NFS_ACL_MAX_ENTRIES) - return -EINVAL; - nfsacl_desc->acl = posix_acl_alloc(desc->array_len, GFP_KERNEL); - if (!nfsacl_desc->acl) - return -ENOMEM; - nfsacl_desc->count = 0; - } - - entry = &nfsacl_desc->acl->a_entries[nfsacl_desc->count++]; - entry->e_tag = ntohl(*p++) & ~NFS_ACL_DEFAULT; - entry->e_id = ntohl(*p++); - entry->e_perm = ntohl(*p++); - - switch(entry->e_tag) { - case ACL_USER_OBJ: - case ACL_USER: - case ACL_GROUP_OBJ: - case ACL_GROUP: - case ACL_OTHER: - if (entry->e_perm & ~S_IRWXO) - return -EINVAL; - break; - case ACL_MASK: - /* Solaris sometimes sets additonal bits in the mask */ - entry->e_perm &= S_IRWXO; - break; - default: - return -EINVAL; - } - - return 0; -} - -static int -cmp_acl_entry(const void *x, const void *y) -{ - const struct posix_acl_entry *a = x, *b = y; - - if (a->e_tag != b->e_tag) - return a->e_tag - b->e_tag; - else if (a->e_id > b->e_id) - return 1; - else if (a->e_id < b->e_id) - return -1; - else - return 0; -} - -/* - * Convert from a Solaris ACL to a POSIX 1003.1e draft 17 ACL. - */ -static int -posix_acl_from_nfsacl(struct posix_acl *acl) -{ - struct posix_acl_entry *pa, *pe, - *group_obj = NULL, *mask = NULL; - - if (!acl) - return 0; - - sort(acl->a_entries, acl->a_count, sizeof(struct posix_acl_entry), - cmp_acl_entry, NULL); - - /* Clear undefined identifier fields and find the ACL_GROUP_OBJ - and ACL_MASK entries. */ - FOREACH_ACL_ENTRY(pa, acl, pe) { - switch(pa->e_tag) { - case ACL_USER_OBJ: - pa->e_id = ACL_UNDEFINED_ID; - break; - case ACL_GROUP_OBJ: - pa->e_id = ACL_UNDEFINED_ID; - group_obj = pa; - break; - case ACL_MASK: - mask = pa; - /* fall through */ - case ACL_OTHER: - pa->e_id = ACL_UNDEFINED_ID; - break; - } - } - if (acl->a_count == 4 && group_obj && mask && - mask->e_perm == group_obj->e_perm) { - /* remove bogus ACL_MASK entry */ - memmove(mask, mask+1, (3 - (mask - acl->a_entries)) * - sizeof(struct posix_acl_entry)); - acl->a_count = 3; - } - return 0; -} - -unsigned int -nfsacl_decode(struct xdr_buf *buf, unsigned int base, unsigned int *aclcnt, - struct posix_acl **pacl) -{ - struct nfsacl_decode_desc nfsacl_desc = { - .desc = { - .elem_size = 12, - .xcode = pacl ? xdr_nfsace_decode : NULL, - }, - }; - u32 entries; - int err; - - if (xdr_decode_word(buf, base, &entries) || - entries > NFS_ACL_MAX_ENTRIES) - return -EINVAL; - err = xdr_decode_array2(buf, base + 4, &nfsacl_desc.desc); - if (err) - return err; - if (pacl) { - if (entries != nfsacl_desc.desc.array_len || - posix_acl_from_nfsacl(nfsacl_desc.acl) != 0) { - posix_acl_release(nfsacl_desc.acl); - return -EINVAL; - } - *pacl = nfsacl_desc.acl; - } - if (aclcnt) - *aclcnt = entries; - return 8 + nfsacl_desc.desc.elem_size * - nfsacl_desc.desc.array_len; -} diff --git a/trunk/fs/nfsd/Makefile b/trunk/fs/nfsd/Makefile index 9f043f44c92f..b8680a247f8b 100644 --- a/trunk/fs/nfsd/Makefile +++ b/trunk/fs/nfsd/Makefile @@ -6,9 +6,7 @@ obj-$(CONFIG_NFSD) += nfsd.o nfsd-y := nfssvc.o nfsctl.o nfsproc.o nfsfh.o vfs.o \ export.o auth.o lockd.o nfscache.o nfsxdr.o stats.o -nfsd-$(CONFIG_NFSD_V2_ACL) += nfs2acl.o nfsd-$(CONFIG_NFSD_V3) += nfs3proc.o nfs3xdr.o -nfsd-$(CONFIG_NFSD_V3_ACL) += nfs3acl.o nfsd-$(CONFIG_NFSD_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o \ nfs4acl.o nfs4callback.o nfsd-objs := $(nfsd-y) diff --git a/trunk/fs/nfsd/nfs2acl.c b/trunk/fs/nfsd/nfs2acl.c deleted file mode 100644 index 7cbf0682b2f0..000000000000 --- a/trunk/fs/nfsd/nfs2acl.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - * linux/fs/nfsd/nfsacl.c - * - * Process version 2 NFSACL requests. - * - * Copyright (C) 2002-2003 Andreas Gruenbacher - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define NFSDDBG_FACILITY NFSDDBG_PROC -#define RETURN_STATUS(st) { resp->status = (st); return (st); } - -/* - * NULL call. - */ -static int -nfsacld_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) -{ - return nfs_ok; -} - -/* - * Get the Access and/or Default ACL of a file. - */ -static int nfsacld_proc_getacl(struct svc_rqst * rqstp, - struct nfsd3_getaclargs *argp, struct nfsd3_getaclres *resp) -{ - svc_fh *fh; - struct posix_acl *acl; - int nfserr = 0; - - dprintk("nfsd: GETACL(2acl) %s\n", SVCFH_fmt(&argp->fh)); - - fh = fh_copy(&resp->fh, &argp->fh); - if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP))) - RETURN_STATUS(nfserr_inval); - - if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) - RETURN_STATUS(nfserr_inval); - resp->mask = argp->mask; - - if (resp->mask & (NFS_ACL|NFS_ACLCNT)) { - acl = nfsd_get_posix_acl(fh, ACL_TYPE_ACCESS); - if (IS_ERR(acl)) { - int err = PTR_ERR(acl); - - if (err == -ENODATA || err == -EOPNOTSUPP) - acl = NULL; - else { - nfserr = nfserrno(err); - goto fail; - } - } - if (acl == NULL) { - /* Solaris returns the inode's minimum ACL. */ - - struct inode *inode = fh->fh_dentry->d_inode; - acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL); - } - resp->acl_access = acl; - } - if (resp->mask & (NFS_DFACL|NFS_DFACLCNT)) { - /* Check how Solaris handles requests for the Default ACL - of a non-directory! */ - - acl = nfsd_get_posix_acl(fh, ACL_TYPE_DEFAULT); - if (IS_ERR(acl)) { - int err = PTR_ERR(acl); - - if (err == -ENODATA || err == -EOPNOTSUPP) - acl = NULL; - else { - nfserr = nfserrno(err); - goto fail; - } - } - resp->acl_default = acl; - } - - /* resp->acl_{access,default} are released in nfssvc_release_getacl. */ - RETURN_STATUS(0); - -fail: - posix_acl_release(resp->acl_access); - posix_acl_release(resp->acl_default); - RETURN_STATUS(nfserr); -} - -/* - * Set the Access and/or Default ACL of a file. - */ -static int nfsacld_proc_setacl(struct svc_rqst * rqstp, - struct nfsd3_setaclargs *argp, - struct nfsd_attrstat *resp) -{ - svc_fh *fh; - int nfserr = 0; - - dprintk("nfsd: SETACL(2acl) %s\n", SVCFH_fmt(&argp->fh)); - - fh = fh_copy(&resp->fh, &argp->fh); - nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP); - - if (!nfserr) { - nfserr = nfserrno( nfsd_set_posix_acl( - fh, ACL_TYPE_ACCESS, argp->acl_access) ); - } - if (!nfserr) { - nfserr = nfserrno( nfsd_set_posix_acl( - fh, ACL_TYPE_DEFAULT, argp->acl_default) ); - } - - /* argp->acl_{access,default} may have been allocated in - nfssvc_decode_setaclargs. */ - posix_acl_release(argp->acl_access); - posix_acl_release(argp->acl_default); - return nfserr; -} - -/* - * Check file attributes - */ -static int nfsacld_proc_getattr(struct svc_rqst * rqstp, - struct nfsd_fhandle *argp, struct nfsd_attrstat *resp) -{ - dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh)); - - fh_copy(&resp->fh, &argp->fh); - return fh_verify(rqstp, &resp->fh, 0, MAY_NOP); -} - -/* - * Check file access - */ -static int nfsacld_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessargs *argp, - struct nfsd3_accessres *resp) -{ - int nfserr; - - dprintk("nfsd: ACCESS(2acl) %s 0x%x\n", - SVCFH_fmt(&argp->fh), - argp->access); - - fh_copy(&resp->fh, &argp->fh); - resp->access = argp->access; - nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL); - return nfserr; -} - -/* - * XDR decode functions - */ -static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, u32 *p, - struct nfsd3_getaclargs *argp) -{ - if (!(p = nfs2svc_decode_fh(p, &argp->fh))) - return 0; - argp->mask = ntohl(*p); p++; - - return xdr_argsize_check(rqstp, p); -} - - -static int nfsaclsvc_decode_setaclargs(struct svc_rqst *rqstp, u32 *p, - struct nfsd3_setaclargs *argp) -{ - struct kvec *head = rqstp->rq_arg.head; - unsigned int base; - int n; - - if (!(p = nfs2svc_decode_fh(p, &argp->fh))) - return 0; - argp->mask = ntohl(*p++); - if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT) || - !xdr_argsize_check(rqstp, p)) - return 0; - - base = (char *)p - (char *)head->iov_base; - n = nfsacl_decode(&rqstp->rq_arg, base, NULL, - (argp->mask & NFS_ACL) ? - &argp->acl_access : NULL); - if (n > 0) - n = nfsacl_decode(&rqstp->rq_arg, base + n, NULL, - (argp->mask & NFS_DFACL) ? - &argp->acl_default : NULL); - return (n > 0); -} - -static int nfsaclsvc_decode_fhandleargs(struct svc_rqst *rqstp, u32 *p, - struct nfsd_fhandle *argp) -{ - if (!(p = nfs2svc_decode_fh(p, &argp->fh))) - return 0; - return xdr_argsize_check(rqstp, p); -} - -static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, u32 *p, - struct nfsd3_accessargs *argp) -{ - if (!(p = nfs2svc_decode_fh(p, &argp->fh))) - return 0; - argp->access = ntohl(*p++); - - return xdr_argsize_check(rqstp, p); -} - -/* - * XDR encode functions - */ - -/* GETACL */ -static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, u32 *p, - struct nfsd3_getaclres *resp) -{ - struct dentry *dentry = resp->fh.fh_dentry; - struct inode *inode = dentry->d_inode; - int w = nfsacl_size( - (resp->mask & NFS_ACL) ? resp->acl_access : NULL, - (resp->mask & NFS_DFACL) ? resp->acl_default : NULL); - struct kvec *head = rqstp->rq_res.head; - unsigned int base; - int n; - - if (dentry == NULL || dentry->d_inode == NULL) - return 0; - inode = dentry->d_inode; - - p = nfs2svc_encode_fattr(rqstp, p, &resp->fh); - *p++ = htonl(resp->mask); - if (!xdr_ressize_check(rqstp, p)) - return 0; - base = (char *)p - (char *)head->iov_base; - - rqstp->rq_res.page_len = w; - while (w > 0) { - if (!svc_take_res_page(rqstp)) - return 0; - w -= PAGE_SIZE; - } - - n = nfsacl_encode(&rqstp->rq_res, base, inode, - resp->acl_access, - resp->mask & NFS_ACL, 0); - if (n > 0) - n = nfsacl_encode(&rqstp->rq_res, base + n, inode, - resp->acl_default, - resp->mask & NFS_DFACL, - NFS_ACL_DEFAULT); - if (n <= 0) - return 0; - return 1; -} - -static int nfsaclsvc_encode_attrstatres(struct svc_rqst *rqstp, u32 *p, - struct nfsd_attrstat *resp) -{ - p = nfs2svc_encode_fattr(rqstp, p, &resp->fh); - return xdr_ressize_check(rqstp, p); -} - -/* ACCESS */ -static int nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, u32 *p, - struct nfsd3_accessres *resp) -{ - p = nfs2svc_encode_fattr(rqstp, p, &resp->fh); - *p++ = htonl(resp->access); - return xdr_ressize_check(rqstp, p); -} - -/* - * XDR release functions - */ -static int nfsaclsvc_release_getacl(struct svc_rqst *rqstp, u32 *p, - struct nfsd3_getaclres *resp) -{ - fh_put(&resp->fh); - posix_acl_release(resp->acl_access); - posix_acl_release(resp->acl_default); - return 1; -} - -static int nfsaclsvc_release_fhandle(struct svc_rqst *rqstp, u32 *p, - struct nfsd_fhandle *resp) -{ - fh_put(&resp->fh); - return 1; -} - -#define nfsaclsvc_decode_voidargs NULL -#define nfsaclsvc_encode_voidres NULL -#define nfsaclsvc_release_void NULL -#define nfsd3_fhandleargs nfsd_fhandle -#define nfsd3_attrstatres nfsd_attrstat -#define nfsd3_voidres nfsd3_voidargs -struct nfsd3_voidargs { int dummy; }; - -#define PROC(name, argt, rest, relt, cache, respsize) \ - { (svc_procfunc) nfsacld_proc_##name, \ - (kxdrproc_t) nfsaclsvc_decode_##argt##args, \ - (kxdrproc_t) nfsaclsvc_encode_##rest##res, \ - (kxdrproc_t) nfsaclsvc_release_##relt, \ - sizeof(struct nfsd3_##argt##args), \ - sizeof(struct nfsd3_##rest##res), \ - 0, \ - cache, \ - respsize, \ - } - -#define ST 1 /* status*/ -#define AT 21 /* attributes */ -#define pAT (1+AT) /* post attributes - conditional */ -#define ACL (1+NFS_ACL_MAX_ENTRIES*3) /* Access Control List */ - -static struct svc_procedure nfsd_acl_procedures2[] = { - PROC(null, void, void, void, RC_NOCACHE, ST), - PROC(getacl, getacl, getacl, getacl, RC_NOCACHE, ST+1+2*(1+ACL)), - PROC(setacl, setacl, attrstat, fhandle, RC_NOCACHE, ST+AT), - PROC(getattr, fhandle, attrstat, fhandle, RC_NOCACHE, ST+AT), - PROC(access, access, access, fhandle, RC_NOCACHE, ST+AT+1), -}; - -struct svc_version nfsd_acl_version2 = { - .vs_vers = 2, - .vs_nproc = 5, - .vs_proc = nfsd_acl_procedures2, - .vs_dispatch = nfsd_dispatch, - .vs_xdrsize = NFS3_SVC_XDRSIZE, -}; diff --git a/trunk/fs/nfsd/nfs3acl.c b/trunk/fs/nfsd/nfs3acl.c deleted file mode 100644 index 64ba40572fea..000000000000 --- a/trunk/fs/nfsd/nfs3acl.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * linux/fs/nfsd/nfs3acl.c - * - * Process version 3 NFSACL requests. - * - * Copyright (C) 2002-2003 Andreas Gruenbacher - */ - -#include -#include -#include -#include -#include -#include -#include - -#define RETURN_STATUS(st) { resp->status = (st); return (st); } - -/* - * NULL call. - */ -static int -nfsd3_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) -{ - return nfs_ok; -} - -/* - * Get the Access and/or Default ACL of a file. - */ -static int nfsd3_proc_getacl(struct svc_rqst * rqstp, - struct nfsd3_getaclargs *argp, struct nfsd3_getaclres *resp) -{ - svc_fh *fh; - struct posix_acl *acl; - int nfserr = 0; - - fh = fh_copy(&resp->fh, &argp->fh); - if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP))) - RETURN_STATUS(nfserr_inval); - - if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) - RETURN_STATUS(nfserr_inval); - resp->mask = argp->mask; - - if (resp->mask & (NFS_ACL|NFS_ACLCNT)) { - acl = nfsd_get_posix_acl(fh, ACL_TYPE_ACCESS); - if (IS_ERR(acl)) { - int err = PTR_ERR(acl); - - if (err == -ENODATA || err == -EOPNOTSUPP) - acl = NULL; - else { - nfserr = nfserrno(err); - goto fail; - } - } - if (acl == NULL) { - /* Solaris returns the inode's minimum ACL. */ - - struct inode *inode = fh->fh_dentry->d_inode; - acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL); - } - resp->acl_access = acl; - } - if (resp->mask & (NFS_DFACL|NFS_DFACLCNT)) { - /* Check how Solaris handles requests for the Default ACL - of a non-directory! */ - - acl = nfsd_get_posix_acl(fh, ACL_TYPE_DEFAULT); - if (IS_ERR(acl)) { - int err = PTR_ERR(acl); - - if (err == -ENODATA || err == -EOPNOTSUPP) - acl = NULL; - else { - nfserr = nfserrno(err); - goto fail; - } - } - resp->acl_default = acl; - } - - /* resp->acl_{access,default} are released in nfs3svc_release_getacl. */ - RETURN_STATUS(0); - -fail: - posix_acl_release(resp->acl_access); - posix_acl_release(resp->acl_default); - RETURN_STATUS(nfserr); -} - -/* - * Set the Access and/or Default ACL of a file. - */ -static int nfsd3_proc_setacl(struct svc_rqst * rqstp, - struct nfsd3_setaclargs *argp, - struct nfsd3_attrstat *resp) -{ - svc_fh *fh; - int nfserr = 0; - - fh = fh_copy(&resp->fh, &argp->fh); - nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP); - - if (!nfserr) { - nfserr = nfserrno( nfsd_set_posix_acl( - fh, ACL_TYPE_ACCESS, argp->acl_access) ); - } - if (!nfserr) { - nfserr = nfserrno( nfsd_set_posix_acl( - fh, ACL_TYPE_DEFAULT, argp->acl_default) ); - } - - /* argp->acl_{access,default} may have been allocated in - nfs3svc_decode_setaclargs. */ - posix_acl_release(argp->acl_access); - posix_acl_release(argp->acl_default); - RETURN_STATUS(nfserr); -} - -/* - * XDR decode functions - */ -static int nfs3svc_decode_getaclargs(struct svc_rqst *rqstp, u32 *p, - struct nfsd3_getaclargs *args) -{ - if (!(p = nfs3svc_decode_fh(p, &args->fh))) - return 0; - args->mask = ntohl(*p); p++; - - return xdr_argsize_check(rqstp, p); -} - - -static int nfs3svc_decode_setaclargs(struct svc_rqst *rqstp, u32 *p, - struct nfsd3_setaclargs *args) -{ - struct kvec *head = rqstp->rq_arg.head; - unsigned int base; - int n; - - if (!(p = nfs3svc_decode_fh(p, &args->fh))) - return 0; - args->mask = ntohl(*p++); - if (args->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT) || - !xdr_argsize_check(rqstp, p)) - return 0; - - base = (char *)p - (char *)head->iov_base; - n = nfsacl_decode(&rqstp->rq_arg, base, NULL, - (args->mask & NFS_ACL) ? - &args->acl_access : NULL); - if (n > 0) - n = nfsacl_decode(&rqstp->rq_arg, base + n, NULL, - (args->mask & NFS_DFACL) ? - &args->acl_default : NULL); - return (n > 0); -} - -/* - * XDR encode functions - */ - -/* GETACL */ -static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, u32 *p, - struct nfsd3_getaclres *resp) -{ - struct dentry *dentry = resp->fh.fh_dentry; - - p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh); - if (resp->status == 0 && dentry && dentry->d_inode) { - struct inode *inode = dentry->d_inode; - int w = nfsacl_size( - (resp->mask & NFS_ACL) ? resp->acl_access : NULL, - (resp->mask & NFS_DFACL) ? resp->acl_default : NULL); - struct kvec *head = rqstp->rq_res.head; - unsigned int base; - int n; - - *p++ = htonl(resp->mask); - if (!xdr_ressize_check(rqstp, p)) - return 0; - base = (char *)p - (char *)head->iov_base; - - rqstp->rq_res.page_len = w; - while (w > 0) { - if (!svc_take_res_page(rqstp)) - return 0; - w -= PAGE_SIZE; - } - - n = nfsacl_encode(&rqstp->rq_res, base, inode, - resp->acl_access, - resp->mask & NFS_ACL, 0); - if (n > 0) - n = nfsacl_encode(&rqstp->rq_res, base + n, inode, - resp->acl_default, - resp->mask & NFS_DFACL, - NFS_ACL_DEFAULT); - if (n <= 0) - return 0; - } else - if (!xdr_ressize_check(rqstp, p)) - return 0; - - return 1; -} - -/* SETACL */ -static int nfs3svc_encode_setaclres(struct svc_rqst *rqstp, u32 *p, - struct nfsd3_attrstat *resp) -{ - p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh); - - return xdr_ressize_check(rqstp, p); -} - -/* - * XDR release functions - */ -static int nfs3svc_release_getacl(struct svc_rqst *rqstp, u32 *p, - struct nfsd3_getaclres *resp) -{ - fh_put(&resp->fh); - posix_acl_release(resp->acl_access); - posix_acl_release(resp->acl_default); - return 1; -} - -#define nfs3svc_decode_voidargs NULL -#define nfs3svc_release_void NULL -#define nfsd3_setaclres nfsd3_attrstat -#define nfsd3_voidres nfsd3_voidargs -struct nfsd3_voidargs { int dummy; }; - -#define PROC(name, argt, rest, relt, cache, respsize) \ - { (svc_procfunc) nfsd3_proc_##name, \ - (kxdrproc_t) nfs3svc_decode_##argt##args, \ - (kxdrproc_t) nfs3svc_encode_##rest##res, \ - (kxdrproc_t) nfs3svc_release_##relt, \ - sizeof(struct nfsd3_##argt##args), \ - sizeof(struct nfsd3_##rest##res), \ - 0, \ - cache, \ - respsize, \ - } - -#define ST 1 /* status*/ -#define AT 21 /* attributes */ -#define pAT (1+AT) /* post attributes - conditional */ -#define ACL (1+NFS_ACL_MAX_ENTRIES*3) /* Access Control List */ - -static struct svc_procedure nfsd_acl_procedures3[] = { - PROC(null, void, void, void, RC_NOCACHE, ST), - PROC(getacl, getacl, getacl, getacl, RC_NOCACHE, ST+1+2*(1+ACL)), - PROC(setacl, setacl, setacl, fhandle, RC_NOCACHE, ST+pAT), -}; - -struct svc_version nfsd_acl_version3 = { - .vs_vers = 3, - .vs_nproc = 3, - .vs_proc = nfsd_acl_procedures3, - .vs_dispatch = nfsd_dispatch, - .vs_xdrsize = NFS3_SVC_XDRSIZE, -}; - diff --git a/trunk/fs/nfsd/nfs3xdr.c b/trunk/fs/nfsd/nfs3xdr.c index e0e134d6baba..11f806835c5a 100644 --- a/trunk/fs/nfsd/nfs3xdr.c +++ b/trunk/fs/nfsd/nfs3xdr.c @@ -71,12 +71,6 @@ decode_fh(u32 *p, struct svc_fh *fhp) return p + XDR_QUADLEN(size); } -/* Helper function for NFSv3 ACL code */ -u32 *nfs3svc_decode_fh(u32 *p, struct svc_fh *fhp) -{ - return decode_fh(p, fhp); -} - static inline u32 * encode_fh(u32 *p, struct svc_fh *fhp) { @@ -239,13 +233,6 @@ encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) return p; } -/* Helper for NFSv3 ACLs */ -u32 * -nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) -{ - return encode_post_op_attr(rqstp, p, fhp); -} - /* * Enocde weak cache consistency data */ diff --git a/trunk/fs/nfsd/nfs4callback.c b/trunk/fs/nfsd/nfs4callback.c index 634465e9cfc6..1a55dfcb74bc 100644 --- a/trunk/fs/nfsd/nfs4callback.c +++ b/trunk/fs/nfsd/nfs4callback.c @@ -430,7 +430,7 @@ nfsd4_probe_callback(struct nfs4_client *clp) clnt = rpc_create_client(xprt, hostname, program, 1, RPC_AUTH_UNIX); if (IS_ERR(clnt)) { dprintk("NFSD: couldn't create callback client\n"); - goto out_err; + goto out_xprt; } clnt->cl_intr = 0; clnt->cl_softrtry = 1; @@ -465,6 +465,8 @@ nfsd4_probe_callback(struct nfs4_client *clp) out_clnt: rpc_shutdown_client(clnt); goto out_err; +out_xprt: + xprt_destroy(xprt); out_err: dprintk("NFSD: warning: no callback path to client %.*s\n", (int)clp->cl_name.len, clp->cl_name.data); diff --git a/trunk/fs/nfsd/nfsproc.c b/trunk/fs/nfsd/nfsproc.c index 0aa1b9603d7f..757f9d208034 100644 --- a/trunk/fs/nfsd/nfsproc.c +++ b/trunk/fs/nfsd/nfsproc.c @@ -591,7 +591,6 @@ nfserrno (int errno) { nfserr_dropit, -ENOMEM }, { nfserr_badname, -ESRCH }, { nfserr_io, -ETXTBSY }, - { nfserr_notsupp, -EOPNOTSUPP }, { -1, -EIO } }; int i; diff --git a/trunk/fs/nfsd/nfssvc.c b/trunk/fs/nfsd/nfssvc.c index 904df604e86b..02ded7cfbdcf 100644 --- a/trunk/fs/nfsd/nfssvc.c +++ b/trunk/fs/nfsd/nfssvc.c @@ -31,7 +31,6 @@ #include #include #include -#include #define NFSDDBG_FACILITY NFSDDBG_SVC @@ -363,32 +362,6 @@ nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp) return 1; } -#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) -static struct svc_stat nfsd_acl_svcstats; -static struct svc_version * nfsd_acl_version[] = { - [2] = &nfsd_acl_version2, - [3] = &nfsd_acl_version3, -}; - -#define NFSD_ACL_NRVERS (sizeof(nfsd_acl_version)/sizeof(nfsd_acl_version[0])) -static struct svc_program nfsd_acl_program = { - .pg_prog = NFS_ACL_PROGRAM, - .pg_nvers = NFSD_ACL_NRVERS, - .pg_vers = nfsd_acl_version, - .pg_name = "nfsd", - .pg_class = "nfsd", - .pg_stats = &nfsd_acl_svcstats, -}; - -static struct svc_stat nfsd_acl_svcstats = { - .program = &nfsd_acl_program, -}; - -#define nfsd_acl_program_p &nfsd_acl_program -#else -#define nfsd_acl_program_p NULL -#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */ - extern struct svc_version nfsd_version2, nfsd_version3, nfsd_version4; static struct svc_version * nfsd_version[] = { @@ -403,7 +376,6 @@ static struct svc_version * nfsd_version[] = { #define NFSD_NRVERS (sizeof(nfsd_version)/sizeof(nfsd_version[0])) struct svc_program nfsd_program = { - .pg_next = nfsd_acl_program_p, .pg_prog = NFS_PROGRAM, /* program number */ .pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */ .pg_vers = nfsd_version, /* version table */ diff --git a/trunk/fs/nfsd/nfsxdr.c b/trunk/fs/nfsd/nfsxdr.c index b45999ff33e6..948b08287c99 100644 --- a/trunk/fs/nfsd/nfsxdr.c +++ b/trunk/fs/nfsd/nfsxdr.c @@ -49,12 +49,6 @@ decode_fh(u32 *p, struct svc_fh *fhp) return p + (NFS_FHSIZE >> 2); } -/* Helper function for NFSv2 ACL code */ -u32 *nfs2svc_decode_fh(u32 *p, struct svc_fh *fhp) -{ - return decode_fh(p, fhp); -} - static inline u32 * encode_fh(u32 *p, struct svc_fh *fhp) { @@ -196,11 +190,6 @@ encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) return p; } -/* Helper function for NFSv2 ACL code */ -u32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) -{ - return encode_fattr(rqstp, p, fhp); -} /* * XDR decode functions diff --git a/trunk/fs/nfsd/vfs.c b/trunk/fs/nfsd/vfs.c index ae3940dc85cc..e3e9d217236e 100644 --- a/trunk/fs/nfsd/vfs.c +++ b/trunk/fs/nfsd/vfs.c @@ -46,9 +46,8 @@ #include #include #include -#include -#include #ifdef CONFIG_NFSD_V4 +#include #include #include #include @@ -1858,107 +1857,3 @@ nfsd_racache_init(int cache_size) nfsdstats.ra_size = cache_size; return 0; } - -#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) -struct posix_acl * -nfsd_get_posix_acl(struct svc_fh *fhp, int type) -{ - struct inode *inode = fhp->fh_dentry->d_inode; - char *name; - void *value = NULL; - ssize_t size; - struct posix_acl *acl; - - if (!IS_POSIXACL(inode) || !inode->i_op || !inode->i_op->getxattr) - return ERR_PTR(-EOPNOTSUPP); - switch(type) { - case ACL_TYPE_ACCESS: - name = XATTR_NAME_ACL_ACCESS; - break; - case ACL_TYPE_DEFAULT: - name = XATTR_NAME_ACL_DEFAULT; - break; - default: - return ERR_PTR(-EOPNOTSUPP); - } - - size = inode->i_op->getxattr(fhp->fh_dentry, name, NULL, 0); - - if (size < 0) { - acl = ERR_PTR(size); - goto getout; - } else if (size > 0) { - value = kmalloc(size, GFP_KERNEL); - if (!value) { - acl = ERR_PTR(-ENOMEM); - goto getout; - } - size = inode->i_op->getxattr(fhp->fh_dentry, name, value, size); - if (size < 0) { - acl = ERR_PTR(size); - goto getout; - } - } - acl = posix_acl_from_xattr(value, size); - -getout: - kfree(value); - return acl; -} - -int -nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl) -{ - struct inode *inode = fhp->fh_dentry->d_inode; - char *name; - void *value = NULL; - size_t size; - int error; - - if (!IS_POSIXACL(inode) || !inode->i_op || - !inode->i_op->setxattr || !inode->i_op->removexattr) - return -EOPNOTSUPP; - switch(type) { - case ACL_TYPE_ACCESS: - name = XATTR_NAME_ACL_ACCESS; - break; - case ACL_TYPE_DEFAULT: - name = XATTR_NAME_ACL_DEFAULT; - break; - default: - return -EOPNOTSUPP; - } - - if (acl && acl->a_count) { - size = xattr_acl_size(acl->a_count); - value = kmalloc(size, GFP_KERNEL); - if (!value) - return -ENOMEM; - size = posix_acl_to_xattr(acl, value, size); - if (size < 0) { - error = size; - goto getout; - } - } else - size = 0; - - if (!fhp->fh_locked) - fh_lock(fhp); /* unlocking is done automatically */ - if (size) - error = inode->i_op->setxattr(fhp->fh_dentry, name, - value, size, 0); - else { - if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT) - error = 0; - else { - error = inode->i_op->removexattr(fhp->fh_dentry, name); - if (error == -ENODATA) - error = 0; - } - } - -getout: - kfree(value); - return error; -} -#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */ diff --git a/trunk/include/asm-arm/pgalloc.h b/trunk/include/asm-arm/pgalloc.h index bc18ff405181..e814f8144f8b 100644 --- a/trunk/include/asm-arm/pgalloc.h +++ b/trunk/include/asm-arm/pgalloc.h @@ -89,13 +89,6 @@ static inline void pte_free(struct page *pte) __free_page(pte); } -static inline void __pmd_populate(pmd_t *pmdp, unsigned long pmdval) -{ - pmdp[0] = __pmd(pmdval); - pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); - flush_pmd_entry(pmdp); -} - /* * Populate the pmdp entry with a pointer to the pte. This pmd is part * of the mm address space. @@ -106,19 +99,32 @@ static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) { unsigned long pte_ptr = (unsigned long)ptep; + unsigned long pmdval; + + BUG_ON(mm != &init_mm); /* * The pmd must be loaded with the physical * address of the PTE table */ pte_ptr -= PTRS_PER_PTE * sizeof(void *); - __pmd_populate(pmdp, __pa(pte_ptr) | _PAGE_KERNEL_TABLE); + pmdval = __pa(pte_ptr) | _PAGE_KERNEL_TABLE; + pmdp[0] = __pmd(pmdval); + pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); + flush_pmd_entry(pmdp); } static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmdp, struct page *ptep) { - __pmd_populate(pmdp, page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE); + unsigned long pmdval; + + BUG_ON(mm == &init_mm); + + pmdval = page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE; + pmdp[0] = __pmd(pmdval); + pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); + flush_pmd_entry(pmdp); } #endif diff --git a/trunk/include/linux/efi.h b/trunk/include/linux/efi.h index 73781ec165b4..047e7222df7a 100644 --- a/trunk/include/linux/efi.h +++ b/trunk/include/linux/efi.h @@ -315,7 +315,7 @@ extern struct efi_memory_map memmap; */ static inline int efi_range_is_wc(unsigned long start, unsigned long len) { - unsigned long i; + int i; for (i = 0; i < len; i += (1UL << EFI_PAGE_SHIFT)) { unsigned long paddr = __pa(start + i); diff --git a/trunk/include/linux/fs.h b/trunk/include/linux/fs.h index e5a8db00df29..9b8b696d4f15 100644 --- a/trunk/include/linux/fs.h +++ b/trunk/include/linux/fs.h @@ -674,7 +674,6 @@ struct file_lock { struct lock_manager_operations *fl_lmops; /* Callbacks for lockmanagers */ union { struct nfs_lock_info nfs_fl; - struct nfs4_lock_info nfs4_fl; } fl_u; }; diff --git a/trunk/include/linux/lockd/lockd.h b/trunk/include/linux/lockd/lockd.h index 16d4e5a08e1d..0d9d22578212 100644 --- a/trunk/include/linux/lockd/lockd.h +++ b/trunk/include/linux/lockd/lockd.h @@ -72,8 +72,6 @@ struct nlm_lockowner { uint32_t pid; }; -struct nlm_wait; - /* * Memory chunk for NLM client RPC request. */ @@ -83,7 +81,6 @@ struct nlm_rqst { struct nlm_host * a_host; /* host handle */ struct nlm_args a_args; /* arguments */ struct nlm_res a_res; /* result */ - struct nlm_wait * a_block; char a_owner[NLMCLNT_OHSIZE]; }; @@ -145,9 +142,7 @@ extern unsigned long nlmsvc_timeout; * Lockd client functions */ struct nlm_rqst * nlmclnt_alloc_call(void); -int nlmclnt_prepare_block(struct nlm_rqst *req, struct nlm_host *host, struct file_lock *fl); -void nlmclnt_finish_block(struct nlm_rqst *req); -long nlmclnt_block(struct nlm_rqst *req, long timeout); +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 *); void nlmclnt_recovery(struct nlm_host *, u32); diff --git a/trunk/include/linux/nfs4.h b/trunk/include/linux/nfs4.h index 5bb5b2fd7ba2..5ca8a8d8ccdf 100644 --- a/trunk/include/linux/nfs4.h +++ b/trunk/include/linux/nfs4.h @@ -382,8 +382,6 @@ enum { NFSPROC4_CLNT_READDIR, NFSPROC4_CLNT_SERVER_CAPS, NFSPROC4_CLNT_DELEGRETURN, - NFSPROC4_CLNT_GETACL, - NFSPROC4_CLNT_SETACL, }; #endif diff --git a/trunk/include/linux/nfs_fs.h b/trunk/include/linux/nfs_fs.h index 8ea249110fb0..dbac7f363e5d 100644 --- a/trunk/include/linux/nfs_fs.h +++ b/trunk/include/linux/nfs_fs.h @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -28,6 +29,7 @@ #include #include #include +#include #include /* @@ -41,6 +43,13 @@ #define NFS_MAX_FILE_IO_BUFFER_SIZE 32768 #define NFS_DEF_FILE_IO_BUFFER_SIZE 4096 +/* + * The upper limit on timeouts for the exponential backoff algorithm. + */ +#define NFS_WRITEBACK_DELAY (5*HZ) +#define NFS_WRITEBACK_LOCKDELAY (60*HZ) +#define NFS_COMMIT_DELAY (5*HZ) + /* * superblock magic number for NFS */ @@ -51,6 +60,9 @@ */ #define NFS_RPC_SWAPFLAGS (RPC_TASK_SWAPPER|RPC_TASK_ROOTCREDS) +#define NFS_RW_SYNC 0x0001 /* O_SYNC handling */ +#define NFS_RW_SWAP 0x0002 /* This is a swap request */ + /* * When flushing a cluster of dirty pages, there can be different * strategies: @@ -84,8 +96,7 @@ struct nfs_open_context { int error; struct list_head list; - - __u64 dir_cookie; + wait_queue_head_t waitq; }; /* @@ -93,8 +104,6 @@ struct nfs_open_context { */ struct nfs_delegation; -struct posix_acl; - /* * nfs fs inode data in memory */ @@ -131,6 +140,7 @@ struct nfs_inode { * * mtime != read_cache_mtime */ + unsigned long readdir_timestamp; unsigned long read_cache_jiffies; unsigned long attrtimeo; unsigned long attrtimeo_timestamp; @@ -148,10 +158,6 @@ struct nfs_inode { atomic_t data_updates; struct nfs_access_entry cache_access; -#ifdef CONFIG_NFS_V3_ACL - struct posix_acl *acl_access; - struct posix_acl *acl_default; -#endif /* * This is the cookie verifier used for NFSv3 readdir @@ -177,13 +183,13 @@ struct nfs_inode { wait_queue_head_t nfs_i_wait; #ifdef CONFIG_NFS_V4 - struct nfs4_cached_acl *nfs4_acl; /* NFSv4 state */ struct list_head open_states; struct nfs_delegation *delegation; int delegation_state; struct rw_semaphore rwsem; #endif /* CONFIG_NFS_V4*/ + struct inode vfs_inode; }; @@ -197,8 +203,6 @@ struct nfs_inode { #define NFS_INO_INVALID_DATA 0x0010 /* cached data is invalid */ #define NFS_INO_INVALID_ATIME 0x0020 /* cached atime is invalid */ #define NFS_INO_INVALID_ACCESS 0x0040 /* cached access cred invalid */ -#define NFS_INO_INVALID_ACL 0x0080 /* cached acls are invalid */ -#define NFS_INO_REVAL_PAGECACHE 0x1000 /* must revalidate pagecache */ static inline struct nfs_inode *NFS_I(struct inode *inode) { @@ -290,12 +294,12 @@ extern int nfs_release(struct inode *, struct file *); extern int nfs_attribute_timeout(struct inode *inode); extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode); extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *); -extern void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping); extern int nfs_setattr(struct dentry *, struct iattr *); extern void nfs_begin_attr_update(struct inode *); extern void nfs_end_attr_update(struct inode *); extern void nfs_begin_data_update(struct inode *); extern void nfs_end_data_update(struct inode *); +extern void nfs_end_data_update_defer(struct inode *); extern struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rpc_cred *cred); extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx); extern void put_nfs_open_context(struct nfs_open_context *ctx); @@ -310,9 +314,6 @@ extern u32 root_nfs_parse_addr(char *name); /*__init*/ * linux/fs/nfs/file.c */ extern struct inode_operations nfs_file_inode_operations; -#ifdef CONFIG_NFS_V3 -extern struct inode_operations nfs3_file_inode_operations; -#endif /* CONFIG_NFS_V3 */ extern struct file_operations nfs_file_operations; extern struct address_space_operations nfs_file_aops; @@ -327,22 +328,6 @@ static inline struct rpc_cred *nfs_file_cred(struct file *file) return NULL; } -/* - * linux/fs/nfs/xattr.c - */ -#ifdef CONFIG_NFS_V3_ACL -extern ssize_t nfs3_listxattr(struct dentry *, char *, size_t); -extern ssize_t nfs3_getxattr(struct dentry *, const char *, void *, size_t); -extern int nfs3_setxattr(struct dentry *, const char *, - const void *, size_t, int); -extern int nfs3_removexattr (struct dentry *, const char *name); -#else -# define nfs3_listxattr NULL -# define nfs3_getxattr NULL -# define nfs3_setxattr NULL -# define nfs3_removexattr NULL -#endif - /* * linux/fs/nfs/direct.c */ @@ -357,9 +342,6 @@ extern ssize_t nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, * linux/fs/nfs/dir.c */ extern struct inode_operations nfs_dir_inode_operations; -#ifdef CONFIG_NFS_V3 -extern struct inode_operations nfs3_dir_inode_operations; -#endif /* CONFIG_NFS_V3 */ extern struct file_operations nfs_dir_operations; extern struct dentry_operations nfs_dentry_operations; @@ -395,10 +377,10 @@ extern void nfs_commit_done(struct rpc_task *); */ extern int nfs_sync_inode(struct inode *, unsigned long, unsigned int, int); #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) -extern int nfs_commit_inode(struct inode *, int); +extern int nfs_commit_inode(struct inode *, unsigned long, unsigned int, int); #else static inline int -nfs_commit_inode(struct inode *inode, int how) +nfs_commit_inode(struct inode *inode, unsigned long idx_start, unsigned int npages, int how) { return 0; } @@ -452,6 +434,11 @@ static inline void nfs_writedata_free(struct nfs_write_data *p) mempool_free(p, nfs_wdata_mempool); } +/* Hack for future NFS swap support */ +#ifndef IS_SWAPFILE +# define IS_SWAPFILE(inode) (0) +#endif + /* * linux/fs/nfs/read.c */ @@ -480,29 +467,6 @@ static inline void nfs_readdata_free(struct nfs_read_data *p) extern void nfs_readdata_release(struct rpc_task *task); -/* - * linux/fs/nfs3proc.c - */ -#ifdef CONFIG_NFS_V3_ACL -extern struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type); -extern int nfs3_proc_setacl(struct inode *inode, int type, - struct posix_acl *acl); -extern int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode, - mode_t mode); -extern void nfs3_forget_cached_acls(struct inode *inode); -#else -static inline int nfs3_proc_set_default_acl(struct inode *dir, - struct inode *inode, - mode_t mode) -{ - return 0; -} - -static inline void nfs3_forget_cached_acls(struct inode *inode) -{ -} -#endif /* CONFIG_NFS_V3_ACL */ - /* * linux/fs/mount_clnt.c * (Used only by nfsroot module) @@ -551,6 +515,230 @@ extern void * nfs_root_data(void); #define NFS_JUKEBOX_RETRY_TIME (5 * HZ) +#ifdef CONFIG_NFS_V4 + +struct idmap; + +/* + * In a seqid-mutating op, this macro controls which error return + * values trigger incrementation of the seqid. + * + * from rfc 3010: + * The client MUST monotonically increment the sequence number for the + * CLOSE, LOCK, LOCKU, OPEN, OPEN_CONFIRM, and OPEN_DOWNGRADE + * operations. This is true even in the event that the previous + * operation that used the sequence number received an error. The only + * exception to this rule is if the previous operation received one of + * the following errors: NFSERR_STALE_CLIENTID, NFSERR_STALE_STATEID, + * NFSERR_BAD_STATEID, NFSERR_BAD_SEQID, NFSERR_BADXDR, + * NFSERR_RESOURCE, NFSERR_NOFILEHANDLE. + * + */ +#define seqid_mutating_err(err) \ +(((err) != NFSERR_STALE_CLIENTID) && \ + ((err) != NFSERR_STALE_STATEID) && \ + ((err) != NFSERR_BAD_STATEID) && \ + ((err) != NFSERR_BAD_SEQID) && \ + ((err) != NFSERR_BAD_XDR) && \ + ((err) != NFSERR_RESOURCE) && \ + ((err) != NFSERR_NOFILEHANDLE)) + +enum nfs4_client_state { + NFS4CLNT_OK = 0, +}; + +/* + * The nfs4_client identifies our client state to the server. + */ +struct nfs4_client { + struct list_head cl_servers; /* Global list of servers */ + struct in_addr cl_addr; /* Server identifier */ + u64 cl_clientid; /* constant */ + nfs4_verifier cl_confirm; + unsigned long cl_state; + + u32 cl_lockowner_id; + + /* + * The following rwsem ensures exclusive access to the server + * while we recover the state following a lease expiration. + */ + struct rw_semaphore cl_sem; + + struct list_head cl_delegations; + struct list_head cl_state_owners; + struct list_head cl_unused; + int cl_nunused; + spinlock_t cl_lock; + atomic_t cl_count; + + struct rpc_clnt * cl_rpcclient; + struct rpc_cred * cl_cred; + + struct list_head cl_superblocks; /* List of nfs_server structs */ + + unsigned long cl_lease_time; + unsigned long cl_last_renewal; + struct work_struct cl_renewd; + struct work_struct cl_recoverd; + + 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; + + /* Our own IP address, as a null-terminated string. + * This is used to generate the clientid, and the callback address. + */ + char cl_ipaddr[16]; + unsigned char cl_id_uniquifier; +}; + +/* + * NFS4 state_owners and lock_owners are simply labels for ordered + * sequences of RPC calls. Their sole purpose is to provide once-only + * semantics by allowing the server to identify replayed requests. + * + * The ->so_sema is held during all state_owner seqid-mutating operations: + * OPEN, OPEN_DOWNGRADE, and CLOSE. Its purpose is to properly serialize + * so_seqid. + */ +struct nfs4_state_owner { + struct list_head so_list; /* per-clientid list of state_owners */ + struct nfs4_client *so_client; + u32 so_id; /* 32-bit identifier, unique */ + struct semaphore so_sema; + u32 so_seqid; /* protected by so_sema */ + atomic_t so_count; + + struct rpc_cred *so_cred; /* Associated cred */ + struct list_head so_states; + struct list_head so_delegations; +}; + +/* + * struct nfs4_state maintains the client-side state for a given + * (state_owner,inode) tuple (OPEN) or state_owner (LOCK). + * + * OPEN: + * In order to know when to OPEN_DOWNGRADE or CLOSE the state on the server, + * we need to know how many files are open for reading or writing on a + * given inode. This information too is stored here. + * + * LOCK: one nfs4_state (LOCK) to hold the lock stateid nfs4_state(OPEN) + */ + +struct nfs4_lock_state { + struct list_head ls_locks; /* Other lock stateids */ + fl_owner_t ls_owner; /* POSIX lock owner */ +#define NFS_LOCK_INITIALIZED 1 + int ls_flags; + u32 ls_seqid; + u32 ls_id; + nfs4_stateid ls_stateid; + atomic_t ls_count; +}; + +/* bits for nfs4_state->flags */ +enum { + LK_STATE_IN_USE, + NFS_DELEGATED_STATE, +}; + +struct nfs4_state { + struct list_head open_states; /* List of states for the same state_owner */ + struct list_head inode_states; /* List of states for the same inode */ + struct list_head lock_states; /* List of subservient lock stateids */ + + struct nfs4_state_owner *owner; /* Pointer to the open owner */ + struct inode *inode; /* Pointer to the inode */ + + unsigned long flags; /* Do we hold any locks? */ + struct semaphore lock_sema; /* Serializes file locking operations */ + rwlock_t state_lock; /* Protects the lock_states list */ + + nfs4_stateid stateid; + + unsigned int nreaders; + unsigned int nwriters; + int state; /* State on the server (R,W, or RW) */ + atomic_t count; +}; + + +struct nfs4_exception { + long timeout; + 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_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 struct inode *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); +extern int nfs4_open_revalidate(struct inode *, struct dentry *, int); + +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 *); +extern void nfs4_renewd_prepare_shutdown(struct nfs_server *); +extern void nfs4_kill_renewd(struct nfs4_client *); + +/* nfs4state.c */ +extern void init_nfsv4_state(struct nfs_server *); +extern void destroy_nfsv4_state(struct nfs_server *); +extern struct nfs4_client *nfs4_get_client(struct in_addr *); +extern void nfs4_put_client(struct nfs4_client *clp); +extern int nfs4_init_client(struct nfs4_client *clp); +extern struct nfs4_client *nfs4_find_client(struct in_addr *); +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); +extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mode_t mode); +extern void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp); +extern void nfs4_schedule_state_recovery(struct nfs4_client *); +extern struct nfs4_lock_state *nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t); +extern struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t); +extern void nfs4_put_lock_state(struct nfs4_lock_state *state); +extern void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *ls); +extern void nfs4_notify_setlk(struct nfs4_state *, struct file_lock *, struct nfs4_lock_state *); +extern void nfs4_notify_unlck(struct nfs4_state *, struct file_lock *, struct nfs4_lock_state *); +extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t); + + + +struct nfs4_mount_data; +#else +#define init_nfsv4_state(server) do { } while (0) +#define destroy_nfsv4_state(server) do { } while (0) +#define nfs4_put_state_owner(inode, owner) do { } while (0) +#define nfs4_put_open_state(state) do { } while (0) +#define nfs4_close_state(a, b) do { } while (0) +#define nfs4_renewd_prepare_shutdown(server) do { } while (0) +#endif + #endif /* __KERNEL__ */ /* diff --git a/trunk/include/linux/nfs_fs_i.h b/trunk/include/linux/nfs_fs_i.h index e2c18dabff86..e9a749588a7b 100644 --- a/trunk/include/linux/nfs_fs_i.h +++ b/trunk/include/linux/nfs_fs_i.h @@ -16,11 +16,6 @@ struct nfs_lock_info { struct nlm_lockowner *owner; }; -struct nfs4_lock_state; -struct nfs4_lock_info { - struct nfs4_lock_state *owner; -}; - /* * Lock flag values */ diff --git a/trunk/include/linux/nfs_fs_sb.h b/trunk/include/linux/nfs_fs_sb.h index 3d3a305488cf..fc51645d61ee 100644 --- a/trunk/include/linux/nfs_fs_sb.h +++ b/trunk/include/linux/nfs_fs_sb.h @@ -10,7 +10,6 @@ struct nfs_server { struct rpc_clnt * client; /* RPC client handle */ struct rpc_clnt * client_sys; /* 2nd handle for FSINFO */ - struct rpc_clnt * client_acl; /* ACL RPC client handle */ struct nfs_rpc_ops * rpc_ops; /* NFS protocol vector */ struct backing_dev_info backing_dev_info; int flags; /* various flags */ diff --git a/trunk/include/linux/nfs_mount.h b/trunk/include/linux/nfs_mount.h index 659c75438454..0071428231f9 100644 --- a/trunk/include/linux/nfs_mount.h +++ b/trunk/include/linux/nfs_mount.h @@ -58,7 +58,6 @@ struct nfs_mount_data { #define NFS_MOUNT_KERBEROS 0x0100 /* 3 */ #define NFS_MOUNT_NONLM 0x0200 /* 3 */ #define NFS_MOUNT_BROKEN_SUID 0x0400 /* 4 */ -#define NFS_MOUNT_NOACL 0x0800 /* 4 */ #define NFS_MOUNT_STRICTLOCK 0x1000 /* reserved for NFSv4 */ #define NFS_MOUNT_SECFLAVOUR 0x2000 /* 5 */ #define NFS_MOUNT_FLAGMASK 0xFFFF diff --git a/trunk/include/linux/nfs_page.h b/trunk/include/linux/nfs_page.h index da2e077b65e2..39e4895bcdb4 100644 --- a/trunk/include/linux/nfs_page.h +++ b/trunk/include/linux/nfs_page.h @@ -19,12 +19,6 @@ #include -/* - * Valid flags for the radix tree - */ -#define NFS_PAGE_TAG_DIRTY 0 -#define NFS_PAGE_TAG_WRITEBACK 1 - /* * Valid flags for a dirty buffer */ @@ -32,7 +26,6 @@ #define PG_NEED_COMMIT 1 #define PG_NEED_RESCHED 2 -struct nfs_inode; struct nfs_page { struct list_head wb_list, /* Defines state of page: */ *wb_list_head; /* read/write/commit */ @@ -61,17 +54,14 @@ extern void nfs_clear_request(struct nfs_page *req); extern void nfs_release_request(struct nfs_page *req); -extern int nfs_scan_lock_dirty(struct nfs_inode *nfsi, struct list_head *dst, - unsigned long idx_start, unsigned int npages); +extern void nfs_list_add_request(struct nfs_page *, struct list_head *); + extern int nfs_scan_list(struct list_head *, struct list_head *, unsigned long, unsigned int); extern int nfs_coalesce_requests(struct list_head *, struct list_head *, unsigned int); extern int nfs_wait_on_request(struct nfs_page *); extern void nfs_unlock_request(struct nfs_page *req); -extern int nfs_set_page_writeback_locked(struct nfs_page *req); -extern void nfs_clear_page_writeback(struct nfs_page *req); - /* * Lock the page of an asynchronous request without incrementing the wb_count @@ -96,18 +86,6 @@ nfs_lock_request(struct nfs_page *req) return 1; } -/** - * nfs_list_add_request - Insert a request into a list - * @req: request - * @head: head of list into which to insert the request. - */ -static inline void -nfs_list_add_request(struct nfs_page *req, struct list_head *head) -{ - list_add_tail(&req->wb_list, head); - req->wb_list_head = head; -} - /** * nfs_list_remove_request - Remove a request from its wb_list @@ -118,6 +96,10 @@ nfs_list_remove_request(struct nfs_page *req) { if (list_empty(&req->wb_list)) return; + if (!NFS_WBACK_BUSY(req)) { + printk(KERN_ERR "NFS: unlocked request attempted removed from list!\n"); + BUG(); + } list_del_init(&req->wb_list); req->wb_list_head = NULL; } diff --git a/trunk/include/linux/nfs_xdr.h b/trunk/include/linux/nfs_xdr.h index a2bf6914ff1b..47037d9521cb 100644 --- a/trunk/include/linux/nfs_xdr.h +++ b/trunk/include/linux/nfs_xdr.h @@ -2,7 +2,6 @@ #define _LINUX_NFS_XDR_H #include -#include struct nfs4_fsid { __u64 major; @@ -327,20 +326,6 @@ struct nfs_setattrargs { const u32 * bitmask; }; -struct nfs_setaclargs { - struct nfs_fh * fh; - size_t acl_len; - unsigned int acl_pgbase; - struct page ** acl_pages; -}; - -struct nfs_getaclargs { - struct nfs_fh * fh; - size_t acl_len; - unsigned int acl_pgbase; - struct page ** acl_pages; -}; - struct nfs_setattrres { struct nfs_fattr * fattr; const struct nfs_server * server; @@ -369,20 +354,6 @@ struct nfs_readdirargs { struct page ** pages; }; -struct nfs3_getaclargs { - struct nfs_fh * fh; - int mask; - struct page ** pages; -}; - -struct nfs3_setaclargs { - struct inode * inode; - int mask; - struct posix_acl * acl_access; - struct posix_acl * acl_default; - struct page ** pages; -}; - struct nfs_diropok { struct nfs_fh * fh; struct nfs_fattr * fattr; @@ -506,15 +477,6 @@ struct nfs3_readdirres { int plus; }; -struct nfs3_getaclres { - struct nfs_fattr * fattr; - int mask; - unsigned int acl_access_count; - unsigned int acl_default_count; - struct posix_acl * acl_access; - struct posix_acl * acl_default; -}; - #ifdef CONFIG_NFS_V4 typedef u64 clientid4; @@ -705,7 +667,6 @@ struct nfs_rpc_ops { int version; /* Protocol version */ struct dentry_operations *dentry_ops; struct inode_operations *dir_inode_ops; - struct inode_operations *file_inode_ops; int (*getroot) (struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); @@ -752,7 +713,6 @@ struct nfs_rpc_ops { int (*file_open) (struct inode *, struct file *); int (*file_release) (struct inode *, struct file *); int (*lock)(struct file *, int, struct file_lock *); - void (*clear_acl_cache)(struct inode *); }; /* @@ -772,7 +732,4 @@ extern struct rpc_version nfs_version2; extern struct rpc_version nfs_version3; extern struct rpc_version nfs_version4; -extern struct rpc_version nfsacl_version3; -extern struct rpc_program nfsacl_program; - #endif diff --git a/trunk/include/linux/nfsacl.h b/trunk/include/linux/nfsacl.h deleted file mode 100644 index 54487a99beb8..000000000000 --- a/trunk/include/linux/nfsacl.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * File: linux/nfsacl.h - * - * (C) 2003 Andreas Gruenbacher - */ -#ifndef __LINUX_NFSACL_H -#define __LINUX_NFSACL_H - -#define NFS_ACL_PROGRAM 100227 - -#define ACLPROC2_GETACL 1 -#define ACLPROC2_SETACL 2 -#define ACLPROC2_GETATTR 3 -#define ACLPROC2_ACCESS 4 - -#define ACLPROC3_GETACL 1 -#define ACLPROC3_SETACL 2 - - -/* Flags for the getacl/setacl mode */ -#define NFS_ACL 0x0001 -#define NFS_ACLCNT 0x0002 -#define NFS_DFACL 0x0004 -#define NFS_DFACLCNT 0x0008 - -/* Flag for Default ACL entries */ -#define NFS_ACL_DEFAULT 0x1000 - -#ifdef __KERNEL__ - -#include - -/* Maximum number of ACL entries over NFS */ -#define NFS_ACL_MAX_ENTRIES 1024 - -#define NFSACL_MAXWORDS (2*(2+3*NFS_ACL_MAX_ENTRIES)) -#define NFSACL_MAXPAGES ((2*(8+12*NFS_ACL_MAX_ENTRIES) + PAGE_SIZE-1) \ - >> PAGE_SHIFT) - -static inline unsigned int -nfsacl_size(struct posix_acl *acl_access, struct posix_acl *acl_default) -{ - unsigned int w = 16; - w += max(acl_access ? (int)acl_access->a_count : 3, 4) * 12; - if (acl_default) - w += max((int)acl_default->a_count, 4) * 12; - return w; -} - -extern unsigned int -nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode, - struct posix_acl *acl, int encode_entries, int typeflag); -extern unsigned int -nfsacl_decode(struct xdr_buf *buf, unsigned int base, unsigned int *aclcnt, - struct posix_acl **pacl); - -#endif /* __KERNEL__ */ -#endif /* __LINUX_NFSACL_H */ diff --git a/trunk/include/linux/nfsd/nfsd.h b/trunk/include/linux/nfsd/nfsd.h index 4bf931d5ff56..8f85d9a59607 100644 --- a/trunk/include/linux/nfsd/nfsd.h +++ b/trunk/include/linux/nfsd/nfsd.h @@ -15,7 +15,6 @@ #include #include #include -#include #include #include @@ -125,21 +124,6 @@ int nfsd_statfs(struct svc_rqst *, struct svc_fh *, int nfsd_notify_change(struct inode *, struct iattr *); int nfsd_permission(struct svc_export *, struct dentry *, int); -#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) -#ifdef CONFIG_NFSD_V2_ACL -extern struct svc_version nfsd_acl_version2; -#else -#define nfsd_acl_version2 NULL -#endif -#ifdef CONFIG_NFSD_V3_ACL -extern struct svc_version nfsd_acl_version3; -#else -#define nfsd_acl_version3 NULL -#endif -struct posix_acl *nfsd_get_posix_acl(struct svc_fh *, int); -int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *); -#endif - /* * NFSv4 State diff --git a/trunk/include/linux/nfsd/xdr.h b/trunk/include/linux/nfsd/xdr.h index 130d4f588a37..ecccef777dae 100644 --- a/trunk/include/linux/nfsd/xdr.h +++ b/trunk/include/linux/nfsd/xdr.h @@ -169,8 +169,4 @@ int nfssvc_encode_entry(struct readdir_cd *, const char *name, int nfssvc_release_fhandle(struct svc_rqst *, u32 *, struct nfsd_fhandle *); -/* Helper functions for NFSv2 ACL code */ -u32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp); -u32 *nfs2svc_decode_fh(u32 *p, struct svc_fh *fhp); - #endif /* LINUX_NFSD_H */ diff --git a/trunk/include/linux/nfsd/xdr3.h b/trunk/include/linux/nfsd/xdr3.h index 21e18ce7ca63..0ae9e0ef5f68 100644 --- a/trunk/include/linux/nfsd/xdr3.h +++ b/trunk/include/linux/nfsd/xdr3.h @@ -110,19 +110,6 @@ struct nfsd3_commitargs { __u32 count; }; -struct nfsd3_getaclargs { - struct svc_fh fh; - int mask; -}; - -struct posix_acl; -struct nfsd3_setaclargs { - struct svc_fh fh; - int mask; - struct posix_acl *acl_access; - struct posix_acl *acl_default; -}; - struct nfsd3_attrstat { __u32 status; struct svc_fh fh; @@ -222,14 +209,6 @@ struct nfsd3_commitres { struct svc_fh fh; }; -struct nfsd3_getaclres { - __u32 status; - struct svc_fh fh; - int mask; - struct posix_acl *acl_access; - struct posix_acl *acl_default; -}; - /* dummy type for release */ struct nfsd3_fhandle_pair { __u32 dummy; @@ -262,7 +241,6 @@ union nfsd3_xdrstore { struct nfsd3_fsinfores fsinfores; struct nfsd3_pathconfres pathconfres; struct nfsd3_commitres commitres; - struct nfsd3_getaclres getaclres; }; #define NFS3_SVC_XDRSIZE sizeof(union nfsd3_xdrstore) @@ -338,10 +316,6 @@ int nfs3svc_encode_entry(struct readdir_cd *, const char *name, int nfs3svc_encode_entry_plus(struct readdir_cd *, const char *name, int namlen, loff_t offset, ino_t ino, unsigned int); -/* Helper functions for NFSv3 ACL code */ -u32 *nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, - struct svc_fh *fhp); -u32 *nfs3svc_decode_fh(u32 *p, struct svc_fh *fhp); #endif /* _LINUX_NFSD_XDR3_H */ diff --git a/trunk/include/linux/sunrpc/clnt.h b/trunk/include/linux/sunrpc/clnt.h index ab151bbb66df..2709caf4d128 100644 --- a/trunk/include/linux/sunrpc/clnt.h +++ b/trunk/include/linux/sunrpc/clnt.h @@ -111,11 +111,6 @@ struct rpc_procinfo { struct rpc_clnt *rpc_create_client(struct rpc_xprt *xprt, char *servname, struct rpc_program *info, u32 version, rpc_authflavor_t authflavor); -struct rpc_clnt *rpc_new_client(struct rpc_xprt *xprt, char *servname, - struct rpc_program *info, - u32 version, rpc_authflavor_t authflavor); -struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *, - struct rpc_program *, int); struct rpc_clnt *rpc_clone_client(struct rpc_clnt *); int rpc_shutdown_client(struct rpc_clnt *); int rpc_destroy_client(struct rpc_clnt *); @@ -134,7 +129,6 @@ 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 *); -int rpc_ping(struct rpc_clnt *clnt, int flags); static __inline__ int rpc_call(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags) diff --git a/trunk/include/linux/sunrpc/sched.h b/trunk/include/linux/sunrpc/sched.h index 4d77e90d0b30..99d17ed7cebb 100644 --- a/trunk/include/linux/sunrpc/sched.h +++ b/trunk/include/linux/sunrpc/sched.h @@ -31,6 +31,7 @@ struct rpc_wait_queue; struct rpc_wait { struct list_head list; /* wait queue links */ struct list_head links; /* Links to related tasks */ + wait_queue_head_t waitq; /* sync: sleep on this q */ struct rpc_wait_queue * rpc_waitq; /* RPC wait queue we're on */ }; diff --git a/trunk/include/linux/sunrpc/svc.h b/trunk/include/linux/sunrpc/svc.h index 5af8800e0ce3..37003970cf2e 100644 --- a/trunk/include/linux/sunrpc/svc.h +++ b/trunk/include/linux/sunrpc/svc.h @@ -185,17 +185,6 @@ xdr_ressize_check(struct svc_rqst *rqstp, u32 *p) return vec->iov_len <= PAGE_SIZE; } -static inline struct page * -svc_take_res_page(struct svc_rqst *rqstp) -{ - if (rqstp->rq_arghi <= rqstp->rq_argused) - return NULL; - rqstp->rq_arghi--; - rqstp->rq_respages[rqstp->rq_resused] = - rqstp->rq_argpages[rqstp->rq_arghi]; - return rqstp->rq_respages[rqstp->rq_resused++]; -} - static inline int svc_take_page(struct svc_rqst *rqstp) { if (rqstp->rq_arghi <= rqstp->rq_argused) @@ -251,10 +240,9 @@ struct svc_deferred_req { }; /* - * List of RPC programs on the same transport endpoint + * RPC program */ struct svc_program { - struct svc_program * pg_next; /* other programs (same xprt) */ u32 pg_prog; /* program number */ unsigned int pg_lovers; /* lowest version */ unsigned int pg_hivers; /* lowest version */ diff --git a/trunk/include/linux/sunrpc/xdr.h b/trunk/include/linux/sunrpc/xdr.h index 34ec3e8d99b3..541dcf838abf 100644 --- a/trunk/include/linux/sunrpc/xdr.h +++ b/trunk/include/linux/sunrpc/xdr.h @@ -146,8 +146,7 @@ extern void xdr_shift_buf(struct xdr_buf *, size_t); extern void xdr_buf_from_iov(struct kvec *, struct xdr_buf *); extern int xdr_buf_subsegment(struct xdr_buf *, struct xdr_buf *, int, int); extern int xdr_buf_read_netobj(struct xdr_buf *, struct xdr_netobj *, int); -extern int read_bytes_from_xdr_buf(struct xdr_buf *, int, void *, int); -extern int write_bytes_to_xdr_buf(struct xdr_buf *, int, void *, int); +extern int read_bytes_from_xdr_buf(struct xdr_buf *buf, int base, void *obj, int len); /* * Helper structure for copying from an sk_buff. @@ -161,7 +160,7 @@ typedef struct { typedef size_t (*skb_read_actor_t)(skb_reader_t *desc, void *to, size_t len); -extern ssize_t xdr_partial_copy_from_skb(struct xdr_buf *, unsigned int, +extern void xdr_partial_copy_from_skb(struct xdr_buf *, unsigned int, skb_reader_t *, skb_read_actor_t); struct socket; @@ -169,22 +168,6 @@ struct sockaddr; extern int xdr_sendpages(struct socket *, struct sockaddr *, int, struct xdr_buf *, unsigned int, int); -extern int xdr_encode_word(struct xdr_buf *, int, u32); -extern int xdr_decode_word(struct xdr_buf *, int, u32 *); - -struct xdr_array2_desc; -typedef int (*xdr_xcode_elem_t)(struct xdr_array2_desc *desc, void *elem); -struct xdr_array2_desc { - unsigned int elem_size; - unsigned int array_len; - xdr_xcode_elem_t xcode; -}; - -extern int xdr_decode_array2(struct xdr_buf *buf, unsigned int base, - struct xdr_array2_desc *desc); -extern int xdr_encode_array2(struct xdr_buf *buf, unsigned int base, - struct xdr_array2_desc *desc); - /* * Provide some simple tools for XDR buffer overflow-checking etc. */ diff --git a/trunk/mm/page_alloc.c b/trunk/mm/page_alloc.c index 559336de9687..206920796f5f 100644 --- a/trunk/mm/page_alloc.c +++ b/trunk/mm/page_alloc.c @@ -1742,17 +1742,10 @@ inline void setup_pageset(struct per_cpu_pageset *p, unsigned long batch) * with interrupts disabled. * * Some NUMA counter updates may also be caught by the boot pagesets. - * - * The boot_pagesets must be kept even after bootup is complete for - * unused processors and/or zones. They do play a role for bootstrapping - * hotplugged processors. - * - * zoneinfo_show() and maybe other functions do - * not check if the processor is online before following the pageset pointer. - * Other parts of the kernel may not check if the zone is available. + * These will be discarded when bootup is complete. */ static struct per_cpu_pageset - boot_pageset[NR_CPUS]; + boot_pageset[NR_CPUS] __initdata; /* * Dynamically allocate memory for the diff --git a/trunk/net/ipv4/netfilter/ipt_CLUSTERIP.c b/trunk/net/ipv4/netfilter/ipt_CLUSTERIP.c index dc4362b57cfa..9cde8c61f525 100644 --- a/trunk/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/trunk/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -339,7 +339,7 @@ target(struct sk_buff **pskb, * error messages (RELATED) and information requests (see below) */ if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP && (ctinfo == IP_CT_RELATED - || ctinfo == IP_CT_IS_REPLY+IP_CT_IS_REPLY)) + || ctinfo == IP_CT_RELATED+IP_CT_IS_REPLY)) return IPT_CONTINUE; /* ip_conntrack_icmp guarantees us that we only have ICMP_ECHO, diff --git a/trunk/net/sunrpc/auth.c b/trunk/net/sunrpc/auth.c index 505e2d4b3d62..9bcec9b927b9 100644 --- a/trunk/net/sunrpc/auth.c +++ b/trunk/net/sunrpc/auth.c @@ -66,10 +66,10 @@ rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt) u32 flavor = pseudoflavor_to_flavor(pseudoflavor); if (flavor >= RPC_AUTH_MAXFLAVOR || !(ops = auth_flavors[flavor])) - return ERR_PTR(-EINVAL); + return NULL; auth = ops->create(clnt, pseudoflavor); - if (IS_ERR(auth)) - return auth; + if (!auth) + return NULL; if (clnt->cl_auth) rpcauth_destroy(clnt->cl_auth); clnt->cl_auth = auth; diff --git a/trunk/net/sunrpc/auth_gss/auth_gss.c b/trunk/net/sunrpc/auth_gss/auth_gss.c index 2f7b867161d2..a33b627cbef4 100644 --- a/trunk/net/sunrpc/auth_gss/auth_gss.c +++ b/trunk/net/sunrpc/auth_gss/auth_gss.c @@ -660,16 +660,14 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) { struct gss_auth *gss_auth; struct rpc_auth * auth; - int err = -ENOMEM; /* XXX? */ dprintk("RPC: creating GSS authenticator for client %p\n",clnt); if (!try_module_get(THIS_MODULE)) - return ERR_PTR(err); + return NULL; if (!(gss_auth = kmalloc(sizeof(*gss_auth), GFP_KERNEL))) goto out_dec; gss_auth->client = clnt; - err = -EINVAL; gss_auth->mech = gss_mech_get_by_pseudoflavor(flavor); if (!gss_auth->mech) { printk(KERN_WARNING "%s: Pseudoflavor %d not found!", @@ -677,8 +675,9 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) goto err_free; } gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor); - if (gss_auth->service == 0) - goto err_put_mech; + /* 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; @@ -688,18 +687,15 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) auth->au_flavor = flavor; atomic_set(&auth->au_count, 1); - err = rpcauth_init_credcache(auth, GSS_CRED_EXPIRE); - if (err) + 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, gss_auth->mech->gm_name); gss_auth->dentry = rpc_mkpipe(gss_auth->path, clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); - if (IS_ERR(gss_auth->dentry)) { - err = PTR_ERR(gss_auth->dentry); + if (IS_ERR(gss_auth->dentry)) goto err_put_mech; - } return auth; err_put_mech: @@ -708,7 +704,7 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) kfree(gss_auth); out_dec: module_put(THIS_MODULE); - return ERR_PTR(err); + return NULL; } static void diff --git a/trunk/net/sunrpc/clnt.c b/trunk/net/sunrpc/clnt.c index f17e6153b688..02bc029d46fe 100644 --- a/trunk/net/sunrpc/clnt.c +++ b/trunk/net/sunrpc/clnt.c @@ -97,13 +97,12 @@ rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name) * made to sleep too long. */ struct rpc_clnt * -rpc_new_client(struct rpc_xprt *xprt, char *servname, +rpc_create_client(struct rpc_xprt *xprt, char *servname, struct rpc_program *program, u32 vers, rpc_authflavor_t flavor) { struct rpc_version *version; struct rpc_clnt *clnt = NULL; - struct rpc_auth *auth; int err; int len; @@ -158,11 +157,10 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname, if (err < 0) goto out_no_path; - auth = rpcauth_create(flavor, clnt); - if (IS_ERR(auth)) { + err = -ENOMEM; + if (!rpcauth_create(flavor, clnt)) { printk(KERN_INFO "RPC: Couldn't create auth handle (flavor %u)\n", flavor); - err = PTR_ERR(auth); goto out_no_auth; } @@ -180,37 +178,6 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname, kfree(clnt->cl_server); kfree(clnt); out_err: - xprt_destroy(xprt); - return ERR_PTR(err); -} - -/** - * Create an RPC client - * @xprt - pointer to xprt struct - * @servname - name of server - * @info - rpc_program - * @version - rpc_program version - * @authflavor - rpc_auth flavour to use - * - * Creates an RPC client structure, then pings the server in order to - * determine if it is up, and if it supports this program and version. - * - * This function should never be called by asynchronous tasks such as - * the portmapper. - */ -struct rpc_clnt *rpc_create_client(struct rpc_xprt *xprt, char *servname, - struct rpc_program *info, u32 version, rpc_authflavor_t authflavor) -{ - struct rpc_clnt *clnt; - int err; - - clnt = rpc_new_client(xprt, servname, info, version, authflavor); - if (IS_ERR(clnt)) - return clnt; - err = rpc_ping(clnt, RPC_TASK_SOFT|RPC_TASK_NOINTR); - if (err == 0) - return clnt; - rpc_shutdown_client(clnt); return ERR_PTR(err); } @@ -241,8 +208,6 @@ rpc_clone_client(struct rpc_clnt *clnt) rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); if (new->cl_auth) atomic_inc(&new->cl_auth->au_count); - new->cl_pmap = &new->cl_pmap_default; - rpc_init_wait_queue(&new->cl_pmap_default.pm_bindwait, "bindwait"); return new; out_no_clnt: printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__); @@ -331,44 +296,6 @@ rpc_release_client(struct rpc_clnt *clnt) rpc_destroy_client(clnt); } -/** - * rpc_bind_new_program - bind a new RPC program to an existing client - * @old - old rpc_client - * @program - rpc program to set - * @vers - rpc program version - * - * Clones the rpc client and sets up a new RPC program. This is mainly - * of use for enabling different RPC programs to share the same transport. - * The Sun NFSv2/v3 ACL protocol can do this. - */ -struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, - struct rpc_program *program, - int vers) -{ - struct rpc_clnt *clnt; - struct rpc_version *version; - int err; - - BUG_ON(vers >= program->nrvers || !program->version[vers]); - version = program->version[vers]; - clnt = rpc_clone_client(old); - if (IS_ERR(clnt)) - goto out; - clnt->cl_procinfo = version->procs; - clnt->cl_maxproc = version->nrprocs; - clnt->cl_protname = program->name; - clnt->cl_prog = program->number; - clnt->cl_vers = version->number; - clnt->cl_stats = program->stats; - err = rpc_ping(clnt, RPC_TASK_SOFT|RPC_TASK_NOINTR); - if (err != 0) { - rpc_shutdown_client(clnt); - clnt = ERR_PTR(err); - } -out: - return clnt; -} - /* * Default callback for async RPC calls */ @@ -378,41 +305,38 @@ rpc_default_callback(struct rpc_task *task) } /* - * Export the signal mask handling for synchronous code that + * Export the signal mask handling for aysnchronous code that * sleeps on RPC calls */ -#define RPC_INTR_SIGNALS (sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGKILL)) -static void rpc_save_sigmask(sigset_t *oldset, int intr) -{ - unsigned long sigallow = 0; - sigset_t sigmask; - - /* Block all signals except those listed in sigallow */ - if (intr) - sigallow |= RPC_INTR_SIGNALS; - siginitsetinv(&sigmask, sigallow); - sigprocmask(SIG_BLOCK, &sigmask, oldset); -} - -static inline void rpc_task_sigmask(struct rpc_task *task, sigset_t *oldset) -{ - rpc_save_sigmask(oldset, !RPC_TASK_UNINTERRUPTIBLE(task)); -} - -static inline void rpc_restore_sigmask(sigset_t *oldset) -{ - sigprocmask(SIG_SETMASK, oldset, NULL); -} - void rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset) { - rpc_save_sigmask(oldset, clnt->cl_intr); + unsigned long sigallow = sigmask(SIGKILL); + unsigned long irqflags; + + /* Turn off various signals */ + if (clnt->cl_intr) { + struct k_sigaction *action = current->sighand->action; + if (action[SIGINT-1].sa.sa_handler == SIG_DFL) + sigallow |= sigmask(SIGINT); + if (action[SIGQUIT-1].sa.sa_handler == SIG_DFL) + sigallow |= sigmask(SIGQUIT); + } + spin_lock_irqsave(¤t->sighand->siglock, irqflags); + *oldset = current->blocked; + siginitsetinv(¤t->blocked, sigallow & ~oldset->sig[0]); + recalc_sigpending(); + spin_unlock_irqrestore(¤t->sighand->siglock, irqflags); } void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset) { - rpc_restore_sigmask(oldset); + unsigned long irqflags; + + spin_lock_irqsave(¤t->sighand->siglock, irqflags); + current->blocked = *oldset; + recalc_sigpending(); + spin_unlock_irqrestore(¤t->sighand->siglock, irqflags); } /* @@ -430,26 +354,26 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) BUG_ON(flags & RPC_TASK_ASYNC); + rpc_clnt_sigmask(clnt, &oldset); + status = -ENOMEM; task = rpc_new_task(clnt, NULL, flags); if (task == NULL) goto out; - /* Mask signals on RPC calls _and_ GSS_AUTH upcalls */ - rpc_task_sigmask(task, &oldset); - rpc_call_setup(task, msg, 0); /* Set up the call info struct and execute the task */ - if (task->tk_status == 0) { + if (task->tk_status == 0) status = rpc_execute(task); - } else { + else { status = task->tk_status; rpc_release_task(task); } - rpc_restore_sigmask(&oldset); out: + rpc_clnt_sigunmask(clnt, &oldset); + return status; } @@ -470,6 +394,8 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, flags |= RPC_TASK_ASYNC; + rpc_clnt_sigmask(clnt, &oldset); + /* Create/initialize a new RPC task */ if (!callback) callback = rpc_default_callback; @@ -478,9 +404,6 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, goto out; task->tk_calldata = data; - /* Mask signals on GSS_AUTH upcalls */ - rpc_task_sigmask(task, &oldset); - rpc_call_setup(task, msg, 0); /* Set up the call info struct and execute the task */ @@ -490,8 +413,9 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, else rpc_release_task(task); - rpc_restore_sigmask(&oldset); out: + rpc_clnt_sigunmask(clnt, &oldset); + return status; } @@ -669,7 +593,7 @@ call_allocate(struct rpc_task *task) return; printk(KERN_INFO "RPC: buffer allocation failed for task %p\n", task); - if (RPC_IS_ASYNC(task) || !signalled()) { + if (RPC_IS_ASYNC(task) || !(task->tk_client->cl_intr && signalled())) { xprt_release(task); task->tk_action = call_reserve; rpc_delay(task, HZ>>4); @@ -1033,9 +957,7 @@ call_header(struct rpc_task *task) *p++ = htonl(clnt->cl_prog); /* program number */ *p++ = htonl(clnt->cl_vers); /* program version */ *p++ = htonl(task->tk_msg.rpc_proc->p_proc); /* procedure */ - p = rpcauth_marshcred(task, p); - req->rq_slen = xdr_adjust_iovec(&req->rq_svec[0], p); - return p; + return rpcauth_marshcred(task, p); } /* @@ -1064,11 +986,10 @@ call_verify(struct rpc_task *task) case RPC_AUTH_ERROR: break; case RPC_MISMATCH: - dprintk("%s: RPC call version mismatch!\n", __FUNCTION__); - error = -EPROTONOSUPPORT; - goto out_err; + printk(KERN_WARNING "%s: RPC call version mismatch!\n", __FUNCTION__); + goto out_eio; default: - dprintk("%s: RPC call rejected, unknown error: %x\n", __FUNCTION__, n); + printk(KERN_WARNING "%s: RPC call rejected, unknown error: %x\n", __FUNCTION__, n); goto out_eio; } if (--len < 0) @@ -1119,26 +1040,23 @@ call_verify(struct rpc_task *task) case RPC_SUCCESS: return p; case RPC_PROG_UNAVAIL: - dprintk("RPC: call_verify: program %u is unsupported by server %s\n", + printk(KERN_WARNING "RPC: call_verify: program %u is unsupported by server %s\n", (unsigned int)task->tk_client->cl_prog, task->tk_client->cl_server); - error = -EPFNOSUPPORT; - goto out_err; + goto out_eio; case RPC_PROG_MISMATCH: - dprintk("RPC: call_verify: program %u, version %u unsupported by server %s\n", + printk(KERN_WARNING "RPC: call_verify: program %u, version %u unsupported by server %s\n", (unsigned int)task->tk_client->cl_prog, (unsigned int)task->tk_client->cl_vers, task->tk_client->cl_server); - error = -EPROTONOSUPPORT; - goto out_err; + goto out_eio; case RPC_PROC_UNAVAIL: - dprintk("RPC: call_verify: proc %p unsupported by program %u, version %u on server %s\n", + printk(KERN_WARNING "RPC: call_verify: proc %p unsupported by program %u, version %u on server %s\n", task->tk_msg.rpc_proc, task->tk_client->cl_prog, task->tk_client->cl_vers, task->tk_client->cl_server); - error = -EOPNOTSUPP; - goto out_err; + goto out_eio; case RPC_GARBAGE_ARGS: dprintk("RPC: %4d %s: server saw garbage\n", task->tk_pid, __FUNCTION__); break; /* retry */ @@ -1151,7 +1069,7 @@ call_verify(struct rpc_task *task) task->tk_client->cl_stats->rpcgarbage++; if (task->tk_garb_retry) { task->tk_garb_retry--; - dprintk("RPC %s: retrying %4d\n", __FUNCTION__, task->tk_pid); + dprintk(KERN_WARNING "RPC %s: retrying %4d\n", __FUNCTION__, task->tk_pid); task->tk_action = call_bind; return NULL; } @@ -1165,30 +1083,3 @@ call_verify(struct rpc_task *task) printk(KERN_WARNING "RPC %s: server reply was truncated.\n", __FUNCTION__); goto out_retry; } - -static int rpcproc_encode_null(void *rqstp, u32 *data, void *obj) -{ - return 0; -} - -static int rpcproc_decode_null(void *rqstp, u32 *data, void *obj) -{ - return 0; -} - -static struct rpc_procinfo rpcproc_null = { - .p_encode = rpcproc_encode_null, - .p_decode = rpcproc_decode_null, -}; - -int rpc_ping(struct rpc_clnt *clnt, int flags) -{ - struct rpc_message msg = { - .rpc_proc = &rpcproc_null, - }; - int err; - msg.rpc_cred = authnull_ops.lookup_cred(NULL, NULL, 0); - err = rpc_call_sync(clnt, &msg, flags); - put_rpccred(msg.rpc_cred); - return err; -} diff --git a/trunk/net/sunrpc/pmap_clnt.c b/trunk/net/sunrpc/pmap_clnt.c index 4e81f2766923..d0b1d2c34a4d 100644 --- a/trunk/net/sunrpc/pmap_clnt.c +++ b/trunk/net/sunrpc/pmap_clnt.c @@ -53,9 +53,6 @@ rpc_getport(struct rpc_task *task, struct rpc_clnt *clnt) task->tk_pid, clnt->cl_server, map->pm_prog, map->pm_vers, map->pm_prot); - /* Autobind on cloned rpc clients is discouraged */ - BUG_ON(clnt->cl_parent != clnt); - spin_lock(&pmap_lock); if (map->pm_binding) { rpc_sleep_on(&map->pm_bindwait, task, NULL, NULL); @@ -210,10 +207,12 @@ pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto) xprt->addr.sin_port = htons(RPC_PMAP_PORT); /* printk("pmap: create clnt\n"); */ - clnt = rpc_new_client(xprt, hostname, + clnt = rpc_create_client(xprt, hostname, &pmap_program, RPC_PMAP_VERSION, RPC_AUTH_UNIX); - if (!IS_ERR(clnt)) { + if (IS_ERR(clnt)) { + xprt_destroy(xprt); + } else { clnt->cl_softrtry = 1; clnt->cl_chatty = 1; clnt->cl_oneshot = 1; diff --git a/trunk/net/sunrpc/sched.c b/trunk/net/sunrpc/sched.c index 2d9eb7fbd521..c06614d0e31d 100644 --- a/trunk/net/sunrpc/sched.c +++ b/trunk/net/sunrpc/sched.c @@ -290,7 +290,7 @@ static void rpc_make_runnable(struct rpc_task *task) return; } } else - wake_up_bit(&task->tk_runstate, RPC_TASK_QUEUED); + wake_up(&task->u.tk_wait.waitq); } /* @@ -554,38 +554,6 @@ __rpc_atrun(struct rpc_task *task) rpc_wake_up_task(task); } -/* - * Helper that calls task->tk_exit if it exists and then returns - * true if we should exit __rpc_execute. - */ -static inline int __rpc_do_exit(struct rpc_task *task) -{ - if (task->tk_exit != NULL) { - lock_kernel(); - task->tk_exit(task); - unlock_kernel(); - /* If tk_action is non-null, we should restart the call */ - if (task->tk_action != NULL) { - if (!RPC_ASSASSINATED(task)) { - /* Release RPC slot and buffer memory */ - xprt_release(task); - rpc_free(task); - return 0; - } - printk(KERN_ERR "RPC: dead task tried to walk away.\n"); - } - } - return 1; -} - -static int rpc_wait_bit_interruptible(void *word) -{ - if (signal_pending(current)) - return -ERESTARTSYS; - schedule(); - return 0; -} - /* * This is the RPC `scheduler' (or rather, the finite state machine). */ @@ -598,7 +566,8 @@ static int __rpc_execute(struct rpc_task *task) BUG_ON(RPC_IS_QUEUED(task)); - for (;;) { + restarted: + while (1) { /* * Garbage collection of pending timers... */ @@ -631,12 +600,11 @@ static int __rpc_execute(struct rpc_task *task) * by someone else. */ if (!RPC_IS_QUEUED(task)) { - if (task->tk_action != NULL) { - lock_kernel(); - task->tk_action(task); - unlock_kernel(); - } else if (__rpc_do_exit(task)) + if (!task->tk_action) break; + lock_kernel(); + task->tk_action(task); + unlock_kernel(); } /* @@ -656,26 +624,44 @@ static int __rpc_execute(struct rpc_task *task) /* sync task: sleep here */ dprintk("RPC: %4d sync task going to sleep\n", task->tk_pid); - /* Note: Caller should be using rpc_clnt_sigmask() */ - status = out_of_line_wait_on_bit(&task->tk_runstate, - RPC_TASK_QUEUED, rpc_wait_bit_interruptible, - TASK_INTERRUPTIBLE); - if (status == -ERESTARTSYS) { + if (RPC_TASK_UNINTERRUPTIBLE(task)) { + __wait_event(task->u.tk_wait.waitq, !RPC_IS_QUEUED(task)); + } else { + __wait_event_interruptible(task->u.tk_wait.waitq, !RPC_IS_QUEUED(task), status); /* * When a sync task receives a signal, it exits with * -ERESTARTSYS. In order to catch any callbacks that * clean up after sleeping on some queue, we don't * break the loop here, but go around once more. */ - dprintk("RPC: %4d got signal\n", task->tk_pid); - task->tk_flags |= RPC_TASK_KILLED; - rpc_exit(task, -ERESTARTSYS); - rpc_wake_up_task(task); + if (status == -ERESTARTSYS) { + dprintk("RPC: %4d got signal\n", task->tk_pid); + task->tk_flags |= RPC_TASK_KILLED; + rpc_exit(task, -ERESTARTSYS); + rpc_wake_up_task(task); + } } rpc_set_running(task); dprintk("RPC: %4d sync task resuming\n", task->tk_pid); } + if (task->tk_exit) { + lock_kernel(); + task->tk_exit(task); + unlock_kernel(); + /* If tk_action is non-null, the user wants us to restart */ + if (task->tk_action) { + if (!RPC_ASSASSINATED(task)) { + /* Release RPC slot and buffer memory */ + if (task->tk_rqstp) + xprt_release(task); + rpc_free(task); + goto restarted; + } + printk(KERN_ERR "RPC: dead task tries to walk away.\n"); + } + } + dprintk("RPC: %4d exit() = %d\n", task->tk_pid, task->tk_status); status = task->tk_status; @@ -773,6 +759,8 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, rpc_action call /* Initialize workqueue for async tasks */ task->tk_workqueue = rpciod_workqueue; + if (!RPC_IS_ASYNC(task)) + init_waitqueue_head(&task->u.tk_wait.waitq); if (clnt) { atomic_inc(&clnt->cl_users); diff --git a/trunk/net/sunrpc/sunrpc_syms.c b/trunk/net/sunrpc/sunrpc_syms.c index 32e8acbc60fe..d4f26bf9e732 100644 --- a/trunk/net/sunrpc/sunrpc_syms.c +++ b/trunk/net/sunrpc/sunrpc_syms.c @@ -42,7 +42,6 @@ EXPORT_SYMBOL(rpc_release_task); /* RPC client functions */ EXPORT_SYMBOL(rpc_create_client); EXPORT_SYMBOL(rpc_clone_client); -EXPORT_SYMBOL(rpc_bind_new_program); EXPORT_SYMBOL(rpc_destroy_client); EXPORT_SYMBOL(rpc_shutdown_client); EXPORT_SYMBOL(rpc_release_client); @@ -62,6 +61,7 @@ EXPORT_SYMBOL(rpc_mkpipe); /* Client transport */ EXPORT_SYMBOL(xprt_create_proto); +EXPORT_SYMBOL(xprt_destroy); EXPORT_SYMBOL(xprt_set_timeout); EXPORT_SYMBOL(xprt_udp_slot_table_entries); EXPORT_SYMBOL(xprt_tcp_slot_table_entries); @@ -129,10 +129,6 @@ EXPORT_SYMBOL(xdr_encode_netobj); EXPORT_SYMBOL(xdr_encode_pages); EXPORT_SYMBOL(xdr_inline_pages); EXPORT_SYMBOL(xdr_shift_buf); -EXPORT_SYMBOL(xdr_encode_word); -EXPORT_SYMBOL(xdr_decode_word); -EXPORT_SYMBOL(xdr_encode_array2); -EXPORT_SYMBOL(xdr_decode_array2); EXPORT_SYMBOL(xdr_buf_from_iov); EXPORT_SYMBOL(xdr_buf_subsegment); EXPORT_SYMBOL(xdr_buf_read_netobj); diff --git a/trunk/net/sunrpc/svc.c b/trunk/net/sunrpc/svc.c index e9bd91265f70..bb2d99f33315 100644 --- a/trunk/net/sunrpc/svc.c +++ b/trunk/net/sunrpc/svc.c @@ -35,24 +35,20 @@ svc_create(struct svc_program *prog, unsigned int bufsize) if (!(serv = (struct svc_serv *) kmalloc(sizeof(*serv), GFP_KERNEL))) return NULL; memset(serv, 0, sizeof(*serv)); - serv->sv_name = prog->pg_name; serv->sv_program = prog; serv->sv_nrthreads = 1; serv->sv_stats = prog->pg_stats; serv->sv_bufsz = bufsize? bufsize : 4096; + prog->pg_lovers = prog->pg_nvers-1; xdrsize = 0; - while (prog) { - prog->pg_lovers = prog->pg_nvers-1; - for (vers=0; verspg_nvers ; vers++) - if (prog->pg_vers[vers]) { - prog->pg_hivers = vers; - if (prog->pg_lovers > vers) - prog->pg_lovers = vers; - if (prog->pg_vers[vers]->vs_xdrsize > xdrsize) - xdrsize = prog->pg_vers[vers]->vs_xdrsize; - } - prog = prog->pg_next; - } + for (vers=0; verspg_nvers ; vers++) + if (prog->pg_vers[vers]) { + prog->pg_hivers = vers; + if (prog->pg_lovers > vers) + prog->pg_lovers = vers; + if (prog->pg_vers[vers]->vs_xdrsize > xdrsize) + xdrsize = prog->pg_vers[vers]->vs_xdrsize; + } serv->sv_xdrsize = xdrsize; INIT_LIST_HEAD(&serv->sv_threads); INIT_LIST_HEAD(&serv->sv_sockets); @@ -60,6 +56,8 @@ svc_create(struct svc_program *prog, unsigned int bufsize) INIT_LIST_HEAD(&serv->sv_permsocks); spin_lock_init(&serv->sv_lock); + serv->sv_name = prog->pg_name; + /* Remove any stale portmap registrations */ svc_register(serv, 0, 0); @@ -283,7 +281,6 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp) rqstp->rq_res.len = 0; rqstp->rq_res.page_base = 0; rqstp->rq_res.page_len = 0; - rqstp->rq_res.buflen = PAGE_SIZE; rqstp->rq_res.tail[0].iov_len = 0; /* tcp needs a space for the record length... */ if (rqstp->rq_prot == IPPROTO_TCP) @@ -341,10 +338,7 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp) goto sendit; } - for (progp = serv->sv_program; progp; progp = progp->pg_next) - if (prog == progp->pg_prog) - break; - if (progp == NULL) + if (prog != progp->pg_prog) goto err_bad_prog; if (vers >= progp->pg_nvers || @@ -457,7 +451,11 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp) goto sendit; err_bad_prog: - dprintk("svc: unknown program %d\n", prog); +#ifdef RPC_PARANOIA + if (prog != 100227 || progp->pg_prog != 100003) + printk("svc: unknown program %d (me %d)\n", prog, progp->pg_prog); + /* else it is just a Solaris client seeing if ACLs are supported */ +#endif serv->sv_stats->rpcbadfmt++; svc_putu32(resv, rpc_prog_unavail); goto sendit; diff --git a/trunk/net/sunrpc/xdr.c b/trunk/net/sunrpc/xdr.c index 8a4d9c106af1..67b9f035ba86 100644 --- a/trunk/net/sunrpc/xdr.c +++ b/trunk/net/sunrpc/xdr.c @@ -176,23 +176,21 @@ xdr_inline_pages(struct xdr_buf *xdr, unsigned int offset, xdr->buflen += len; } -ssize_t +void xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base, skb_reader_t *desc, skb_read_actor_t copy_actor) { struct page **ppage = xdr->pages; unsigned int len, pglen = xdr->page_len; - ssize_t copied = 0; int ret; len = xdr->head[0].iov_len; if (base < len) { len -= base; ret = copy_actor(desc, (char *)xdr->head[0].iov_base + base, len); - copied += ret; if (ret != len || !desc->count) - goto out; + return; base = 0; } else base -= len; @@ -212,17 +210,6 @@ xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base, do { char *kaddr; - /* ACL likes to be lazy in allocating pages - ACLs - * are small by default but can get huge. */ - if (unlikely(*ppage == NULL)) { - *ppage = alloc_page(GFP_ATOMIC); - if (unlikely(*ppage == NULL)) { - if (copied == 0) - copied = -ENOMEM; - goto out; - } - } - len = PAGE_CACHE_SIZE; kaddr = kmap_atomic(*ppage, KM_SKB_SUNRPC_DATA); if (base) { @@ -238,17 +225,14 @@ xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base, } flush_dcache_page(*ppage); kunmap_atomic(kaddr, KM_SKB_SUNRPC_DATA); - copied += ret; if (ret != len || !desc->count) - goto out; + return; ppage++; } while ((pglen -= len) != 0); copy_tail: len = xdr->tail[0].iov_len; if (base < len) - copied += copy_actor(desc, (char *)xdr->tail[0].iov_base + base, len - base); -out: - return copied; + copy_actor(desc, (char *)xdr->tail[0].iov_base + base, len - base); } @@ -632,24 +616,12 @@ xdr_shift_buf(struct xdr_buf *buf, size_t len) void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, uint32_t *p) { struct kvec *iov = buf->head; - int scratch_len = buf->buflen - buf->page_len - buf->tail[0].iov_len; - BUG_ON(scratch_len < 0); xdr->buf = buf; xdr->iov = iov; - xdr->p = (uint32_t *)((char *)iov->iov_base + iov->iov_len); - xdr->end = (uint32_t *)((char *)iov->iov_base + scratch_len); - BUG_ON(iov->iov_len > scratch_len); - - if (p != xdr->p && p != NULL) { - size_t len; - - BUG_ON(p < xdr->p || p > xdr->end); - len = (char *)p - (char *)xdr->p; - xdr->p = p; - buf->len += len; - iov->iov_len += len; - } + xdr->end = (uint32_t *)((char *)iov->iov_base + iov->iov_len); + buf->len = iov->iov_len = (char *)p - (char *)iov->iov_base; + xdr->p = p; } EXPORT_SYMBOL(xdr_init_encode); @@ -887,34 +859,8 @@ read_bytes_from_xdr_buf(struct xdr_buf *buf, int base, void *obj, int len) return status; } -/* obj is assumed to point to allocated memory of size at least len: */ -int -write_bytes_to_xdr_buf(struct xdr_buf *buf, int base, void *obj, int len) -{ - struct xdr_buf subbuf; - int this_len; - int status; - - status = xdr_buf_subsegment(buf, &subbuf, base, len); - if (status) - goto out; - this_len = min(len, (int)subbuf.head[0].iov_len); - memcpy(subbuf.head[0].iov_base, obj, this_len); - len -= this_len; - obj += this_len; - this_len = min(len, (int)subbuf.page_len); - if (this_len) - _copy_to_pages(subbuf.pages, subbuf.page_base, obj, this_len); - len -= this_len; - obj += this_len; - this_len = min(len, (int)subbuf.tail[0].iov_len); - memcpy(subbuf.tail[0].iov_base, obj, this_len); -out: - return status; -} - -int -xdr_decode_word(struct xdr_buf *buf, int base, u32 *obj) +static int +read_u32_from_xdr_buf(struct xdr_buf *buf, int base, u32 *obj) { u32 raw; int status; @@ -926,14 +872,6 @@ xdr_decode_word(struct xdr_buf *buf, int base, u32 *obj) return 0; } -int -xdr_encode_word(struct xdr_buf *buf, int base, u32 obj) -{ - u32 raw = htonl(obj); - - return write_bytes_to_xdr_buf(buf, base, &raw, sizeof(obj)); -} - /* If the netobj starting offset bytes from the start of xdr_buf is contained * entirely in the head or the tail, set object to point to it; otherwise * try to find space for it at the end of the tail, copy it there, and @@ -944,7 +882,7 @@ xdr_buf_read_netobj(struct xdr_buf *buf, struct xdr_netobj *obj, int offset) u32 tail_offset = buf->head[0].iov_len + buf->page_len; u32 obj_end_offset; - if (xdr_decode_word(buf, offset, &obj->len)) + if (read_u32_from_xdr_buf(buf, offset, &obj->len)) goto out; obj_end_offset = offset + 4 + obj->len; @@ -977,219 +915,3 @@ xdr_buf_read_netobj(struct xdr_buf *buf, struct xdr_netobj *obj, int offset) out: return -1; } - -/* Returns 0 on success, or else a negative error code. */ -static int -xdr_xcode_array2(struct xdr_buf *buf, unsigned int base, - struct xdr_array2_desc *desc, int encode) -{ - char *elem = NULL, *c; - unsigned int copied = 0, todo, avail_here; - struct page **ppages = NULL; - int err; - - if (encode) { - if (xdr_encode_word(buf, base, desc->array_len) != 0) - return -EINVAL; - } else { - if (xdr_decode_word(buf, base, &desc->array_len) != 0 || - (unsigned long) base + 4 + desc->array_len * - desc->elem_size > buf->len) - return -EINVAL; - } - base += 4; - - if (!desc->xcode) - return 0; - - todo = desc->array_len * desc->elem_size; - - /* process head */ - if (todo && base < buf->head->iov_len) { - c = buf->head->iov_base + base; - avail_here = min_t(unsigned int, todo, - buf->head->iov_len - base); - todo -= avail_here; - - while (avail_here >= desc->elem_size) { - err = desc->xcode(desc, c); - if (err) - goto out; - c += desc->elem_size; - avail_here -= desc->elem_size; - } - if (avail_here) { - if (!elem) { - elem = kmalloc(desc->elem_size, GFP_KERNEL); - err = -ENOMEM; - if (!elem) - goto out; - } - if (encode) { - err = desc->xcode(desc, elem); - if (err) - goto out; - memcpy(c, elem, avail_here); - } else - memcpy(elem, c, avail_here); - copied = avail_here; - } - base = buf->head->iov_len; /* align to start of pages */ - } - - /* process pages array */ - base -= buf->head->iov_len; - if (todo && base < buf->page_len) { - unsigned int avail_page; - - avail_here = min(todo, buf->page_len - base); - todo -= avail_here; - - base += buf->page_base; - ppages = buf->pages + (base >> PAGE_CACHE_SHIFT); - base &= ~PAGE_CACHE_MASK; - avail_page = min_t(unsigned int, PAGE_CACHE_SIZE - base, - avail_here); - c = kmap(*ppages) + base; - - while (avail_here) { - avail_here -= avail_page; - if (copied || avail_page < desc->elem_size) { - unsigned int l = min(avail_page, - desc->elem_size - copied); - if (!elem) { - elem = kmalloc(desc->elem_size, - GFP_KERNEL); - err = -ENOMEM; - if (!elem) - goto out; - } - if (encode) { - if (!copied) { - err = desc->xcode(desc, elem); - if (err) - goto out; - } - memcpy(c, elem + copied, l); - copied += l; - if (copied == desc->elem_size) - copied = 0; - } else { - memcpy(elem + copied, c, l); - copied += l; - if (copied == desc->elem_size) { - err = desc->xcode(desc, elem); - if (err) - goto out; - copied = 0; - } - } - avail_page -= l; - c += l; - } - while (avail_page >= desc->elem_size) { - err = desc->xcode(desc, c); - if (err) - goto out; - c += desc->elem_size; - avail_page -= desc->elem_size; - } - if (avail_page) { - unsigned int l = min(avail_page, - desc->elem_size - copied); - if (!elem) { - elem = kmalloc(desc->elem_size, - GFP_KERNEL); - err = -ENOMEM; - if (!elem) - goto out; - } - if (encode) { - if (!copied) { - err = desc->xcode(desc, elem); - if (err) - goto out; - } - memcpy(c, elem + copied, l); - copied += l; - if (copied == desc->elem_size) - copied = 0; - } else { - memcpy(elem + copied, c, l); - copied += l; - if (copied == desc->elem_size) { - err = desc->xcode(desc, elem); - if (err) - goto out; - copied = 0; - } - } - } - if (avail_here) { - kunmap(*ppages); - ppages++; - c = kmap(*ppages); - } - - avail_page = min(avail_here, - (unsigned int) PAGE_CACHE_SIZE); - } - base = buf->page_len; /* align to start of tail */ - } - - /* process tail */ - base -= buf->page_len; - if (todo) { - c = buf->tail->iov_base + base; - if (copied) { - unsigned int l = desc->elem_size - copied; - - if (encode) - memcpy(c, elem + copied, l); - else { - memcpy(elem + copied, c, l); - err = desc->xcode(desc, elem); - if (err) - goto out; - } - todo -= l; - c += l; - } - while (todo) { - err = desc->xcode(desc, c); - if (err) - goto out; - c += desc->elem_size; - todo -= desc->elem_size; - } - } - err = 0; - -out: - if (elem) - kfree(elem); - if (ppages) - kunmap(*ppages); - return err; -} - -int -xdr_decode_array2(struct xdr_buf *buf, unsigned int base, - struct xdr_array2_desc *desc) -{ - if (base >= buf->len) - return -EINVAL; - - return xdr_xcode_array2(buf, base, desc, 0); -} - -int -xdr_encode_array2(struct xdr_buf *buf, unsigned int base, - struct xdr_array2_desc *desc) -{ - if ((unsigned long) base + 4 + desc->array_len * desc->elem_size > - buf->head->iov_len + buf->page_len + buf->tail->iov_len) - return -EINVAL; - - return xdr_xcode_array2(buf, base, desc, 1); -} diff --git a/trunk/net/sunrpc/xprt.c b/trunk/net/sunrpc/xprt.c index eca92405948f..c74a6bb94074 100644 --- a/trunk/net/sunrpc/xprt.c +++ b/trunk/net/sunrpc/xprt.c @@ -569,11 +569,8 @@ void xprt_connect(struct rpc_task *task) if (xprt->sock != NULL) schedule_delayed_work(&xprt->sock_connect, RPC_REESTABLISH_TIMEOUT); - else { + else schedule_work(&xprt->sock_connect); - if (!RPC_IS_ASYNC(task)) - flush_scheduled_work(); - } } return; out_write: @@ -728,8 +725,7 @@ csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb) goto no_checksum; desc.csum = csum_partial(skb->data, desc.offset, skb->csum); - if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_and_csum_bits) < 0) - return -1; + xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_and_csum_bits); if (desc.offset != skb->len) { unsigned int csum2; csum2 = skb_checksum(skb, desc.offset, skb->len - desc.offset, 0); @@ -741,8 +737,7 @@ csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb) return -1; return 0; no_checksum: - if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits) < 0) - return -1; + xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits); if (desc.count) return -1; return 0; @@ -826,15 +821,10 @@ tcp_copy_data(skb_reader_t *desc, void *p, size_t len) { if (len > desc->count) len = desc->count; - if (skb_copy_bits(desc->skb, desc->offset, p, len)) { - dprintk("RPC: failed to copy %zu bytes from skb. %zu bytes remain\n", - len, desc->count); + if (skb_copy_bits(desc->skb, desc->offset, p, len)) return 0; - } desc->offset += len; desc->count -= len; - dprintk("RPC: copied %zu bytes from skb. %zu bytes remain\n", - len, desc->count); return len; } @@ -873,8 +863,6 @@ tcp_read_fraghdr(struct rpc_xprt *xprt, skb_reader_t *desc) static void tcp_check_recm(struct rpc_xprt *xprt) { - dprintk("RPC: xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u, tcp_flags = %lx\n", - xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen, xprt->tcp_flags); if (xprt->tcp_offset == xprt->tcp_reclen) { xprt->tcp_flags |= XPRT_COPY_RECM; xprt->tcp_offset = 0; @@ -919,7 +907,6 @@ tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc) struct rpc_rqst *req; struct xdr_buf *rcvbuf; size_t len; - ssize_t r; /* Find and lock the request corresponding to this xid */ spin_lock(&xprt->sock_lock); @@ -940,40 +927,15 @@ tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc) len = xprt->tcp_reclen - xprt->tcp_offset; memcpy(&my_desc, desc, sizeof(my_desc)); my_desc.count = len; - r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied, + xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied, &my_desc, tcp_copy_data); - desc->count -= r; - desc->offset += r; + desc->count -= len; + desc->offset += len; } else - r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied, + xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied, desc, tcp_copy_data); - - if (r > 0) { - xprt->tcp_copied += r; - xprt->tcp_offset += r; - } - if (r != len) { - /* Error when copying to the receive buffer, - * usually because we weren't able to allocate - * additional buffer pages. All we can do now - * is turn off XPRT_COPY_DATA, so the request - * will not receive any additional updates, - * and time out. - * Any remaining data from this record will - * be discarded. - */ - xprt->tcp_flags &= ~XPRT_COPY_DATA; - dprintk("RPC: XID %08x truncated request\n", - ntohl(xprt->tcp_xid)); - dprintk("RPC: xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n", - xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen); - goto out; - } - - dprintk("RPC: XID %08x read %u bytes\n", - ntohl(xprt->tcp_xid), r); - dprintk("RPC: xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n", - xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen); + xprt->tcp_copied += len; + xprt->tcp_offset += len; if (xprt->tcp_copied == req->rq_private_buf.buflen) xprt->tcp_flags &= ~XPRT_COPY_DATA; @@ -982,7 +944,6 @@ tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc) xprt->tcp_flags &= ~XPRT_COPY_DATA; } -out: if (!(xprt->tcp_flags & XPRT_COPY_DATA)) { dprintk("RPC: %4d received reply complete\n", req->rq_task->tk_pid); @@ -1006,7 +967,6 @@ tcp_read_discard(struct rpc_xprt *xprt, skb_reader_t *desc) desc->count -= len; desc->offset += len; xprt->tcp_offset += len; - dprintk("RPC: discarded %u bytes\n", len); tcp_check_recm(xprt); } @@ -1104,7 +1064,8 @@ tcp_state_change(struct sock *sk) case TCP_SYN_RECV: break; default: - xprt_disconnect(xprt); + if (xprt_test_and_clear_connected(xprt)) + rpc_wake_up_status(&xprt->pending, -ENOTCONN); break; } out: @@ -1242,8 +1203,6 @@ xprt_transmit(struct rpc_task *task) list_add_tail(&req->rq_list, &xprt->recv); spin_unlock_bh(&xprt->sock_lock); xprt_reset_majortimeo(req); - /* Turn off autodisconnect */ - del_singleshot_timer_sync(&xprt->timer); } } else if (!req->rq_bytes_sent) return; @@ -1374,6 +1333,8 @@ xprt_reserve(struct rpc_task *task) spin_lock(&xprt->xprt_lock); do_xprt_reserve(task); spin_unlock(&xprt->xprt_lock); + if (task->tk_rqstp) + del_timer_sync(&xprt->timer); } } @@ -1688,10 +1649,6 @@ xprt_shutdown(struct rpc_xprt *xprt) rpc_wake_up(&xprt->backlog); wake_up(&xprt->cong_wait); del_timer_sync(&xprt->timer); - - /* synchronously wait for connect worker to finish */ - cancel_delayed_work(&xprt->sock_connect); - flush_scheduled_work(); } /*