]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'for-linus' of git://brick.kernel.dk/data/git/linux-2.6-block
authorLinus Torvalds <torvalds@g5.osdl.org>
Fri, 28 Oct 2005 15:53:00 +0000 (08:53 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Fri, 28 Oct 2005 15:53:00 +0000 (08:53 -0700)
281 files changed:
Makefile
arch/alpha/kernel/pci-noop.c
arch/alpha/kernel/pci_iommu.c
arch/arm/mm/consistent.c
arch/frv/mb93090-mb00/pci-dma-nommu.c
arch/frv/mb93090-mb00/pci-dma.c
arch/frv/mm/dma-alloc.c
arch/ia64/hp/common/hwsw_iommu.c
arch/ia64/hp/common/sba_iommu.c
arch/ia64/lib/swiotlb.c
arch/ia64/sn/kernel/xpc.h
arch/ia64/sn/pci/pci_dma.c
arch/mips/mm/dma-coherent.c
arch/mips/mm/dma-ip27.c
arch/mips/mm/dma-ip32.c
arch/mips/mm/dma-noncoherent.c
arch/parisc/kernel/pci-dma.c
arch/ppc/8xx_io/cs4218.h
arch/ppc/8xx_io/cs4218_tdm.c
arch/ppc/kernel/dma-mapping.c
arch/ppc/mm/pgtable.c
arch/sh/boards/renesas/rts7751r2d/mach.c
arch/sh/cchips/voyagergx/consistent.c
arch/sh/drivers/pci/dma-dreamcast.c
arch/sh/mm/consistent.c
arch/sparc64/solaris/socksys.c
arch/sparc64/solaris/timod.c
arch/um/kernel/mem.c
arch/um/kernel/process_kern.c
arch/x86_64/kernel/pci-gart.c
arch/x86_64/kernel/pci-nommu.c
arch/xtensa/kernel/pci-dma.c
drivers/block/as-iosched.c
drivers/block/cfq-iosched.c
drivers/block/deadline-iosched.c
drivers/block/elevator.c
drivers/block/ll_rw_blk.c
drivers/block/loop.c
drivers/block/rd.c
drivers/char/n_tty.c
drivers/ieee1394/eth1394.c
drivers/infiniband/hw/mthca/mthca_cmd.c
drivers/infiniband/hw/mthca/mthca_cmd.h
drivers/infiniband/hw/mthca/mthca_memfree.c
drivers/infiniband/hw/mthca/mthca_memfree.h
drivers/md/bitmap.c
drivers/md/dm-crypt.c
drivers/net/cassini.c
drivers/net/lance.c
drivers/net/myri_sbus.c
drivers/net/myri_sbus.h
drivers/net/sunbmac.c
drivers/net/sunbmac.h
drivers/parisc/ccio-dma.c
drivers/parisc/sba_iommu.c
drivers/s390/net/fsm.c
drivers/s390/net/fsm.h
drivers/scsi/eata.c
drivers/scsi/hosts.c
drivers/scsi/lpfc/lpfc_mem.c
drivers/scsi/osst.c
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_rscn.c
drivers/scsi/scsi.c
drivers/scsi/scsi_ioctl.c
drivers/scsi/scsi_lib.c
drivers/scsi/sg.c
drivers/scsi/st.c
drivers/usb/core/buffer.c
drivers/usb/core/hcd.c
drivers/usb/core/hcd.h
drivers/usb/core/message.c
drivers/usb/core/urb.c
drivers/usb/core/usb.c
drivers/usb/gadget/dummy_hcd.c
drivers/usb/gadget/ether.c
drivers/usb/gadget/goku_udc.c
drivers/usb/gadget/lh7a40x_udc.c
drivers/usb/gadget/net2280.c
drivers/usb/gadget/omap_udc.c
drivers/usb/gadget/pxa2xx_udc.c
drivers/usb/gadget/serial.c
drivers/usb/gadget/zero.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-mem.c
drivers/usb/host/ehci-q.c
drivers/usb/host/ehci-sched.c
drivers/usb/host/isp116x-hcd.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-mem.c
drivers/usb/host/sl811-hcd.c
drivers/usb/host/uhci-q.c
drivers/usb/misc/uss720.c
drivers/usb/net/asix.c
drivers/usb/net/gl620a.c
drivers/usb/net/kaweth.c
drivers/usb/net/net1080.c
drivers/usb/net/rndis_host.c
drivers/usb/net/usbnet.c
drivers/usb/net/usbnet.h
drivers/usb/net/zaurus.c
drivers/usb/net/zd1201.c
fs/afs/file.c
fs/bio.c
fs/buffer.c
fs/dcache.c
fs/dquot.c
fs/exec.c
fs/ext3/inode.c
fs/hfs/inode.c
fs/hfsplus/inode.c
fs/inode.c
fs/jbd/journal.c
fs/jbd/transaction.c
fs/jfs/jfs_metapage.c
fs/lockd/host.c
fs/locks.c
fs/mbcache.c
fs/namei.c
fs/nfs/delegation.c
fs/nfs/delegation.h
fs/nfs/dir.c
fs/nfs/file.c
fs/nfs/inode.c
fs/nfs/nfs2xdr.c
fs/nfs/nfs3proc.c
fs/nfs/nfs3xdr.c
fs/nfs/nfs4_fs.h
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/nfs4xdr.c
fs/nfs/proc.c
fs/nfs/read.c
fs/nfs/write.c
fs/open.c
fs/reiserfs/fix_node.c
fs/reiserfs/inode.c
fs/reiserfs/xattr.c
fs/xfs/linux-2.6/kmem.c
fs/xfs/linux-2.6/kmem.h
fs/xfs/linux-2.6/xfs_aops.c
fs/xfs/linux-2.6/xfs_buf.c
include/asm-alpha/dma-mapping.h
include/asm-arm/dma-mapping.h
include/asm-cris/dma-mapping.h
include/asm-frv/dma-mapping.h
include/asm-frv/pci.h
include/asm-generic/dma-mapping-broken.h
include/asm-ia64/machvec.h
include/asm-m32r/dma-mapping.h
include/asm-mips/dma-mapping.h
include/asm-parisc/dma-mapping.h
include/asm-ppc/dma-mapping.h
include/asm-sh/dma-mapping.h
include/asm-sh/machvec.h
include/asm-sh64/dma-mapping.h
include/asm-sparc/dma-mapping.h
include/asm-sparc64/dma-mapping.h
include/asm-um/dma-mapping.h
include/asm-um/page.h
include/asm-x86_64/dma-mapping.h
include/asm-x86_64/swiotlb.h
include/asm-xtensa/dma-mapping.h
include/linux/audit.h
include/linux/bio.h
include/linux/blkdev.h
include/linux/buffer_head.h
include/linux/elevator.h
include/linux/fs.h
include/linux/gfp.h
include/linux/i2o.h
include/linux/idr.h
include/linux/jbd.h
include/linux/kobject.h
include/linux/loop.h
include/linux/mbcache.h
include/linux/mm.h
include/linux/mmzone.h
include/linux/namei.h
include/linux/nfs_fs.h
include/linux/nfs_xdr.h
include/linux/pagemap.h
include/linux/radix-tree.h
include/linux/reiserfs_fs.h
include/linux/security.h
include/linux/skbuff.h
include/linux/slab.h
include/linux/sunrpc/auth.h
include/linux/sunrpc/debug.h
include/linux/sunrpc/gss_api.h
include/linux/sunrpc/gss_err.h
include/linux/sunrpc/gss_krb5.h
include/linux/sunrpc/gss_spkm3.h
include/linux/sunrpc/msg_prot.h
include/linux/sunrpc/xdr.h
include/linux/sunrpc/xprt.h
include/linux/suspend.h
include/linux/swap.h
include/linux/textsearch.h
include/linux/types.h
include/linux/usb.h
include/linux/usb_gadget.h
include/net/dst.h
include/net/sock.h
include/scsi/scsi_cmnd.h
include/scsi/scsi_request.h
include/sound/memalloc.h
kernel/audit.c
kernel/auditsc.c
kernel/kexec.c
kernel/power/swsusp.c
lib/idr.c
lib/kobject.c
lib/kobject_uevent.c
lib/textsearch.c
mm/filemap.c
mm/highmem.c
mm/mempolicy.c
mm/mempool.c
mm/page_alloc.c
mm/shmem.c
mm/slab.c
mm/vmscan.c
net/core/neighbour.c
net/core/pktgen.c
net/core/skbuff.c
net/core/sock.c
net/dccp/output.c
net/decnet/af_decnet.c
net/ipv4/devinet.c
net/ipv4/fib_trie.c
net/ipv4/icmp.c
net/ipv4/ip_output.c
net/ipv4/netfilter/ip_conntrack_core.c
net/ipv4/proc.c
net/ipv6/icmp.c
net/ipv6/proc.c
net/netlink/af_netlink.c
net/rose/rose_route.c
net/sctp/proc.c
net/sunrpc/Makefile
net/sunrpc/auth.c
net/sunrpc/auth_gss/Makefile
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/auth_gss/gss_krb5_crypto.c
net/sunrpc/auth_gss/gss_krb5_mech.c
net/sunrpc/auth_gss/gss_krb5_seal.c
net/sunrpc/auth_gss/gss_krb5_unseal.c
net/sunrpc/auth_gss/gss_krb5_wrap.c [new file with mode: 0644]
net/sunrpc/auth_gss/gss_mech_switch.c
net/sunrpc/auth_gss/gss_spkm3_mech.c
net/sunrpc/auth_gss/gss_spkm3_seal.c
net/sunrpc/auth_gss/gss_spkm3_unseal.c
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/auth_null.c
net/sunrpc/auth_unix.c
net/sunrpc/clnt.c
net/sunrpc/pmap_clnt.c
net/sunrpc/rpc_pipe.c
net/sunrpc/socklib.c [new file with mode: 0644]
net/sunrpc/sunrpc_syms.c
net/sunrpc/svcsock.c
net/sunrpc/sysctl.c
net/sunrpc/xdr.c
net/sunrpc/xprt.c
net/sunrpc/xprtsock.c [new file with mode: 0644]
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c
security/dummy.c
security/selinux/hooks.c
sound/core/memalloc.c
sound/core/seq/instr/ainstr_gf1.c
sound/core/seq/instr/ainstr_iw.c
sound/core/seq/instr/ainstr_simple.c
sound/oss/dmasound/dmasound.h
sound/oss/dmasound/dmasound_atari.c
sound/oss/dmasound/dmasound_awacs.c
sound/oss/dmasound/dmasound_paula.c
sound/oss/dmasound/dmasound_q40.c
sound/usb/usbmidi.c

index 1fa7e5343464d69373858c598154da813e66285d..f1d121f23025c664ebd5e6bbebb29c62bce49c5b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -334,7 +334,7 @@ KALLSYMS    = scripts/kallsyms
 PERL           = perl
 CHECK          = sparse
 
-CHECKFLAGS     := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ $(CF)
+CHECKFLAGS     := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise $(CF)
 MODFLAGS       = -DMODULE
 CFLAGS_MODULE   = $(MODFLAGS)
 AFLAGS_MODULE   = $(MODFLAGS)
index 582a3519fb28d24bbf42dd8e1cb46c700b5f2c22..9903e3a79102486184dc66e282fab60a9048fe6d 100644 (file)
@@ -154,7 +154,7 @@ pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask)
 
 void *
 dma_alloc_coherent(struct device *dev, size_t size,
-                  dma_addr_t *dma_handle, int gfp)
+                  dma_addr_t *dma_handle, gfp_t gfp)
 {
        void *ret;
 
index 7cb23f12ecbd03a15cd8a6d52f84d887f96736df..c468e312e5f815bd67b19c7354bf65422ea51d4b 100644 (file)
@@ -397,7 +397,7 @@ pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp)
 {
        void *cpu_addr;
        long order = get_order(size);
-       int gfp = GFP_ATOMIC;
+       gfp_t gfp = GFP_ATOMIC;
 
 try_again:
        cpu_addr = (void *)__get_free_pages(gfp, order);
index 26356ce4da5448165bcac172139deef54a008462..82f4d5e27c5492f98dac798f807194eb6800fc03 100644 (file)
@@ -75,7 +75,7 @@ static struct vm_region consistent_head = {
 };
 
 static struct vm_region *
-vm_region_alloc(struct vm_region *head, size_t size, int gfp)
+vm_region_alloc(struct vm_region *head, size_t size, gfp_t gfp)
 {
        unsigned long addr = head->vm_start, end = head->vm_end - size;
        unsigned long flags;
@@ -133,7 +133,7 @@ static struct vm_region *vm_region_find(struct vm_region *head, unsigned long ad
 #endif
 
 static void *
-__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, int gfp,
+__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
            pgprot_t prot)
 {
        struct page *page;
@@ -251,7 +251,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, int gfp,
  * virtual and bus address for that space.
  */
 void *
-dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, int gfp)
+dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
 {
        return __dma_alloc(dev, size, handle, gfp,
                           pgprot_noncached(pgprot_kernel));
@@ -263,7 +263,7 @@ EXPORT_SYMBOL(dma_alloc_coherent);
  * dma_alloc_coherent above.
  */
 void *
-dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, int gfp)
+dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
 {
        return __dma_alloc(dev, size, handle, gfp,
                           pgprot_writecombine(pgprot_kernel));
index 819895cf0b9eda0c773022cd347bf5d18dfb7e2d..2082a9647f4fb03172ee7ae33468e85077142598 100644 (file)
@@ -33,7 +33,7 @@ struct dma_alloc_record {
 static DEFINE_SPINLOCK(dma_alloc_lock);
 static LIST_HEAD(dma_alloc_list);
 
-void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, int gfp)
+void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, gfp_t gfp)
 {
        struct dma_alloc_record *new;
        struct list_head *this = &dma_alloc_list;
index 27eb1206650761255054093bd9492662be0e056e..86fbdadc51b6b2eb01cbece116a7797e94467938 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/highmem.h>
 #include <asm/io.h>
 
-void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, int gfp)
+void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, gfp_t gfp)
 {
        void *ret;
 
index 4b38d45435f69795809d449979aacd205568e9aa..cfc4f97490c693ca4517014343cbea904510a00d 100644 (file)
@@ -81,7 +81,7 @@ static int map_page(unsigned long va, unsigned long pa, pgprot_t prot)
  * portions of the kernel with single large page TLB entries, and
  * still get unique uncached pages for consistent DMA.
  */
-void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)
+void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *dma_handle)
 {
        struct vm_struct *area;
        unsigned long page, va, pa;
index 80f8ef013939f4bc5c55686a97fa013c3e8ad3e8..1ba02baf2f94fbc77a000374b0e859b411303008 100644 (file)
@@ -71,7 +71,7 @@ hwsw_init (void)
 }
 
 void *
-hwsw_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, int flags)
+hwsw_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flags)
 {
        if (use_swiotlb(dev))
                return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
index 11957598a8b9447dc4852fdca8c810546f315fb1..21bffba78b6dfc36bc19de97da662590cfc9b064 100644 (file)
@@ -1076,7 +1076,7 @@ void sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, int dir)
  * See Documentation/DMA-mapping.txt
  */
 void *
-sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, int flags)
+sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flags)
 {
        struct ioc *ioc;
        void *addr;
index a604efc7f6c9db2f859243dae31a35760b6406da..3ebbb3c8ba368f0ef818c659e9f9ecbe4d5797b7 100644 (file)
@@ -314,7 +314,7 @@ sync_single(struct device *hwdev, char *dma_addr, size_t size, int dir)
 
 void *
 swiotlb_alloc_coherent(struct device *hwdev, size_t size,
-                      dma_addr_t *dma_handle, int flags)
+                      dma_addr_t *dma_handle, gfp_t flags)
 {
        unsigned long dev_addr;
        void *ret;
index d0ee635daf2e7f4104c8b0dca480d9c4712d7dda..e5f5a4e51f700eda856591624ea4c5e6f2f9ea9e 100644 (file)
@@ -939,7 +939,7 @@ xpc_map_bte_errors(bte_result_t error)
 
 
 static inline void *
-xpc_kmalloc_cacheline_aligned(size_t size, int flags, void **base)
+xpc_kmalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
 {
        /* see if kmalloc will give us cachline aligned memory by default */
        *base = kmalloc(size, flags);
index 0e4b9ad9ef0250f2a1898dcae7c4a79c6a4f4bcc..75e6e874bebff043ed33fdd3fcf34bab62d0cb7a 100644 (file)
@@ -75,7 +75,7 @@ EXPORT_SYMBOL(sn_dma_set_mask);
  * more information.
  */
 void *sn_dma_alloc_coherent(struct device *dev, size_t size,
-                           dma_addr_t * dma_handle, int flags)
+                           dma_addr_t * dma_handle, gfp_t flags)
 {
        void *cpuaddr;
        unsigned long phys_addr;
index 97a50d38c98f33e3bdfa47733008582dfb744cfc..a617f8c327e8700171de2eae55b684357be7dff0 100644 (file)
@@ -18,7 +18,7 @@
 #include <asm/io.h>
 
 void *dma_alloc_noncoherent(struct device *dev, size_t size,
-       dma_addr_t * dma_handle, int gfp)
+       dma_addr_t * dma_handle, gfp_t gfp)
 {
        void *ret;
        /* ignore region specifiers */
@@ -39,7 +39,7 @@ void *dma_alloc_noncoherent(struct device *dev, size_t size,
 EXPORT_SYMBOL(dma_alloc_noncoherent);
 
 void *dma_alloc_coherent(struct device *dev, size_t size,
-       dma_addr_t * dma_handle, int gfp)
+       dma_addr_t * dma_handle, gfp_t gfp)
        __attribute__((alias("dma_alloc_noncoherent")));
 
 EXPORT_SYMBOL(dma_alloc_coherent);
index aa7c94b5d7817af04538aefdbfc44c752061350b..8da19fd22ac6f0bbbf5b64d3408e611b5f215f99 100644 (file)
@@ -22,7 +22,7 @@
        pdev_to_baddr(to_pci_dev(dev), (addr))
 
 void *dma_alloc_noncoherent(struct device *dev, size_t size,
-       dma_addr_t * dma_handle, int gfp)
+       dma_addr_t * dma_handle, gfp_t gfp)
 {
        void *ret;
 
@@ -44,7 +44,7 @@ void *dma_alloc_noncoherent(struct device *dev, size_t size,
 EXPORT_SYMBOL(dma_alloc_noncoherent);
 
 void *dma_alloc_coherent(struct device *dev, size_t size,
-       dma_addr_t * dma_handle, int gfp)
+       dma_addr_t * dma_handle, gfp_t gfp)
        __attribute__((alias("dma_alloc_noncoherent")));
 
 EXPORT_SYMBOL(dma_alloc_coherent);
index 2cbe196c35fb5884982afc5b34d9950f37a02a0b..a7e3072ff78d5b7570d394c6eac2bd0521b498dc 100644 (file)
@@ -37,7 +37,7 @@
 #define RAM_OFFSET_MASK        0x3fffffff
 
 void *dma_alloc_noncoherent(struct device *dev, size_t size,
-       dma_addr_t * dma_handle, int gfp)
+       dma_addr_t * dma_handle, gfp_t gfp)
 {
        void *ret;
        /* ignore region specifiers */
@@ -61,7 +61,7 @@ void *dma_alloc_noncoherent(struct device *dev, size_t size,
 EXPORT_SYMBOL(dma_alloc_noncoherent);
 
 void *dma_alloc_coherent(struct device *dev, size_t size,
-       dma_addr_t * dma_handle, int gfp)
+       dma_addr_t * dma_handle, gfp_t gfp)
 {
        void *ret;
 
index 59e54f12212ecf86a41a22a4705936cdc3b6b2b2..4ce02028a292cb4e3d9f5f3d1fbdcea3b02813c1 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 void *dma_alloc_noncoherent(struct device *dev, size_t size,
-       dma_addr_t * dma_handle, int gfp)
+       dma_addr_t * dma_handle, gfp_t gfp)
 {
        void *ret;
        /* ignore region specifiers */
@@ -45,7 +45,7 @@ void *dma_alloc_noncoherent(struct device *dev, size_t size,
 EXPORT_SYMBOL(dma_alloc_noncoherent);
 
 void *dma_alloc_coherent(struct device *dev, size_t size,
-       dma_addr_t * dma_handle, int gfp)
+       dma_addr_t * dma_handle, gfp_t gfp)
 {
        void *ret;
 
index 368cc095c99fd4a0611708709c2c1f018aead9ec..844c2877a2e386a34169bc2e97b9bc42f866f950 100644 (file)
@@ -349,7 +349,7 @@ pcxl_dma_init(void)
 
 __initcall(pcxl_dma_init);
 
-static void * pa11_dma_alloc_consistent (struct device *dev, size_t size, dma_addr_t *dma_handle, int flag)
+static void * pa11_dma_alloc_consistent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag)
 {
        unsigned long vaddr;
        unsigned long paddr;
@@ -502,13 +502,13 @@ struct hppa_dma_ops pcxl_dma_ops = {
 };
 
 static void *fail_alloc_consistent(struct device *dev, size_t size,
-                                  dma_addr_t *dma_handle, int flag)
+                                  dma_addr_t *dma_handle, gfp_t flag)
 {
        return NULL;
 }
 
 static void *pa11_dma_alloc_noncoherent(struct device *dev, size_t size,
-                                         dma_addr_t *dma_handle, int flag)
+                                         dma_addr_t *dma_handle, gfp_t flag)
 {
        void *addr = NULL;
 
index a3c38c5a5db2dd69136491a29dfe04936b3fb694..f1c7392255f869693740a9a2cd5ff4ab353f0759 100644 (file)
@@ -78,7 +78,7 @@ typedef struct {
     const char *name2;
     void (*open)(void);
     void (*release)(void);
-    void *(*dma_alloc)(unsigned int, int);
+    void *(*dma_alloc)(unsigned int, gfp_t);
     void (*dma_free)(void *, unsigned int);
     int (*irqinit)(void);
 #ifdef MODULE
index 2ca9ec7ec3a7b4d161be57bf48f5dd3d76c18773..532caa388dc258b9a90407d96a0a978c71854f9b 100644 (file)
@@ -318,7 +318,7 @@ struct cs_sound_settings {
 
 static struct cs_sound_settings sound;
 
-static void *CS_Alloc(unsigned int size, int flags);
+static void *CS_Alloc(unsigned int size, gfp_t flags);
 static void CS_Free(void *ptr, unsigned int size);
 static int CS_IrqInit(void);
 #ifdef MODULE
@@ -959,7 +959,7 @@ static TRANS transCSNormalRead = {
 
 /*** Low level stuff *********************************************************/
 
-static void *CS_Alloc(unsigned int size, int flags)
+static void *CS_Alloc(unsigned int size, gfp_t flags)
 {
        int     order;
 
index 8edee806dae720f616c4d7fb7519c68225103fc7..0f710d2baec60923e0eb84daef8b5a00da5f2510 100644 (file)
@@ -115,7 +115,7 @@ static struct vm_region consistent_head = {
 };
 
 static struct vm_region *
-vm_region_alloc(struct vm_region *head, size_t size, int gfp)
+vm_region_alloc(struct vm_region *head, size_t size, gfp_t gfp)
 {
        unsigned long addr = head->vm_start, end = head->vm_end - size;
        unsigned long flags;
@@ -173,7 +173,7 @@ static struct vm_region *vm_region_find(struct vm_region *head, unsigned long ad
  * virtual and bus address for that space.
  */
 void *
-__dma_alloc_coherent(size_t size, dma_addr_t *handle, int gfp)
+__dma_alloc_coherent(size_t size, dma_addr_t *handle, gfp_t gfp)
 {
        struct page *page;
        struct vm_region *c;
index 81a3d7446d3718576505f4cd847c75c644bd33e2..43505b1fc5d88bf95f3afaab02c89ac815bb3150 100644 (file)
@@ -114,9 +114,9 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
        struct page *ptepage;
 
 #ifdef CONFIG_HIGHPTE
-       int flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_REPEAT;
+       gfp_t flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_REPEAT;
 #else
-       int flags = GFP_KERNEL | __GFP_REPEAT;
+       gfp_t flags = GFP_KERNEL | __GFP_REPEAT;
 #endif
 
        ptepage = alloc_pages(flags, 0);
index 1efc18e786d51145db81e383cd0af96b0186762e..610740512d56aeb9c967ba24dea4273ae807288c 100644 (file)
@@ -23,7 +23,7 @@ extern void init_rts7751r2d_IRQ(void);
 extern void *rts7751r2d_ioremap(unsigned long, unsigned long);
 extern int rts7751r2d_irq_demux(int irq);
 
-extern void *voyagergx_consistent_alloc(struct device *, size_t, dma_addr_t *, int);
+extern void *voyagergx_consistent_alloc(struct device *, size_t, dma_addr_t *, gfp_t);
 extern int voyagergx_consistent_free(struct device *, size_t, void *, dma_addr_t);
 
 /*
index 5b92585a38d2b3512889557b9cb18e30f78921bc..3d9a02c093a39d948d0e43ff7b0e7da17199357e 100644 (file)
@@ -31,7 +31,7 @@ static LIST_HEAD(voya_alloc_list);
 #define OHCI_SRAM_SIZE 0x10000
 
 void *voyagergx_consistent_alloc(struct device *dev, size_t size,
-                                dma_addr_t *handle, int flag)
+                                dma_addr_t *handle, gfp_t flag)
 {
        struct list_head *list = &voya_alloc_list;
        struct voya_alloc_entry *entry;
index 83de7ef4e7df6722d6f04468e0007b773599042b..e12418bb1fa5ee3f753ee284a3a8cd6410ca4039 100644 (file)
@@ -33,7 +33,7 @@
 static int gapspci_dma_used = 0;
 
 void *dreamcast_consistent_alloc(struct device *dev, size_t size,
-                                dma_addr_t *dma_handle, int flag)
+                                dma_addr_t *dma_handle, gfp_t flag)
 {
        unsigned long buf;
 
index 1f7af0c73cf454820e9575c46ea037e2314d0368..df3a9e452cc55321c238143b05190557401bb867 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/dma-mapping.h>
 #include <asm/io.h>
 
-void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle)
+void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle)
 {
        struct page *page, *end, *free;
        void *ret;
index d7c1c76582cc3698d3f2b028103166a3f8c31266..fc6669e8dde189640a053c40f629e63720795d9c 100644 (file)
@@ -49,7 +49,7 @@ IPPROTO_EGP, IPPROTO_PUP, IPPROTO_UDP, IPPROTO_IDP, IPPROTO_RAW,
 
 #else
 
-extern void * mykmalloc(size_t s, int gfp);
+extern void * mykmalloc(size_t s, gfp_t gfp);
 extern void mykfree(void *);
 
 #endif
index aaad29c35c83870a4a65cc710e8535765c27279d..b84e5456b0250b2f17dfd3fe8b78578348177dc8 100644 (file)
@@ -39,7 +39,7 @@ static char * page = NULL ;
 
 #else
 
-void * mykmalloc(size_t s, int gfp)
+void * mykmalloc(size_t s, gfp_t gfp)
 {
        static char * page;
        static size_t free;
index ea008b031a8f50203fa928bb88b40198322fe76e..462cc9d65386a60bcfc57969158c0fc1263f85c8 100644 (file)
@@ -252,7 +252,7 @@ void paging_init(void)
 #endif
 }
 
-struct page *arch_validate(struct page *page, int mask, int order)
+struct page *arch_validate(struct page *page, gfp_t mask, int order)
 {
        unsigned long addr, zero = 0;
        int i;
index ea65db679e9cc59d11a1985a0c935deebdf06fd1..0d73ceeece72cdc34c88e58ca0966d74b84d18a9 100644 (file)
@@ -80,7 +80,7 @@ void free_stack(unsigned long stack, int order)
 unsigned long alloc_stack(int order, int atomic)
 {
        unsigned long page;
-       int flags = GFP_KERNEL;
+       gfp_t flags = GFP_KERNEL;
 
        if (atomic)
                flags = GFP_ATOMIC;
index cf0a0315d586a15bc17dcd2de072956a00dc0d2e..88be97c96987ad17edc63673b1134ffa4864b896 100644 (file)
@@ -187,7 +187,7 @@ static void flush_gart(struct device *dev)
 
 /* Allocate DMA memory on node near device */
 noinline
-static void *dma_alloc_pages(struct device *dev, unsigned gfp, unsigned order)
+static void *dma_alloc_pages(struct device *dev, gfp_t gfp, unsigned order)
 {
        struct page *page;
        int node;
@@ -204,7 +204,7 @@ static void *dma_alloc_pages(struct device *dev, unsigned gfp, unsigned order)
  */
 void *
 dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
-                  unsigned gfp)
+                  gfp_t gfp)
 {
        void *memory;
        unsigned long dma_mask = 0;
index 67d90b89af0b0836a2c83364c4ecd9c72caa2710..5a981dca87ffb1c6f9abb2bec204d35b7f6903e2 100644 (file)
@@ -24,7 +24,7 @@ EXPORT_SYMBOL(iommu_sac_force);
  */
 
 void *dma_alloc_coherent(struct device *hwdev, size_t size,
-                        dma_addr_t *dma_handle, unsigned gfp)
+                        dma_addr_t *dma_handle, gfp_t gfp)
 {
        void *ret;
        u64 mask;
index 84fde258cf855393b6d5531f50b435fab767b8c0..1ff82268e8eacf354e5f16eae1a9ea182d3ca191 100644 (file)
@@ -29,7 +29,7 @@
  */
 
 void *
-dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, int gfp)
+dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
 {
        void *ret;
 
index 95c0a3690b0ffc15618acb6dfcae29f81234d846..1f08e14697e9965bcd25c33f17a7977257ed09e0 100644 (file)
@@ -1807,7 +1807,7 @@ static void as_put_request(request_queue_t *q, struct request *rq)
 }
 
 static int as_set_request(request_queue_t *q, struct request *rq,
-                         struct bio *bio, int gfp_mask)
+                         struct bio *bio, gfp_t gfp_mask)
 {
        struct as_data *ad = q->elevator->elevator_data;
        struct as_rq *arq = mempool_alloc(ad->arq_pool, gfp_mask);
index cd056e7e64ec15d5cf81f16068623e29e07ad187..d3bfe8cfb0397023fcee75237b3350f0eba0a705 100644 (file)
@@ -1422,7 +1422,7 @@ static void cfq_exit_io_context(struct cfq_io_context *cic)
 }
 
 static struct cfq_io_context *
-cfq_alloc_io_context(struct cfq_data *cfqd, int gfp_mask)
+cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
 {
        struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_mask);
 
@@ -1517,7 +1517,7 @@ static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio)
 
 static struct cfq_queue *
 cfq_get_queue(struct cfq_data *cfqd, unsigned int key, unsigned short ioprio,
-             int gfp_mask)
+             gfp_t gfp_mask)
 {
        const int hashval = hash_long(key, CFQ_QHASH_SHIFT);
        struct cfq_queue *cfqq, *new_cfqq = NULL;
@@ -1578,7 +1578,7 @@ out:
  * cfqq, so we don't need to worry about it disappearing
  */
 static struct cfq_io_context *
-cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, int gfp_mask)
+cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
 {
        struct io_context *ioc = NULL;
        struct cfq_io_context *cic;
@@ -2075,7 +2075,7 @@ static void cfq_put_request(request_queue_t *q, struct request *rq)
  */
 static int
 cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
-               int gfp_mask)
+               gfp_t gfp_mask)
 {
        struct cfq_data *cfqd = q->elevator->elevator_data;
        struct task_struct *tsk = current;
index 52a3ae5289a09a7af79081df5de2ec7e4c40ff26..753546ba2262f07328e1d4935c2e7536e6dc20fc 100644 (file)
@@ -756,7 +756,7 @@ static void deadline_put_request(request_queue_t *q, struct request *rq)
 
 static int
 deadline_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
-                    int gfp_mask)
+                    gfp_t gfp_mask)
 {
        struct deadline_data *dd = q->elevator->elevator_data;
        struct deadline_rq *drq;
index 4144f30d82a97aeb6de21d1a87ba463e20e18c1f..4f69d222b183fed2b3f145c98cf2e11498ea8196 100644 (file)
@@ -492,7 +492,7 @@ struct request *elv_former_request(request_queue_t *q, struct request *rq)
 }
 
 int elv_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
-                   int gfp_mask)
+                   gfp_t gfp_mask)
 {
        elevator_t *e = q->elevator;
 
index 4e2b1b06b411d12accfad7ae28ef00cc28dbe95b..ac31ea1700580753b6ce1747ede9eb7c6c632214 100644 (file)
@@ -1652,13 +1652,13 @@ static int blk_init_free_list(request_queue_t *q)
 
 static int __make_request(request_queue_t *, struct bio *);
 
-request_queue_t *blk_alloc_queue(int gfp_mask)
+request_queue_t *blk_alloc_queue(gfp_t gfp_mask)
 {
        return blk_alloc_queue_node(gfp_mask, -1);
 }
 EXPORT_SYMBOL(blk_alloc_queue);
 
-request_queue_t *blk_alloc_queue_node(int gfp_mask, int node_id)
+request_queue_t *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
 {
        request_queue_t *q;
 
@@ -1787,7 +1787,7 @@ static inline void blk_free_request(request_queue_t *q, struct request *rq)
 }
 
 static inline struct request *
-blk_alloc_request(request_queue_t *q, int rw, struct bio *bio, int gfp_mask)
+blk_alloc_request(request_queue_t *q, int rw, struct bio *bio, gfp_t gfp_mask)
 {
        struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask);
 
@@ -1885,7 +1885,7 @@ static void freed_request(request_queue_t *q, int rw)
  * Returns !NULL on success, with queue_lock *not held*.
  */
 static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
-                                  int gfp_mask)
+                                  gfp_t gfp_mask)
 {
        struct request *rq = NULL;
        struct request_list *rl = &q->rq;
@@ -2019,7 +2019,7 @@ static struct request *get_request_wait(request_queue_t *q, int rw,
        return rq;
 }
 
-struct request *blk_get_request(request_queue_t *q, int rw, int gfp_mask)
+struct request *blk_get_request(request_queue_t *q, int rw, gfp_t gfp_mask)
 {
        struct request *rq;
 
@@ -2251,7 +2251,7 @@ EXPORT_SYMBOL(blk_rq_unmap_user);
  * @gfp_mask:  memory allocation flags
  */
 int blk_rq_map_kern(request_queue_t *q, struct request *rq, void *kbuf,
-                   unsigned int len, unsigned int gfp_mask)
+                   unsigned int len, gfp_t gfp_mask)
 {
        struct bio *bio;
 
@@ -3395,7 +3395,7 @@ void exit_io_context(void)
  * but since the current task itself holds a reference, the context can be
  * used in general code, so long as it stays within `current` context.
  */
-struct io_context *current_io_context(int gfp_flags)
+struct io_context *current_io_context(gfp_t gfp_flags)
 {
        struct task_struct *tsk = current;
        struct io_context *ret;
@@ -3426,7 +3426,7 @@ EXPORT_SYMBOL(current_io_context);
  *
  * This is always called in the context of the task which submitted the I/O.
  */
-struct io_context *get_io_context(int gfp_flags)
+struct io_context *get_io_context(gfp_t gfp_flags)
 {
        struct io_context *ret;
        ret = current_io_context(gfp_flags);
index b35e08876dd4b77cb1b661571c204d51e610fcd9..96c664af8d069f9f5d96d77efea7b293f2549fe6 100644 (file)
@@ -881,7 +881,7 @@ loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer,
 static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
 {
        struct file *filp = lo->lo_backing_file;
-       int gfp = lo->old_gfp_mask;
+       gfp_t gfp = lo->old_gfp_mask;
 
        if (lo->lo_state != Lo_bound)
                return -ENXIO;
index 145c1fbffe0135648992806cf3166fd36fa89832..68c60a5bcdabaf4f172854bbd1df959ecbe80689 100644 (file)
@@ -348,7 +348,7 @@ static int rd_open(struct inode *inode, struct file *filp)
                struct block_device *bdev = inode->i_bdev;
                struct address_space *mapping;
                unsigned bsize;
-               int gfp_mask;
+               gfp_t gfp_mask;
 
                inode = igrab(bdev->bd_inode);
                rd_bdev[unit] = bdev;
index c9bdf544ed2cd1126f6d67840c082ee6bb53d42e..c556f4d3ccd7cda2122fa91098cce56491d3387d 100644 (file)
@@ -62,7 +62,7 @@
 
 static inline unsigned char *alloc_buf(void)
 {
-       unsigned int prio = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
+       gfp_t prio = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
 
        if (PAGE_SIZE != N_TTY_BUF_SIZE)
                return kmalloc(N_TTY_BUF_SIZE, prio);
index 4802bbbb6dc9817c9b4f49b08bcad65268f8f84a..c9e92d85c8931e62516a642d74d3a3b016382bc4 100644 (file)
@@ -1630,7 +1630,7 @@ static void ether1394_complete_cb(void *__ptask)
 /* Transmit a packet (called by kernel) */
 static int ether1394_tx (struct sk_buff *skb, struct net_device *dev)
 {
-       int kmflags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
+       gfp_t kmflags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
        struct eth1394hdr *eth;
        struct eth1394_priv *priv = netdev_priv(dev);
        int proto;
index f6a8ac026557db5639d446bf1188cf9d73b22739..378646b5a1b8389339e31569dc3ee15b0e619bd4 100644 (file)
@@ -524,7 +524,7 @@ void mthca_cmd_use_polling(struct mthca_dev *dev)
 }
 
 struct mthca_mailbox *mthca_alloc_mailbox(struct mthca_dev *dev,
-                                         unsigned int gfp_mask)
+                                         gfp_t gfp_mask)
 {
        struct mthca_mailbox *mailbox;
 
index 65f976a13e02065469c99001d41d2a09201853e7..18175bec84c27619a69839f1b3e84c527c03a9aa 100644 (file)
@@ -248,7 +248,7 @@ void mthca_cmd_event(struct mthca_dev *dev, u16 token,
                     u8  status, u64 out_param);
 
 struct mthca_mailbox *mthca_alloc_mailbox(struct mthca_dev *dev,
-                                         unsigned int gfp_mask);
+                                         gfp_t gfp_mask);
 void mthca_free_mailbox(struct mthca_dev *dev, struct mthca_mailbox *mailbox);
 
 int mthca_SYS_EN(struct mthca_dev *dev, u8 *status);
index 7bd7a4bec7b433f2e533602681a75d7e06553940..9ad8b3b6cfef9e9a5a01615dd07507a15bdbed0c 100644 (file)
@@ -82,7 +82,7 @@ void mthca_free_icm(struct mthca_dev *dev, struct mthca_icm *icm)
 }
 
 struct mthca_icm *mthca_alloc_icm(struct mthca_dev *dev, int npages,
-                                 unsigned int gfp_mask)
+                                 gfp_t gfp_mask)
 {
        struct mthca_icm *icm;
        struct mthca_icm_chunk *chunk = NULL;
index bafa51544aa39db8db19cf2626361550fec7ea89..29433f295253afc530169a10cbe4c7e5f96a66b3 100644 (file)
@@ -77,7 +77,7 @@ struct mthca_icm_iter {
 struct mthca_dev;
 
 struct mthca_icm *mthca_alloc_icm(struct mthca_dev *dev, int npages,
-                                 unsigned int gfp_mask);
+                                 gfp_t gfp_mask);
 void mthca_free_icm(struct mthca_dev *dev, struct mthca_icm *icm);
 
 struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
index 2fba2bbe72d8f627136d5983b40c421c55220f6d..01654fcabc52128ce866728b24ddaa73c1437a1f 100644 (file)
@@ -91,7 +91,7 @@ int bitmap_active(struct bitmap *bitmap)
 
 #define WRITE_POOL_SIZE 256
 /* mempool for queueing pending writes on the bitmap file */
-static void *write_pool_alloc(unsigned int gfp_flags, void *data)
+static void *write_pool_alloc(gfp_t gfp_flags, void *data)
 {
        return kmalloc(sizeof(struct page_list), gfp_flags);
 }
index b6148f6f78367230accacaf0770b74a5b0bc30df..28c1a628621fa21a7c37f1a9534ee090e834621c 100644 (file)
@@ -331,7 +331,7 @@ crypt_alloc_buffer(struct crypt_config *cc, unsigned int size,
 {
        struct bio *bio;
        unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
-       int gfp_mask = GFP_NOIO | __GFP_HIGHMEM;
+       gfp_t gfp_mask = GFP_NOIO | __GFP_HIGHMEM;
        unsigned int i;
 
        /*
index 2e617424d3fbf631237d29b592a5c811e26976b3..50f43dbf31aed4c8313e72c3ef08729407be1a95 100644 (file)
@@ -489,7 +489,7 @@ static int cas_page_free(struct cas *cp, cas_page_t *page)
 /* local page allocation routines for the receive buffers. jumbo pages
  * require at least 8K contiguous and 8K aligned buffers.
  */
-static cas_page_t *cas_page_alloc(struct cas *cp, const int flags)
+static cas_page_t *cas_page_alloc(struct cas *cp, const gfp_t flags)
 {
        cas_page_t *page;
 
@@ -561,7 +561,7 @@ static void cas_spare_free(struct cas *cp)
 }
 
 /* replenish spares if needed */
-static void cas_spare_recover(struct cas *cp, const int flags)
+static void cas_spare_recover(struct cas *cp, const gfp_t flags)
 {
        struct list_head list, *elem, *tmp;
        int needed, i;
index b4929beb33b2359d29a37fc16e4535590c1098e9..1d75ca0bb939429587b354ff6cd8e3f4463b247c 100644 (file)
@@ -298,7 +298,7 @@ enum {OLD_LANCE = 0, PCNET_ISA=1, PCNET_ISAP=2, PCNET_PCI=3, PCNET_VLB=4, PCNET_
 static unsigned char lance_need_isa_bounce_buffers = 1;
 
 static int lance_open(struct net_device *dev);
-static void lance_init_ring(struct net_device *dev, int mode);
+static void lance_init_ring(struct net_device *dev, gfp_t mode);
 static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static int lance_rx(struct net_device *dev);
 static irqreturn_t lance_interrupt(int irq, void *dev_id, struct pt_regs *regs);
@@ -846,7 +846,7 @@ lance_purge_ring(struct net_device *dev)
 
 /* Initialize the LANCE Rx and Tx rings. */
 static void
-lance_init_ring(struct net_device *dev, int gfp)
+lance_init_ring(struct net_device *dev, gfp_t gfp)
 {
        struct lance_private *lp = dev->priv;
        int i;
index f0996ce5c268698b060a784fbe1ab0661817b577..6c86dca62e2a565b6d611178d3894ee7120d9874 100644 (file)
@@ -277,7 +277,7 @@ static void myri_init_rings(struct myri_eth *mp, int from_irq)
        struct recvq __iomem *rq = mp->rq;
        struct myri_rxd __iomem *rxd = &rq->myri_rxd[0];
        struct net_device *dev = mp->dev;
-       int gfp_flags = GFP_KERNEL;
+       gfp_t gfp_flags = GFP_KERNEL;
        int i;
 
        if (from_irq || in_interrupt())
index 9391e55a5e92488d247ae41875e8bf065a7bd93b..47722f708a41822da4da40fc88f0e4752235fd5c 100644 (file)
@@ -296,7 +296,7 @@ struct myri_eth {
 /* We use this to acquire receive skb's that we can DMA directly into. */
 #define ALIGNED_RX_SKB_ADDR(addr) \
         ((((unsigned long)(addr) + (64 - 1)) & ~(64 - 1)) - (unsigned long)(addr))
-static inline struct sk_buff *myri_alloc_skb(unsigned int length, int gfp_flags)
+static inline struct sk_buff *myri_alloc_skb(unsigned int length, gfp_t gfp_flags)
 {
        struct sk_buff *skb;
 
index f88f5e32b7145164f916a58e2d23efe3d20fca76..cfaf47c63c58dd1fbeb6c3c5f59290fa49fad804 100644 (file)
@@ -214,7 +214,8 @@ static void bigmac_init_rings(struct bigmac *bp, int from_irq)
 {
        struct bmac_init_block *bb = bp->bmac_block;
        struct net_device *dev = bp->dev;
-       int i, gfp_flags = GFP_KERNEL;
+       int i;
+       gfp_t gfp_flags = GFP_KERNEL;
 
        if (from_irq || in_interrupt())
                gfp_flags = GFP_ATOMIC;
index 5674003fc38aa70b73e4b7937ec811e3c0515851..b0dbc5187143690b4fcab25070bd3703fca142dd 100644 (file)
@@ -339,7 +339,7 @@ struct bigmac {
 #define ALIGNED_RX_SKB_ADDR(addr) \
         ((((unsigned long)(addr) + (64 - 1)) & ~(64 - 1)) - (unsigned long)(addr))
 
-static inline struct sk_buff *big_mac_alloc_skb(unsigned int length, int gfp_flags)
+static inline struct sk_buff *big_mac_alloc_skb(unsigned int length, gfp_t gfp_flags)
 {
        struct sk_buff *skb;
 
index 0e98a9d9834cb5f7c32a0a4317b1fdedc98d6e7b..a3bd91a618274672e31b30ff7913772ae34187f9 100644 (file)
@@ -836,7 +836,7 @@ ccio_unmap_single(struct device *dev, dma_addr_t iova, size_t size,
  * This function implements the pci_alloc_consistent function.
  */
 static void * 
-ccio_alloc_consistent(struct device *dev, size_t size, dma_addr_t *dma_handle, int flag)
+ccio_alloc_consistent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag)
 {
       void *ret;
 #if 0
index 82ea68b55df4f435a35ed1d69f12d7a62f14c132..bd8b3e5a5cd76ebf79e6056fc852555f8ee6f03a 100644 (file)
@@ -986,7 +986,7 @@ sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size,
  * See Documentation/DMA-mapping.txt
  */
 static void *sba_alloc_consistent(struct device *hwdev, size_t size,
-                                       dma_addr_t *dma_handle, int gfp)
+                                       dma_addr_t *dma_handle, gfp_t gfp)
 {
        void *ret;
 
index fa09440d82e549e59f0700ca09da9fed7fb31543..38f50b7129a24fce668493909b15d385de086db3 100644 (file)
@@ -16,7 +16,7 @@ MODULE_LICENSE("GPL");
 
 fsm_instance *
 init_fsm(char *name, const char **state_names, const char **event_names, int nr_states,
-               int nr_events, const fsm_node *tmpl, int tmpl_len, int order)
+               int nr_events, const fsm_node *tmpl, int tmpl_len, gfp_t order)
 {
        int i;
        fsm_instance *this;
index f9a011001eb693fe90f8b816fe23e3690b10db1e..1b8a7e7c34f3cd9f9d95857b335999eced5ddf3f 100644 (file)
@@ -110,7 +110,7 @@ extern fsm_instance *
 init_fsm(char *name, const char **state_names,
         const char **event_names,
         int nr_states, int nr_events, const fsm_node *tmpl,
-        int tmpl_len, int order);
+        int tmpl_len, gfp_t order);
 
 /**
  * Releases an FSM
index c10e45b94b6269bd8d70bfdecf6519ffe4fff9c1..3d13fdee4fc26e2f53f237e316853691770d3189 100644 (file)
@@ -1357,7 +1357,7 @@ static int port_detect(unsigned long port_base, unsigned int j,
 
        for (i = 0; i < shost->can_queue; i++) {
                size_t sz = shost->sg_tablesize *sizeof(struct sg_list);
-               unsigned int gfp_mask = (shost->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC;
+               gfp_t gfp_mask = (shost->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC;
                ha->cp[i].sglist = kmalloc(sz, gfp_mask);
                if (!ha->cp[i].sglist) {
                        printk
index 02fe371b0ab87142b718e2d707bf365427f08ea9..f24d84538fd56ab5c1d2cdd8df3c509fac8e5092 100644 (file)
@@ -287,7 +287,8 @@ static void scsi_host_dev_release(struct device *dev)
 struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
 {
        struct Scsi_Host *shost;
-       int gfp_mask = GFP_KERNEL, rval;
+       gfp_t gfp_mask = GFP_KERNEL;
+       int rval;
 
        if (sht->unchecked_isa_dma && privsize)
                gfp_mask |= __GFP_DMA;
index 0aba13ceaacfe9c2d6d976c882981df19aeb59bb..352df47bcaca1026d7090e3cd5d1b4d305ca3eb5 100644 (file)
@@ -39,7 +39,7 @@
 #define LPFC_MEM_POOL_SIZE      64      /* max elem in non-DMA safety pool */
 
 static void *
-lpfc_pool_kmalloc(unsigned int gfp_flags, void *data)
+lpfc_pool_kmalloc(gfp_t gfp_flags, void *data)
 {
        return kmalloc((unsigned long)data, gfp_flags);
 }
index 3f2f2464fa6351ebbe8938c594e3f3cce3dec9c1..af1133104b3f95ef17986e41fde352761b6fcb9a 100644 (file)
@@ -5146,7 +5146,8 @@ static long osst_compat_ioctl(struct file * file, unsigned int cmd_in, unsigned
 /* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
 static struct osst_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
 {
-       int i, priority;
+       int i;
+       gfp_t priority;
        struct osst_buffer *tb;
 
        if (from_initialization)
@@ -5178,7 +5179,8 @@ static struct osst_buffer * new_tape_buffer( int from_initialization, int need_d
 /* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
 static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma)
 {
-       int segs, nbr, max_segs, b_size, priority, order, got;
+       int segs, nbr, max_segs, b_size, order, got;
+       gfp_t priority;
 
        if (STbuffer->buffer_size >= OS_FRAME_SIZE)
                return 1;
index 1ed32e7b5472091ef7324e154dfdcf32464f0ae8..e451941ad81d11ce3ce7a601cf07a916cf1bf22f 100644 (file)
@@ -52,7 +52,7 @@ extern int qla2x00_load_risc(struct scsi_qla_host *, uint32_t *);
 extern int qla24xx_load_risc_flash(scsi_qla_host_t *, uint32_t *);
 extern int qla24xx_load_risc_hotplug(scsi_qla_host_t *, uint32_t *);
 
-extern fc_port_t *qla2x00_alloc_fcport(scsi_qla_host_t *, int);
+extern fc_port_t *qla2x00_alloc_fcport(scsi_qla_host_t *, gfp_t);
 
 extern int qla2x00_loop_resync(scsi_qla_host_t *);
 
@@ -277,7 +277,7 @@ extern int qla2x00_fdmi_register(scsi_qla_host_t *);
 /*
  * Global Function Prototypes in qla_rscn.c source file.
  */
-extern fc_port_t *qla2x00_alloc_rscn_fcport(scsi_qla_host_t *, int);
+extern fc_port_t *qla2x00_alloc_rscn_fcport(scsi_qla_host_t *, gfp_t);
 extern int qla2x00_handle_port_rscn(scsi_qla_host_t *, uint32_t, fc_port_t *,
     int);
 extern void qla2x00_process_iodesc(scsi_qla_host_t *, struct mbx_entry *);
index 23d095d3817b8cb8b35d431564083f1a03da9b71..fbb6feee40cfeb1921ead1abd59a1a970b57a9a7 100644 (file)
@@ -1685,7 +1685,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
  * Returns a pointer to the allocated fcport, or NULL, if none available.
  */
 fc_port_t *
-qla2x00_alloc_fcport(scsi_qla_host_t *ha, int flags)
+qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags)
 {
        fc_port_t *fcport;
 
index 1eba988286360efd49a696eb80613e5310953663..7534efcc891860e7598cdffb28389b48bf16e312 100644 (file)
@@ -1066,7 +1066,7 @@ qla2x00_send_login_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
  * Returns a pointer to the allocated RSCN fcport, or NULL, if none available.
  */
 fc_port_t *
-qla2x00_alloc_rscn_fcport(scsi_qla_host_t *ha, int flags)
+qla2x00_alloc_rscn_fcport(scsi_qla_host_t *ha, gfp_t flags)
 {
        fc_port_t *fcport;
 
index 1f0ebabf6d47663ffd0f9e6e62fc4b7eff21c422..a5711d545d713501a60d57bfa7296007cf3dda3e 100644 (file)
@@ -130,7 +130,7 @@ EXPORT_SYMBOL(scsi_device_types);
  * Returns:     Pointer to request block.
  */
 struct scsi_request *scsi_allocate_request(struct scsi_device *sdev,
-                                          int gfp_mask)
+                                          gfp_t gfp_mask)
 {
        const int offset = ALIGN(sizeof(struct scsi_request), 4);
        const int size = offset + sizeof(struct request);
@@ -196,7 +196,7 @@ struct scsi_host_cmd_pool {
        unsigned int    users;
        char            *name;
        unsigned int    slab_flags;
-       unsigned int    gfp_mask;
+       gfp_t           gfp_mask;
 };
 
 static struct scsi_host_cmd_pool scsi_cmd_pool = {
@@ -213,7 +213,7 @@ static struct scsi_host_cmd_pool scsi_cmd_dma_pool = {
 static DECLARE_MUTEX(host_cmd_pool_mutex);
 
 static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost,
-                                           int gfp_mask)
+                                           gfp_t gfp_mask)
 {
        struct scsi_cmnd *cmd;
 
@@ -245,7 +245,7 @@ static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost,
  *
  * Returns:    The allocated scsi command structure.
  */
-struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, int gfp_mask)
+struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, gfp_t gfp_mask)
 {
        struct scsi_cmnd *cmd;
 
index de7f98cc38feb020863323b06e4fd6d2e4f426a9..6a3f6aae8a976c8ef1011dafc6bd5c8806952109 100644 (file)
@@ -205,7 +205,8 @@ int scsi_ioctl_send_command(struct scsi_device *sdev,
        unsigned int inlen, outlen, cmdlen;
        unsigned int needed, buf_needed;
        int timeout, retries, result;
-       int data_direction, gfp_mask = GFP_KERNEL;
+       int data_direction;
+       gfp_t gfp_mask = GFP_KERNEL;
 
        if (!sic)
                return -EINVAL;
index 0074f28c37b2719e49388a0da93f6a9a87505a82..3ff538809786fb5647c0e8f2f6e74339aca0106d 100644 (file)
@@ -677,7 +677,7 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate,
        return NULL;
 }
 
-static struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, int gfp_mask)
+static struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask)
 {
        struct scsi_host_sg_pool *sgp;
        struct scatterlist *sgl;
index ad94367df430a8d8df9d9b62109fc2bf545b7af9..fd56b7ec88b656e645a2af4551be76873d746531 100644 (file)
@@ -2644,7 +2644,7 @@ static char *
 sg_page_malloc(int rqSz, int lowDma, int *retSzp)
 {
        char *resp = NULL;
-       int page_mask;
+       gfp_t page_mask;
        int order, a_size;
        int resSz = rqSz;
 
index d001c046551bcab0663ffa151bd83a382b6406dc..927d700f00736af5a0249cc8f17ee7bff6b90179 100644 (file)
@@ -3577,7 +3577,8 @@ static long st_compat_ioctl(struct file *file, unsigned int cmd, unsigned long a
 static struct st_buffer *
  new_tape_buffer(int from_initialization, int need_dma, int max_sg)
 {
-       int i, priority, got = 0, segs = 0;
+       int i, got = 0, segs = 0;
+       gfp_t priority;
        struct st_buffer *tb;
 
        if (from_initialization)
@@ -3610,7 +3611,8 @@ static struct st_buffer *
 /* Try to allocate enough space in the tape buffer */
 static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dma)
 {
-       int segs, nbr, max_segs, b_size, priority, order, got;
+       int segs, nbr, max_segs, b_size, order, got;
+       gfp_t priority;
 
        if (new_size <= STbuffer->buffer_size)
                return 1;
index fc15b4acc8af33e8c70f8275de29af69e1b59e0b..57e800ac3cee80890eed1871dff6d7093e699bc9 100644 (file)
@@ -106,7 +106,7 @@ void hcd_buffer_destroy (struct usb_hcd *hcd)
 void *hcd_buffer_alloc (
        struct usb_bus          *bus,
        size_t                  size,
-       unsigned                mem_flags,
+       gfp_t                   mem_flags,
        dma_addr_t              *dma
 )
 {
index 1017a97a418b110e7e5d6a55b56727d2bf17e79f..ff19d64041b548baddc360f67fe6dcb921eed4ea 100644 (file)
@@ -1112,7 +1112,7 @@ static void urb_unlink (struct urb *urb)
  * expects usb_submit_urb() to have sanity checked and conditioned all
  * inputs in the urb
  */
-static int hcd_submit_urb (struct urb *urb, unsigned mem_flags)
+static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
 {
        int                     status;
        struct usb_hcd          *hcd = urb->dev->bus->hcpriv;
index ac451fa7e4d273787e814c08f5092c6fc1feab37..1f1ed6211af8a6aa17f13508b6d126130df844b4 100644 (file)
@@ -142,12 +142,12 @@ struct hcd_timeout {      /* timeouts we allocate */
 
 struct usb_operations {
        int (*get_frame_number) (struct usb_device *usb_dev);
-       int (*submit_urb) (struct urb *urb, unsigned mem_flags);
+       int (*submit_urb) (struct urb *urb, gfp_t mem_flags);
        int (*unlink_urb) (struct urb *urb, int status);
 
        /* allocate dma-consistent buffer for URB_DMA_NOMAPPING */
        void *(*buffer_alloc)(struct usb_bus *bus, size_t size,
-                       unsigned mem_flags,
+                       gfp_t mem_flags,
                        dma_addr_t *dma);
        void (*buffer_free)(struct usb_bus *bus, size_t size,
                        void *addr, dma_addr_t dma);
@@ -200,7 +200,7 @@ struct hc_driver {
        int     (*urb_enqueue) (struct usb_hcd *hcd,
                                        struct usb_host_endpoint *ep,
                                        struct urb *urb,
-                                       unsigned mem_flags);
+                                       gfp_t mem_flags);
        int     (*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb);
 
        /* hw synch, freeing endpoint resources that urb_dequeue can't */
@@ -247,7 +247,7 @@ int hcd_buffer_create (struct usb_hcd *hcd);
 void hcd_buffer_destroy (struct usb_hcd *hcd);
 
 void *hcd_buffer_alloc (struct usb_bus *bus, size_t size,
-       unsigned mem_flags, dma_addr_t *dma);
+       gfp_t mem_flags, dma_addr_t *dma);
 void hcd_buffer_free (struct usb_bus *bus, size_t size,
        void *addr, dma_addr_t dma);
 
index f1fb67fe22a82806533a4875801fd14a7f180833..f9a81e84dbdf642d85d24f917192d393432d1765 100644 (file)
@@ -321,7 +321,7 @@ int usb_sg_init (
        struct scatterlist      *sg,
        int                     nents,
        size_t                  length,
-       unsigned                mem_flags
+       gfp_t                   mem_flags
 )
 {
        int                     i;
index c846fefb73862049fa7960dce85c7a4c96780b05..b32898e0a27d1da41c256f346347275d495b268e 100644 (file)
@@ -60,7 +60,7 @@ void usb_init_urb(struct urb *urb)
  *
  * The driver must call usb_free_urb() when it is finished with the urb.
  */
-struct urb *usb_alloc_urb(int iso_packets, unsigned mem_flags)
+struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)
 {
        struct urb *urb;
 
@@ -224,7 +224,7 @@ struct urb * usb_get_urb(struct urb *urb)
  *      GFP_NOIO, unless b) or c) apply
  *
  */
-int usb_submit_urb(struct urb *urb, unsigned mem_flags)
+int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 {
        int                     pipe, temp, max;
        struct usb_device       *dev;
index 7d131509e41909a0aa92bac2665cf1acbccb2d1b..4c57f3f649ede7894e1df8c7591440601f6ed867 100644 (file)
@@ -1147,7 +1147,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
 void *usb_buffer_alloc (
        struct usb_device *dev,
        size_t size,
-       unsigned mem_flags,
+       gfp_t mem_flags,
        dma_addr_t *dma
 )
 {
index 583db7c38cf192e7751eeacea3f8994ad8677803..8d9d8ee8955428a4dcd6ded1a666ed05a382aca2 100644 (file)
@@ -470,7 +470,7 @@ static int dummy_disable (struct usb_ep *_ep)
 }
 
 static struct usb_request *
-dummy_alloc_request (struct usb_ep *_ep, unsigned mem_flags)
+dummy_alloc_request (struct usb_ep *_ep, gfp_t mem_flags)
 {
        struct dummy_ep         *ep;
        struct dummy_request    *req;
@@ -507,7 +507,7 @@ dummy_alloc_buffer (
        struct usb_ep *_ep,
        unsigned bytes,
        dma_addr_t *dma,
-       unsigned mem_flags
+       gfp_t mem_flags
 ) {
        char                    *retval;
        struct dummy_ep         *ep;
@@ -541,7 +541,7 @@ fifo_complete (struct usb_ep *ep, struct usb_request *req)
 
 static int
 dummy_queue (struct usb_ep *_ep, struct usb_request *_req,
-               unsigned mem_flags)
+               gfp_t mem_flags)
 {
        struct dummy_ep         *ep;
        struct dummy_request    *req;
@@ -999,7 +999,7 @@ static int dummy_urb_enqueue (
        struct usb_hcd                  *hcd,
        struct usb_host_endpoint        *ep,
        struct urb                      *urb,
-       unsigned                        mem_flags
+       gfp_t                           mem_flags
 ) {
        struct dummy    *dum;
        struct urbp     *urbp;
index 49459e33e952a654b4a58ffff03f3a52851f3346..f1024e804d5c4ae359c869c71122f0602b94105d 100644 (file)
@@ -945,11 +945,11 @@ config_buf (enum usb_device_speed speed,
 
 /*-------------------------------------------------------------------------*/
 
-static void eth_start (struct eth_dev *dev, unsigned gfp_flags);
-static int alloc_requests (struct eth_dev *dev, unsigned n, unsigned gfp_flags);
+static void eth_start (struct eth_dev *dev, gfp_t gfp_flags);
+static int alloc_requests (struct eth_dev *dev, unsigned n, gfp_t gfp_flags);
 
 static int
-set_ether_config (struct eth_dev *dev, unsigned gfp_flags)
+set_ether_config (struct eth_dev *dev, gfp_t gfp_flags)
 {
        int                                     result = 0;
        struct usb_gadget                       *gadget = dev->gadget;
@@ -1081,7 +1081,7 @@ static void eth_reset_config (struct eth_dev *dev)
  * that returns config descriptors, and altsetting code.
  */
 static int
-eth_set_config (struct eth_dev *dev, unsigned number, unsigned gfp_flags)
+eth_set_config (struct eth_dev *dev, unsigned number, gfp_t gfp_flags)
 {
        int                     result = 0;
        struct usb_gadget       *gadget = dev->gadget;
@@ -1598,7 +1598,7 @@ static void defer_kevent (struct eth_dev *dev, int flag)
 static void rx_complete (struct usb_ep *ep, struct usb_request *req);
 
 static int
-rx_submit (struct eth_dev *dev, struct usb_request *req, unsigned gfp_flags)
+rx_submit (struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
 {
        struct sk_buff          *skb;
        int                     retval = -ENOMEM;
@@ -1724,7 +1724,7 @@ clean:
 }
 
 static int prealloc (struct list_head *list, struct usb_ep *ep,
-                       unsigned n, unsigned gfp_flags)
+                       unsigned n, gfp_t gfp_flags)
 {
        unsigned                i;
        struct usb_request      *req;
@@ -1763,7 +1763,7 @@ extra:
        return 0;
 }
 
-static int alloc_requests (struct eth_dev *dev, unsigned n, unsigned gfp_flags)
+static int alloc_requests (struct eth_dev *dev, unsigned n, gfp_t gfp_flags)
 {
        int status;
 
@@ -1779,7 +1779,7 @@ fail:
        return status;
 }
 
-static void rx_fill (struct eth_dev *dev, unsigned gfp_flags)
+static void rx_fill (struct eth_dev *dev, gfp_t gfp_flags)
 {
        struct usb_request      *req;
        unsigned long           flags;
@@ -1962,7 +1962,7 @@ drop:
  * normally just one notification will be queued.
  */
 
-static struct usb_request *eth_req_alloc (struct usb_ep *, unsigned, unsigned);
+static struct usb_request *eth_req_alloc (struct usb_ep *, unsigned, gfp_t);
 static void eth_req_free (struct usb_ep *ep, struct usb_request *req);
 
 static void
@@ -2024,7 +2024,7 @@ static int rndis_control_ack (struct net_device *net)
 
 #endif /* RNDIS */
 
-static void eth_start (struct eth_dev *dev, unsigned gfp_flags)
+static void eth_start (struct eth_dev *dev, gfp_t gfp_flags)
 {
        DEBUG (dev, "%s\n", __FUNCTION__);
 
@@ -2092,7 +2092,7 @@ static int eth_stop (struct net_device *net)
 /*-------------------------------------------------------------------------*/
 
 static struct usb_request *
-eth_req_alloc (struct usb_ep *ep, unsigned size, unsigned gfp_flags)
+eth_req_alloc (struct usb_ep *ep, unsigned size, gfp_t gfp_flags)
 {
        struct usb_request      *req;
 
index eaab26f4ed3712688c28a67baea49f4368060355..b0f3cd63e3b9110ed8d3e73d10a2754b1917001f 100644 (file)
@@ -269,7 +269,7 @@ static int goku_ep_disable(struct usb_ep *_ep)
 /*-------------------------------------------------------------------------*/
 
 static struct usb_request *
-goku_alloc_request(struct usb_ep *_ep, unsigned gfp_flags)
+goku_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
 {
        struct goku_request     *req;
 
@@ -327,7 +327,7 @@ goku_free_request(struct usb_ep *_ep, struct usb_request *_req)
  */
 static void *
 goku_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
-                       dma_addr_t *dma, unsigned gfp_flags)
+                       dma_addr_t *dma, gfp_t gfp_flags)
 {
        void            *retval;
        struct goku_ep  *ep;
@@ -789,7 +789,7 @@ finished:
 /*-------------------------------------------------------------------------*/
 
 static int
-goku_queue(struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags)
+goku_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 {
        struct goku_request     *req;
        struct goku_ep          *ep;
index 4842577789c93f52bb95943a4f211ab5d69ef3af..012d1e5f1524385b32cdb0ad870744f264b50f1f 100644 (file)
@@ -71,13 +71,13 @@ static char *state_names[] = {
 static int lh7a40x_ep_enable(struct usb_ep *ep,
                             const struct usb_endpoint_descriptor *);
 static int lh7a40x_ep_disable(struct usb_ep *ep);
-static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep, int);
+static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep, gfp_t);
 static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *);
 static void *lh7a40x_alloc_buffer(struct usb_ep *ep, unsigned, dma_addr_t *,
-                                 int);
+                                 gfp_t);
 static void lh7a40x_free_buffer(struct usb_ep *ep, void *, dma_addr_t,
                                unsigned);
-static int lh7a40x_queue(struct usb_ep *ep, struct usb_request *, int);
+static int lh7a40x_queue(struct usb_ep *ep, struct usb_request *, gfp_t);
 static int lh7a40x_dequeue(struct usb_ep *ep, struct usb_request *);
 static int lh7a40x_set_halt(struct usb_ep *ep, int);
 static int lh7a40x_fifo_status(struct usb_ep *ep);
@@ -1106,7 +1106,7 @@ static int lh7a40x_ep_disable(struct usb_ep *_ep)
 }
 
 static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep,
-                                                unsigned gfp_flags)
+                                                gfp_t gfp_flags)
 {
        struct lh7a40x_request *req;
 
@@ -1134,7 +1134,7 @@ static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *_req)
 }
 
 static void *lh7a40x_alloc_buffer(struct usb_ep *ep, unsigned bytes,
-                                 dma_addr_t * dma, unsigned gfp_flags)
+                                 dma_addr_t * dma, gfp_t gfp_flags)
 {
        char *retval;
 
@@ -1158,7 +1158,7 @@ static void lh7a40x_free_buffer(struct usb_ep *ep, void *buf, dma_addr_t dma,
  *  NOTE: Sets INDEX register
  */
 static int lh7a40x_queue(struct usb_ep *_ep, struct usb_request *_req,
-                        unsigned gfp_flags)
+                        gfp_t gfp_flags)
 {
        struct lh7a40x_request *req;
        struct lh7a40x_ep *ep;
index 477fab2e74d118375a22475aa05e07d7b0983d46..c32e1f7476da46d67b4e2f8336ab8cd5929b1b75 100644 (file)
@@ -376,7 +376,7 @@ static int net2280_disable (struct usb_ep *_ep)
 /*-------------------------------------------------------------------------*/
 
 static struct usb_request *
-net2280_alloc_request (struct usb_ep *_ep, unsigned gfp_flags)
+net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
 {
        struct net2280_ep       *ep;
        struct net2280_request  *req;
@@ -463,7 +463,7 @@ net2280_alloc_buffer (
        struct usb_ep           *_ep,
        unsigned                bytes,
        dma_addr_t              *dma,
-       unsigned                gfp_flags
+       gfp_t                   gfp_flags
 )
 {
        void                    *retval;
@@ -897,7 +897,7 @@ done (struct net2280_ep *ep, struct net2280_request *req, int status)
 /*-------------------------------------------------------------------------*/
 
 static int
-net2280_queue (struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags)
+net2280_queue (struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 {
        struct net2280_request  *req;
        struct net2280_ep       *ep;
index ff5533e6956047fd25688d3fd37af3f23421b38f..287c5900fb13236def46a4a96764f10d6099352c 100644 (file)
@@ -269,7 +269,7 @@ static int omap_ep_disable(struct usb_ep *_ep)
 /*-------------------------------------------------------------------------*/
 
 static struct usb_request *
-omap_alloc_request(struct usb_ep *ep, unsigned gfp_flags)
+omap_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
 {
        struct omap_req *req;
 
@@ -298,7 +298,7 @@ omap_alloc_buffer(
        struct usb_ep   *_ep,
        unsigned        bytes,
        dma_addr_t      *dma,
-       unsigned        gfp_flags
+       gfp_t           gfp_flags
 )
 {
        void            *retval;
@@ -937,7 +937,7 @@ static void dma_channel_release(struct omap_ep *ep)
 /*-------------------------------------------------------------------------*/
 
 static int
-omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags)
+omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 {
        struct omap_ep  *ep = container_of(_ep, struct omap_ep, ep);
        struct omap_req *req = container_of(_req, struct omap_req, req);
index 73f8c9404156be4f6d2afa9351d8bd20a14e1bf6..6e545393cfff9e2ed943f404db3cedd8de766782 100644 (file)
@@ -332,7 +332,7 @@ static int pxa2xx_ep_disable (struct usb_ep *_ep)
  *     pxa2xx_ep_alloc_request - allocate a request data structure
  */
 static struct usb_request *
-pxa2xx_ep_alloc_request (struct usb_ep *_ep, unsigned gfp_flags)
+pxa2xx_ep_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
 {
        struct pxa2xx_request *req;
 
@@ -367,7 +367,7 @@ pxa2xx_ep_free_request (struct usb_ep *_ep, struct usb_request *_req)
  */
 static void *
 pxa2xx_ep_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
-       dma_addr_t *dma, unsigned gfp_flags)
+       dma_addr_t *dma, gfp_t gfp_flags)
 {
        char                    *retval;
 
@@ -874,7 +874,7 @@ done:
 /*-------------------------------------------------------------------------*/
 
 static int
-pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags)
+pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 {
        struct pxa2xx_request   *req;
        struct pxa2xx_ep        *ep;
index c925d9222f53c4baaef730dd1046b8aa75620897..b35ac6d334f8e3aa5246c5d4d1e832349ce02994 100644 (file)
@@ -300,18 +300,18 @@ static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed,
                u8 type, unsigned int index, int is_otg);
 
 static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len,
-       unsigned kmalloc_flags);
+       gfp_t kmalloc_flags);
 static void gs_free_req(struct usb_ep *ep, struct usb_request *req);
 
 static struct gs_req_entry *gs_alloc_req_entry(struct usb_ep *ep, unsigned len,
-       unsigned kmalloc_flags);
+       gfp_t kmalloc_flags);
 static void gs_free_req_entry(struct usb_ep *ep, struct gs_req_entry *req);
 
-static int gs_alloc_ports(struct gs_dev *dev, unsigned kmalloc_flags);
+static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags);
 static void gs_free_ports(struct gs_dev *dev);
 
 /* circular buffer */
-static struct gs_buf *gs_buf_alloc(unsigned int size, unsigned kmalloc_flags);
+static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags);
 static void gs_buf_free(struct gs_buf *gb);
 static void gs_buf_clear(struct gs_buf *gb);
 static unsigned int gs_buf_data_avail(struct gs_buf *gb);
@@ -2091,7 +2091,7 @@ static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed,
  * usb_request or NULL if there is an error.
  */
 static struct usb_request *
-gs_alloc_req(struct usb_ep *ep, unsigned int len, unsigned kmalloc_flags)
+gs_alloc_req(struct usb_ep *ep, unsigned int len, gfp_t kmalloc_flags)
 {
        struct usb_request *req;
 
@@ -2132,7 +2132,7 @@ static void gs_free_req(struct usb_ep *ep, struct usb_request *req)
  * endpoint, buffer len, and kmalloc flags.
  */
 static struct gs_req_entry *
-gs_alloc_req_entry(struct usb_ep *ep, unsigned len, unsigned kmalloc_flags)
+gs_alloc_req_entry(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags)
 {
        struct gs_req_entry     *req;
 
@@ -2173,7 +2173,7 @@ static void gs_free_req_entry(struct usb_ep *ep, struct gs_req_entry *req)
  *
  * The device lock is normally held when calling this function.
  */
-static int gs_alloc_ports(struct gs_dev *dev, unsigned kmalloc_flags)
+static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags)
 {
        int i;
        struct gs_port *port;
@@ -2255,7 +2255,7 @@ static void gs_free_ports(struct gs_dev *dev)
  *
  * Allocate a circular buffer and all associated memory.
  */
-static struct gs_buf *gs_buf_alloc(unsigned int size, unsigned kmalloc_flags)
+static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags)
 {
        struct gs_buf *gb;
 
index 6890e773b2a2a38f6ddf8469e0e141b47e8fb1ef..ec9c424f1d9706e59fa6a31612c96cacfdbd75ab 100644 (file)
@@ -612,7 +612,7 @@ static void source_sink_complete (struct usb_ep *ep, struct usb_request *req)
 }
 
 static struct usb_request *
-source_sink_start_ep (struct usb_ep *ep, unsigned gfp_flags)
+source_sink_start_ep (struct usb_ep *ep, gfp_t gfp_flags)
 {
        struct usb_request      *req;
        int                     status;
@@ -640,7 +640,7 @@ source_sink_start_ep (struct usb_ep *ep, unsigned gfp_flags)
 }
 
 static int
-set_source_sink_config (struct zero_dev *dev, unsigned gfp_flags)
+set_source_sink_config (struct zero_dev *dev, gfp_t gfp_flags)
 {
        int                     result = 0;
        struct usb_ep           *ep;
@@ -744,7 +744,7 @@ static void loopback_complete (struct usb_ep *ep, struct usb_request *req)
 }
 
 static int
-set_loopback_config (struct zero_dev *dev, unsigned gfp_flags)
+set_loopback_config (struct zero_dev *dev, gfp_t gfp_flags)
 {
        int                     result = 0;
        struct usb_ep           *ep;
@@ -845,7 +845,7 @@ static void zero_reset_config (struct zero_dev *dev)
  * by limiting configuration choices (like the pxa2xx).
  */
 static int
-zero_set_config (struct zero_dev *dev, unsigned number, unsigned gfp_flags)
+zero_set_config (struct zero_dev *dev, unsigned number, gfp_t gfp_flags)
 {
        int                     result = 0;
        struct usb_gadget       *gadget = dev->gadget;
index b948ffd94f4587ab3d07e6ccf1743a18a89e9ebd..f5eb9e7b5b1875ee8178404307ca45be1d5d5693 100644 (file)
@@ -983,7 +983,7 @@ static int ehci_urb_enqueue (
        struct usb_hcd  *hcd,
        struct usb_host_endpoint *ep,
        struct urb      *urb,
-       unsigned        mem_flags
+       gfp_t           mem_flags
 ) {
        struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
        struct list_head        qtd_list;
index 5c38ad869485e8870f20d1834f78eb264cbe8104..91c2ab43cbcc1a58412751505400e1db045f1909 100644 (file)
@@ -45,7 +45,7 @@ static inline void ehci_qtd_init (struct ehci_qtd *qtd, dma_addr_t dma)
        INIT_LIST_HEAD (&qtd->qtd_list);
 }
 
-static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, int flags)
+static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, gfp_t flags)
 {
        struct ehci_qtd         *qtd;
        dma_addr_t              dma;
@@ -79,7 +79,7 @@ static void qh_destroy (struct kref *kref)
        dma_pool_free (ehci->qh_pool, qh, qh->qh_dma);
 }
 
-static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, int flags)
+static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags)
 {
        struct ehci_qh          *qh;
        dma_addr_t              dma;
@@ -161,7 +161,7 @@ static void ehci_mem_cleanup (struct ehci_hcd *ehci)
 }
 
 /* remember to add cleanup code (above) if you add anything here */
-static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
+static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
 {
        int i;
 
index 940d38ca7d91785534bffe0f8da2f5e015c563a2..5bb872c3496d70c3767d1b4f40a8fdd2979ba354 100644 (file)
@@ -477,7 +477,7 @@ qh_urb_transaction (
        struct ehci_hcd         *ehci,
        struct urb              *urb,
        struct list_head        *head,
-       int                     flags
+       gfp_t                   flags
 ) {
        struct ehci_qtd         *qtd, *qtd_prev;
        dma_addr_t              buf;
@@ -629,7 +629,7 @@ static struct ehci_qh *
 qh_make (
        struct ehci_hcd         *ehci,
        struct urb              *urb,
-       int                     flags
+       gfp_t                   flags
 ) {
        struct ehci_qh          *qh = ehci_qh_alloc (ehci, flags);
        u32                     info1 = 0, info2 = 0;
@@ -906,7 +906,7 @@ submit_async (
        struct usb_host_endpoint *ep,
        struct urb              *urb,
        struct list_head        *qtd_list,
-       unsigned                mem_flags
+       gfp_t                   mem_flags
 ) {
        struct ehci_qtd         *qtd;
        int                     epnum;
index ccc7300baa6d717a2bb1dab4140ba8d84337eb6d..f0c8aa1ccd5dc016aa8c61ea3b84944c99a25c1c 100644 (file)
@@ -589,7 +589,7 @@ static int intr_submit (
        struct usb_host_endpoint *ep,
        struct urb              *urb,
        struct list_head        *qtd_list,
-       unsigned                mem_flags
+       gfp_t                   mem_flags
 ) {
        unsigned                epnum;
        unsigned long           flags;
@@ -634,7 +634,7 @@ done:
 /* ehci_iso_stream ops work with both ITD and SITD */
 
 static struct ehci_iso_stream *
-iso_stream_alloc (unsigned mem_flags)
+iso_stream_alloc (gfp_t mem_flags)
 {
        struct ehci_iso_stream *stream;
 
@@ -851,7 +851,7 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb)
 /* ehci_iso_sched ops can be ITD-only or SITD-only */
 
 static struct ehci_iso_sched *
-iso_sched_alloc (unsigned packets, unsigned mem_flags)
+iso_sched_alloc (unsigned packets, gfp_t mem_flags)
 {
        struct ehci_iso_sched   *iso_sched;
        int                     size = sizeof *iso_sched;
@@ -924,7 +924,7 @@ itd_urb_transaction (
        struct ehci_iso_stream  *stream,
        struct ehci_hcd         *ehci,
        struct urb              *urb,
-       unsigned                mem_flags
+       gfp_t                   mem_flags
 )
 {
        struct ehci_itd         *itd;
@@ -1418,7 +1418,7 @@ itd_complete (
 /*-------------------------------------------------------------------------*/
 
 static int itd_submit (struct ehci_hcd *ehci, struct urb *urb,
-       unsigned mem_flags)
+       gfp_t mem_flags)
 {
        int                     status = -EINVAL;
        unsigned long           flags;
@@ -1529,7 +1529,7 @@ sitd_urb_transaction (
        struct ehci_iso_stream  *stream,
        struct ehci_hcd         *ehci,
        struct urb              *urb,
-       unsigned                mem_flags
+       gfp_t                   mem_flags
 )
 {
        struct ehci_sitd        *sitd;
@@ -1779,7 +1779,7 @@ sitd_complete (
 
 
 static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
-       unsigned mem_flags)
+       gfp_t mem_flags)
 {
        int                     status = -EINVAL;
        unsigned long           flags;
index e142056b0d2cd5fc8c46e267564cc1ed2318033b..2548d94fcd72eac9056019a6ba5efb51028065ba 100644 (file)
@@ -694,7 +694,7 @@ static int balance(struct isp116x *isp116x, u16 period, u16 load)
 
 static int isp116x_urb_enqueue(struct usb_hcd *hcd,
                               struct usb_host_endpoint *hep, struct urb *urb,
-                              unsigned mem_flags)
+                              gfp_t mem_flags)
 {
        struct isp116x *isp116x = hcd_to_isp116x(hcd);
        struct usb_device *udev = urb->dev;
index 67c1aa5eb1c175994faa6593a33b009d496164cb..f8da8c7af7c66b69ff8746b943f0266b1bc3b8ce 100644 (file)
@@ -180,7 +180,7 @@ static int ohci_urb_enqueue (
        struct usb_hcd  *hcd,
        struct usb_host_endpoint *ep,
        struct urb      *urb,
-       unsigned        mem_flags
+       gfp_t           mem_flags
 ) {
        struct ohci_hcd *ohci = hcd_to_ohci (hcd);
        struct ed       *ed;
index fd3c4d3714bd80578b3ae62f8c659141855b0452..9fb83dfb1eb44114fbdb12df95c3a83f2e606dad 100644 (file)
@@ -84,7 +84,7 @@ dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma)
 
 /* TDs ... */
 static struct td *
-td_alloc (struct ohci_hcd *hc, unsigned mem_flags)
+td_alloc (struct ohci_hcd *hc, gfp_t mem_flags)
 {
        dma_addr_t      dma;
        struct td       *td;
@@ -118,7 +118,7 @@ td_free (struct ohci_hcd *hc, struct td *td)
 
 /* EDs ... */
 static struct ed *
-ed_alloc (struct ohci_hcd *hc, unsigned mem_flags)
+ed_alloc (struct ohci_hcd *hc, gfp_t mem_flags)
 {
        dma_addr_t      dma;
        struct ed       *ed;
index d42a15d10a462de96a4ba16869990f4ae41f1057..cad858575cea783caab2656313fbbb455337a984 100644 (file)
@@ -818,7 +818,7 @@ static int sl811h_urb_enqueue(
        struct usb_hcd          *hcd,
        struct usb_host_endpoint *hep,
        struct urb              *urb,
-       unsigned                mem_flags
+       gfp_t                   mem_flags
 ) {
        struct sl811            *sl811 = hcd_to_sl811(hcd);
        struct usb_device       *udev = urb->dev;
index ea0d168a8c676a520b9309227db4b1b8960bc8a5..4e0fbe2c1a9ab9cd1b53175a46caae0b7541b0d3 100644 (file)
@@ -1164,7 +1164,7 @@ static struct urb *uhci_find_urb_ep(struct uhci_hcd *uhci, struct urb *urb)
 
 static int uhci_urb_enqueue(struct usb_hcd *hcd,
                struct usb_host_endpoint *ep,
-               struct urb *urb, unsigned mem_flags)
+               struct urb *urb, gfp_t mem_flags)
 {
        int ret;
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
index 03fb70ef2eb3ec14e60c5f32188a24d78d5295b4..0592cb5e6c4d65c6fdf7ecd6e7777bb145f1d4ab 100644 (file)
@@ -137,7 +137,7 @@ static void async_complete(struct urb *urb, struct pt_regs *ptregs)
 
 static struct uss720_async_request *submit_async_request(struct parport_uss720_private *priv,
                                                         __u8 request, __u8 requesttype, __u16 value, __u16 index,
-                                                        unsigned int mem_flags)
+                                                        gfp_t mem_flags)
 {
        struct usb_device *usbdev;
        struct uss720_async_request *rq;
@@ -204,7 +204,7 @@ static unsigned int kill_all_async_requests_priv(struct parport_uss720_private *
 
 /* --------------------------------------------------------------------- */
 
-static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val, unsigned int mem_flags)
+static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val, gfp_t mem_flags)
 {
        struct parport_uss720_private *priv;
        struct uss720_async_request *rq;
@@ -238,7 +238,7 @@ static int get_1284_register(struct parport *pp, unsigned char reg, unsigned cha
        return -EIO;
 }
 
-static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val, unsigned int mem_flags)
+static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val, gfp_t mem_flags)
 {
        struct parport_uss720_private *priv;
        struct uss720_async_request *rq;
index 861f00a4375010315c7d59e9092cebd75ab90624..252a34fbb42cc24931703fcdbac29d6657942421 100644 (file)
@@ -753,7 +753,7 @@ static int ax88772_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 }
 
 static struct sk_buff *ax88772_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
-                                       unsigned flags)
+                                       gfp_t flags)
 {
        int padlen;
        int headroom = skb_headroom(skb);
index c8763ae33c737a3729fabc233551a014dfbd0c27..c0f263b202a60ea70eeda768593d7ee8337b1190 100644 (file)
@@ -301,7 +301,7 @@ static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 }
 
 static struct sk_buff *
-genelink_tx_fixup(struct usbnet *dev, struct sk_buff *skb, unsigned flags)
+genelink_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
 {
        int     padlen;
        int     length = skb->len;
index e04b0ce3611a3e0b9999bdf6ecc8bacedf032fa9..c82655d3d448ebf31ff19137cd4b39e3f9ea4965 100644 (file)
@@ -477,13 +477,13 @@ static int kaweth_reset(struct kaweth_device *kaweth)
 }
 
 static void kaweth_usb_receive(struct urb *, struct pt_regs *regs);
-static int kaweth_resubmit_rx_urb(struct kaweth_device *, unsigned);
+static int kaweth_resubmit_rx_urb(struct kaweth_device *, gfp_t);
 
 /****************************************************************
        int_callback
 *****************************************************************/
 
-static void kaweth_resubmit_int_urb(struct kaweth_device *kaweth, int mf)
+static void kaweth_resubmit_int_urb(struct kaweth_device *kaweth, gfp_t mf)
 {
        int status;
 
@@ -550,7 +550,7 @@ static void kaweth_resubmit_tl(void *d)
  *     kaweth_resubmit_rx_urb
  ****************************************************************/
 static int kaweth_resubmit_rx_urb(struct kaweth_device *kaweth,
-                                               unsigned mem_flags)
+                                               gfp_t mem_flags)
 {
        int result;
 
index a4309c4a491b88b07fc2bcdcf4609df4ab7ab3d9..cee55f8cf64fb5b2ff97b9f146615bcbb91e2146 100644 (file)
@@ -500,7 +500,7 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 }
 
 static struct sk_buff *
-net1080_tx_fixup(struct usbnet *dev, struct sk_buff *skb, unsigned flags)
+net1080_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
 {
        int                     padlen;
        struct sk_buff          *skb2;
index 2ed2e5fb77780e2f8a46c487aecae6734aa109ac..b5a925dc1beb2623c97d78973944f5c3157fc1bd 100644 (file)
@@ -517,7 +517,7 @@ static int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 }
 
 static struct sk_buff *
-rndis_tx_fixup(struct usbnet *dev, struct sk_buff *skb, unsigned flags)
+rndis_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
 {
        struct rndis_data_hdr   *hdr;
        struct sk_buff          *skb2;
index 6c460918d54f53a81bb6b6c0cd5fd163796c66a1..fce81d73893393ca9db60554448370caf7ade939 100644 (file)
@@ -288,7 +288,7 @@ EXPORT_SYMBOL_GPL(usbnet_defer_kevent);
 
 static void rx_complete (struct urb *urb, struct pt_regs *regs);
 
-static void rx_submit (struct usbnet *dev, struct urb *urb, unsigned flags)
+static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
 {
        struct sk_buff          *skb;
        struct skb_data         *entry;
index 7aa0abd1a9bd2c0a3386034c28b78dcdc95fa364..89fc4958eecf81f72c5f93128d5994168b7f3c43 100644 (file)
@@ -107,7 +107,7 @@ struct driver_info {
 
        /* fixup tx packet (add framing) */
        struct sk_buff  *(*tx_fixup)(struct usbnet *dev,
-                               struct sk_buff *skb, unsigned flags);
+                               struct sk_buff *skb, gfp_t flags);
 
        /* for new devices, use the descriptor-reading code instead */
        int             in;             /* rx endpoint */
index ee3b892aeabce231d83b5c712423ba8b8bcaf609..5d4b7d55b097c8937032e335243a51e510e0dfaa 100644 (file)
@@ -62,7 +62,7 @@
  */
 
 static struct sk_buff *
-zaurus_tx_fixup(struct usbnet *dev, struct sk_buff *skb, unsigned flags)
+zaurus_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
 {
        int                     padlen;
        struct sk_buff          *skb2;
index c4e479ee926aa75b3b53e27eb5744fca5c20859a..2f52261c7cc13eb0e23dd7f8430dfe9df3fe4b9f 100644 (file)
@@ -521,7 +521,7 @@ static int zd1201_setconfig(struct zd1201 *zd, int rid, void *buf, int len, int
        int reqlen;
        char seq=0;
        struct urb *urb;
-       unsigned int gfp_mask = wait ? GFP_NOIO : GFP_ATOMIC;
+       gfp_t gfp_mask = wait ? GFP_NOIO : GFP_ATOMIC;
 
        len += 4;                       /* first 4 are for header */
 
index 23c125128024adb92a3f6023790e0e8d3f7db402..0d576987ec670dae2349d0586defdeb58dc52356 100644 (file)
@@ -29,7 +29,7 @@ static int afs_file_release(struct inode *inode, struct file *file);
 
 static int afs_file_readpage(struct file *file, struct page *page);
 static int afs_file_invalidatepage(struct page *page, unsigned long offset);
-static int afs_file_releasepage(struct page *page, int gfp_flags);
+static int afs_file_releasepage(struct page *page, gfp_t gfp_flags);
 
 static ssize_t afs_file_write(struct file *file, const char __user *buf,
                              size_t size, loff_t *off);
@@ -279,7 +279,7 @@ static int afs_file_invalidatepage(struct page *page, unsigned long offset)
 /*
  * release a page and cleanup its private data
  */
-static int afs_file_releasepage(struct page *page, int gfp_flags)
+static int afs_file_releasepage(struct page *page, gfp_t gfp_flags)
 {
        struct cachefs_page *pageio;
 
index 7d81a93afd480c9d9f0335c208f130946b1dc259..460554b07ff91501739ae7b2f21ea14392ea5e51 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -778,7 +778,7 @@ static int bio_map_kern_endio(struct bio *bio, unsigned int bytes_done, int err)
 
 
 static struct bio *__bio_map_kern(request_queue_t *q, void *data,
-                                 unsigned int len, unsigned int gfp_mask)
+                                 unsigned int len, gfp_t gfp_mask)
 {
        unsigned long kaddr = (unsigned long)data;
        unsigned long end = (kaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
@@ -825,7 +825,7 @@ static struct bio *__bio_map_kern(request_queue_t *q, void *data,
  *     device. Returns an error pointer in case of error.
  */
 struct bio *bio_map_kern(request_queue_t *q, void *data, unsigned int len,
-                        unsigned int gfp_mask)
+                        gfp_t gfp_mask)
 {
        struct bio *bio;
 
index 1216c0d3c8ce179adecc466a772d06ea26f4ed8d..b1667986442f130b9fe523b85f174966100cd09e 100644 (file)
@@ -502,7 +502,7 @@ static void free_more_memory(void)
        yield();
 
        for_each_pgdat(pgdat) {
-               zones = pgdat->node_zonelists[GFP_NOFS&GFP_ZONEMASK].zones;
+               zones = pgdat->node_zonelists[gfp_zone(GFP_NOFS)].zones;
                if (*zones)
                        try_to_free_pages(zones, GFP_NOFS);
        }
@@ -1571,7 +1571,7 @@ static inline void discard_buffer(struct buffer_head * bh)
  *
  * NOTE: @gfp_mask may go away, and this function may become non-blocking.
  */
-int try_to_release_page(struct page *page, int gfp_mask)
+int try_to_release_page(struct page *page, gfp_t gfp_mask)
 {
        struct address_space * const mapping = page->mapping;
 
index fb10386c59bed6b34a51af4fb930eb79c86ac586..e90512ed35a4eca72e839434a075d1a4b8886c24 100644 (file)
@@ -689,7 +689,7 @@ void shrink_dcache_anon(struct hlist_head *head)
  *
  * In this case we return -1 to tell the caller that we baled.
  */
-static int shrink_dcache_memory(int nr, unsigned int gfp_mask)
+static int shrink_dcache_memory(int nr, gfp_t gfp_mask)
 {
        if (nr) {
                if (!(gfp_mask & __GFP_FS))
index b9732335bcdcd6006733a9561e9ef8ceb8769117..05f3327d64a3f7b93b064af0e323b34dbeff97af 100644 (file)
@@ -500,7 +500,7 @@ static void prune_dqcache(int count)
  * more memory
  */
 
-static int shrink_dqcache_memory(int nr, unsigned int gfp_mask)
+static int shrink_dqcache_memory(int nr, gfp_t gfp_mask)
 {
        if (nr) {
                spin_lock(&dq_list_lock);
index a04a575ad433c7143dd376ab96d99ae9a782ace8..d2208f7c87db81c30d8bdd3ddf965e887f693e4a 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -126,8 +126,7 @@ asmlinkage long sys_uselib(const char __user * library)
        struct nameidata nd;
        int error;
 
-       nd.intent.open.flags = FMODE_READ;
-       error = __user_walk(library, LOOKUP_FOLLOW|LOOKUP_OPEN, &nd);
+       error = __user_path_lookup_open(library, LOOKUP_FOLLOW, &nd, FMODE_READ);
        if (error)
                goto out;
 
@@ -139,7 +138,7 @@ asmlinkage long sys_uselib(const char __user * library)
        if (error)
                goto exit;
 
-       file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
+       file = nameidata_to_filp(&nd, O_RDONLY);
        error = PTR_ERR(file);
        if (IS_ERR(file))
                goto out;
@@ -167,6 +166,7 @@ asmlinkage long sys_uselib(const char __user * library)
 out:
        return error;
 exit:
+       release_open_intent(&nd);
        path_release(&nd);
        goto out;
 }
@@ -490,8 +490,7 @@ struct file *open_exec(const char *name)
        int err;
        struct file *file;
 
-       nd.intent.open.flags = FMODE_READ;
-       err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_OPEN, &nd);
+       err = path_lookup_open(name, LOOKUP_FOLLOW, &nd, FMODE_READ);
        file = ERR_PTR(err);
 
        if (!err) {
@@ -504,7 +503,7 @@ struct file *open_exec(const char *name)
                                err = -EACCES;
                        file = ERR_PTR(err);
                        if (!err) {
-                               file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
+                               file = nameidata_to_filp(&nd, O_RDONLY);
                                if (!IS_ERR(file)) {
                                        err = deny_write_access(file);
                                        if (err) {
@@ -516,6 +515,7 @@ out:
                                return file;
                        }
                }
+               release_open_intent(&nd);
                path_release(&nd);
        }
        goto out;
index b5177c90d6f111e63fe3d13f498c4bd93306b22f..8b38f2232796fda9c0f25294654c49a8d25cde11 100644 (file)
@@ -1434,7 +1434,7 @@ static int ext3_invalidatepage(struct page *page, unsigned long offset)
        return journal_invalidatepage(journal, page, offset);
 }
 
-static int ext3_releasepage(struct page *page, int wait)
+static int ext3_releasepage(struct page *page, gfp_t wait)
 {
        journal_t *journal = EXT3_JOURNAL(page->mapping->host);
 
index f1570b9f9de30427f133670f02893a67726ed6ed..3f680c5675bf5c7e45a9805b6102752e8d0f0b1e 100644 (file)
@@ -46,7 +46,7 @@ static sector_t hfs_bmap(struct address_space *mapping, sector_t block)
        return generic_block_bmap(mapping, block, hfs_get_block);
 }
 
-static int hfs_releasepage(struct page *page, int mask)
+static int hfs_releasepage(struct page *page, gfp_t mask)
 {
        struct inode *inode = page->mapping->host;
        struct super_block *sb = inode->i_sb;
index d5642705f6336279088811e6e109a4e6629b0a8f..f205773ddfbebc661fce1278306234cfd1538945 100644 (file)
@@ -40,7 +40,7 @@ static sector_t hfsplus_bmap(struct address_space *mapping, sector_t block)
        return generic_block_bmap(mapping, block, hfsplus_get_block);
 }
 
-static int hfsplus_releasepage(struct page *page, int mask)
+static int hfsplus_releasepage(struct page *page, gfp_t mask)
 {
        struct inode *inode = page->mapping->host;
        struct super_block *sb = inode->i_sb;
index f80a79ff156b5c4feafe54d17fee693fdec6b71c..7d3316527767ce9896f5d299d0bb18a7baea6538 100644 (file)
@@ -475,7 +475,7 @@ static void prune_icache(int nr_to_scan)
  * This function is passed the number of inodes to scan, and it returns the
  * total number of remaining possibly-reclaimable inodes.
  */
-static int shrink_icache_memory(int nr, unsigned int gfp_mask)
+static int shrink_icache_memory(int nr, gfp_t gfp_mask)
 {
        if (nr) {
                /*
index 7ae2c4fe506bb5bd7b2ac21c6bbf80795741361d..e4b516ac4989ef3ddef852f5c764ef816e0c3a56 100644 (file)
@@ -1606,7 +1606,7 @@ int journal_blocks_per_page(struct inode *inode)
  * Simple support for retrying memory allocations.  Introduced to help to
  * debug different VM deadlock avoidance strategies. 
  */
-void * __jbd_kmalloc (const char *where, size_t size, int flags, int retry)
+void * __jbd_kmalloc (const char *where, size_t size, gfp_t flags, int retry)
 {
        return kmalloc(size, flags | (retry ? __GFP_NOFAIL : 0));
 }
index 49bbc2be3d72937ba4719e656a140bf1c9ea7aba..13cb05bf60489e0005d635d66a63b47692ed72a6 100644 (file)
@@ -1621,7 +1621,7 @@ out:
  * while the data is part of a transaction.  Yes?
  */
 int journal_try_to_free_buffers(journal_t *journal, 
-                               struct page *page, int unused_gfp_mask)
+                               struct page *page, gfp_t unused_gfp_mask)
 {
        struct buffer_head *head;
        struct buffer_head *bh;
index 13d7e3f1feb4e0c8a0d18462fd5cfb657702da1f..eeb37d70e6509439498aa224b7f00f723d00270e 100644 (file)
@@ -198,7 +198,7 @@ static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags)
        }
 }
 
-static inline struct metapage *alloc_metapage(unsigned int gfp_mask)
+static inline struct metapage *alloc_metapage(gfp_t gfp_mask)
 {
        return mempool_alloc(metapage_mempool, gfp_mask);
 }
@@ -534,7 +534,7 @@ add_failed:
        return -EIO;
 }
 
-static int metapage_releasepage(struct page *page, int gfp_mask)
+static int metapage_releasepage(struct page *page, gfp_t gfp_mask)
 {
        struct metapage *mp;
        int busy = 0;
index 82c77df81c5f1e2ed706d7f4be5206b121dd1454..c4c8601096e03f384160e2c9c923f6793a288735 100644 (file)
@@ -173,11 +173,10 @@ nlm_bind_host(struct nlm_host *host)
 
        /* If we've already created an RPC client, check whether
         * RPC rebind is required
-        * Note: why keep rebinding if we're on a tcp connection?
         */
        if ((clnt = host->h_rpcclnt) != NULL) {
                xprt = clnt->cl_xprt;
-               if (!xprt->stream && time_after_eq(jiffies, host->h_nextrebind)) {
+               if (time_after_eq(jiffies, host->h_nextrebind)) {
                        clnt->cl_port = 0;
                        host->h_nextrebind = jiffies + NLM_HOST_REBIND;
                        dprintk("lockd: next rebind in %ld jiffies\n",
@@ -189,7 +188,6 @@ 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 */
index f7daa5f48949c41ea02b687e1521a440387b0592..a1e8b2248014c0aa1d7ae8b2766440f753929908 100644 (file)
@@ -316,21 +316,22 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,
        /* POSIX-1996 leaves the case l->l_len < 0 undefined;
           POSIX-2001 defines it. */
        start += l->l_start;
-       end = start + l->l_len - 1;
-       if (l->l_len < 0) {
+       if (start < 0)
+               return -EINVAL;
+       fl->fl_end = OFFSET_MAX;
+       if (l->l_len > 0) {
+               end = start + l->l_len - 1;
+               fl->fl_end = end;
+       } else if (l->l_len < 0) {
                end = start - 1;
+               fl->fl_end = end;
                start += l->l_len;
+               if (start < 0)
+                       return -EINVAL;
        }
-
-       if (start < 0)
-               return -EINVAL;
-       if (l->l_len > 0 && end < 0)
-               return -EOVERFLOW;
-
        fl->fl_start = start;   /* we record the absolute position */
-       fl->fl_end = end;
-       if (l->l_len == 0)
-               fl->fl_end = OFFSET_MAX;
+       if (fl->fl_end < fl->fl_start)
+               return -EOVERFLOW;
        
        fl->fl_owner = current->files;
        fl->fl_pid = current->tgid;
@@ -362,14 +363,21 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
                return -EINVAL;
        }
 
-       if (((start += l->l_start) < 0) || (l->l_len < 0))
+       start += l->l_start;
+       if (start < 0)
                return -EINVAL;
-       fl->fl_end = start + l->l_len - 1;
-       if (l->l_len > 0 && fl->fl_end < 0)
-               return -EOVERFLOW;
+       fl->fl_end = OFFSET_MAX;
+       if (l->l_len > 0) {
+               fl->fl_end = start + l->l_len - 1;
+       } else if (l->l_len < 0) {
+               fl->fl_end = start - 1;
+               start += l->l_len;
+               if (start < 0)
+                       return -EINVAL;
+       }
        fl->fl_start = start;   /* we record the absolute position */
-       if (l->l_len == 0)
-               fl->fl_end = OFFSET_MAX;
+       if (fl->fl_end < fl->fl_start)
+               return -EOVERFLOW;
        
        fl->fl_owner = current->files;
        fl->fl_pid = current->tgid;
@@ -829,12 +837,16 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request)
                /* Detect adjacent or overlapping regions (if same lock type)
                 */
                if (request->fl_type == fl->fl_type) {
+                       /* In all comparisons of start vs end, use
+                        * "start - 1" rather than "end + 1". If end
+                        * is OFFSET_MAX, end + 1 will become negative.
+                        */
                        if (fl->fl_end < request->fl_start - 1)
                                goto next_lock;
                        /* If the next lock in the list has entirely bigger
                         * addresses than the new one, insert the lock here.
                         */
-                       if (fl->fl_start > request->fl_end + 1)
+                       if (fl->fl_start - 1 > request->fl_end)
                                break;
 
                        /* If we come here, the new and old lock are of the
index b002a088857da50e26efcfc72d8f76e0d0b8379c..298997f174755649a7b3ca5b72bb9e2613a53464 100644 (file)
@@ -116,7 +116,7 @@ mb_cache_indexes(struct mb_cache *cache)
  * What the mbcache registers as to get shrunk dynamically.
  */
 
-static int mb_cache_shrink_fn(int nr_to_scan, unsigned int gfp_mask);
+static int mb_cache_shrink_fn(int nr_to_scan, gfp_t gfp_mask);
 
 
 static inline int
@@ -140,7 +140,7 @@ __mb_cache_entry_unhash(struct mb_cache_entry *ce)
 
 
 static inline void
-__mb_cache_entry_forget(struct mb_cache_entry *ce, int gfp_mask)
+__mb_cache_entry_forget(struct mb_cache_entry *ce, gfp_t gfp_mask)
 {
        struct mb_cache *cache = ce->e_cache;
 
@@ -193,7 +193,7 @@ forget:
  * Returns the number of objects which are present in the cache.
  */
 static int
-mb_cache_shrink_fn(int nr_to_scan, unsigned int gfp_mask)
+mb_cache_shrink_fn(int nr_to_scan, gfp_t gfp_mask)
 {
        LIST_HEAD(free_list);
        struct list_head *l, *ltmp;
index aa62dbda93ac01234670658a315c5472552238aa..aaaa810362344af7790e066a47a233100d491542 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/syscalls.h>
 #include <linux/mount.h>
 #include <linux/audit.h>
+#include <linux/file.h>
 #include <asm/namei.h>
 #include <asm/uaccess.h>
 
@@ -317,6 +318,18 @@ void path_release_on_umount(struct nameidata *nd)
        mntput_no_expire(nd->mnt);
 }
 
+/**
+ * release_open_intent - free up open intent resources
+ * @nd: pointer to nameidata
+ */
+void release_open_intent(struct nameidata *nd)
+{
+       if (nd->intent.open.file->f_dentry == NULL)
+               put_filp(nd->intent.open.file);
+       else
+               fput(nd->intent.open.file);
+}
+
 /*
  * Internal lookup() using the new generic dcache.
  * SMP-safe
@@ -750,6 +763,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
                struct qstr this;
                unsigned int c;
 
+               nd->flags |= LOOKUP_CONTINUE;
                err = exec_permission_lite(inode, nd);
                if (err == -EAGAIN) { 
                        err = permission(inode, MAY_EXEC, nd);
@@ -802,7 +816,6 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
                        if (err < 0)
                                break;
                }
-               nd->flags |= LOOKUP_CONTINUE;
                /* This does the actual lookups.. */
                err = do_lookup(nd, &this, &next);
                if (err)
@@ -1052,6 +1065,70 @@ out:
        return retval;
 }
 
+static int __path_lookup_intent_open(const char *name, unsigned int lookup_flags,
+               struct nameidata *nd, int open_flags, int create_mode)
+{
+       struct file *filp = get_empty_filp();
+       int err;
+
+       if (filp == NULL)
+               return -ENFILE;
+       nd->intent.open.file = filp;
+       nd->intent.open.flags = open_flags;
+       nd->intent.open.create_mode = create_mode;
+       err = path_lookup(name, lookup_flags|LOOKUP_OPEN, nd);
+       if (IS_ERR(nd->intent.open.file)) {
+               if (err == 0) {
+                       err = PTR_ERR(nd->intent.open.file);
+                       path_release(nd);
+               }
+       } else if (err != 0)
+               release_open_intent(nd);
+       return err;
+}
+
+/**
+ * path_lookup_open - lookup a file path with open intent
+ * @name: pointer to file name
+ * @lookup_flags: lookup intent flags
+ * @nd: pointer to nameidata
+ * @open_flags: open intent flags
+ */
+int path_lookup_open(const char *name, unsigned int lookup_flags,
+               struct nameidata *nd, int open_flags)
+{
+       return __path_lookup_intent_open(name, lookup_flags, nd,
+                       open_flags, 0);
+}
+
+/**
+ * path_lookup_create - lookup a file path with open + create intent
+ * @name: pointer to file name
+ * @lookup_flags: lookup intent flags
+ * @nd: pointer to nameidata
+ * @open_flags: open intent flags
+ * @create_mode: create intent flags
+ */
+int path_lookup_create(const char *name, unsigned int lookup_flags,
+               struct nameidata *nd, int open_flags, int create_mode)
+{
+       return __path_lookup_intent_open(name, lookup_flags|LOOKUP_CREATE, nd,
+                       open_flags, create_mode);
+}
+
+int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags,
+               struct nameidata *nd, int open_flags)
+{
+       char *tmp = getname(name);
+       int err = PTR_ERR(tmp);
+
+       if (!IS_ERR(tmp)) {
+               err = __path_lookup_intent_open(tmp, lookup_flags, nd, open_flags, 0);
+               putname(tmp);
+       }
+       return err;
+}
+
 /*
  * Restricted form of lookup. Doesn't follow links, single-component only,
  * needs parent already locked. Doesn't follow mounts.
@@ -1416,27 +1493,27 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
  */
 int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
 {
-       int acc_mode, error = 0;
+       int acc_mode, error;
        struct path path;
        struct dentry *dir;
        int count = 0;
 
        acc_mode = ACC_MODE(flag);
 
+       /* O_TRUNC implies we need access checks for write permissions */
+       if (flag & O_TRUNC)
+               acc_mode |= MAY_WRITE;
+
        /* Allow the LSM permission hook to distinguish append 
           access from general write access. */
        if (flag & O_APPEND)
                acc_mode |= MAY_APPEND;
 
-       /* Fill in the open() intent data */
-       nd->intent.open.flags = flag;
-       nd->intent.open.create_mode = mode;
-
        /*
         * The simplest case - just a plain lookup.
         */
        if (!(flag & O_CREAT)) {
-               error = path_lookup(pathname, lookup_flags(flag)|LOOKUP_OPEN, nd);
+               error = path_lookup_open(pathname, lookup_flags(flag), nd, flag);
                if (error)
                        return error;
                goto ok;
@@ -1445,7 +1522,7 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
        /*
         * Create - we need to know the parent.
         */
-       error = path_lookup(pathname, LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE, nd);
+       error = path_lookup_create(pathname, LOOKUP_PARENT, nd, flag, mode);
        if (error)
                return error;
 
@@ -1520,6 +1597,8 @@ ok:
 exit_dput:
        dput_path(&path, nd);
 exit:
+       if (!IS_ERR(nd->intent.open.file))
+               release_open_intent(nd);
        path_release(nd);
        return error;
 
index 4a36839f0bbdc7adb31dfdae9d8a739bc6a1b0ab..44135af9894cc44bf733546d18513ce360c86fda 100644 (file)
@@ -142,7 +142,7 @@ static void nfs_msync_inode(struct inode *inode)
 /*
  * Basic procedure for returning a delegation to the server
  */
-int nfs_inode_return_delegation(struct inode *inode)
+int __nfs_inode_return_delegation(struct inode *inode)
 {
        struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state;
        struct nfs_inode *nfsi = NFS_I(inode);
index 3f6c45a29d6a4978d2a7a5bf39b8d2110b309564..8017846b561f9ece35baa6489432b6d721c96e42 100644 (file)
@@ -25,7 +25,7 @@ struct nfs_delegation {
 
 int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
 void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
-int nfs_inode_return_delegation(struct inode *inode);
+int __nfs_inode_return_delegation(struct inode *inode);
 int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid);
 
 struct inode *nfs_delegation_find_inode(struct nfs4_client *clp, const struct nfs_fh *fhandle);
@@ -47,11 +47,25 @@ static inline int nfs_have_delegation(struct inode *inode, int flags)
                return 1;
        return 0;
 }
+
+static inline int nfs_inode_return_delegation(struct inode *inode)
+{
+       int err = 0;
+
+       if (NFS_I(inode)->delegation != NULL)
+               err = __nfs_inode_return_delegation(inode);
+       return err;
+}
 #else
 static inline int nfs_have_delegation(struct inode *inode, int flags)
 {
        return 0;
 }
+
+static inline int nfs_inode_return_delegation(struct inode *inode)
+{
+       return 0;
+}
 #endif
 
 #endif
index 2df639f143e8065cdd647044a4283e28fe89d092..8272ed3fc70797160bbfc8e3bf764ba4e099b0b8 100644 (file)
@@ -532,6 +532,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
        my_entry.eof = 0;
        my_entry.fh = &fh;
        my_entry.fattr = &fattr;
+       nfs_fattr_init(&fattr);
        desc->entry = &my_entry;
 
        while(!desc->entry->eof) {
@@ -565,8 +566,6 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                }
        }
        unlock_kernel();
-       if (desc->error < 0)
-               return desc->error;
        if (res < 0)
                return res;
        return 0;
@@ -803,6 +802,7 @@ static int nfs_dentry_delete(struct dentry *dentry)
  */
 static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode)
 {
+       nfs_inode_return_delegation(inode);
        if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
                lock_kernel();
                inode->i_nlink--;
@@ -853,12 +853,6 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
        dentry->d_op = NFS_PROTO(dir)->dentry_ops;
 
        lock_kernel();
-       /* Revalidate parent directory attribute cache */
-       error = nfs_revalidate_inode(NFS_SERVER(dir), dir);
-       if (error < 0) {
-               res = ERR_PTR(error);
-               goto out_unlock;
-       }
 
        /* If we're doing an exclusive create, optimize away the lookup */
        if (nfs_is_exclusive_create(dir, nd))
@@ -916,7 +910,6 @@ static int is_atomic_open(struct inode *dir, struct nameidata *nd)
 static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
        struct dentry *res = NULL;
-       struct inode *inode = NULL;
        int error;
 
        /* Check that we are indeed trying to open this file */
@@ -930,8 +923,10 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
        dentry->d_op = NFS_PROTO(dir)->dentry_ops;
 
        /* Let vfs_create() deal with O_EXCL */
-       if (nd->intent.open.flags & O_EXCL)
-               goto no_entry;
+       if (nd->intent.open.flags & O_EXCL) {
+               d_add(dentry, NULL);
+               goto out;
+       }
 
        /* Open the file on the server */
        lock_kernel();
@@ -945,32 +940,30 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
 
        if (nd->intent.open.flags & O_CREAT) {
                nfs_begin_data_update(dir);
-               inode = nfs4_atomic_open(dir, dentry, nd);
+               res = nfs4_atomic_open(dir, dentry, nd);
                nfs_end_data_update(dir);
        } else
-               inode = nfs4_atomic_open(dir, dentry, nd);
+               res = nfs4_atomic_open(dir, dentry, nd);
        unlock_kernel();
-       if (IS_ERR(inode)) {
-               error = PTR_ERR(inode);
+       if (IS_ERR(res)) {
+               error = PTR_ERR(res);
                switch (error) {
                        /* Make a negative dentry */
                        case -ENOENT:
-                               inode = NULL;
-                               break;
+                               res = NULL;
+                               goto out;
                        /* This turned out not to be a regular file */
+                       case -EISDIR:
+                       case -ENOTDIR:
+                               goto no_open;
                        case -ELOOP:
                                if (!(nd->intent.open.flags & O_NOFOLLOW))
                                        goto no_open;
-                       /* case -EISDIR: */
                        /* case -EINVAL: */
                        default:
-                               res = ERR_PTR(error);
                                goto out;
                }
-       }
-no_entry:
-       res = d_add_unique(dentry, inode);
-       if (res != NULL)
+       } else if (res != NULL)
                dentry = res;
        nfs_renew_times(dentry);
        nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
@@ -1014,7 +1007,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
         */
        lock_kernel();
        verifier = nfs_save_change_attribute(dir);
-       ret = nfs4_open_revalidate(dir, dentry, openflags);
+       ret = nfs4_open_revalidate(dir, dentry, openflags, nd);
        if (!ret)
                nfs_set_verifier(dentry, verifier);
        unlock_kernel();
@@ -1137,7 +1130,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
 
        lock_kernel();
        nfs_begin_data_update(dir);
-       error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags);
+       error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, nd);
        nfs_end_data_update(dir);
        if (error != 0)
                goto out_err;
@@ -1332,6 +1325,7 @@ static int nfs_safe_remove(struct dentry *dentry)
 
        nfs_begin_data_update(dir);
        if (inode != NULL) {
+               nfs_inode_return_delegation(inode);
                nfs_begin_data_update(inode);
                error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
                /* The VFS may want to delete this inode */
@@ -1438,17 +1432,14 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
                old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
                dentry->d_parent->d_name.name, dentry->d_name.name);
 
-       /*
-        * Drop the dentry in advance to force a new lookup.
-        * Since nfs_proc_link doesn't return a file handle,
-        * we can't use the existing dentry.
-        */
        lock_kernel();
-       d_drop(dentry);
-
        nfs_begin_data_update(dir);
        nfs_begin_data_update(inode);
        error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name);
+       if (error == 0) {
+               atomic_inc(&inode->i_count);
+               d_instantiate(dentry, inode);
+       }
        nfs_end_data_update(inode);
        nfs_end_data_update(dir);
        unlock_kernel();
@@ -1512,9 +1503,11 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
         */
        if (!new_inode)
                goto go_ahead;
-       if (S_ISDIR(new_inode->i_mode))
-               goto out;
-       else if (atomic_read(&new_dentry->d_count) > 2) {
+       if (S_ISDIR(new_inode->i_mode)) {
+               error = -EISDIR;
+               if (!S_ISDIR(old_inode->i_mode))
+                       goto out;
+       } else if (atomic_read(&new_dentry->d_count) > 2) {
                int err;
                /* copy the target dentry's name */
                dentry = d_alloc(new_dentry->d_parent,
@@ -1539,7 +1532,8 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 #endif
                        goto out;
                }
-       }
+       } else
+               new_inode->i_nlink--;
 
 go_ahead:
        /*
@@ -1549,6 +1543,7 @@ go_ahead:
                nfs_wb_all(old_inode);
                shrink_dcache_parent(old_dentry);
        }
+       nfs_inode_return_delegation(old_inode);
 
        if (new_inode)
                d_delete(new_dentry);
index 6bdcfa95de94630771ecbe79393c0cfdfd4f22bd..57d3e77d97ee1eb2e9c291695078d8b06f902d24 100644 (file)
@@ -205,8 +205,8 @@ nfs_file_flush(struct file *file)
        if (!status) {
                status = ctx->error;
                ctx->error = 0;
-               if (!status && !nfs_have_delegation(inode, FMODE_READ))
-                       __nfs_revalidate_inode(NFS_SERVER(inode), inode);
+               if (!status)
+                       nfs_revalidate_inode(NFS_SERVER(inode), inode);
        }
        unlock_kernel();
        return status;
@@ -376,22 +376,31 @@ out_swapfile:
 
 static int do_getlk(struct file *filp, int cmd, struct file_lock *fl)
 {
+       struct file_lock *cfl;
        struct inode *inode = filp->f_mapping->host;
        int status = 0;
 
        lock_kernel();
-       /* Use local locking if mounted with "-onolock" */
-       if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM))
-               status = NFS_PROTO(inode)->lock(filp, cmd, fl);
-       else {
-               struct file_lock *cfl = posix_test_lock(filp, fl);
-
-               fl->fl_type = F_UNLCK;
-               if (cfl != NULL)
-                       memcpy(fl, cfl, sizeof(*fl));
+       /* Try local locking first */
+       cfl = posix_test_lock(filp, fl);
+       if (cfl != NULL) {
+               locks_copy_lock(fl, cfl);
+               goto out;
        }
+
+       if (nfs_have_delegation(inode, FMODE_READ))
+               goto out_noconflict;
+
+       if (NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)
+               goto out_noconflict;
+
+       status = NFS_PROTO(inode)->lock(filp, cmd, fl);
+out:
        unlock_kernel();
        return status;
+out_noconflict:
+       fl->fl_type = F_UNLCK;
+       goto out;
 }
 
 static int do_vfs_lock(struct file *file, struct file_lock *fl)
index d4eadeea128e94f738c013eabe1bc69167645092..f2781ca42761c885a56ad2ea70effd4ca5f4599a 100644 (file)
@@ -358,6 +358,35 @@ out_no_root:
        return no_root_error;
 }
 
+static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, unsigned int timeo, unsigned int retrans)
+{
+       to->to_initval = timeo * HZ / 10;
+       to->to_retries = retrans;
+       if (!to->to_retries)
+               to->to_retries = 2;
+
+       switch (proto) {
+       case IPPROTO_TCP:
+               if (!to->to_initval)
+                       to->to_initval = 60 * HZ;
+               if (to->to_initval > NFS_MAX_TCP_TIMEOUT)
+                       to->to_initval = NFS_MAX_TCP_TIMEOUT;
+               to->to_increment = to->to_initval;
+               to->to_maxval = to->to_initval + (to->to_increment * to->to_retries);
+               to->to_exponential = 0;
+               break;
+       case IPPROTO_UDP:
+       default:
+               if (!to->to_initval)
+                       to->to_initval = 11 * HZ / 10;
+               if (to->to_initval > NFS_MAX_UDP_TIMEOUT)
+                       to->to_initval = NFS_MAX_UDP_TIMEOUT;
+               to->to_maxval = NFS_MAX_UDP_TIMEOUT;
+               to->to_exponential = 1;
+               break;
+       }
+}
+
 /*
  * Create an RPC client handle.
  */
@@ -367,22 +396,12 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data)
        struct rpc_timeout      timeparms;
        struct rpc_xprt         *xprt = NULL;
        struct rpc_clnt         *clnt = NULL;
-       int                     tcp   = (data->flags & NFS_MOUNT_TCP);
-
-       /* Initialize timeout values */
-       timeparms.to_initval = data->timeo * HZ / 10;
-       timeparms.to_retries = data->retrans;
-       timeparms.to_maxval  = tcp ? RPC_MAX_TCP_TIMEOUT : RPC_MAX_UDP_TIMEOUT;
-       timeparms.to_exponential = 1;
+       int                     proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
 
-       if (!timeparms.to_initval)
-               timeparms.to_initval = (tcp ? 600 : 11) * HZ / 10;
-       if (!timeparms.to_retries)
-               timeparms.to_retries = 5;
+       nfs_init_timeout_values(&timeparms, proto, data->timeo, data->retrans);
 
        /* create transport and client */
-       xprt = xprt_create_proto(tcp ? IPPROTO_TCP : IPPROTO_UDP,
-                                &server->addr, &timeparms);
+       xprt = xprt_create_proto(proto, &server->addr, &timeparms);
        if (IS_ERR(xprt)) {
                dprintk("%s: cannot create RPC transport. Error = %ld\n",
                                __FUNCTION__, PTR_ERR(xprt));
@@ -576,7 +595,6 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
                { NFS_MOUNT_SOFT, ",soft", ",hard" },
                { NFS_MOUNT_INTR, ",intr", "" },
                { NFS_MOUNT_POSIX, ",posix", "" },
-               { NFS_MOUNT_TCP, ",tcp", ",udp" },
                { NFS_MOUNT_NOCTO, ",nocto", "" },
                { NFS_MOUNT_NOAC, ",noac", "" },
                { NFS_MOUNT_NONLM, ",nolock", ",lock" },
@@ -585,6 +603,8 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
        };
        struct proc_nfs_info *nfs_infop;
        struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);
+       char buf[12];
+       char *proto;
 
        seq_printf(m, ",v%d", nfss->rpc_ops->version);
        seq_printf(m, ",rsize=%d", nfss->rsize);
@@ -603,6 +623,18 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
                else
                        seq_puts(m, nfs_infop->nostr);
        }
+       switch (nfss->client->cl_xprt->prot) {
+               case IPPROTO_TCP:
+                       proto = "tcp";
+                       break;
+               case IPPROTO_UDP:
+                       proto = "udp";
+                       break;
+               default:
+                       snprintf(buf, sizeof(buf), "%u", nfss->client->cl_xprt->prot);
+                       proto = buf;
+       }
+       seq_printf(m, ",proto=%s", proto);
        seq_puts(m, ",addr=");
        seq_escape(m, nfss->hostname, " \t\n\\");
        return 0;
@@ -753,7 +785,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
                else
                        init_special_inode(inode, inode->i_mode, fattr->rdev);
 
-               nfsi->read_cache_jiffies = fattr->timestamp;
+               nfsi->read_cache_jiffies = fattr->time_start;
+               nfsi->last_updated = jiffies;
                inode->i_atime = fattr->atime;
                inode->i_mtime = fattr->mtime;
                inode->i_ctime = fattr->ctime;
@@ -821,6 +854,11 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
                        filemap_fdatawait(inode->i_mapping);
                nfs_wb_all(inode);
        }
+       /*
+        * Return any delegations if we're going to change ACLs
+        */
+       if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0)
+               nfs_inode_return_delegation(inode);
        error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr);
        if (error == 0)
                nfs_refresh_inode(inode, &fattr);
@@ -1019,15 +1057,11 @@ int nfs_open(struct inode *inode, struct file *filp)
        ctx->mode = filp->f_mode;
        nfs_file_set_open_context(filp, ctx);
        put_nfs_open_context(ctx);
-       if ((filp->f_mode & FMODE_WRITE) != 0)
-               nfs_begin_data_update(inode);
        return 0;
 }
 
 int nfs_release(struct inode *inode, struct file *filp)
 {
-       if ((filp->f_mode & FMODE_WRITE) != 0)
-               nfs_end_data_update(inode);
        nfs_file_clear_open_context(filp);
        return 0;
 }
@@ -1083,14 +1117,15 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
                goto out;
        }
 
+       spin_lock(&inode->i_lock);
        status = nfs_update_inode(inode, &fattr, verifier);
        if (status) {
+               spin_unlock(&inode->i_lock);
                dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n",
                         inode->i_sb->s_id,
                         (long long)NFS_FILEID(inode), status);
                goto out;
        }
-       spin_lock(&inode->i_lock);
        cache_validity = nfsi->cache_validity;
        nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE;
 
@@ -1098,7 +1133,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
         * We may need to keep the attributes marked as invalid if
         * we raced with nfs_end_attr_update().
         */
-       if (verifier == nfsi->cache_change_attribute)
+       if (time_after_eq(verifier, nfsi->cache_change_attribute))
                nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME);
        spin_unlock(&inode->i_lock);
 
@@ -1165,7 +1200,7 @@ void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
                if (S_ISDIR(inode->i_mode)) {
                        memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf));
                        /* This ensures we revalidate child dentries */
-                       nfsi->cache_change_attribute++;
+                       nfsi->cache_change_attribute = jiffies;
                }
                spin_unlock(&inode->i_lock);
 
@@ -1197,20 +1232,19 @@ void nfs_end_data_update(struct inode *inode)
        struct nfs_inode *nfsi = NFS_I(inode);
 
        if (!nfs_have_delegation(inode, FMODE_READ)) {
-               /* Mark the attribute cache for revalidation */
-               spin_lock(&inode->i_lock);
-               nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
-               /* Directories and symlinks: invalidate page cache too */
-               if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+               /* Directories and symlinks: invalidate page cache */
+               if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) {
+                       spin_lock(&inode->i_lock);
                        nfsi->cache_validity |= NFS_INO_INVALID_DATA;
-               spin_unlock(&inode->i_lock);
+                       spin_unlock(&inode->i_lock);
+               }
        }
-       nfsi->cache_change_attribute ++;
+       nfsi->cache_change_attribute = jiffies;
        atomic_dec(&nfsi->data_updates);
 }
 
 /**
- * nfs_refresh_inode - verify consistency of the inode attribute cache
+ * nfs_check_inode_attributes - verify consistency of the inode attribute cache
  * @inode - pointer to inode
  * @fattr - updated attributes
  *
@@ -1218,13 +1252,12 @@ void nfs_end_data_update(struct inode *inode)
  * so that fattr carries weak cache consistency data, then it may
  * also update the ctime/mtime/change_attribute.
  */
-int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
+static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fattr)
 {
        struct nfs_inode *nfsi = NFS_I(inode);
        loff_t cur_size, new_isize;
        int data_unstable;
 
-       spin_lock(&inode->i_lock);
 
        /* Are we in the process of updating data on the server? */
        data_unstable = nfs_caches_unstable(inode);
@@ -1288,11 +1321,67 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
        if (!timespec_equal(&inode->i_atime, &fattr->atime))
                nfsi->cache_validity |= NFS_INO_INVALID_ATIME;
 
-       nfsi->read_cache_jiffies = fattr->timestamp;
-       spin_unlock(&inode->i_lock);
+       nfsi->read_cache_jiffies = fattr->time_start;
        return 0;
 }
 
+/**
+ * nfs_refresh_inode - try to update the inode attribute cache
+ * @inode - pointer to inode
+ * @fattr - updated attributes
+ *
+ * Check that an RPC call that returned attributes has not overlapped with
+ * other recent updates of the inode metadata, then decide whether it is
+ * safe to do a full update of the inode attributes, or whether just to
+ * call nfs_check_inode_attributes.
+ */
+int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
+{
+       struct nfs_inode *nfsi = NFS_I(inode);
+       int status;
+
+       if ((fattr->valid & NFS_ATTR_FATTR) == 0)
+               return 0;
+       spin_lock(&inode->i_lock);
+       nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE;
+       if (nfs_verify_change_attribute(inode, fattr->time_start))
+               nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME);
+       if (time_after(fattr->time_start, nfsi->last_updated))
+               status = nfs_update_inode(inode, fattr, fattr->time_start);
+       else
+               status = nfs_check_inode_attributes(inode, fattr);
+
+       spin_unlock(&inode->i_lock);
+       return status;
+}
+
+/**
+ * nfs_post_op_update_inode - try to update the inode attribute cache
+ * @inode - pointer to inode
+ * @fattr - updated attributes
+ *
+ * After an operation that has changed the inode metadata, mark the
+ * attribute cache as being invalid, then try to update it.
+ */
+int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr)
+{
+       struct nfs_inode *nfsi = NFS_I(inode);
+       int status = 0;
+
+       spin_lock(&inode->i_lock);
+       if (unlikely((fattr->valid & NFS_ATTR_FATTR) == 0)) {
+               nfsi->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS;
+               goto out;
+       }
+       status = nfs_update_inode(inode, fattr, fattr->time_start);
+       if (time_after_eq(fattr->time_start, nfsi->cache_change_attribute))
+               nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME|NFS_INO_REVAL_PAGECACHE);
+       nfsi->cache_change_attribute = jiffies;
+out:
+       spin_unlock(&inode->i_lock);
+       return status;
+}
+
 /*
  * Many nfs protocol calls return the new file attributes after
  * an operation.  Here we update the inode to reflect the state
@@ -1328,20 +1417,17 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
                goto out_err;
        }
 
-       spin_lock(&inode->i_lock);
-
        /*
         * Make sure the inode's type hasn't changed.
         */
-       if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) {
-               spin_unlock(&inode->i_lock);
+       if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT))
                goto out_changed;
-       }
 
        /*
         * Update the read time so we don't revalidate too often.
         */
-       nfsi->read_cache_jiffies = fattr->timestamp;
+       nfsi->read_cache_jiffies = fattr->time_start;
+       nfsi->last_updated = jiffies;
 
        /* Are we racing with known updates of the metadata on the server? */
        data_unstable = ! (nfs_verify_change_attribute(inode, verifier) ||
@@ -1354,7 +1440,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
                /* 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 (time_after_eq(verifier,  nfsi->cache_change_attribute)) {
                                inode->i_size = new_isize;
                                invalid |= NFS_INO_INVALID_DATA;
                        }
@@ -1430,7 +1516,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
        if (!nfs_have_delegation(inode, FMODE_READ))
                nfsi->cache_validity |= invalid;
 
-       spin_unlock(&inode->i_lock);
        return 0;
  out_changed:
        /*
@@ -1639,8 +1724,7 @@ static void nfs4_clear_inode(struct inode *inode)
        struct nfs_inode *nfsi = NFS_I(inode);
 
        /* If we are holding a delegation, return it! */
-       if (nfsi->delegation != NULL)
-               nfs_inode_return_delegation(inode);
+       nfs_inode_return_delegation(inode);
        /* First call standard NFS clear_inode() code */
        nfs_clear_inode(inode);
        /* Now clear out any remaining state */
@@ -1669,7 +1753,7 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
        struct rpc_clnt *clnt = NULL;
        struct rpc_timeout timeparms;
        rpc_authflavor_t authflavour;
-       int proto, err = -EIO;
+       int err = -EIO;
 
        sb->s_blocksize_bits = 0;
        sb->s_blocksize = 0;
@@ -1687,30 +1771,8 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
        server->acdirmax = data->acdirmax*HZ;
 
        server->rpc_ops = &nfs_v4_clientops;
-       /* Initialize timeout values */
-
-       timeparms.to_initval = data->timeo * HZ / 10;
-       timeparms.to_retries = data->retrans;
-       timeparms.to_exponential = 1;
-       if (!timeparms.to_retries)
-               timeparms.to_retries = 5;
 
-       proto = data->proto;
-       /* Which IP protocol do we use? */
-       switch (proto) {
-       case IPPROTO_TCP:
-               timeparms.to_maxval  = RPC_MAX_TCP_TIMEOUT;
-               if (!timeparms.to_initval)
-                       timeparms.to_initval = 600 * HZ / 10;
-               break;
-       case IPPROTO_UDP:
-               timeparms.to_maxval  = RPC_MAX_UDP_TIMEOUT;
-               if (!timeparms.to_initval)
-                       timeparms.to_initval = 11 * HZ / 10;
-               break;
-       default:
-               return -EINVAL;
-       }
+       nfs_init_timeout_values(&timeparms, data->proto, data->timeo, data->retrans);
 
        clp = nfs4_get_client(&server->addr.sin_addr);
        if (!clp) {
@@ -1735,7 +1797,7 @@ 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)) {
-               xprt = xprt_create_proto(proto, &server->addr, &timeparms);
+               xprt = xprt_create_proto(data->proto, &server->addr, &timeparms);
                if (IS_ERR(xprt)) {
                        up_write(&clp->cl_sem);
                        err = PTR_ERR(xprt);
index d91b69044a4d0d9ace47d2759cec997b6b3760fb..59049e864ca7818288559a91625526a45ec081db 100644 (file)
@@ -143,7 +143,6 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
                fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
                fattr->rdev = 0;
        }
-       fattr->timestamp = jiffies;
        return p;
 }
 
index edc95514046d50415b127988fc36ae577b8b3d97..92c870d19ccdbe61a44d4dcb110c83ef9067e3da 100644 (file)
@@ -78,7 +78,7 @@ nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
        int     status;
 
        dprintk("%s: call  fsinfo\n", __FUNCTION__);
-       info->fattr->valid = 0;
+       nfs_fattr_init(info->fattr);
        status = rpc_call(server->client_sys, NFS3PROC_FSINFO, fhandle, info, 0);
        dprintk("%s: reply fsinfo: %d\n", __FUNCTION__, status);
        if (!(info->fattr->valid & NFS_ATTR_FATTR)) {
@@ -98,7 +98,7 @@ nfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
        int     status;
 
        dprintk("NFS call  getattr\n");
-       fattr->valid = 0;
+       nfs_fattr_init(fattr);
        status = rpc_call(server->client, NFS3PROC_GETATTR,
                          fhandle, fattr, 0);
        dprintk("NFS reply getattr: %d\n", status);
@@ -117,7 +117,7 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
        int     status;
 
        dprintk("NFS call  setattr\n");
-       fattr->valid = 0;
+       nfs_fattr_init(fattr);
        status = rpc_call(NFS_CLIENT(inode), NFS3PROC_SETATTR, &arg, fattr, 0);
        if (status == 0)
                nfs_setattr_update_inode(inode, sattr);
@@ -143,8 +143,8 @@ nfs3_proc_lookup(struct inode *dir, struct qstr *name,
        int                     status;
 
        dprintk("NFS call  lookup %s\n", name->name);
-       dir_attr.valid = 0;
-       fattr->valid = 0;
+       nfs_fattr_init(&dir_attr);
+       nfs_fattr_init(fattr);
        status = rpc_call(NFS_CLIENT(dir), NFS3PROC_LOOKUP, &arg, &res, 0);
        if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR))
                status = rpc_call(NFS_CLIENT(dir), NFS3PROC_GETATTR,
@@ -174,7 +174,6 @@ static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry)
        int status;
 
        dprintk("NFS call  access\n");
-       fattr.valid = 0;
 
        if (mode & MAY_READ)
                arg.access |= NFS3_ACCESS_READ;
@@ -189,6 +188,7 @@ static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry)
                if (mode & MAY_EXEC)
                        arg.access |= NFS3_ACCESS_EXECUTE;
        }
+       nfs_fattr_init(&fattr);
        status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
        nfs_refresh_inode(inode, &fattr);
        if (status == 0) {
@@ -217,7 +217,7 @@ static int nfs3_proc_readlink(struct inode *inode, struct page *page,
        int                     status;
 
        dprintk("NFS call  readlink\n");
-       fattr.valid = 0;
+       nfs_fattr_init(&fattr);
        status = rpc_call(NFS_CLIENT(inode), NFS3PROC_READLINK,
                          &args, &fattr, 0);
        nfs_refresh_inode(inode, &fattr);
@@ -240,7 +240,7 @@ static int nfs3_proc_read(struct nfs_read_data *rdata)
 
        dprintk("NFS call  read %d @ %Ld\n", rdata->args.count,
                        (long long) rdata->args.offset);
-       fattr->valid = 0;
+       nfs_fattr_init(fattr);
        status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
        if (status >= 0)
                nfs_refresh_inode(inode, fattr);
@@ -263,10 +263,10 @@ static int nfs3_proc_write(struct nfs_write_data *wdata)
 
        dprintk("NFS call  write %d @ %Ld\n", wdata->args.count,
                        (long long) wdata->args.offset);
-       fattr->valid = 0;
+       nfs_fattr_init(fattr);
        status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags);
        if (status >= 0)
-               nfs_refresh_inode(inode, fattr);
+               nfs_post_op_update_inode(inode, fattr);
        dprintk("NFS reply write: %d\n", status);
        return status < 0? status : wdata->res.count;
 }
@@ -285,10 +285,10 @@ static int nfs3_proc_commit(struct nfs_write_data *cdata)
 
        dprintk("NFS call  commit %d @ %Ld\n", cdata->args.count,
                        (long long) cdata->args.offset);
-       fattr->valid = 0;
+       nfs_fattr_init(fattr);
        status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
        if (status >= 0)
-               nfs_refresh_inode(inode, fattr);
+               nfs_post_op_update_inode(inode, fattr);
        dprintk("NFS reply commit: %d\n", status);
        return status;
 }
@@ -299,7 +299,7 @@ static int nfs3_proc_commit(struct nfs_write_data *cdata)
  */
 static int
 nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-                int flags)
+                int flags, struct nameidata *nd)
 {
        struct nfs_fh           fhandle;
        struct nfs_fattr        fattr;
@@ -329,10 +329,10 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
        sattr->ia_mode &= ~current->fs->umask;
 
 again:
-       dir_attr.valid = 0;
-       fattr.valid = 0;
+       nfs_fattr_init(&dir_attr);
+       nfs_fattr_init(&fattr);
        status = rpc_call(NFS_CLIENT(dir), NFS3PROC_CREATE, &arg, &res, 0);
-       nfs_refresh_inode(dir, &dir_attr);
+       nfs_post_op_update_inode(dir, &dir_attr);
 
        /* If the server doesn't support the exclusive creation semantics,
         * try again with simple 'guarded' mode. */
@@ -401,9 +401,9 @@ nfs3_proc_remove(struct inode *dir, struct qstr *name)
        int                     status;
 
        dprintk("NFS call  remove %s\n", name->name);
-       dir_attr.valid = 0;
+       nfs_fattr_init(&dir_attr);
        status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
-       nfs_refresh_inode(dir, &dir_attr);
+       nfs_post_op_update_inode(dir, &dir_attr);
        dprintk("NFS reply remove: %d\n", status);
        return status;
 }
@@ -422,7 +422,7 @@ nfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr
        ptr->arg.fh = NFS_FH(dir->d_inode);
        ptr->arg.name = name->name;
        ptr->arg.len = name->len;
-       ptr->res.valid = 0;
+       nfs_fattr_init(&ptr->res);
        msg->rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE];
        msg->rpc_argp = &ptr->arg;
        msg->rpc_resp = &ptr->res;
@@ -439,7 +439,7 @@ nfs3_proc_unlink_done(struct dentry *dir, struct rpc_task *task)
                return 1;
        if (msg->rpc_argp) {
                dir_attr = (struct nfs_fattr*)msg->rpc_resp;
-               nfs_refresh_inode(dir->d_inode, dir_attr);
+               nfs_post_op_update_inode(dir->d_inode, dir_attr);
                kfree(msg->rpc_argp);
        }
        return 0;
@@ -465,11 +465,11 @@ nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name,
        int                     status;
 
        dprintk("NFS call  rename %s -> %s\n", old_name->name, new_name->name);
-       old_dir_attr.valid = 0;
-       new_dir_attr.valid = 0;
+       nfs_fattr_init(&old_dir_attr);
+       nfs_fattr_init(&new_dir_attr);
        status = rpc_call(NFS_CLIENT(old_dir), NFS3PROC_RENAME, &arg, &res, 0);
-       nfs_refresh_inode(old_dir, &old_dir_attr);
-       nfs_refresh_inode(new_dir, &new_dir_attr);
+       nfs_post_op_update_inode(old_dir, &old_dir_attr);
+       nfs_post_op_update_inode(new_dir, &new_dir_attr);
        dprintk("NFS reply rename: %d\n", status);
        return status;
 }
@@ -491,11 +491,11 @@ nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
        int                     status;
 
        dprintk("NFS call  link %s\n", name->name);
-       dir_attr.valid = 0;
-       fattr.valid = 0;
+       nfs_fattr_init(&dir_attr);
+       nfs_fattr_init(&fattr);
        status = rpc_call(NFS_CLIENT(inode), NFS3PROC_LINK, &arg, &res, 0);
-       nfs_refresh_inode(dir, &dir_attr);
-       nfs_refresh_inode(inode, &fattr);
+       nfs_post_op_update_inode(dir, &dir_attr);
+       nfs_post_op_update_inode(inode, &fattr);
        dprintk("NFS reply link: %d\n", status);
        return status;
 }
@@ -524,10 +524,10 @@ nfs3_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
        if (path->len > NFS3_MAXPATHLEN)
                return -ENAMETOOLONG;
        dprintk("NFS call  symlink %s -> %s\n", name->name, path->name);
-       dir_attr.valid = 0;
-       fattr->valid = 0;
+       nfs_fattr_init(&dir_attr);
+       nfs_fattr_init(fattr);
        status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SYMLINK, &arg, &res, 0);
-       nfs_refresh_inode(dir, &dir_attr);
+       nfs_post_op_update_inode(dir, &dir_attr);
        dprintk("NFS reply symlink: %d\n", status);
        return status;
 }
@@ -552,13 +552,13 @@ nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
        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;
 
+       nfs_fattr_init(&dir_attr);
+       nfs_fattr_init(&fattr);
        status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, 0);
-       nfs_refresh_inode(dir, &dir_attr);
+       nfs_post_op_update_inode(dir, &dir_attr);
        if (status != 0)
                goto out;
        status = nfs_instantiate(dentry, &fhandle, &fattr);
@@ -582,9 +582,9 @@ nfs3_proc_rmdir(struct inode *dir, struct qstr *name)
        int                     status;
 
        dprintk("NFS call  rmdir %s\n", name->name);
-       dir_attr.valid = 0;
+       nfs_fattr_init(&dir_attr);
        status = rpc_call(NFS_CLIENT(dir), NFS3PROC_RMDIR, &arg, &dir_attr, 0);
-       nfs_refresh_inode(dir, &dir_attr);
+       nfs_post_op_update_inode(dir, &dir_attr);
        dprintk("NFS reply rmdir: %d\n", status);
        return status;
 }
@@ -634,7 +634,7 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
        dprintk("NFS call  readdir%s %d\n",
                        plus? "plus" : "", (unsigned int) cookie);
 
-       dir_attr.valid = 0;
+       nfs_fattr_init(&dir_attr);
        status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
        nfs_refresh_inode(dir, &dir_attr);
        dprintk("NFS reply readdir: %d\n", status);
@@ -676,10 +676,10 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 
        sattr->ia_mode &= ~current->fs->umask;
 
-       dir_attr.valid = 0;
-       fattr.valid = 0;
+       nfs_fattr_init(&dir_attr);
+       nfs_fattr_init(&fattr);
        status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, 0);
-       nfs_refresh_inode(dir, &dir_attr);
+       nfs_post_op_update_inode(dir, &dir_attr);
        if (status != 0)
                goto out;
        status = nfs_instantiate(dentry, &fh, &fattr);
@@ -698,7 +698,7 @@ nfs3_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
        int     status;
 
        dprintk("NFS call  fsstat\n");
-       stat->fattr->valid = 0;
+       nfs_fattr_init(stat->fattr);
        status = rpc_call(server->client, NFS3PROC_FSSTAT, fhandle, stat, 0);
        dprintk("NFS reply statfs: %d\n", status);
        return status;
@@ -711,7 +711,7 @@ nfs3_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
        int     status;
 
        dprintk("NFS call  fsinfo\n");
-       info->fattr->valid = 0;
+       nfs_fattr_init(info->fattr);
        status = rpc_call(server->client_sys, NFS3PROC_FSINFO, fhandle, info, 0);
        dprintk("NFS reply fsinfo: %d\n", status);
        return status;
@@ -724,7 +724,7 @@ nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
        int     status;
 
        dprintk("NFS call  pathconf\n");
-       info->fattr->valid = 0;
+       nfs_fattr_init(info->fattr);
        status = rpc_call(server->client, NFS3PROC_PATHCONF, fhandle, info, 0);
        dprintk("NFS reply pathconf: %d\n", status);
        return status;
@@ -735,7 +735,7 @@ extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int);
 static void
 nfs3_read_done(struct rpc_task *task)
 {
-       struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
+       struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata;
 
        if (nfs3_async_handle_jukebox(task))
                return;
@@ -775,7 +775,7 @@ nfs3_write_done(struct rpc_task *task)
                return;
        data = (struct nfs_write_data *)task->tk_calldata;
        if (task->tk_status >= 0)
-               nfs_refresh_inode(data->inode, data->res.fattr);
+               nfs_post_op_update_inode(data->inode, data->res.fattr);
        nfs_writeback_done(task);
 }
 
@@ -819,7 +819,7 @@ nfs3_commit_done(struct rpc_task *task)
                return;
        data = (struct nfs_write_data *)task->tk_calldata;
        if (task->tk_status >= 0)
-               nfs_refresh_inode(data->inode, data->res.fattr);
+               nfs_post_op_update_inode(data->inode, data->res.fattr);
        nfs_commit_done(task);
 }
 
index db4a904810a460f0dd6090b12c65c7e5526ac499..0498bd36602cba22cef6cf1c760e645dfaa72318 100644 (file)
@@ -174,7 +174,6 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
 
        /* Update the mode bits */
        fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3);
-       fattr->timestamp = jiffies;
        return p;
 }
 
index ec1a22d7b876694199c5d5b23fb3dc22b92b646a..78a53f5a9f18ae629606e1b9ddabb441baa72f28 100644 (file)
@@ -92,26 +92,51 @@ struct nfs4_client {
        unsigned char           cl_id_uniquifier;
 };
 
+/*
+ * struct rpc_sequence ensures that RPC calls are sent in the exact
+ * order that they appear on the list.
+ */
+struct rpc_sequence {
+       struct rpc_wait_queue   wait;   /* RPC call delay queue */
+       spinlock_t lock;                /* Protects the list */
+       struct list_head list;          /* Defines sequence of RPC calls */
+};
+
+#define NFS_SEQID_CONFIRMED 1
+struct nfs_seqid_counter {
+       struct rpc_sequence *sequence;
+       int flags;
+       u32 counter;
+};
+
+struct nfs_seqid {
+       struct nfs_seqid_counter *sequence;
+       struct list_head list;
+};
+
+static inline void nfs_confirm_seqid(struct nfs_seqid_counter *seqid, int status)
+{
+       if (seqid_mutating_err(-status))
+               seqid->flags |= NFS_SEQID_CONFIRMED;
+}
+
 /*
  * 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 {
+       spinlock_t           so_lock;
        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 nfs_seqid_counter so_seqid;
+       struct rpc_sequence  so_sequence;
 };
 
 /*
@@ -132,7 +157,7 @@ struct nfs4_lock_state {
        fl_owner_t              ls_owner;       /* POSIX lock owner */
 #define NFS_LOCK_INITIALIZED 1
        int                     ls_flags;
-       u32                     ls_seqid;
+       struct nfs_seqid_counter        ls_seqid;
        u32                     ls_id;
        nfs4_stateid            ls_stateid;
        atomic_t                ls_count;
@@ -153,7 +178,6 @@ struct nfs4_state {
        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;
@@ -191,8 +215,8 @@ 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 dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
+extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
 
 extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
 extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops;
@@ -224,12 +248,17 @@ extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state
 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 void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
 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 struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter);
+extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task);
+extern void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid);
+extern void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid);
+extern void nfs_free_seqid(struct nfs_seqid *seqid);
+
 extern const nfs4_stateid zero_stateid;
 
 /* nfs4xdr.c */
index 9701ca8c942855a719ccd98559fd878c60ee636c..933e13b383f8f45d1f548d585127409bfe05d69e 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/nfs_page.h>
 #include <linux/smp_lock.h>
 #include <linux/namei.h>
+#include <linux/mount.h>
 
 #include "nfs4_fs.h"
 #include "delegation.h"
 #define NFS4_POLL_RETRY_MIN    (1*HZ)
 #define NFS4_POLL_RETRY_MAX    (15*HZ)
 
+static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid, struct nfs_seqid *seqid);
 static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
-static int nfs4_async_handle_error(struct rpc_task *, struct nfs_server *);
+static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *);
 static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry);
-static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
+static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
 extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus);
 extern struct rpc_procinfo nfs4_procedures[];
 
@@ -185,8 +187,26 @@ static void update_changeattr(struct inode *inode, struct nfs4_change_info *cinf
 {
        struct nfs_inode *nfsi = NFS_I(inode);
 
+       spin_lock(&inode->i_lock);
+       nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
        if (cinfo->before == nfsi->change_attr && cinfo->atomic)
                nfsi->change_attr = cinfo->after;
+       spin_unlock(&inode->i_lock);
+}
+
+/* Helper for asynchronous RPC calls */
+static int nfs4_call_async(struct rpc_clnt *clnt, rpc_action tk_begin,
+               rpc_action tk_exit, void *calldata)
+{
+       struct rpc_task *task;
+
+       if (!(task = rpc_new_task(clnt, tk_exit, RPC_TASK_ASYNC)))
+               return -ENOMEM;
+
+       task->tk_calldata = calldata;
+       task->tk_action = tk_begin;
+       rpc_execute(task);
+       return 0;
 }
 
 static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags)
@@ -195,6 +215,7 @@ static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid,
 
        open_flags &= (FMODE_READ|FMODE_WRITE);
        /* Protect against nfs4_find_state() */
+       spin_lock(&state->owner->so_lock);
        spin_lock(&inode->i_lock);
        state->state |= open_flags;
        /* NB! List reordering - see the reclaim code for why.  */
@@ -204,12 +225,12 @@ static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid,
                state->nreaders++;
        memcpy(&state->stateid, stateid, sizeof(state->stateid));
        spin_unlock(&inode->i_lock);
+       spin_unlock(&state->owner->so_lock);
 }
 
 /*
  * OPEN_RECLAIM:
  *     reclaim state on the server after a reboot.
- *     Assumes caller is holding the sp->so_sem
  */
 static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
 {
@@ -218,7 +239,6 @@ static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *st
        struct nfs_delegation *delegation = NFS_I(inode)->delegation;
        struct nfs_openargs o_arg = {
                .fh = NFS_FH(inode),
-               .seqid = sp->so_seqid,
                .id = sp->so_id,
                .open_flags = state->state,
                .clientid = server->nfs4_state->cl_clientid,
@@ -245,8 +265,13 @@ static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *st
                }
                o_arg.u.delegation_type = delegation->type;
        }
+       o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
+       if (o_arg.seqid == NULL)
+               return -ENOMEM;
        status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
-       nfs4_increment_seqid(status, sp);
+       /* Confirm the sequence as being established */
+       nfs_confirm_seqid(&sp->so_seqid, status);
+       nfs_increment_open_seqid(status, o_arg.seqid);
        if (status == 0) {
                memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid));
                if (o_res.delegation_type != 0) {
@@ -256,6 +281,7 @@ static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *st
                                nfs_async_inode_return_delegation(inode, &o_res.stateid);
                }
        }
+       nfs_free_seqid(o_arg.seqid);
        clear_bit(NFS_DELEGATED_STATE, &state->flags);
        /* Ensure we update the inode attributes */
        NFS_CACHEINV(inode);
@@ -302,23 +328,35 @@ static int _nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state
        };
        int status = 0;
 
-       down(&sp->so_sema);
        if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
                goto out;
        if (state->state == 0)
                goto out;
-       arg.seqid = sp->so_seqid;
+       arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
+       status = -ENOMEM;
+       if (arg.seqid == NULL)
+               goto out;
        arg.open_flags = state->state;
        memcpy(arg.u.delegation.data, state->stateid.data, sizeof(arg.u.delegation.data));
        status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
-       nfs4_increment_seqid(status, sp);
+       nfs_increment_open_seqid(status, arg.seqid);
+       if (status != 0)
+               goto out_free;
+       if(res.rflags & NFS4_OPEN_RESULT_CONFIRM) {
+               status = _nfs4_proc_open_confirm(server->client, NFS_FH(inode),
+                               sp, &res.stateid, arg.seqid);
+               if (status != 0)
+                       goto out_free;
+       }
+       nfs_confirm_seqid(&sp->so_seqid, 0);
        if (status >= 0) {
                memcpy(state->stateid.data, res.stateid.data,
                                sizeof(state->stateid.data));
                clear_bit(NFS_DELEGATED_STATE, &state->flags);
        }
+out_free:
+       nfs_free_seqid(arg.seqid);
 out:
-       up(&sp->so_sema);
        dput(parent);
        return status;
 }
@@ -345,11 +383,11 @@ int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
        return err;
 }
 
-static inline int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid)
+static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid, struct nfs_seqid *seqid)
 {
        struct nfs_open_confirmargs arg = {
                .fh             = fh,
-               .seqid          = sp->so_seqid,
+               .seqid          = seqid,
                .stateid        = *stateid,
        };
        struct nfs_open_confirmres res;
@@ -362,7 +400,9 @@ static inline int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nf
        int status;
 
        status = rpc_call_sync(clnt, &msg, RPC_TASK_NOINTR);
-       nfs4_increment_seqid(status, sp);
+       /* Confirm the sequence as being established */
+       nfs_confirm_seqid(&sp->so_seqid, status);
+       nfs_increment_open_seqid(status, seqid);
        if (status >= 0)
                memcpy(stateid, &res.stateid, sizeof(*stateid));
        return status;
@@ -380,21 +420,41 @@ static int _nfs4_proc_open(struct inode *dir, struct nfs4_state_owner  *sp, stru
        int status;
 
        /* Update sequence id. The caller must serialize! */
-       o_arg->seqid = sp->so_seqid;
        o_arg->id = sp->so_id;
        o_arg->clientid = sp->so_client->cl_clientid;
 
        status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
-       nfs4_increment_seqid(status, sp);
+       if (status == 0) {
+               /* OPEN on anything except a regular file is disallowed in NFSv4 */
+               switch (o_res->f_attr->mode & S_IFMT) {
+                       case S_IFREG:
+                               break;
+                       case S_IFLNK:
+                               status = -ELOOP;
+                               break;
+                       case S_IFDIR:
+                               status = -EISDIR;
+                               break;
+                       default:
+                               status = -ENOTDIR;
+               }
+       }
+
+       nfs_increment_open_seqid(status, o_arg->seqid);
        if (status != 0)
                goto out;
-       update_changeattr(dir, &o_res->cinfo);
+       if (o_arg->open_flags & O_CREAT) {
+               update_changeattr(dir, &o_res->cinfo);
+               nfs_post_op_update_inode(dir, o_res->dir_attr);
+       } else
+               nfs_refresh_inode(dir, o_res->dir_attr);
        if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
                status = _nfs4_proc_open_confirm(server->client, &o_res->fh,
-                               sp, &o_res->stateid);
+                               sp, &o_res->stateid, o_arg->seqid);
                if (status != 0)
                        goto out;
        }
+       nfs_confirm_seqid(&sp->so_seqid, 0);
        if (!(o_res->f_attr->valid & NFS_ATTR_FATTR))
                status = server->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr);
 out:
@@ -441,9 +501,7 @@ static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st
        struct inode *inode = state->inode;
        struct nfs_server *server = NFS_SERVER(dir);
        struct nfs_delegation *delegation = NFS_I(inode)->delegation;
-       struct nfs_fattr        f_attr = {
-               .valid = 0,
-       };
+       struct nfs_fattr f_attr, dir_attr;
        struct nfs_openargs o_arg = {
                .fh = NFS_FH(dir),
                .open_flags = state->state,
@@ -453,6 +511,7 @@ static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st
        };
        struct nfs_openres o_res = {
                .f_attr = &f_attr,
+               .dir_attr = &dir_attr,
                .server = server,
        };
        int status = 0;
@@ -465,6 +524,12 @@ static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st
                set_bit(NFS_DELEGATED_STATE, &state->flags);
                goto out;
        }
+       o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
+       status = -ENOMEM;
+       if (o_arg.seqid == NULL)
+               goto out;
+       nfs_fattr_init(&f_attr);
+       nfs_fattr_init(&dir_attr);
        status = _nfs4_proc_open(dir, sp, &o_arg, &o_res);
        if (status != 0)
                goto out_nodeleg;
@@ -490,6 +555,7 @@ static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st
                        nfs_inode_reclaim_delegation(inode, sp->so_cred, &o_res);
        }
 out_nodeleg:
+       nfs_free_seqid(o_arg.seqid);
        clear_bit(NFS_DELEGATED_STATE, &state->flags);
 out:
        dput(parent);
@@ -564,7 +630,6 @@ static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred
                dprintk("%s: nfs4_get_state_owner failed!\n", __FUNCTION__);
                goto out_err;
        }
-       down(&sp->so_sema);
        state = nfs4_get_open_state(inode, sp);
        if (state == NULL)
                goto out_err;
@@ -589,7 +654,6 @@ static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred
        set_bit(NFS_DELEGATED_STATE, &state->flags);
        update_open_stateid(state, &delegation->stateid, open_flags);
 out_ok:
-       up(&sp->so_sema);
        nfs4_put_state_owner(sp);
        up_read(&nfsi->rwsem);
        up_read(&clp->cl_sem);
@@ -600,11 +664,12 @@ out_err:
        if (sp != NULL) {
                if (state != NULL)
                        nfs4_put_open_state(state);
-               up(&sp->so_sema);
                nfs4_put_state_owner(sp);
        }
        up_read(&nfsi->rwsem);
        up_read(&clp->cl_sem);
+       if (err != -EACCES)
+               nfs_inode_return_delegation(inode);
        return err;
 }
 
@@ -635,9 +700,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st
        struct nfs4_client *clp = server->nfs4_state;
        struct inode *inode = NULL;
        int                     status;
-       struct nfs_fattr        f_attr = {
-               .valid          = 0,
-       };
+       struct nfs_fattr f_attr, dir_attr;
        struct nfs_openargs o_arg = {
                .fh             = NFS_FH(dir),
                .open_flags     = flags,
@@ -648,6 +711,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st
        };
        struct nfs_openres o_res = {
                .f_attr         = &f_attr,
+               .dir_attr       = &dir_attr,
                .server         = server,
        };
 
@@ -665,8 +729,12 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st
        } else
                o_arg.u.attrs = sattr;
        /* Serialization for the sequence id */
-       down(&sp->so_sema);
 
+       o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
+       if (o_arg.seqid == NULL)
+               return -ENOMEM;
+       nfs_fattr_init(&f_attr);
+       nfs_fattr_init(&dir_attr);
        status = _nfs4_proc_open(dir, sp, &o_arg, &o_res);
        if (status != 0)
                goto out_err;
@@ -681,7 +749,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st
        update_open_stateid(state, &o_res.stateid, flags);
        if (o_res.delegation_type != 0)
                nfs_inode_set_delegation(inode, cred, &o_res);
-       up(&sp->so_sema);
+       nfs_free_seqid(o_arg.seqid);
        nfs4_put_state_owner(sp);
        up_read(&clp->cl_sem);
        *res = state;
@@ -690,7 +758,7 @@ out_err:
        if (sp != NULL) {
                if (state != NULL)
                        nfs4_put_open_state(state);
-               up(&sp->so_sema);
+               nfs_free_seqid(o_arg.seqid);
                nfs4_put_state_owner(sp);
        }
        /* Note: clp->cl_sem must be released before nfs4_put_open_state()! */
@@ -718,7 +786,7 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry,
                 * It is actually a sign of a bug on the client or on the server.
                 *
                 * If we receive a BAD_SEQID error in the particular case of
-                * doing an OPEN, we assume that nfs4_increment_seqid() will
+                * doing an OPEN, we assume that nfs_increment_open_seqid() will
                 * have unhashed the old state_owner for us, and that we can
                 * therefore safely retry using a new one. We should still warn
                 * the user though...
@@ -728,6 +796,16 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry,
                        exception.retry = 1;
                        continue;
                }
+               /*
+                * BAD_STATEID on OPEN means that the server cancelled our
+                * state before it received the OPEN_CONFIRM.
+                * Recover by retrying the request as per the discussion
+                * on Page 181 of RFC3530.
+                */
+               if (status == -NFS4ERR_BAD_STATEID) {
+                       exception.retry = 1;
+                       continue;
+               }
                res = ERR_PTR(nfs4_handle_exception(NFS_SERVER(dir),
                                        status, &exception));
        } while (exception.retry);
@@ -755,7 +833,7 @@ static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
         };
        int status;
 
-        fattr->valid = 0;
+       nfs_fattr_init(fattr);
 
        if (state != NULL) {
                msg.rpc_cred = state->owner->so_cred;
@@ -787,19 +865,30 @@ struct nfs4_closedata {
        struct nfs4_state *state;
        struct nfs_closeargs arg;
        struct nfs_closeres res;
+       struct nfs_fattr fattr;
 };
 
+static void nfs4_free_closedata(struct nfs4_closedata *calldata)
+{
+       struct nfs4_state *state = calldata->state;
+       struct nfs4_state_owner *sp = state->owner;
+
+       nfs4_put_open_state(calldata->state);
+       nfs_free_seqid(calldata->arg.seqid);
+       nfs4_put_state_owner(sp);
+       kfree(calldata);
+}
+
 static void nfs4_close_done(struct rpc_task *task)
 {
        struct nfs4_closedata *calldata = (struct nfs4_closedata *)task->tk_calldata;
        struct nfs4_state *state = calldata->state;
-       struct nfs4_state_owner *sp = state->owner;
        struct nfs_server *server = NFS_SERVER(calldata->inode);
 
         /* hmm. we are done with the inode, and in the process of freeing
         * the state_owner. we keep this around to process errors
         */
-       nfs4_increment_seqid(task->tk_status, sp);
+       nfs_increment_open_seqid(task->tk_status, calldata->arg.seqid);
        switch (task->tk_status) {
                case 0:
                        memcpy(&state->stateid, &calldata->res.stateid,
@@ -816,25 +905,49 @@ static void nfs4_close_done(struct rpc_task *task)
                                return;
                        }
        }
+       nfs_refresh_inode(calldata->inode, calldata->res.fattr);
        state->state = calldata->arg.open_flags;
-       nfs4_put_open_state(state);
-       up(&sp->so_sema);
-       nfs4_put_state_owner(sp);
-       up_read(&server->nfs4_state->cl_sem);
-       kfree(calldata);
+       nfs4_free_closedata(calldata);
 }
 
-static inline int nfs4_close_call(struct rpc_clnt *clnt, struct nfs4_closedata *calldata)
+static void nfs4_close_begin(struct rpc_task *task)
 {
+       struct nfs4_closedata *calldata = (struct nfs4_closedata *)task->tk_calldata;
+       struct nfs4_state *state = calldata->state;
        struct rpc_message msg = {
                .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE],
                .rpc_argp = &calldata->arg,
                .rpc_resp = &calldata->res,
-               .rpc_cred = calldata->state->owner->so_cred,
+               .rpc_cred = state->owner->so_cred,
        };
-       if (calldata->arg.open_flags != 0)
+       int mode = 0;
+       int status;
+
+       status = nfs_wait_on_sequence(calldata->arg.seqid, task);
+       if (status != 0)
+               return;
+       /* Don't reorder reads */
+       smp_rmb();
+       /* Recalculate the new open mode in case someone reopened the file
+        * while we were waiting in line to be scheduled.
+        */
+       if (state->nreaders != 0)
+               mode |= FMODE_READ;
+       if (state->nwriters != 0)
+               mode |= FMODE_WRITE;
+       if (test_bit(NFS_DELEGATED_STATE, &state->flags))
+               state->state = mode;
+       if (mode == state->state) {
+               nfs4_free_closedata(calldata);
+               task->tk_exit = NULL;
+               rpc_exit(task, 0);
+               return;
+       }
+       nfs_fattr_init(calldata->res.fattr);
+       if (mode != 0)
                msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
-       return rpc_call_async(clnt, &msg, 0, nfs4_close_done, calldata);
+       calldata->arg.open_flags = mode;
+       rpc_call_setup(task, &msg, 0);
 }
 
 /* 
@@ -850,40 +963,57 @@ static inline int nfs4_close_call(struct rpc_clnt *clnt, struct nfs4_closedata *
  */
 int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode) 
 {
+       struct nfs_server *server = NFS_SERVER(inode);
        struct nfs4_closedata *calldata;
-       int status;
+       int status = -ENOMEM;
 
-       /* Tell caller we're done */
-       if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
-               state->state = mode;
-               return 0;
-       }
-       calldata = (struct nfs4_closedata *)kmalloc(sizeof(*calldata), GFP_KERNEL);
+       calldata = kmalloc(sizeof(*calldata), GFP_KERNEL);
        if (calldata == NULL)
-               return -ENOMEM;
+               goto out;
        calldata->inode = inode;
        calldata->state = state;
        calldata->arg.fh = NFS_FH(inode);
+       calldata->arg.stateid = &state->stateid;
        /* Serialization for the sequence id */
-       calldata->arg.seqid = state->owner->so_seqid;
-       calldata->arg.open_flags = mode;
-       memcpy(&calldata->arg.stateid, &state->stateid,
-                       sizeof(calldata->arg.stateid));
-       status = nfs4_close_call(NFS_SERVER(inode)->client, calldata);
-       /*
-        * Return -EINPROGRESS on success in order to indicate to the
-        * caller that an asynchronous RPC call has been launched, and
-        * that it will release the semaphores on completion.
-        */
-       return (status == 0) ? -EINPROGRESS : status;
+       calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid);
+       if (calldata->arg.seqid == NULL)
+               goto out_free_calldata;
+       calldata->arg.bitmask = server->attr_bitmask;
+       calldata->res.fattr = &calldata->fattr;
+       calldata->res.server = server;
+
+       status = nfs4_call_async(server->client, nfs4_close_begin,
+                       nfs4_close_done, calldata);
+       if (status == 0)
+               goto out;
+
+       nfs_free_seqid(calldata->arg.seqid);
+out_free_calldata:
+       kfree(calldata);
+out:
+       return status;
 }
 
-struct inode *
+static void nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, struct nfs4_state *state)
+{
+       struct file *filp;
+
+       filp = lookup_instantiate_filp(nd, dentry, NULL);
+       if (!IS_ERR(filp)) {
+               struct nfs_open_context *ctx;
+               ctx = (struct nfs_open_context *)filp->private_data;
+               ctx->state = state;
+       } else
+               nfs4_close_state(state, nd->intent.open.flags);
+}
+
+struct dentry *
 nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
        struct iattr attr;
        struct rpc_cred *cred;
        struct nfs4_state *state;
+       struct dentry *res;
 
        if (nd->flags & LOOKUP_CREATE) {
                attr.ia_mode = nd->intent.open.create_mode;
@@ -897,16 +1027,23 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 
        cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
        if (IS_ERR(cred))
-               return (struct inode *)cred;
+               return (struct dentry *)cred;
        state = nfs4_do_open(dir, dentry, nd->intent.open.flags, &attr, cred);
        put_rpccred(cred);
-       if (IS_ERR(state))
-               return (struct inode *)state;
-       return state->inode;
+       if (IS_ERR(state)) {
+               if (PTR_ERR(state) == -ENOENT)
+                       d_add(dentry, NULL);
+               return (struct dentry *)state;
+       }
+       res = d_add_unique(dentry, state->inode);
+       if (res != NULL)
+               dentry = res;
+       nfs4_intent_set_file(nd, dentry, state);
+       return res;
 }
 
 int
-nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags)
+nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, struct nameidata *nd)
 {
        struct rpc_cred *cred;
        struct nfs4_state *state;
@@ -919,18 +1056,30 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags)
        if (IS_ERR(state))
                state = nfs4_do_open(dir, dentry, openflags, NULL, cred);
        put_rpccred(cred);
-       if (state == ERR_PTR(-ENOENT) && dentry->d_inode == 0)
-               return 1;
-       if (IS_ERR(state))
-               return 0;
+       if (IS_ERR(state)) {
+               switch (PTR_ERR(state)) {
+                       case -EPERM:
+                       case -EACCES:
+                       case -EDQUOT:
+                       case -ENOSPC:
+                       case -EROFS:
+                               lookup_instantiate_filp(nd, (struct dentry *)state, NULL);
+                               return 1;
+                       case -ENOENT:
+                               if (dentry->d_inode == NULL)
+                                       return 1;
+               }
+               goto out_drop;
+       }
        inode = state->inode;
+       iput(inode);
        if (inode == dentry->d_inode) {
-               iput(inode);
+               nfs4_intent_set_file(nd, dentry, state);
                return 1;
        }
-       d_drop(dentry);
        nfs4_close_state(state, openflags);
-       iput(inode);
+out_drop:
+       d_drop(dentry);
        return 0;
 }
 
@@ -974,13 +1123,12 @@ static int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fh
 static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
                struct nfs_fsinfo *info)
 {
-       struct nfs_fattr *      fattr = info->fattr;
        struct nfs4_lookup_root_arg args = {
                .bitmask = nfs4_fattr_bitmap,
        };
        struct nfs4_lookup_res res = {
                .server = server,
-               .fattr = fattr,
+               .fattr = info->fattr,
                .fh = fhandle,
        };
        struct rpc_message msg = {
@@ -988,7 +1136,7 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
                .rpc_argp = &args,
                .rpc_resp = &res,
        };
-       fattr->valid = 0;
+       nfs_fattr_init(info->fattr);
        return rpc_call_sync(server->client, &msg, 0);
 }
 
@@ -1051,7 +1199,7 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
                q.len = p - q.name;
 
                do {
-                       fattr->valid = 0;
+                       nfs_fattr_init(fattr);
                        status = nfs4_handle_exception(server,
                                        rpc_call_sync(server->client, &msg, 0),
                                        &exception);
@@ -1088,7 +1236,7 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
                .rpc_resp = &res,
        };
        
-       fattr->valid = 0;
+       nfs_fattr_init(fattr);
        return rpc_call_sync(server->client, &msg, 0);
 }
 
@@ -1130,7 +1278,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
        struct nfs4_state *state;
        int status;
 
-       fattr->valid = 0;
+       nfs_fattr_init(fattr);
        
        cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
        if (IS_ERR(cred))
@@ -1176,7 +1324,7 @@ static int _nfs4_proc_lookup(struct inode *dir, struct qstr *name,
                .rpc_resp = &res,
        };
        
-       fattr->valid = 0;
+       nfs_fattr_init(fattr);
        
        dprintk("NFS call  lookup %s\n", name->name);
        status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
@@ -1325,7 +1473,7 @@ static int _nfs4_proc_read(struct nfs_read_data *rdata)
        dprintk("NFS call  read %d @ %Ld\n", rdata->args.count,
                        (long long) rdata->args.offset);
 
-       fattr->valid = 0;
+       nfs_fattr_init(fattr);
        status = rpc_call_sync(server->client, &msg, flags);
        if (!status)
                renew_lease(server, timestamp);
@@ -1362,7 +1510,7 @@ static int _nfs4_proc_write(struct nfs_write_data *wdata)
        dprintk("NFS call  write %d @ %Ld\n", wdata->args.count,
                        (long long) wdata->args.offset);
 
-       fattr->valid = 0;
+       nfs_fattr_init(fattr);
        status = rpc_call_sync(server->client, &msg, rpcflags);
        dprintk("NFS reply write: %d\n", status);
        return status;
@@ -1396,7 +1544,7 @@ static int _nfs4_proc_commit(struct nfs_write_data *cdata)
        dprintk("NFS call  commit %d @ %Ld\n", cdata->args.count,
                        (long long) cdata->args.offset);
 
-       fattr->valid = 0;
+       nfs_fattr_init(fattr);
        status = rpc_call_sync(server->client, &msg, 0);
        dprintk("NFS reply commit: %d\n", status);
        return status;
@@ -1431,7 +1579,7 @@ static int nfs4_proc_commit(struct nfs_write_data *cdata)
 
 static int
 nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-                 int flags)
+                 int flags, struct nameidata *nd)
 {
        struct nfs4_state *state;
        struct rpc_cred *cred;
@@ -1453,24 +1601,30 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                struct nfs_fattr fattr;
                status = nfs4_do_setattr(NFS_SERVER(dir), &fattr,
                                     NFS_FH(state->inode), sattr, state);
-               if (status == 0) {
+               if (status == 0)
                        nfs_setattr_update_inode(state->inode, sattr);
-                       goto out;
-               }
-       } else if (flags != 0)
-               goto out;
-       nfs4_close_state(state, flags);
+       }
+       if (status == 0 && nd != NULL && (nd->flags & LOOKUP_OPEN))
+               nfs4_intent_set_file(nd, dentry, state);
+       else
+               nfs4_close_state(state, flags);
 out:
        return status;
 }
 
 static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
 {
+       struct nfs_server *server = NFS_SERVER(dir);
        struct nfs4_remove_arg args = {
                .fh = NFS_FH(dir),
                .name = name,
+               .bitmask = server->attr_bitmask,
+       };
+       struct nfs_fattr dir_attr;
+       struct nfs4_remove_res  res = {
+               .server = server,
+               .dir_attr = &dir_attr,
        };
-       struct nfs4_change_info res;
        struct rpc_message msg = {
                .rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_REMOVE],
                .rpc_argp       = &args,
@@ -1478,9 +1632,12 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
        };
        int                     status;
 
-       status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
-       if (status == 0)
-               update_changeattr(dir, &res);
+       nfs_fattr_init(res.dir_attr);
+       status = rpc_call_sync(server->client, &msg, 0);
+       if (status == 0) {
+               update_changeattr(dir, &res.cinfo);
+               nfs_post_op_update_inode(dir, res.dir_attr);
+       }
        return status;
 }
 
@@ -1498,12 +1655,14 @@ static int nfs4_proc_remove(struct inode *dir, struct qstr *name)
 
 struct unlink_desc {
        struct nfs4_remove_arg  args;
-       struct nfs4_change_info res;
+       struct nfs4_remove_res  res;
+       struct nfs_fattr dir_attr;
 };
 
 static int nfs4_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir,
                struct qstr *name)
 {
+       struct nfs_server *server = NFS_SERVER(dir->d_inode);
        struct unlink_desc *up;
 
        up = (struct unlink_desc *) kmalloc(sizeof(*up), GFP_KERNEL);
@@ -1512,6 +1671,9 @@ static int nfs4_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir,
        
        up->args.fh = NFS_FH(dir->d_inode);
        up->args.name = name;
+       up->args.bitmask = server->attr_bitmask;
+       up->res.server = server;
+       up->res.dir_attr = &up->dir_attr;
        
        msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE];
        msg->rpc_argp = &up->args;
@@ -1526,7 +1688,8 @@ static int nfs4_proc_unlink_done(struct dentry *dir, struct rpc_task *task)
        
        if (msg->rpc_resp != NULL) {
                up = container_of(msg->rpc_resp, struct unlink_desc, res);
-               update_changeattr(dir->d_inode, &up->res);
+               update_changeattr(dir->d_inode, &up->res.cinfo);
+               nfs_post_op_update_inode(dir->d_inode, up->res.dir_attr);
                kfree(up);
                msg->rpc_resp = NULL;
                msg->rpc_argp = NULL;
@@ -1537,13 +1700,20 @@ static int nfs4_proc_unlink_done(struct dentry *dir, struct rpc_task *task)
 static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
                struct inode *new_dir, struct qstr *new_name)
 {
+       struct nfs_server *server = NFS_SERVER(old_dir);
        struct nfs4_rename_arg arg = {
                .old_dir = NFS_FH(old_dir),
                .new_dir = NFS_FH(new_dir),
                .old_name = old_name,
                .new_name = new_name,
+               .bitmask = server->attr_bitmask,
+       };
+       struct nfs_fattr old_fattr, new_fattr;
+       struct nfs4_rename_res res = {
+               .server = server,
+               .old_fattr = &old_fattr,
+               .new_fattr = &new_fattr,
        };
-       struct nfs4_rename_res res = { };
        struct rpc_message msg = {
                .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME],
                .rpc_argp = &arg,
@@ -1551,11 +1721,15 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
        };
        int                     status;
        
-       status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0);
+       nfs_fattr_init(res.old_fattr);
+       nfs_fattr_init(res.new_fattr);
+       status = rpc_call_sync(server->client, &msg, 0);
 
        if (!status) {
                update_changeattr(old_dir, &res.old_cinfo);
+               nfs_post_op_update_inode(old_dir, res.old_fattr);
                update_changeattr(new_dir, &res.new_cinfo);
+               nfs_post_op_update_inode(new_dir, res.new_fattr);
        }
        return status;
 }
@@ -1576,22 +1750,34 @@ static int nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
 
 static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
 {
+       struct nfs_server *server = NFS_SERVER(inode);
        struct nfs4_link_arg arg = {
                .fh     = NFS_FH(inode),
                .dir_fh = NFS_FH(dir),
                .name   = name,
+               .bitmask = server->attr_bitmask,
+       };
+       struct nfs_fattr fattr, dir_attr;
+       struct nfs4_link_res res = {
+               .server = server,
+               .fattr = &fattr,
+               .dir_attr = &dir_attr,
        };
-       struct nfs4_change_info cinfo = { };
        struct rpc_message msg = {
                .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK],
                .rpc_argp = &arg,
-               .rpc_resp = &cinfo,
+               .rpc_resp = &res,
        };
        int                     status;
 
-       status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
-       if (!status)
-               update_changeattr(dir, &cinfo);
+       nfs_fattr_init(res.fattr);
+       nfs_fattr_init(res.dir_attr);
+       status = rpc_call_sync(server->client, &msg, 0);
+       if (!status) {
+               update_changeattr(dir, &res.cinfo);
+               nfs_post_op_update_inode(dir, res.dir_attr);
+               nfs_refresh_inode(inode, res.fattr);
+       }
 
        return status;
 }
@@ -1613,6 +1799,7 @@ static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name,
                struct nfs_fattr *fattr)
 {
        struct nfs_server *server = NFS_SERVER(dir);
+       struct nfs_fattr dir_fattr;
        struct nfs4_create_arg arg = {
                .dir_fh = NFS_FH(dir),
                .server = server,
@@ -1625,6 +1812,7 @@ static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name,
                .server = server,
                .fh = fhandle,
                .fattr = fattr,
+               .dir_fattr = &dir_fattr,
        };
        struct rpc_message msg = {
                .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK],
@@ -1636,11 +1824,13 @@ static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name,
        if (path->len > NFS4_MAXPATHLEN)
                return -ENAMETOOLONG;
        arg.u.symlink = path;
-       fattr->valid = 0;
+       nfs_fattr_init(fattr);
+       nfs_fattr_init(&dir_fattr);
        
        status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
        if (!status)
                update_changeattr(dir, &res.dir_cinfo);
+       nfs_post_op_update_inode(dir, res.dir_fattr);
        return status;
 }
 
@@ -1664,7 +1854,7 @@ static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
 {
        struct nfs_server *server = NFS_SERVER(dir);
        struct nfs_fh fhandle;
-       struct nfs_fattr fattr;
+       struct nfs_fattr fattr, dir_fattr;
        struct nfs4_create_arg arg = {
                .dir_fh = NFS_FH(dir),
                .server = server,
@@ -1677,6 +1867,7 @@ static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
                .server = server,
                .fh = &fhandle,
                .fattr = &fattr,
+               .dir_fattr = &dir_fattr,
        };
        struct rpc_message msg = {
                .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
@@ -1685,11 +1876,13 @@ static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
        };
        int                     status;
 
-       fattr.valid = 0;
+       nfs_fattr_init(&fattr);
+       nfs_fattr_init(&dir_fattr);
        
        status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
        if (!status) {
                update_changeattr(dir, &res.dir_cinfo);
+               nfs_post_op_update_inode(dir, res.dir_fattr);
                status = nfs_instantiate(dentry, &fhandle, &fattr);
        }
        return status;
@@ -1762,7 +1955,7 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
 {
        struct nfs_server *server = NFS_SERVER(dir);
        struct nfs_fh fh;
-       struct nfs_fattr fattr;
+       struct nfs_fattr fattr, dir_fattr;
        struct nfs4_create_arg arg = {
                .dir_fh = NFS_FH(dir),
                .server = server,
@@ -1774,6 +1967,7 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
                .server = server,
                .fh = &fh,
                .fattr = &fattr,
+               .dir_fattr = &dir_fattr,
        };
        struct rpc_message msg = {
                .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
@@ -1783,7 +1977,8 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
        int                     status;
        int                     mode = sattr->ia_mode;
 
-       fattr.valid = 0;
+       nfs_fattr_init(&fattr);
+       nfs_fattr_init(&dir_fattr);
 
        BUG_ON(!(sattr->ia_valid & ATTR_MODE));
        BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode));
@@ -1805,6 +2000,7 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
        status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
        if (status == 0) {
                update_changeattr(dir, &res.dir_cinfo);
+               nfs_post_op_update_inode(dir, res.dir_fattr);
                status = nfs_instantiate(dentry, &fh, &fattr);
        }
        return status;
@@ -1836,7 +2032,7 @@ static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
                .rpc_resp = fsstat,
        };
 
-       fsstat->fattr->valid = 0;
+       nfs_fattr_init(fsstat->fattr);
        return rpc_call_sync(server->client, &msg, 0);
 }
 
@@ -1883,7 +2079,7 @@ static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, str
 
 static int nfs4_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
 {
-       fsinfo->fattr->valid = 0;
+       nfs_fattr_init(fsinfo->fattr);
        return nfs4_do_fsinfo(server, fhandle, fsinfo);
 }
 
@@ -1906,7 +2102,7 @@ static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle
                return 0;
        }
 
-       pathconf->fattr->valid = 0;
+       nfs_fattr_init(pathconf->fattr);
        return rpc_call_sync(server->client, &msg, 0);
 }
 
@@ -1973,8 +2169,10 @@ nfs4_write_done(struct rpc_task *task)
                rpc_restart_call(task);
                return;
        }
-       if (task->tk_status >= 0)
+       if (task->tk_status >= 0) {
                renew_lease(NFS_SERVER(inode), data->timestamp);
+               nfs_post_op_update_inode(inode, data->res.fattr);
+       }
        /* Call back common NFS writeback processing */
        nfs_writeback_done(task);
 }
@@ -1990,6 +2188,7 @@ nfs4_proc_write_setup(struct nfs_write_data *data, int how)
                .rpc_cred = data->cred,
        };
        struct inode *inode = data->inode;
+       struct nfs_server *server = NFS_SERVER(inode);
        int stable;
        int flags;
        
@@ -2001,6 +2200,8 @@ nfs4_proc_write_setup(struct nfs_write_data *data, int how)
        } else
                stable = NFS_UNSTABLE;
        data->args.stable = stable;
+       data->args.bitmask = server->attr_bitmask;
+       data->res.server = server;
 
        data->timestamp   = jiffies;
 
@@ -2022,6 +2223,8 @@ nfs4_commit_done(struct rpc_task *task)
                rpc_restart_call(task);
                return;
        }
+       if (task->tk_status >= 0)
+               nfs_post_op_update_inode(inode, data->res.fattr);
        /* Call back common NFS writeback processing */
        nfs_commit_done(task);
 }
@@ -2037,8 +2240,12 @@ nfs4_proc_commit_setup(struct nfs_write_data *data, int how)
                .rpc_cred = data->cred,
        };      
        struct inode *inode = data->inode;
+       struct nfs_server *server = NFS_SERVER(inode);
        int flags;
        
+       data->args.bitmask = server->attr_bitmask;
+       data->res.server = server;
+
        /* Set the initial flags for the task.  */
        flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
 
@@ -2106,65 +2313,6 @@ nfs4_proc_renew(struct nfs4_client *clp)
        return 0;
 }
 
-/*
- * We will need to arrange for the VFS layer to provide an atomic open.
- * Until then, this open method is prone to inefficiency and race conditions
- * due to the lookup, potential create, and open VFS calls from sys_open()
- * placed on the wire.
- */
-static int
-nfs4_proc_file_open(struct inode *inode, struct file *filp)
-{
-       struct dentry *dentry = filp->f_dentry;
-       struct nfs_open_context *ctx;
-       struct nfs4_state *state = NULL;
-       struct rpc_cred *cred;
-       int status = -ENOMEM;
-
-       dprintk("nfs4_proc_file_open: starting on (%.*s/%.*s)\n",
-                              (int)dentry->d_parent->d_name.len,
-                              dentry->d_parent->d_name.name,
-                              (int)dentry->d_name.len, dentry->d_name.name);
-
-
-       /* Find our open stateid */
-       cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
-       if (IS_ERR(cred))
-               return PTR_ERR(cred);
-       ctx = alloc_nfs_open_context(dentry, cred);
-       put_rpccred(cred);
-       if (unlikely(ctx == NULL))
-               return -ENOMEM;
-       status = -EIO; /* ERACE actually */
-       state = nfs4_find_state(inode, cred, filp->f_mode);
-       if (unlikely(state == NULL))
-               goto no_state;
-       ctx->state = state;
-       nfs4_close_state(state, filp->f_mode);
-       ctx->mode = filp->f_mode;
-       nfs_file_set_open_context(filp, ctx);
-       put_nfs_open_context(ctx);
-       if (filp->f_mode & FMODE_WRITE)
-               nfs_begin_data_update(inode);
-       return 0;
-no_state:
-       printk(KERN_WARNING "NFS: v4 raced in function %s\n", __FUNCTION__);
-       put_nfs_open_context(ctx);
-       return status;
-}
-
-/*
- * Release our state
- */
-static int
-nfs4_proc_file_release(struct inode *inode, struct file *filp)
-{
-       if (filp->f_mode & FMODE_WRITE)
-               nfs_end_data_update(inode);
-       nfs_file_clear_open_context(filp);
-       return 0;
-}
-
 static inline int nfs4_server_supports_acls(struct nfs_server *server)
 {
        return (server->caps & NFS_CAP_ACLS)
@@ -2285,7 +2433,7 @@ static inline ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size
                        return -ENOMEM;
                args.acl_pages[0] = localpage;
                args.acl_pgbase = 0;
-               args.acl_len = PAGE_SIZE;
+               resp_len = args.acl_len = PAGE_SIZE;
        } else {
                resp_buf = buf;
                buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase);
@@ -2345,6 +2493,7 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen
 
        if (!nfs4_server_supports_acls(server))
                return -EOPNOTSUPP;
+       nfs_inode_return_delegation(inode);
        buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
        ret = rpc_call_sync(NFS_SERVER(inode)->client, &msg, 0);
        if (ret == 0)
@@ -2353,7 +2502,7 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen
 }
 
 static int
-nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server)
+nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)
 {
        struct nfs4_client *clp = server->nfs4_state;
 
@@ -2431,7 +2580,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout)
 /* This is the error handling routine for processes that are allowed
  * to sleep.
  */
-int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception)
+int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception)
 {
        struct nfs4_client *clp = server->nfs4_state;
        int ret = errorcode;
@@ -2632,7 +2781,6 @@ 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;
@@ -2659,7 +2807,6 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock
                status = 0;
        }
 out:
-       up(&state->lock_sema);
        up_read(&clp->cl_sem);
        return status;
 }
@@ -2696,79 +2843,149 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl)
        return res;
 }
 
-static int _nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
+struct nfs4_unlockdata {
+       struct nfs_lockargs arg;
+       struct nfs_locku_opargs luargs;
+       struct nfs_lockres res;
+       struct nfs4_lock_state *lsp;
+       struct nfs_open_context *ctx;
+       atomic_t refcount;
+       struct completion completion;
+};
+
+static void nfs4_locku_release_calldata(struct nfs4_unlockdata *calldata)
 {
-       struct inode *inode = state->inode;
-       struct nfs_server *server = NFS_SERVER(inode);
-       struct nfs4_client *clp = server->nfs4_state;
-       struct nfs_lockargs arg = {
-               .fh = NFS_FH(inode),
-               .type = nfs4_lck_type(cmd, request),
-               .offset = request->fl_start,
-               .length = nfs4_lck_length(request),
-       };
-       struct nfs_lockres res = {
-               .server = server,
-       };
+       if (atomic_dec_and_test(&calldata->refcount)) {
+               nfs_free_seqid(calldata->luargs.seqid);
+               nfs4_put_lock_state(calldata->lsp);
+               put_nfs_open_context(calldata->ctx);
+               kfree(calldata);
+       }
+}
+
+static void nfs4_locku_complete(struct nfs4_unlockdata *calldata)
+{
+       complete(&calldata->completion);
+       nfs4_locku_release_calldata(calldata);
+}
+
+static void nfs4_locku_done(struct rpc_task *task)
+{
+       struct nfs4_unlockdata *calldata = (struct nfs4_unlockdata *)task->tk_calldata;
+
+       nfs_increment_lock_seqid(task->tk_status, calldata->luargs.seqid);
+       switch (task->tk_status) {
+               case 0:
+                       memcpy(calldata->lsp->ls_stateid.data,
+                                       calldata->res.u.stateid.data,
+                                       sizeof(calldata->lsp->ls_stateid.data));
+                       break;
+               case -NFS4ERR_STALE_STATEID:
+               case -NFS4ERR_EXPIRED:
+                       nfs4_schedule_state_recovery(calldata->res.server->nfs4_state);
+                       break;
+               default:
+                       if (nfs4_async_handle_error(task, calldata->res.server) == -EAGAIN) {
+                               rpc_restart_call(task);
+                               return;
+                       }
+       }
+       nfs4_locku_complete(calldata);
+}
+
+static void nfs4_locku_begin(struct rpc_task *task)
+{
+       struct nfs4_unlockdata *calldata = (struct nfs4_unlockdata *)task->tk_calldata;
        struct rpc_message msg = {
                .rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_LOCKU],
-               .rpc_argp       = &arg,
-               .rpc_resp       = &res,
-               .rpc_cred       = state->owner->so_cred,
+               .rpc_argp       = &calldata->arg,
+               .rpc_resp       = &calldata->res,
+               .rpc_cred       = calldata->lsp->ls_state->owner->so_cred,
        };
+       int status;
+
+       status = nfs_wait_on_sequence(calldata->luargs.seqid, task);
+       if (status != 0)
+               return;
+       if ((calldata->lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) {
+               nfs4_locku_complete(calldata);
+               task->tk_exit = NULL;
+               rpc_exit(task, 0);
+               return;
+       }
+       rpc_call_setup(task, &msg, 0);
+}
+
+static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
+{
+       struct nfs4_unlockdata *calldata;
+       struct inode *inode = state->inode;
+       struct nfs_server *server = NFS_SERVER(inode);
        struct nfs4_lock_state *lsp;
-       struct nfs_locku_opargs luargs;
        int status;
-                       
-       down_read(&clp->cl_sem);
-       down(&state->lock_sema);
+
        status = nfs4_set_lock_state(state, request);
        if (status != 0)
-               goto out;
+               return status;
        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 (status == 0)
-               memcpy(&lsp->ls_stateid,  &res.u.stateid, 
-                               sizeof(lsp->ls_stateid));
-out:
-       up(&state->lock_sema);
+               return 0;
+       calldata = kmalloc(sizeof(*calldata), GFP_KERNEL);
+       if (calldata == NULL)
+               return -ENOMEM;
+       calldata->luargs.seqid = nfs_alloc_seqid(&lsp->ls_seqid);
+       if (calldata->luargs.seqid == NULL) {
+               kfree(calldata);
+               return -ENOMEM;
+       }
+       calldata->luargs.stateid = &lsp->ls_stateid;
+       calldata->arg.fh = NFS_FH(inode);
+       calldata->arg.type = nfs4_lck_type(cmd, request);
+       calldata->arg.offset = request->fl_start;
+       calldata->arg.length = nfs4_lck_length(request);
+       calldata->arg.u.locku = &calldata->luargs;
+       calldata->res.server = server;
+       calldata->lsp = lsp;
+       atomic_inc(&lsp->ls_count);
+
+       /* Ensure we don't close file until we're done freeing locks! */
+       calldata->ctx = get_nfs_open_context((struct nfs_open_context*)request->fl_file->private_data);
+
+       atomic_set(&calldata->refcount, 2);
+       init_completion(&calldata->completion);
+
+       status = nfs4_call_async(NFS_SERVER(inode)->client, nfs4_locku_begin,
+                       nfs4_locku_done, calldata);
        if (status == 0)
-               do_vfs_lock(request->fl_file, request);
-       up_read(&clp->cl_sem);
+               wait_for_completion_interruptible(&calldata->completion);
+       do_vfs_lock(request->fl_file, request);
+       nfs4_locku_release_calldata(calldata);
        return status;
 }
 
-static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
-{
-       struct nfs4_exception exception = { };
-       int err;
-
-       do {
-               err = nfs4_handle_exception(NFS_SERVER(state->inode),
-                               _nfs4_proc_unlck(state, cmd, request),
-                               &exception);
-       } while (exception.retry);
-       return err;
-}
-
 static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *request, int reclaim)
 {
        struct inode *inode = state->inode;
        struct nfs_server *server = NFS_SERVER(inode);
        struct nfs4_lock_state *lsp = request->fl_u.nfs4_fl.owner;
+       struct nfs_lock_opargs largs = {
+               .lock_stateid = &lsp->ls_stateid,
+               .open_stateid = &state->stateid,
+               .lock_owner = {
+                       .clientid = server->nfs4_state->cl_clientid,
+                       .id = lsp->ls_id,
+               },
+               .reclaim = reclaim,
+       };
        struct nfs_lockargs arg = {
                .fh = NFS_FH(inode),
                .type = nfs4_lck_type(cmd, request),
                .offset = request->fl_start,
                .length = nfs4_lck_length(request),
+               .u = {
+                       .lock = &largs,
+               },
        };
        struct nfs_lockres res = {
                .server = server,
@@ -2779,53 +2996,39 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *r
                .rpc_resp       = &res,
                .rpc_cred       = state->owner->so_cred,
        };
-       struct nfs_lock_opargs largs = {
-               .reclaim = reclaim,
-               .new_lock_owner = 0,
-       };
-       int status;
+       int status = -ENOMEM;
 
-       if (!(lsp->ls_flags & NFS_LOCK_INITIALIZED)) {
+       largs.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid);
+       if (largs.lock_seqid == NULL)
+               return -ENOMEM;
+       if (!(lsp->ls_seqid.flags & NFS_SEQID_CONFIRMED)) {
                struct nfs4_state_owner *owner = state->owner;
-               struct nfs_open_to_lock otl = {
-                       .lock_owner = {
-                               .clientid = server->nfs4_state->cl_clientid,
-                       },
-               };
-
-               otl.lock_seqid = lsp->ls_seqid;
-               otl.lock_owner.id = lsp->ls_id;
-               memcpy(&otl.open_stateid, &state->stateid, sizeof(otl.open_stateid));
-               largs.u.open_lock = &otl;
+
+               largs.open_seqid = nfs_alloc_seqid(&owner->so_seqid);
+               if (largs.open_seqid == NULL)
+                       goto out;
                largs.new_lock_owner = 1;
-               arg.u.lock = &largs;
-               down(&owner->so_sema);
-               otl.open_seqid = owner->so_seqid;
                status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
-               /* increment open_owner seqid on success, and 
-               * seqid mutating errors */
-               nfs4_increment_seqid(status, owner);
-               up(&owner->so_sema);
-               if (status == 0) {
-                       lsp->ls_flags |= NFS_LOCK_INITIALIZED;
-                       lsp->ls_seqid++;
+               /* increment open seqid on success, and seqid mutating errors */
+               if (largs.new_lock_owner != 0) {
+                       nfs_increment_open_seqid(status, largs.open_seqid);
+                       if (status == 0)
+                               nfs_confirm_seqid(&lsp->ls_seqid, 0);
                }
-       } else {
-               struct nfs_exist_lock el = {
-                       .seqid = lsp->ls_seqid,
-               };
-               memcpy(&el.stateid, &lsp->ls_stateid, sizeof(el.stateid));
-               largs.u.exist_lock = &el;
-               arg.u.lock = &largs;
+               nfs_free_seqid(largs.open_seqid);
+       } else
                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 lock seqid on success, and seqid mutating errors*/
+       nfs_increment_lock_seqid(status, largs.lock_seqid);
        /* save the returned stateid. */
-       if (status == 0)
-               memcpy(&lsp->ls_stateid, &res.u.stateid, sizeof(nfs4_stateid));
-       else if (status == -NFS4ERR_DENIED)
+       if (status == 0) {
+               memcpy(lsp->ls_stateid.data, res.u.stateid.data,
+                               sizeof(lsp->ls_stateid.data));
+               lsp->ls_flags |= NFS_LOCK_INITIALIZED;
+       } else if (status == -NFS4ERR_DENIED)
                status = -EAGAIN;
+out:
+       nfs_free_seqid(largs.lock_seqid);
        return status;
 }
 
@@ -2865,11 +3068,9 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock
        int status;
 
        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);
-       up(&state->lock_sema);
        if (status == 0) {
                /* Note: we always want to sleep here! */
                request->fl_flags |= FL_SLEEP;
@@ -3024,8 +3225,8 @@ struct nfs_rpc_ops        nfs_v4_clientops = {
        .read_setup     = nfs4_proc_read_setup,
        .write_setup    = nfs4_proc_write_setup,
        .commit_setup   = nfs4_proc_commit_setup,
-       .file_open      = nfs4_proc_file_open,
-       .file_release   = nfs4_proc_file_release,
+       .file_open      = nfs_open,
+       .file_release   = nfs_release,
        .lock           = nfs4_proc_lock,
        .clear_acl_cache = nfs4_zap_acl_attr,
 };
index afe587d82f1e71ebc8eabab97c1b9e45bdf67365..2d5a6a2b9dec780616ff5691258a86bc9cea45f6 100644 (file)
@@ -264,13 +264,16 @@ nfs4_alloc_state_owner(void)
 {
        struct nfs4_state_owner *sp;
 
-       sp = kmalloc(sizeof(*sp),GFP_KERNEL);
+       sp = kzalloc(sizeof(*sp),GFP_KERNEL);
        if (!sp)
                return NULL;
-       init_MUTEX(&sp->so_sema);
-       sp->so_seqid = 0;                 /* arbitrary */
+       spin_lock_init(&sp->so_lock);
        INIT_LIST_HEAD(&sp->so_states);
        INIT_LIST_HEAD(&sp->so_delegations);
+       rpc_init_wait_queue(&sp->so_sequence.wait, "Seqid_waitqueue");
+       sp->so_seqid.sequence = &sp->so_sequence;
+       spin_lock_init(&sp->so_sequence.lock);
+       INIT_LIST_HEAD(&sp->so_sequence.list);
        atomic_set(&sp->so_count, 1);
        return sp;
 }
@@ -359,7 +362,6 @@ nfs4_alloc_open_state(void)
        memset(state->stateid.data, 0, sizeof(state->stateid.data));
        atomic_set(&state->count, 1);
        INIT_LIST_HEAD(&state->lock_states);
-       init_MUTEX(&state->lock_sema);
        spin_lock_init(&state->state_lock);
        return state;
 }
@@ -437,21 +439,23 @@ nfs4_get_open_state(struct inode *inode, struct nfs4_state_owner *owner)
        if (state)
                goto out;
        new = nfs4_alloc_open_state();
+       spin_lock(&owner->so_lock);
        spin_lock(&inode->i_lock);
        state = __nfs4_find_state_byowner(inode, owner);
        if (state == NULL && new != NULL) {
                state = new;
-               /* Caller *must* be holding owner->so_sem */
-               /* Note: The reclaim code dictates that we add stateless
-                * and read-only stateids to the end of the list */
-               list_add_tail(&state->open_states, &owner->so_states);
                state->owner = owner;
                atomic_inc(&owner->so_count);
                list_add(&state->inode_states, &nfsi->open_states);
                state->inode = igrab(inode);
                spin_unlock(&inode->i_lock);
+               /* Note: The reclaim code dictates that we add stateless
+                * and read-only stateids to the end of the list */
+               list_add_tail(&state->open_states, &owner->so_states);
+               spin_unlock(&owner->so_lock);
        } else {
                spin_unlock(&inode->i_lock);
+               spin_unlock(&owner->so_lock);
                if (new)
                        nfs4_free_open_state(new);
        }
@@ -461,19 +465,21 @@ out:
 
 /*
  * Beware! Caller must be holding exactly one
- * reference to clp->cl_sem and owner->so_sema!
+ * reference to clp->cl_sem!
  */
 void nfs4_put_open_state(struct nfs4_state *state)
 {
        struct inode *inode = state->inode;
        struct nfs4_state_owner *owner = state->owner;
 
-       if (!atomic_dec_and_lock(&state->count, &inode->i_lock))
+       if (!atomic_dec_and_lock(&state->count, &owner->so_lock))
                return;
+       spin_lock(&inode->i_lock);
        if (!list_empty(&state->inode_states))
                list_del(&state->inode_states);
-       spin_unlock(&inode->i_lock);
        list_del(&state->open_states);
+       spin_unlock(&inode->i_lock);
+       spin_unlock(&owner->so_lock);
        iput(inode);
        BUG_ON (state->state != 0);
        nfs4_free_open_state(state);
@@ -481,20 +487,17 @@ void nfs4_put_open_state(struct nfs4_state *state)
 }
 
 /*
- * Beware! Caller must be holding no references to clp->cl_sem!
- * of owner->so_sema!
+ * Close the current file.
  */
 void nfs4_close_state(struct nfs4_state *state, mode_t mode)
 {
        struct inode *inode = state->inode;
        struct nfs4_state_owner *owner = state->owner;
-       struct nfs4_client *clp = owner->so_client;
        int newstate;
 
        atomic_inc(&owner->so_count);
-       down_read(&clp->cl_sem);
-       down(&owner->so_sema);
        /* Protect against nfs4_find_state() */
+       spin_lock(&owner->so_lock);
        spin_lock(&inode->i_lock);
        if (mode & FMODE_READ)
                state->nreaders--;
@@ -507,6 +510,7 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode)
                list_move_tail(&state->open_states, &owner->so_states);
        }
        spin_unlock(&inode->i_lock);
+       spin_unlock(&owner->so_lock);
        newstate = 0;
        if (state->state != 0) {
                if (state->nreaders)
@@ -515,14 +519,16 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode)
                        newstate |= FMODE_WRITE;
                if (state->state == newstate)
                        goto out;
-               if (nfs4_do_close(inode, state, newstate) == -EINPROGRESS)
+               if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
+                       state->state = newstate;
+                       goto out;
+               }
+               if (nfs4_do_close(inode, state, newstate) == 0)
                        return;
        }
 out:
        nfs4_put_open_state(state);
-       up(&owner->so_sema);
        nfs4_put_state_owner(owner);
-       up_read(&clp->cl_sem);
 }
 
 /*
@@ -546,19 +552,16 @@ __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
  * Return a compatible lock_state. If no initialized lock_state structure
  * exists, return an uninitialized one.
  *
- * The caller must be holding state->lock_sema
  */
 static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
 {
        struct nfs4_lock_state *lsp;
        struct nfs4_client *clp = state->owner->so_client;
 
-       lsp = kmalloc(sizeof(*lsp), GFP_KERNEL);
+       lsp = kzalloc(sizeof(*lsp), GFP_KERNEL);
        if (lsp == NULL)
                return NULL;
-       lsp->ls_flags = 0;
-       lsp->ls_seqid = 0;      /* arbitrary */
-       memset(lsp->ls_stateid.data, 0, sizeof(lsp->ls_stateid.data));
+       lsp->ls_seqid.sequence = &state->owner->so_sequence;
        atomic_set(&lsp->ls_count, 1);
        lsp->ls_owner = fl_owner;
        spin_lock(&clp->cl_lock);
@@ -572,7 +575,7 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f
  * Return a compatible lock_state. If no initialized lock_state structure
  * exists, return an uninitialized one.
  *
- * The caller must be holding state->lock_sema and clp->cl_sem
+ * The caller must be holding clp->cl_sem
  */
 static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner)
 {
@@ -605,7 +608,7 @@ static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_
  * Release reference to lock_state, and free it if we see that
  * it is no longer in use
  */
-static void nfs4_put_lock_state(struct nfs4_lock_state *lsp)
+void nfs4_put_lock_state(struct nfs4_lock_state *lsp)
 {
        struct nfs4_state *state;
 
@@ -673,29 +676,94 @@ void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t f
        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)
+struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter)
 {
-       if (status == NFS_OK || seqid_mutating_err(-status))
-               lsp->ls_seqid++;
+       struct nfs_seqid *new;
+
+       new = kmalloc(sizeof(*new), GFP_KERNEL);
+       if (new != NULL) {
+               new->sequence = counter;
+               INIT_LIST_HEAD(&new->list);
+       }
+       return new;
+}
+
+void nfs_free_seqid(struct nfs_seqid *seqid)
+{
+       struct rpc_sequence *sequence = seqid->sequence->sequence;
+
+       if (!list_empty(&seqid->list)) {
+               spin_lock(&sequence->lock);
+               list_del(&seqid->list);
+               spin_unlock(&sequence->lock);
+       }
+       rpc_wake_up_next(&sequence->wait);
+       kfree(seqid);
 }
 
 /*
-* Called with sp->so_sema and clp->cl_sem held.
-*
-* Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or
-* failed with a seqid incrementing error -
-* see comments nfs_fs.h:seqid_mutating_error()
-*/
-void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp)
-{
-       if (status == NFS_OK || seqid_mutating_err(-status))
-               sp->so_seqid++;
-       /* If the server returns BAD_SEQID, unhash state_owner here */
-       if (status == -NFS4ERR_BAD_SEQID)
+ * Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or
+ * failed with a seqid incrementing error -
+ * see comments nfs_fs.h:seqid_mutating_error()
+ */
+static inline void nfs_increment_seqid(int status, struct nfs_seqid *seqid)
+{
+       switch (status) {
+               case 0:
+                       break;
+               case -NFS4ERR_BAD_SEQID:
+               case -NFS4ERR_STALE_CLIENTID:
+               case -NFS4ERR_STALE_STATEID:
+               case -NFS4ERR_BAD_STATEID:
+               case -NFS4ERR_BADXDR:
+               case -NFS4ERR_RESOURCE:
+               case -NFS4ERR_NOFILEHANDLE:
+                       /* Non-seqid mutating errors */
+                       return;
+       };
+       /*
+        * Note: no locking needed as we are guaranteed to be first
+        * on the sequence list
+        */
+       seqid->sequence->counter++;
+}
+
+void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid)
+{
+       if (status == -NFS4ERR_BAD_SEQID) {
+               struct nfs4_state_owner *sp = container_of(seqid->sequence,
+                               struct nfs4_state_owner, so_seqid);
                nfs4_drop_state_owner(sp);
+       }
+       return nfs_increment_seqid(status, seqid);
+}
+
+/*
+ * Increment the seqid if the LOCK/LOCKU succeeded, or
+ * failed with a seqid incrementing error -
+ * see comments nfs_fs.h:seqid_mutating_error()
+ */
+void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid)
+{
+       return nfs_increment_seqid(status, seqid);
+}
+
+int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task)
+{
+       struct rpc_sequence *sequence = seqid->sequence->sequence;
+       int status = 0;
+
+       if (sequence->list.next == &seqid->list)
+               goto out;
+       spin_lock(&sequence->lock);
+       if (!list_empty(&sequence->list)) {
+               rpc_sleep_on(&sequence->wait, task, NULL, NULL);
+               status = -EAGAIN;
+       } else
+               list_add(&seqid->list, &sequence->list);
+       spin_unlock(&sequence->lock);
+out:
+       return status;
 }
 
 static int reclaimer(void *);
@@ -791,8 +859,6 @@ static int nfs4_reclaim_open_state(struct nfs4_state_recovery_ops *ops, struct n
                if (state->state == 0)
                        continue;
                status = ops->recover_open(sp, state);
-               list_for_each_entry(lock, &state->lock_states, ls_locks)
-                       lock->ls_flags &= ~NFS_LOCK_INITIALIZED;
                if (status >= 0) {
                        status = nfs4_reclaim_locks(ops, state);
                        if (status < 0)
@@ -831,6 +897,28 @@ out_err:
        return status;
 }
 
+static void nfs4_state_mark_reclaim(struct nfs4_client *clp)
+{
+       struct nfs4_state_owner *sp;
+       struct nfs4_state *state;
+       struct nfs4_lock_state *lock;
+
+       /* Reset all sequence ids to zero */
+       list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
+               sp->so_seqid.counter = 0;
+               sp->so_seqid.flags = 0;
+               spin_lock(&sp->so_lock);
+               list_for_each_entry(state, &sp->so_states, open_states) {
+                       list_for_each_entry(lock, &state->lock_states, ls_locks) {
+                               lock->ls_seqid.counter = 0;
+                               lock->ls_seqid.flags = 0;
+                               lock->ls_flags &= ~NFS_LOCK_INITIALIZED;
+                       }
+               }
+               spin_unlock(&sp->so_lock);
+       }
+}
+
 static int reclaimer(void *ptr)
 {
        struct reclaimer_args *args = (struct reclaimer_args *)ptr;
@@ -864,6 +952,7 @@ restart_loop:
                default:
                        ops = &nfs4_network_partition_recovery_ops;
        };
+       nfs4_state_mark_reclaim(clp);
        status = __nfs4_init_client(clp);
        if (status)
                goto out_error;
index 6c564ef9489ef833fb293eb776aee4ec75db1290..fbbace8a30c4da649507d66827cec057f0c7df40 100644 (file)
@@ -95,6 +95,8 @@ static int nfs_stat_to_errno(int);
 #define decode_getattr_maxsz    (op_decode_hdr_maxsz + nfs4_fattr_maxsz)
 #define encode_savefh_maxsz     (op_encode_hdr_maxsz)
 #define decode_savefh_maxsz     (op_decode_hdr_maxsz)
+#define encode_restorefh_maxsz  (op_encode_hdr_maxsz)
+#define decode_restorefh_maxsz  (op_decode_hdr_maxsz)
 #define encode_fsinfo_maxsz    (op_encode_hdr_maxsz + 2)
 #define decode_fsinfo_maxsz    (op_decode_hdr_maxsz + 11)
 #define encode_renew_maxsz     (op_encode_hdr_maxsz + 3)
@@ -157,16 +159,20 @@ static int nfs_stat_to_errno(int);
                                op_decode_hdr_maxsz + 2)
 #define NFS4_enc_write_sz      (compound_encode_hdr_maxsz + \
                                encode_putfh_maxsz + \
-                               op_encode_hdr_maxsz + 8)
+                               op_encode_hdr_maxsz + 8 + \
+                               encode_getattr_maxsz)
 #define NFS4_dec_write_sz      (compound_decode_hdr_maxsz + \
                                decode_putfh_maxsz + \
-                               op_decode_hdr_maxsz + 4)
+                               op_decode_hdr_maxsz + 4 + \
+                               decode_getattr_maxsz)
 #define NFS4_enc_commit_sz     (compound_encode_hdr_maxsz + \
                                encode_putfh_maxsz + \
-                               op_encode_hdr_maxsz + 3)
+                               op_encode_hdr_maxsz + 3 + \
+                               encode_getattr_maxsz)
 #define NFS4_dec_commit_sz     (compound_decode_hdr_maxsz + \
                                decode_putfh_maxsz + \
-                               op_decode_hdr_maxsz + 2)
+                               op_decode_hdr_maxsz + 2 + \
+                               decode_getattr_maxsz)
 #define NFS4_enc_open_sz        (compound_encode_hdr_maxsz + \
                                 encode_putfh_maxsz + \
                                 op_encode_hdr_maxsz + \
@@ -196,17 +202,21 @@ static int nfs_stat_to_errno(int);
 #define NFS4_enc_open_downgrade_sz \
                                (compound_encode_hdr_maxsz + \
                                 encode_putfh_maxsz + \
-                                op_encode_hdr_maxsz + 7)
+                                op_encode_hdr_maxsz + 7 + \
+                               encode_getattr_maxsz)
 #define NFS4_dec_open_downgrade_sz \
                                (compound_decode_hdr_maxsz + \
                                 decode_putfh_maxsz + \
-                                op_decode_hdr_maxsz + 4)
+                                op_decode_hdr_maxsz + 4 + \
+                               decode_getattr_maxsz)
 #define NFS4_enc_close_sz       (compound_encode_hdr_maxsz + \
                                 encode_putfh_maxsz + \
-                                op_encode_hdr_maxsz + 5)
+                                op_encode_hdr_maxsz + 5 + \
+                               encode_getattr_maxsz)
 #define NFS4_dec_close_sz       (compound_decode_hdr_maxsz + \
                                 decode_putfh_maxsz + \
-                                op_decode_hdr_maxsz + 4)
+                                op_decode_hdr_maxsz + 4 + \
+                               decode_getattr_maxsz)
 #define NFS4_enc_setattr_sz     (compound_encode_hdr_maxsz + \
                                 encode_putfh_maxsz + \
                                 op_encode_hdr_maxsz + 4 + \
@@ -300,30 +310,44 @@ static int nfs_stat_to_errno(int);
                                decode_getfh_maxsz)
 #define NFS4_enc_remove_sz     (compound_encode_hdr_maxsz + \
                                encode_putfh_maxsz + \
-                               encode_remove_maxsz)
+                               encode_remove_maxsz + \
+                               encode_getattr_maxsz)
 #define NFS4_dec_remove_sz     (compound_decode_hdr_maxsz + \
                                decode_putfh_maxsz + \
-                               op_decode_hdr_maxsz + 5)
+                               op_decode_hdr_maxsz + 5 + \
+                               decode_getattr_maxsz)
 #define NFS4_enc_rename_sz     (compound_encode_hdr_maxsz + \
                                encode_putfh_maxsz + \
                                encode_savefh_maxsz + \
                                encode_putfh_maxsz + \
-                               encode_rename_maxsz)
+                               encode_rename_maxsz + \
+                               encode_getattr_maxsz + \
+                               encode_restorefh_maxsz + \
+                               encode_getattr_maxsz)
 #define NFS4_dec_rename_sz     (compound_decode_hdr_maxsz + \
                                decode_putfh_maxsz + \
                                decode_savefh_maxsz + \
                                decode_putfh_maxsz + \
-                               decode_rename_maxsz)
+                               decode_rename_maxsz + \
+                               decode_getattr_maxsz + \
+                               decode_restorefh_maxsz + \
+                               decode_getattr_maxsz)
 #define NFS4_enc_link_sz       (compound_encode_hdr_maxsz + \
                                encode_putfh_maxsz + \
                                encode_savefh_maxsz + \
                                encode_putfh_maxsz + \
-                               encode_link_maxsz)
+                               encode_link_maxsz + \
+                               decode_getattr_maxsz + \
+                               encode_restorefh_maxsz + \
+                               decode_getattr_maxsz)
 #define NFS4_dec_link_sz       (compound_decode_hdr_maxsz + \
                                decode_putfh_maxsz + \
                                decode_savefh_maxsz + \
                                decode_putfh_maxsz + \
-                               decode_link_maxsz)
+                               decode_link_maxsz + \
+                               decode_getattr_maxsz + \
+                               decode_restorefh_maxsz + \
+                               decode_getattr_maxsz)
 #define NFS4_enc_symlink_sz    (compound_encode_hdr_maxsz + \
                                encode_putfh_maxsz + \
                                encode_symlink_maxsz + \
@@ -336,14 +360,20 @@ static int nfs_stat_to_errno(int);
                                decode_getfh_maxsz)
 #define NFS4_enc_create_sz     (compound_encode_hdr_maxsz + \
                                encode_putfh_maxsz + \
+                               encode_savefh_maxsz + \
                                encode_create_maxsz + \
+                               encode_getfh_maxsz + \
                                encode_getattr_maxsz + \
-                               encode_getfh_maxsz)
+                               encode_restorefh_maxsz + \
+                               encode_getattr_maxsz)
 #define NFS4_dec_create_sz     (compound_decode_hdr_maxsz + \
                                decode_putfh_maxsz + \
+                               decode_savefh_maxsz + \
                                decode_create_maxsz + \
+                               decode_getfh_maxsz + \
                                decode_getattr_maxsz + \
-                               decode_getfh_maxsz)
+                               decode_restorefh_maxsz + \
+                               decode_getattr_maxsz)
 #define NFS4_enc_pathconf_sz   (compound_encode_hdr_maxsz + \
                                encode_putfh_maxsz + \
                                encode_getattr_maxsz)
@@ -602,10 +632,10 @@ static int encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg)
 {
        uint32_t *p;
 
-       RESERVE_SPACE(8+sizeof(arg->stateid.data));
+       RESERVE_SPACE(8+sizeof(arg->stateid->data));
        WRITE32(OP_CLOSE);
-       WRITE32(arg->seqid);
-       WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data));
+       WRITE32(arg->seqid->sequence->counter);
+       WRITEMEM(arg->stateid->data, sizeof(arg->stateid->data));
        
        return 0;
 }
@@ -729,22 +759,18 @@ static int encode_lock(struct xdr_stream *xdr, const struct nfs_lockargs *arg)
        WRITE64(arg->length);
        WRITE32(opargs->new_lock_owner);
        if (opargs->new_lock_owner){
-               struct nfs_open_to_lock *ol = opargs->u.open_lock;
-
                RESERVE_SPACE(40);
-               WRITE32(ol->open_seqid);
-               WRITEMEM(&ol->open_stateid, sizeof(ol->open_stateid));
-               WRITE32(ol->lock_seqid);
-               WRITE64(ol->lock_owner.clientid);
+               WRITE32(opargs->open_seqid->sequence->counter);
+               WRITEMEM(opargs->open_stateid->data, sizeof(opargs->open_stateid->data));
+               WRITE32(opargs->lock_seqid->sequence->counter);
+               WRITE64(opargs->lock_owner.clientid);
                WRITE32(4);
-               WRITE32(ol->lock_owner.id);
+               WRITE32(opargs->lock_owner.id);
        }
        else {
-               struct nfs_exist_lock *el = opargs->u.exist_lock;
-
                RESERVE_SPACE(20);
-               WRITEMEM(&el->stateid, sizeof(el->stateid));
-               WRITE32(el->seqid);
+               WRITEMEM(opargs->lock_stateid->data, sizeof(opargs->lock_stateid->data));
+               WRITE32(opargs->lock_seqid->sequence->counter);
        }
 
        return 0;
@@ -775,8 +801,8 @@ static int encode_locku(struct xdr_stream *xdr, const struct nfs_lockargs *arg)
        RESERVE_SPACE(44);
        WRITE32(OP_LOCKU);
        WRITE32(arg->type);
-       WRITE32(opargs->seqid);
-       WRITEMEM(&opargs->stateid, sizeof(opargs->stateid));
+       WRITE32(opargs->seqid->sequence->counter);
+       WRITEMEM(opargs->stateid->data, sizeof(opargs->stateid->data));
        WRITE64(arg->offset);
        WRITE64(arg->length);
 
@@ -826,7 +852,7 @@ static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_opena
  */
        RESERVE_SPACE(8);
        WRITE32(OP_OPEN);
-       WRITE32(arg->seqid);
+       WRITE32(arg->seqid->sequence->counter);
        encode_share_access(xdr, arg->open_flags);
        RESERVE_SPACE(16);
        WRITE64(arg->clientid);
@@ -941,7 +967,7 @@ static int encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_con
        RESERVE_SPACE(8+sizeof(arg->stateid.data));
        WRITE32(OP_OPEN_CONFIRM);
        WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data));
-       WRITE32(arg->seqid);
+       WRITE32(arg->seqid->sequence->counter);
 
        return 0;
 }
@@ -950,10 +976,10 @@ static int encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closea
 {
        uint32_t *p;
 
-       RESERVE_SPACE(8+sizeof(arg->stateid.data));
+       RESERVE_SPACE(8+sizeof(arg->stateid->data));
        WRITE32(OP_OPEN_DOWNGRADE);
-       WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data));
-       WRITE32(arg->seqid);
+       WRITEMEM(arg->stateid->data, sizeof(arg->stateid->data));
+       WRITE32(arg->seqid->sequence->counter);
        encode_share_access(xdr, arg->open_flags);
        return 0;
 }
@@ -1116,6 +1142,17 @@ static int encode_renew(struct xdr_stream *xdr, const struct nfs4_client *client
        return 0;
 }
 
+static int
+encode_restorefh(struct xdr_stream *xdr)
+{
+       uint32_t *p;
+
+       RESERVE_SPACE(4);
+       WRITE32(OP_RESTOREFH);
+
+       return 0;
+}
+
 static int
 encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg)
 {
@@ -1296,14 +1333,18 @@ static int nfs4_xdr_enc_remove(struct rpc_rqst *req, uint32_t *p, const struct n
 {
        struct xdr_stream xdr;
        struct compound_hdr hdr = {
-               .nops = 2,
+               .nops = 3,
        };
        int status;
 
        xdr_init_encode(&xdr, &req->rq_snd_buf, p);
        encode_compound_hdr(&xdr, &hdr);
-       if ((status = encode_putfh(&xdr, args->fh)) == 0)
-               status = encode_remove(&xdr, args->name);
+       if ((status = encode_putfh(&xdr, args->fh)) != 0)
+               goto out;
+       if ((status = encode_remove(&xdr, args->name)) != 0)
+               goto out;
+       status = encode_getfattr(&xdr, args->bitmask);
+out:
        return status;
 }
 
@@ -1314,7 +1355,7 @@ static int nfs4_xdr_enc_rename(struct rpc_rqst *req, uint32_t *p, const struct n
 {
        struct xdr_stream xdr;
        struct compound_hdr hdr = {
-               .nops = 4,
+               .nops = 7,
        };
        int status;
 
@@ -1326,7 +1367,13 @@ static int nfs4_xdr_enc_rename(struct rpc_rqst *req, uint32_t *p, const struct n
                goto out;
        if ((status = encode_putfh(&xdr, args->new_dir)) != 0)
                goto out;
-       status = encode_rename(&xdr, args->old_name, args->new_name);
+       if ((status = encode_rename(&xdr, args->old_name, args->new_name)) != 0)
+               goto out;
+       if ((status = encode_getfattr(&xdr, args->bitmask)) != 0)
+               goto out;
+       if ((status = encode_restorefh(&xdr)) != 0)
+               goto out;
+       status = encode_getfattr(&xdr, args->bitmask);
 out:
        return status;
 }
@@ -1338,7 +1385,7 @@ static int nfs4_xdr_enc_link(struct rpc_rqst *req, uint32_t *p, const struct nfs
 {
        struct xdr_stream xdr;
        struct compound_hdr hdr = {
-               .nops = 4,
+               .nops = 7,
        };
        int status;
 
@@ -1350,7 +1397,13 @@ static int nfs4_xdr_enc_link(struct rpc_rqst *req, uint32_t *p, const struct nfs
                goto out;
        if ((status = encode_putfh(&xdr, args->dir_fh)) != 0)
                goto out;
-       status = encode_link(&xdr, args->name);
+       if ((status = encode_link(&xdr, args->name)) != 0)
+               goto out;
+       if ((status = encode_getfattr(&xdr, args->bitmask)) != 0)
+               goto out;
+       if ((status = encode_restorefh(&xdr)) != 0)
+               goto out;
+       status = encode_getfattr(&xdr, args->bitmask);
 out:
        return status;
 }
@@ -1362,7 +1415,7 @@ static int nfs4_xdr_enc_create(struct rpc_rqst *req, uint32_t *p, const struct n
 {
        struct xdr_stream xdr;
        struct compound_hdr hdr = {
-               .nops = 4,
+               .nops = 7,
        };
        int status;
 
@@ -1370,10 +1423,16 @@ static int nfs4_xdr_enc_create(struct rpc_rqst *req, uint32_t *p, const struct n
        encode_compound_hdr(&xdr, &hdr);
        if ((status = encode_putfh(&xdr, args->dir_fh)) != 0)
                goto out;
+       if ((status = encode_savefh(&xdr)) != 0)
+               goto out;
        if ((status = encode_create(&xdr, args)) != 0)
                goto out;
        if ((status = encode_getfh(&xdr)) != 0)
                goto out;
+       if ((status = encode_getfattr(&xdr, args->bitmask)) != 0)
+               goto out;
+       if ((status = encode_restorefh(&xdr)) != 0)
+               goto out;
        status = encode_getfattr(&xdr, args->bitmask);
 out:
        return status;
@@ -1412,7 +1471,7 @@ static int nfs4_xdr_enc_close(struct rpc_rqst *req, uint32_t *p, struct nfs_clos
 {
         struct xdr_stream xdr;
         struct compound_hdr hdr = {
-                .nops   = 2,
+                .nops   = 3,
         };
         int status;
 
@@ -1422,6 +1481,9 @@ static int nfs4_xdr_enc_close(struct rpc_rqst *req, uint32_t *p, struct nfs_clos
         if(status)
                 goto out;
         status = encode_close(&xdr, args);
+       if (status != 0)
+               goto out;
+       status = encode_getfattr(&xdr, args->bitmask);
 out:
         return status;
 }
@@ -1433,13 +1495,19 @@ static int nfs4_xdr_enc_open(struct rpc_rqst *req, uint32_t *p, struct nfs_opena
 {
        struct xdr_stream xdr;
        struct compound_hdr hdr = {
-               .nops = 4,
+               .nops = 7,
        };
        int status;
 
+       status = nfs_wait_on_sequence(args->seqid, req->rq_task);
+       if (status != 0)
+               goto out;
        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_savefh(&xdr);
        if (status)
                goto out;
        status = encode_open(&xdr, args);
@@ -1449,6 +1517,12 @@ static int nfs4_xdr_enc_open(struct rpc_rqst *req, uint32_t *p, struct nfs_opena
        if (status)
                goto out;
        status = encode_getfattr(&xdr, args->bitmask);
+       if (status)
+               goto out;
+       status = encode_restorefh(&xdr);
+       if (status)
+               goto out;
+       status = encode_getfattr(&xdr, args->bitmask);
 out:
        return status;
 }
@@ -1464,6 +1538,9 @@ static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, uint32_t *p, struct n
        };
        int status;
 
+       status = nfs_wait_on_sequence(args->seqid, req->rq_task);
+       if (status != 0)
+               goto out;
        xdr_init_encode(&xdr, &req->rq_snd_buf, p);
        encode_compound_hdr(&xdr, &hdr);
        status = encode_putfh(&xdr, args->fh);
@@ -1485,6 +1562,9 @@ static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, uint32_t *p, struct nf
        };
        int status;
 
+       status = nfs_wait_on_sequence(args->seqid, req->rq_task);
+       if (status != 0)
+               goto out;
        xdr_init_encode(&xdr, &req->rq_snd_buf, p);
        encode_compound_hdr(&xdr, &hdr);
        status = encode_putfh(&xdr, args->fh);
@@ -1502,7 +1582,7 @@ static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, uint32_t *p, struct
 {
        struct xdr_stream xdr;
        struct compound_hdr hdr = {
-               .nops   = 2,
+               .nops   = 3,
        };
        int status;
 
@@ -1512,6 +1592,9 @@ static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, uint32_t *p, struct
        if (status)
                goto out;
        status = encode_open_downgrade(&xdr, args);
+       if (status != 0)
+               goto out;
+       status = encode_getfattr(&xdr, args->bitmask);
 out:
        return status;
 }
@@ -1525,8 +1608,15 @@ static int nfs4_xdr_enc_lock(struct rpc_rqst *req, uint32_t *p, struct nfs_locka
        struct compound_hdr hdr = {
                .nops   = 2,
        };
+       struct nfs_lock_opargs *opargs = args->u.lock;
        int status;
 
+       status = nfs_wait_on_sequence(opargs->lock_seqid, req->rq_task);
+       if (status != 0)
+               goto out;
+       /* Do we need to do an open_to_lock_owner? */
+       if (opargs->lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)
+               opargs->new_lock_owner = 0;
        xdr_init_encode(&xdr, &req->rq_snd_buf, p);
        encode_compound_hdr(&xdr, &hdr);
        status = encode_putfh(&xdr, args->fh);
@@ -1713,7 +1803,7 @@ static int nfs4_xdr_enc_write(struct rpc_rqst *req, uint32_t *p, struct nfs_writ
 {
        struct xdr_stream xdr;
        struct compound_hdr hdr = {
-               .nops = 2,
+               .nops = 3,
        };
        int status;
 
@@ -1723,6 +1813,9 @@ static int nfs4_xdr_enc_write(struct rpc_rqst *req, uint32_t *p, struct nfs_writ
        if (status)
                goto out;
        status = encode_write(&xdr, args);
+       if (status)
+               goto out;
+       status = encode_getfattr(&xdr, args->bitmask);
 out:
        return status;
 }
@@ -1734,7 +1827,7 @@ static int nfs4_xdr_enc_commit(struct rpc_rqst *req, uint32_t *p, struct nfs_wri
 {
        struct xdr_stream xdr;
        struct compound_hdr hdr = {
-               .nops = 2,
+               .nops = 3,
        };
        int status;
 
@@ -1744,6 +1837,9 @@ static int nfs4_xdr_enc_commit(struct rpc_rqst *req, uint32_t *p, struct nfs_wri
        if (status)
                goto out;
        status = encode_commit(&xdr, args);
+       if (status)
+               goto out;
+       status = encode_getfattr(&xdr, args->bitmask);
 out:
        return status;
 }
@@ -2670,8 +2766,7 @@ static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_re
                goto xdr_error;
        status = verify_attr_len(xdr, savep, attrlen);
 xdr_error:
-       if (status != 0)
-               printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status);
+       dprintk("%s: xdr returned %d!\n", __FUNCTION__, -status);
        return status;
 }
        
@@ -2704,8 +2799,7 @@ static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat)
 
        status = verify_attr_len(xdr, savep, attrlen);
 xdr_error:
-       if (status != 0)
-               printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status);
+       dprintk("%s: xdr returned %d!\n", __FUNCTION__, -status);
        return status;
 }
 
@@ -2730,8 +2824,7 @@ static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf
 
        status = verify_attr_len(xdr, savep, attrlen);
 xdr_error:
-       if (status != 0)
-               printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status);
+       dprintk("%s: xdr returned %d!\n", __FUNCTION__, -status);
        return status;
 }
 
@@ -2787,13 +2880,10 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, cons
                goto xdr_error;
        if ((status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime)) != 0)
                goto xdr_error;
-       if ((status = verify_attr_len(xdr, savep, attrlen)) == 0) {
+       if ((status = verify_attr_len(xdr, savep, attrlen)) == 0)
                fattr->valid = NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4;
-               fattr->timestamp = jiffies;
-       }
 xdr_error:
-       if (status != 0)
-               printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status);
+       dprintk("%s: xdr returned %d\n", __FUNCTION__, -status);
        return status;
 }
 
@@ -2826,8 +2916,7 @@ static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
 
        status = verify_attr_len(xdr, savep, attrlen);
 xdr_error:
-       if (status != 0)
-               printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status);
+       dprintk("%s: xdr returned %d!\n", __FUNCTION__, -status);
        return status;
 }
 
@@ -2890,8 +2979,8 @@ static int decode_lock(struct xdr_stream *xdr, struct nfs_lockres *res)
 
        status = decode_op_hdr(xdr, OP_LOCK);
        if (status == 0) {
-               READ_BUF(sizeof(nfs4_stateid));
-               COPYMEM(&res->u.stateid, sizeof(res->u.stateid));
+               READ_BUF(sizeof(res->u.stateid.data));
+               COPYMEM(res->u.stateid.data, sizeof(res->u.stateid.data));
        } else if (status == -NFS4ERR_DENIED)
                return decode_lock_denied(xdr, &res->u.denied);
        return status;
@@ -2913,8 +3002,8 @@ static int decode_locku(struct xdr_stream *xdr, struct nfs_lockres *res)
 
        status = decode_op_hdr(xdr, OP_LOCKU);
        if (status == 0) {
-               READ_BUF(sizeof(nfs4_stateid));
-               COPYMEM(&res->u.stateid, sizeof(res->u.stateid));
+               READ_BUF(sizeof(res->u.stateid.data));
+               COPYMEM(res->u.stateid.data, sizeof(res->u.stateid.data));
        }
        return status;
 }
@@ -2994,7 +3083,7 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
         p += bmlen;
        return decode_delegation(xdr, res);
 xdr_error:
-       printk(KERN_NOTICE "%s: xdr error!\n", __FUNCTION__);
+       dprintk("%s: Bitmap too large! Length = %u\n", __FUNCTION__, bmlen);
        return -EIO;
 }
 
@@ -3208,6 +3297,12 @@ static int decode_renew(struct xdr_stream *xdr)
        return decode_op_hdr(xdr, OP_RENEW);
 }
 
+static int
+decode_restorefh(struct xdr_stream *xdr)
+{
+       return decode_op_hdr(xdr, OP_RESTOREFH);
+}
+
 static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
                size_t *acl_len)
 {
@@ -3243,7 +3338,8 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
                if (attrlen <= *acl_len)
                        xdr_read_pages(xdr, attrlen);
                *acl_len = attrlen;
-       }
+       } else
+               status = -EOPNOTSUPP;
 
 out:
        return status;
@@ -3352,6 +3448,9 @@ static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, uint32_t *p, stru
         if (status)
                 goto out;
         status = decode_open_downgrade(&xdr, res);
+       if (status != 0)
+               goto out;
+       decode_getfattr(&xdr, res->fattr, res->server);
 out:
         return status;
 }
@@ -3424,7 +3523,7 @@ out:
 /*
  * Decode REMOVE response
  */
-static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_change_info *cinfo)
+static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_remove_res *res)
 {
        struct xdr_stream xdr;
        struct compound_hdr hdr;
@@ -3433,8 +3532,11 @@ static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_
        xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
        if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
                goto out;
-       if ((status = decode_putfh(&xdr)) == 0)
-               status = decode_remove(&xdr, cinfo);
+       if ((status = decode_putfh(&xdr)) != 0)
+               goto out;
+       if ((status = decode_remove(&xdr, &res->cinfo)) != 0)
+               goto out;
+       decode_getfattr(&xdr, res->dir_attr, res->server);
 out:
        return status;
 }
@@ -3457,7 +3559,14 @@ static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_
                goto out;
        if ((status = decode_putfh(&xdr)) != 0)
                goto out;
-       status = decode_rename(&xdr, &res->old_cinfo, &res->new_cinfo);
+       if ((status = decode_rename(&xdr, &res->old_cinfo, &res->new_cinfo)) != 0)
+               goto out;
+       /* Current FH is target directory */
+       if (decode_getfattr(&xdr, res->new_fattr, res->server) != 0)
+               goto out;
+       if ((status = decode_restorefh(&xdr)) != 0)
+               goto out;
+       decode_getfattr(&xdr, res->old_fattr, res->server);
 out:
        return status;
 }
@@ -3465,7 +3574,7 @@ out:
 /*
  * Decode LINK response
  */
-static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_change_info *cinfo)
+static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_link_res *res)
 {
        struct xdr_stream xdr;
        struct compound_hdr hdr;
@@ -3480,7 +3589,17 @@ static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_ch
                goto out;
        if ((status = decode_putfh(&xdr)) != 0)
                goto out;
-       status = decode_link(&xdr, cinfo);
+       if ((status = decode_link(&xdr, &res->cinfo)) != 0)
+               goto out;
+       /*
+        * Note order: OP_LINK leaves the directory as the current
+        *             filehandle.
+        */
+       if (decode_getfattr(&xdr, res->dir_attr, res->server) != 0)
+               goto out;
+       if ((status = decode_restorefh(&xdr)) != 0)
+               goto out;
+       decode_getfattr(&xdr, res->fattr, res->server);
 out:
        return status;
 }
@@ -3499,13 +3618,17 @@ static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_
                goto out;
        if ((status = decode_putfh(&xdr)) != 0)
                goto out;
+       if ((status = decode_savefh(&xdr)) != 0)
+               goto out;
        if ((status = decode_create(&xdr,&res->dir_cinfo)) != 0)
                goto out;
        if ((status = decode_getfh(&xdr, res->fh)) != 0)
                goto out;
-       status = decode_getfattr(&xdr, res->fattr, res->server);
-       if (status == NFS4ERR_DELAY)
-               status = 0;
+       if (decode_getfattr(&xdr, res->fattr, res->server) != 0)
+               goto out;
+       if ((status = decode_restorefh(&xdr)) != 0)
+               goto out;
+       decode_getfattr(&xdr, res->dir_fattr, res->server);
 out:
        return status;
 }
@@ -3623,6 +3746,15 @@ static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_cl
         if (status)
                 goto out;
         status = decode_close(&xdr, res);
+       if (status != 0)
+               goto out;
+       /*
+        * Note: Server may do delete on close for this file
+        *      in which case the getattr call will fail with
+        *      an ESTALE error. Shouldn't be a problem,
+        *      though, since fattr->valid will remain unset.
+        */
+       decode_getfattr(&xdr, res->fattr, res->server);
 out:
         return status;
 }
@@ -3643,15 +3775,20 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_ope
         status = decode_putfh(&xdr);
         if (status)
                 goto out;
+        status = decode_savefh(&xdr);
+       if (status)
+               goto out;
         status = decode_open(&xdr, res);
         if (status)
                 goto out;
        status = decode_getfh(&xdr, &res->fh);
         if (status)
                goto out;
-       status = decode_getfattr(&xdr, res->f_attr, res->server);
-       if (status == NFS4ERR_DELAY)
-               status = 0;
+       if (decode_getfattr(&xdr, res->f_attr, res->server) != 0)
+               goto out;
+       if ((status = decode_restorefh(&xdr)) != 0)
+               goto out;
+       decode_getfattr(&xdr, res->dir_attr, res->server);
 out:
         return status;
 }
@@ -3869,6 +4006,9 @@ static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_wr
        if (status)
                goto out;
        status = decode_write(&xdr, res);
+       if (status)
+               goto out;
+       decode_getfattr(&xdr, res->fattr, res->server);
        if (!status)
                status = res->count;
 out:
@@ -3892,6 +4032,9 @@ static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_w
        if (status)
                goto out;
        status = decode_commit(&xdr, res);
+       if (status)
+               goto out;
+       decode_getfattr(&xdr, res->fattr, res->server);
 out:
        return status;
 }
index be23c3fb9260051b8069ad4afbf2257bed1ca502..a48a003242c006c94f8823fdc081d3c03289289e 100644 (file)
@@ -61,7 +61,7 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
        int status;
 
        dprintk("%s: call getattr\n", __FUNCTION__);
-       fattr->valid = 0;
+       nfs_fattr_init(fattr);
        status = rpc_call(server->client_sys, NFSPROC_GETATTR, fhandle, fattr, 0);
        dprintk("%s: reply getattr: %d\n", __FUNCTION__, status);
        if (status)
@@ -93,7 +93,7 @@ nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
        int     status;
 
        dprintk("NFS call  getattr\n");
-       fattr->valid = 0;
+       nfs_fattr_init(fattr);
        status = rpc_call(server->client, NFSPROC_GETATTR,
                                fhandle, fattr, 0);
        dprintk("NFS reply getattr: %d\n", status);
@@ -112,7 +112,7 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
        int     status;
 
        dprintk("NFS call  setattr\n");
-       fattr->valid = 0;
+       nfs_fattr_init(fattr);
        status = rpc_call(NFS_CLIENT(inode), NFSPROC_SETATTR, &arg, fattr, 0);
        if (status == 0)
                nfs_setattr_update_inode(inode, sattr);
@@ -136,7 +136,7 @@ nfs_proc_lookup(struct inode *dir, struct qstr *name,
        int                     status;
 
        dprintk("NFS call  lookup %s\n", name->name);
-       fattr->valid = 0;
+       nfs_fattr_init(fattr);
        status = rpc_call(NFS_CLIENT(dir), NFSPROC_LOOKUP, &arg, &res, 0);
        dprintk("NFS reply lookup: %d\n", status);
        return status;
@@ -174,7 +174,7 @@ static int nfs_proc_read(struct nfs_read_data *rdata)
 
        dprintk("NFS call  read %d @ %Ld\n", rdata->args.count,
                        (long long) rdata->args.offset);
-       fattr->valid = 0;
+       nfs_fattr_init(fattr);
        status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
        if (status >= 0) {
                nfs_refresh_inode(inode, fattr);
@@ -203,10 +203,10 @@ static int nfs_proc_write(struct nfs_write_data *wdata)
 
        dprintk("NFS call  write %d @ %Ld\n", wdata->args.count,
                        (long long) wdata->args.offset);
-       fattr->valid = 0;
+       nfs_fattr_init(fattr);
        status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
        if (status >= 0) {
-               nfs_refresh_inode(inode, fattr);
+               nfs_post_op_update_inode(inode, fattr);
                wdata->res.count = wdata->args.count;
                wdata->verf.committed = NFS_FILE_SYNC;
        }
@@ -216,7 +216,7 @@ static int nfs_proc_write(struct nfs_write_data *wdata)
 
 static int
 nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-               int flags)
+               int flags, struct nameidata *nd)
 {
        struct nfs_fh           fhandle;
        struct nfs_fattr        fattr;
@@ -232,7 +232,7 @@ nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
        };
        int                     status;
 
-       fattr.valid = 0;
+       nfs_fattr_init(&fattr);
        dprintk("NFS call  create %s\n", dentry->d_name.name);
        status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0);
        if (status == 0)
@@ -273,12 +273,13 @@ nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                sattr->ia_size = new_encode_dev(rdev);/* get out your barf bag */
        }
 
-       fattr.valid = 0;
+       nfs_fattr_init(&fattr);
        status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0);
+       nfs_mark_for_revalidate(dir);
 
        if (status == -EINVAL && S_ISFIFO(mode)) {
                sattr->ia_mode = mode;
-               fattr.valid = 0;
+               nfs_fattr_init(&fattr);
                status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0);
        }
        if (status == 0)
@@ -305,6 +306,7 @@ nfs_proc_remove(struct inode *dir, struct qstr *name)
 
        dprintk("NFS call  remove %s\n", name->name);
        status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+       nfs_mark_for_revalidate(dir);
 
        dprintk("NFS reply remove: %d\n", status);
        return status;
@@ -331,8 +333,10 @@ nfs_proc_unlink_done(struct dentry *dir, struct rpc_task *task)
 {
        struct rpc_message *msg = &task->tk_msg;
        
-       if (msg->rpc_argp)
+       if (msg->rpc_argp) {
+               nfs_mark_for_revalidate(dir->d_inode);
                kfree(msg->rpc_argp);
+       }
        return 0;
 }
 
@@ -352,6 +356,8 @@ nfs_proc_rename(struct inode *old_dir, struct qstr *old_name,
 
        dprintk("NFS call  rename %s -> %s\n", old_name->name, new_name->name);
        status = rpc_call(NFS_CLIENT(old_dir), NFSPROC_RENAME, &arg, NULL, 0);
+       nfs_mark_for_revalidate(old_dir);
+       nfs_mark_for_revalidate(new_dir);
        dprintk("NFS reply rename: %d\n", status);
        return status;
 }
@@ -369,6 +375,7 @@ nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
 
        dprintk("NFS call  link %s\n", name->name);
        status = rpc_call(NFS_CLIENT(inode), NFSPROC_LINK, &arg, NULL, 0);
+       nfs_mark_for_revalidate(dir);
        dprintk("NFS reply link: %d\n", status);
        return status;
 }
@@ -391,9 +398,10 @@ nfs_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
        if (path->len > NFS2_MAXPATHLEN)
                return -ENAMETOOLONG;
        dprintk("NFS call  symlink %s -> %s\n", name->name, path->name);
-       fattr->valid = 0;
+       nfs_fattr_init(fattr);
        fhandle->size = 0;
        status = rpc_call(NFS_CLIENT(dir), NFSPROC_SYMLINK, &arg, NULL, 0);
+       nfs_mark_for_revalidate(dir);
        dprintk("NFS reply symlink: %d\n", status);
        return status;
 }
@@ -416,8 +424,9 @@ nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
        int                     status;
 
        dprintk("NFS call  mkdir %s\n", dentry->d_name.name);
-       fattr.valid = 0;
+       nfs_fattr_init(&fattr);
        status = rpc_call(NFS_CLIENT(dir), NFSPROC_MKDIR, &arg, &res, 0);
+       nfs_mark_for_revalidate(dir);
        if (status == 0)
                status = nfs_instantiate(dentry, &fhandle, &fattr);
        dprintk("NFS reply mkdir: %d\n", status);
@@ -436,6 +445,7 @@ nfs_proc_rmdir(struct inode *dir, struct qstr *name)
 
        dprintk("NFS call  rmdir %s\n", name->name);
        status = rpc_call(NFS_CLIENT(dir), NFSPROC_RMDIR, &arg, NULL, 0);
+       nfs_mark_for_revalidate(dir);
        dprintk("NFS reply rmdir: %d\n", status);
        return status;
 }
@@ -484,7 +494,7 @@ nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
        int     status;
 
        dprintk("NFS call  statfs\n");
-       stat->fattr->valid = 0;
+       nfs_fattr_init(stat->fattr);
        status = rpc_call(server->client, NFSPROC_STATFS, fhandle, &fsinfo, 0);
        dprintk("NFS reply statfs: %d\n", status);
        if (status)
@@ -507,7 +517,7 @@ nfs_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
        int     status;
 
        dprintk("NFS call  fsinfo\n");
-       info->fattr->valid = 0;
+       nfs_fattr_init(info->fattr);
        status = rpc_call(server->client, NFSPROC_STATFS, fhandle, &fsinfo, 0);
        dprintk("NFS reply fsinfo: %d\n", status);
        if (status)
@@ -579,7 +589,7 @@ nfs_write_done(struct rpc_task *task)
        struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
 
        if (task->tk_status >= 0)
-               nfs_refresh_inode(data->inode, data->res.fattr);
+               nfs_post_op_update_inode(data->inode, data->res.fattr);
        nfs_writeback_done(task);
 }
 
index 9758ebd49905a704146fffc23443890b38b8e318..43b03b19731b52bfeabfe0b063e9bc70e9d07e2d 100644 (file)
@@ -215,6 +215,7 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
        data->res.fattr   = &data->fattr;
        data->res.count   = count;
        data->res.eof     = 0;
+       nfs_fattr_init(&data->fattr);
 
        NFS_PROTO(inode)->read_setup(data);
 
index 5130eda231d7a0513e887a3138e26aef3b1f5cbc..819a65f5071f8e9482e0cff5114e4574a940fd1b 100644 (file)
@@ -870,6 +870,7 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
        data->res.fattr   = &data->fattr;
        data->res.count   = count;
        data->res.verf    = &data->verf;
+       nfs_fattr_init(&data->fattr);
 
        NFS_PROTO(inode)->write_setup(data, how);
 
@@ -1237,6 +1238,7 @@ static void nfs_commit_rpcsetup(struct list_head *head,
        data->res.count   = 0;
        data->res.fattr   = &data->fattr;
        data->res.verf    = &data->verf;
+       nfs_fattr_init(&data->fattr);
        
        NFS_PROTO(inode)->commit_setup(data, how);
 
index f0d90cf0495c490316d427e309c38695ceb4e005..8d06ec911fd9df99762741ecb2ae7cf6b75ab8b0 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -739,7 +739,8 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
 }
 
 static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
-                                       int flags, struct file *f)
+                                       int flags, struct file *f,
+                                       int (*open)(struct inode *, struct file *))
 {
        struct inode *inode;
        int error;
@@ -761,11 +762,14 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
        f->f_op = fops_get(inode->i_fop);
        file_move(f, &inode->i_sb->s_files);
 
-       if (f->f_op && f->f_op->open) {
-               error = f->f_op->open(inode,f);
+       if (!open && f->f_op)
+               open = f->f_op->open;
+       if (open) {
+               error = open(inode, f);
                if (error)
                        goto cleanup_all;
        }
+
        f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
 
        file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);
@@ -814,28 +818,75 @@ struct file *filp_open(const char * filename, int flags, int mode)
 {
        int namei_flags, error;
        struct nameidata nd;
-       struct file *f;
 
        namei_flags = flags;
        if ((namei_flags+1) & O_ACCMODE)
                namei_flags++;
-       if (namei_flags & O_TRUNC)
-               namei_flags |= 2;
-
-       error = -ENFILE;
-       f = get_empty_filp();
-       if (f == NULL)
-               return ERR_PTR(error);
 
        error = open_namei(filename, namei_flags, mode, &nd);
        if (!error)
-               return __dentry_open(nd.dentry, nd.mnt, flags, f);
+               return nameidata_to_filp(&nd, flags);
 
-       put_filp(f);
        return ERR_PTR(error);
 }
 EXPORT_SYMBOL(filp_open);
 
+/**
+ * lookup_instantiate_filp - instantiates the open intent filp
+ * @nd: pointer to nameidata
+ * @dentry: pointer to dentry
+ * @open: open callback
+ *
+ * Helper for filesystems that want to use lookup open intents and pass back
+ * a fully instantiated struct file to the caller.
+ * This function is meant to be called from within a filesystem's
+ * lookup method.
+ * Note that in case of error, nd->intent.open.file is destroyed, but the
+ * path information remains valid.
+ * If the open callback is set to NULL, then the standard f_op->open()
+ * filesystem callback is substituted.
+ */
+struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
+               int (*open)(struct inode *, struct file *))
+{
+       if (IS_ERR(nd->intent.open.file))
+               goto out;
+       if (IS_ERR(dentry))
+               goto out_err;
+       nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->mnt),
+                                            nd->intent.open.flags - 1,
+                                            nd->intent.open.file,
+                                            open);
+out:
+       return nd->intent.open.file;
+out_err:
+       release_open_intent(nd);
+       nd->intent.open.file = (struct file *)dentry;
+       goto out;
+}
+EXPORT_SYMBOL_GPL(lookup_instantiate_filp);
+
+/**
+ * nameidata_to_filp - convert a nameidata to an open filp.
+ * @nd: pointer to nameidata
+ * @flags: open flags
+ *
+ * Note that this function destroys the original nameidata
+ */
+struct file *nameidata_to_filp(struct nameidata *nd, int flags)
+{
+       struct file *filp;
+
+       /* Pick up the filp from the open intent */
+       filp = nd->intent.open.file;
+       /* Has the filesystem initialised the file for us? */
+       if (filp->f_dentry == NULL)
+               filp = __dentry_open(nd->dentry, nd->mnt, flags, filp, NULL);
+       else
+               path_release(nd);
+       return filp;
+}
+
 struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
 {
        int error;
@@ -846,7 +897,7 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
        if (f == NULL)
                return ERR_PTR(error);
 
-       return __dentry_open(dentry, mnt, flags, f);
+       return __dentry_open(dentry, mnt, flags, f, NULL);
 }
 EXPORT_SYMBOL(dentry_open);
 
index 2706e2adffab2df85da09f8884f68f38d5b9a747..45829889dcdc0a13dd93bcd523b305c5756f71dc 100644 (file)
@@ -2022,7 +2022,7 @@ static int get_neighbors(struct tree_balance *p_s_tb, int n_h)
 }
 
 #ifdef CONFIG_REISERFS_CHECK
-void *reiserfs_kmalloc(size_t size, int flags, struct super_block *s)
+void *reiserfs_kmalloc(size_t size, gfp_t flags, struct super_block *s)
 {
        void *vp;
        static size_t malloced;
index d76ee6c4f9b8874f1a26acdaa37a9fe9d693e490..5f82352b97e179c263366e550ab8f7564ebf1d16 100644 (file)
@@ -2842,7 +2842,7 @@ static int reiserfs_set_page_dirty(struct page *page)
  * even in -o notail mode, we can't be sure an old mount without -o notail
  * didn't create files with tails.
  */
-static int reiserfs_releasepage(struct page *page, int unused_gfp_flags)
+static int reiserfs_releasepage(struct page *page, gfp_t unused_gfp_flags)
 {
        struct inode *inode = page->mapping->host;
        struct reiserfs_journal *j = SB_JOURNAL(inode->i_sb);
index 87ac9dc8b381e8325ec2e26a1411c2e6d9449cc9..72e120798677a0ff20852c4a528bc8c4c5c9aa12 100644 (file)
@@ -453,7 +453,7 @@ static struct page *reiserfs_get_page(struct inode *dir, unsigned long n)
        struct page *page;
        /* We can deadlock if we try to free dentries,
           and an unlink/rmdir has just occured - GFP_NOFS avoids this */
-       mapping->flags = (mapping->flags & ~__GFP_BITS_MASK) | GFP_NOFS;
+       mapping_set_gfp_mask(mapping, GFP_NOFS);
        page = read_cache_page(mapping, n,
                               (filler_t *) mapping->a_ops->readpage, NULL);
        if (!IS_ERR(page)) {
index d2653b589b1c9d431d225e0d83de88fd95320565..3c92162dc7285280ab22682abf57fd4c4a647442 100644 (file)
 
 
 void *
-kmem_alloc(size_t size, gfp_t flags)
+kmem_alloc(size_t size, unsigned int __nocast flags)
 {
-       int             retries = 0;
-       unsigned int    lflags = kmem_flags_convert(flags);
-       void            *ptr;
+       int     retries = 0;
+       gfp_t   lflags = kmem_flags_convert(flags);
+       void    *ptr;
 
        do {
                if (size < MAX_SLAB_SIZE || retries > MAX_VMALLOCS)
@@ -67,7 +67,7 @@ kmem_alloc(size_t size, gfp_t flags)
 }
 
 void *
-kmem_zalloc(size_t size, gfp_t flags)
+kmem_zalloc(size_t size, unsigned int __nocast flags)
 {
        void    *ptr;
 
@@ -90,7 +90,7 @@ kmem_free(void *ptr, size_t size)
 
 void *
 kmem_realloc(void *ptr, size_t newsize, size_t oldsize,
-            gfp_t flags)
+            unsigned int __nocast flags)
 {
        void    *new;
 
@@ -105,11 +105,11 @@ kmem_realloc(void *ptr, size_t newsize, size_t oldsize,
 }
 
 void *
-kmem_zone_alloc(kmem_zone_t *zone, gfp_t flags)
+kmem_zone_alloc(kmem_zone_t *zone, unsigned int __nocast flags)
 {
-       int             retries = 0;
-       unsigned int    lflags = kmem_flags_convert(flags);
-       void            *ptr;
+       int     retries = 0;
+       gfp_t   lflags = kmem_flags_convert(flags);
+       void    *ptr;
 
        do {
                ptr = kmem_cache_alloc(zone, lflags);
@@ -124,7 +124,7 @@ kmem_zone_alloc(kmem_zone_t *zone, gfp_t flags)
 }
 
 void *
-kmem_zone_zalloc(kmem_zone_t *zone, gfp_t flags)
+kmem_zone_zalloc(kmem_zone_t *zone, unsigned int __nocast flags)
 {
        void    *ptr;
 
index ee7010f085bc1926e33f1ec98abd40c09bde76b7..f4bb78c268c0948e64b7d30122825e7adc7edd8b 100644 (file)
@@ -81,9 +81,9 @@ typedef unsigned long xfs_pflags_t;
        *(NSTATEP) = *(OSTATEP);        \
 } while (0)
 
-static __inline unsigned int kmem_flags_convert(gfp_t flags)
+static __inline gfp_t kmem_flags_convert(unsigned int __nocast flags)
 {
-       unsigned int    lflags = __GFP_NOWARN;  /* we'll report problems, if need be */
+       gfp_t lflags = __GFP_NOWARN;    /* we'll report problems, if need be */
 
 #ifdef DEBUG
        if (unlikely(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS|KM_MAYFAIL))) {
@@ -125,16 +125,16 @@ kmem_zone_destroy(kmem_zone_t *zone)
                BUG();
 }
 
-extern void        *kmem_zone_zalloc(kmem_zone_t *, gfp_t);
-extern void        *kmem_zone_alloc(kmem_zone_t *, gfp_t);
+extern void        *kmem_zone_zalloc(kmem_zone_t *, unsigned int __nocast);
+extern void        *kmem_zone_alloc(kmem_zone_t *, unsigned int __nocast);
 
-extern void        *kmem_alloc(size_t, gfp_t);
-extern void        *kmem_realloc(void *, size_t, size_t, gfp_t);
-extern void        *kmem_zalloc(size_t, gfp_t);
+extern void        *kmem_alloc(size_t, unsigned int __nocast);
+extern void        *kmem_realloc(void *, size_t, size_t, unsigned int __nocast);
+extern void        *kmem_zalloc(size_t, unsigned int __nocast);
 extern void         kmem_free(void *, size_t);
 
 typedef struct shrinker *kmem_shaker_t;
-typedef int (*kmem_shake_func_t)(int, unsigned int);
+typedef int (*kmem_shake_func_t)(int, gfp_t);
 
 static __inline kmem_shaker_t
 kmem_shake_register(kmem_shake_func_t sfunc)
@@ -149,7 +149,7 @@ kmem_shake_deregister(kmem_shaker_t shrinker)
 }
 
 static __inline int
-kmem_shake_allow(unsigned int gfp_mask)
+kmem_shake_allow(gfp_t gfp_mask)
 {
        return (gfp_mask & __GFP_WAIT);
 }
index c6c077978fe38bbc662e11de0d40cf0846a5dcfc..7aa398724706a9d1d8d6e2dada0fd7126acae9d4 100644 (file)
@@ -1296,7 +1296,7 @@ linvfs_invalidate_page(
 STATIC int
 linvfs_release_page(
        struct page             *page,
-       int                     gfp_mask)
+       gfp_t                   gfp_mask)
 {
        struct inode            *inode = page->mapping->host;
        int                     dirty, delalloc, unmapped, unwritten;
index e82cf72ac599a55aad2539c6fe0158f2788b15d0..ba4767c04adfbf0fc3895a04086370f9f35b4d2b 100644 (file)
@@ -64,7 +64,7 @@
 
 STATIC kmem_cache_t *pagebuf_zone;
 STATIC kmem_shaker_t pagebuf_shake;
-STATIC int xfsbufd_wakeup(int, unsigned int);
+STATIC int xfsbufd_wakeup(int, gfp_t);
 STATIC void pagebuf_delwri_queue(xfs_buf_t *, int);
 
 STATIC struct workqueue_struct *xfslogd_workqueue;
@@ -383,7 +383,7 @@ _pagebuf_lookup_pages(
        size_t                  blocksize = bp->pb_target->pbr_bsize;
        size_t                  size = bp->pb_count_desired;
        size_t                  nbytes, offset;
-       int                     gfp_mask = pb_to_gfp(flags);
+       gfp_t                   gfp_mask = pb_to_gfp(flags);
        unsigned short          page_count, i;
        pgoff_t                 first;
        loff_t                  end;
@@ -1749,8 +1749,8 @@ STATIC int xfsbufd_force_sleep;
 
 STATIC int
 xfsbufd_wakeup(
-       int                     priority,
-       unsigned int            mask)
+       int             priority,
+       gfp_t           mask)
 {
        if (xfsbufd_force_sleep)
                return 0;
index c675f282d6ad9d8090ddefeb42d25343635b161a..680f7ecbb28f7df56d7e85a2089f45d454a4f751 100644 (file)
@@ -31,7 +31,7 @@
 #else  /* no PCI - no IOMMU. */
 
 void *dma_alloc_coherent(struct device *dev, size_t size,
-                        dma_addr_t *dma_handle, int gfp);
+                        dma_addr_t *dma_handle, gfp_t gfp);
 int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
               enum dma_data_direction direction);
 
index d62ade4e4cbb24facf3b95a3774e4ec508ba6001..e3e8541ee63b07f57d915e5409e279d0f09ce2c6 100644 (file)
@@ -70,7 +70,7 @@ static inline int dma_mapping_error(dma_addr_t dma_addr)
  * device-viewed address.
  */
 extern void *
-dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, int gfp);
+dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp);
 
 /**
  * dma_free_coherent - free memory allocated by dma_alloc_coherent
@@ -117,7 +117,7 @@ int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
  * device-viewed address.
  */
 extern void *
-dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, int gfp);
+dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp);
 
 #define dma_free_writecombine(dev,size,cpu_addr,handle) \
        dma_free_coherent(dev,size,cpu_addr,handle)
index 0b5c3fdaefe1f14941d9e20b52feb7dab2eb847d..8eff51349ae75235f59764974031bf73f9705210 100644 (file)
 
 #ifdef CONFIG_PCI
 void *dma_alloc_coherent(struct device *dev, size_t size,
-                          dma_addr_t *dma_handle, int flag);
+                          dma_addr_t *dma_handle, gfp_t flag);
 
 void dma_free_coherent(struct device *dev, size_t size,
                         void *vaddr, dma_addr_t dma_handle);
 #else
 static inline void *
 dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
-                   int flag)
+                   gfp_t flag)
 {
         BUG();
         return NULL;
index 0206ab35eae08babea7c12f7c4fdf170b17b71e9..5003e017fd1ecae1905950c1fb49f75e8aca37c1 100644 (file)
@@ -13,7 +13,7 @@
 extern unsigned long __nongprelbss dma_coherent_mem_start;
 extern unsigned long __nongprelbss dma_coherent_mem_end;
 
-void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, int gfp);
+void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp);
 void dma_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle);
 
 /*
index b4efe5e3591a5b22a7f511b606c13c4d3cf4b0ce..1168451c275fb1603892630bf3510a6899dace0b 100644 (file)
@@ -32,7 +32,7 @@ extern void pcibios_set_master(struct pci_dev *dev);
 extern void pcibios_penalize_isa_irq(int irq);
 
 #ifdef CONFIG_MMU
-extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle);
+extern void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *dma_handle);
 extern void consistent_free(void *vaddr);
 extern void consistent_sync(void *vaddr, size_t size, int direction);
 extern void consistent_sync_page(struct page *page, unsigned long offset,
index fd9de9502dff09f52df54458f3d5fd0265372298..a7f1a55ce6b0a07b2bf7850e4dda29c3eb88d67d 100644 (file)
@@ -6,7 +6,7 @@
 
 static inline void *
 dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
-                  int flag)
+                  gfp_t flag)
 {
        BUG();
        return NULL;
index 79e89a7db5665563aa265523c756ea4763fe3e8a..a2f6ac5aef7d9d2a4a0cafb70fcafac6aef0e1ee 100644 (file)
@@ -37,7 +37,7 @@ typedef int ia64_mv_pci_legacy_write_t (struct pci_bus *, u16 port, u32 val,
 
 /* DMA-mapping interface: */
 typedef void ia64_mv_dma_init (void);
-typedef void *ia64_mv_dma_alloc_coherent (struct device *, size_t, dma_addr_t *, int);
+typedef void *ia64_mv_dma_alloc_coherent (struct device *, size_t, dma_addr_t *, gfp_t);
 typedef void ia64_mv_dma_free_coherent (struct device *, size_t, void *, dma_addr_t);
 typedef dma_addr_t ia64_mv_dma_map_single (struct device *, void *, size_t, int);
 typedef void ia64_mv_dma_unmap_single (struct device *, dma_addr_t, size_t, int);
index 3a2db28834b68d84bcd47d9c751cb703706363bc..a7fa0302bda7e0a5258a506254a701bf37d59fed 100644 (file)
@@ -8,7 +8,7 @@
 
 static inline void *
 dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
-                  int flag)
+                  gfp_t flag)
 {
        return (void *)NULL;
 }
index af28dc88930b40aa59c6c6102e46ac7d5e62ec09..43288634c38a7bbca2793d295f801de22ffaf2ea 100644 (file)
@@ -5,13 +5,13 @@
 #include <asm/cache.h>
 
 void *dma_alloc_noncoherent(struct device *dev, size_t size,
-                          dma_addr_t *dma_handle, int flag);
+                          dma_addr_t *dma_handle, gfp_t flag);
 
 void dma_free_noncoherent(struct device *dev, size_t size,
                         void *vaddr, dma_addr_t dma_handle);
 
 void *dma_alloc_coherent(struct device *dev, size_t size,
-                          dma_addr_t *dma_handle, int flag);
+                          dma_addr_t *dma_handle, gfp_t flag);
 
 void dma_free_coherent(struct device *dev, size_t size,
                         void *vaddr, dma_addr_t dma_handle);
index 4db84f969e9eb7543d7234365a8a9a89058e0028..74d4ac6f2151ebfdece63746f6d93fd1e3bde8c3 100644 (file)
@@ -9,8 +9,8 @@
 /* See Documentation/DMA-mapping.txt */
 struct hppa_dma_ops {
        int  (*dma_supported)(struct device *dev, u64 mask);
-       void *(*alloc_consistent)(struct device *dev, size_t size, dma_addr_t *iova, int flag);
-       void *(*alloc_noncoherent)(struct device *dev, size_t size, dma_addr_t *iova, int flag);
+       void *(*alloc_consistent)(struct device *dev, size_t size, dma_addr_t *iova, gfp_t flag);
+       void *(*alloc_noncoherent)(struct device *dev, size_t size, dma_addr_t *iova, gfp_t flag);
        void (*free_consistent)(struct device *dev, size_t size, void *vaddr, dma_addr_t iova);
        dma_addr_t (*map_single)(struct device *dev, void *addr, size_t size, enum dma_data_direction direction);
        void (*unmap_single)(struct device *dev, dma_addr_t iova, size_t size, enum dma_data_direction direction);
@@ -49,14 +49,14 @@ extern struct hppa_dma_ops *hppa_dma_ops;
 
 static inline void *
 dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
-                  int flag)
+                  gfp_t flag)
 {
        return hppa_dma_ops->alloc_consistent(dev, size, dma_handle, flag);
 }
 
 static inline void *
 dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
-                     int flag)
+                     gfp_t flag)
 {
        return hppa_dma_ops->alloc_noncoherent(dev, size, dma_handle, flag);
 }
index 061bfcac1bf1c359802f9f755b776d92b3b78e22..6e9635114433a94e2a08b934487f6dd82e0b8cf5 100644 (file)
@@ -19,7 +19,7 @@
  * allocate the space "normally" and use the cache management functions
  * to ensure it is consistent.
  */
-extern void *__dma_alloc_coherent(size_t size, dma_addr_t *handle, int gfp);
+extern void *__dma_alloc_coherent(size_t size, dma_addr_t *handle, gfp_t gfp);
 extern void __dma_free_coherent(size_t size, void *vaddr);
 extern void __dma_sync(void *vaddr, size_t size, int direction);
 extern void __dma_sync_page(struct page *page, unsigned long offset,
index 80d164c1529efb121726108bf7d24fc44d8bbcde..d3fa5c2b889d270139407f9cba31bddfaf58ab82 100644 (file)
@@ -9,7 +9,7 @@
 extern struct bus_type pci_bus_type;
 
 /* arch/sh/mm/consistent.c */
-extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle);
+extern void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle);
 extern void consistent_free(void *vaddr, size_t size);
 extern void consistent_sync(void *vaddr, size_t size, int direction);
 
@@ -26,7 +26,7 @@ static inline int dma_set_mask(struct device *dev, u64 mask)
 }
 
 static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-                        dma_addr_t *dma_handle, int flag)
+                        dma_addr_t *dma_handle, gfp_t flag)
 {
        if (sh_mv.mv_consistent_alloc) {
                void *ret;
index 5771f4baa47871fdd4623e20a631ed1ff076e3c2..3f18aa18051693e78f810c85eb71f3d0a55ebfa6 100644 (file)
@@ -64,7 +64,7 @@ struct sh_machine_vector
 
        void (*mv_heartbeat)(void);
 
-       void *(*mv_consistent_alloc)(struct device *, size_t, dma_addr_t *, int);
+       void *(*mv_consistent_alloc)(struct device *, size_t, dma_addr_t *, gfp_t);
        int (*mv_consistent_free)(struct device *, size_t, void *, dma_addr_t);
 };
 
index b8d26fe677f4f92cbedd09fff90ea70d1af44c4b..cc9a2e86f5b413d566f81c07781596cc4a7b5b65 100644 (file)
@@ -25,7 +25,7 @@ static inline int dma_set_mask(struct device *dev, u64 mask)
 }
 
 static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-                        dma_addr_t *dma_handle, int flag)
+                        dma_addr_t *dma_handle, gfp_t flag)
 {
        return consistent_alloc(NULL, size, dma_handle);
 }
index 2dc5bb8effa6ff1d3d592f53a86e3c76f1f43de2..d7c3b0f0a90103de71853fbdaa5aedf380197c49 100644 (file)
@@ -8,7 +8,7 @@
 #else
 
 static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-                        dma_addr_t *dma_handle, int flag)
+                        dma_addr_t *dma_handle, gfp_t flag)
 {
        BUG();
        return NULL;
index 1c5da41653a44c1ed21dd6d5d554958ea67b51cc..c7d5804ba76df1a1e458746cea57a828cbe93ac2 100644 (file)
@@ -10,7 +10,7 @@
 struct device;
 
 static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-                        dma_addr_t *dma_handle, int flag)
+                        dma_addr_t *dma_handle, gfp_t flag)
 {
        BUG();
        return NULL;
index 13e6291f71511dbb05248ce644a29f3e6597c8d0..babd2989511465887973098e1619e6d20a067669 100644 (file)
@@ -19,7 +19,7 @@ dma_set_mask(struct device *dev, u64 dma_mask)
 
 static inline void *
 dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
-                  int flag)
+                  gfp_t flag)
 {
        BUG();
        return((void *) 0);
index 2c192abe9aeb0d29ac9ce1946214bc697af7c170..0229814af31e6bedad5d66381187d21f31f85796 100644 (file)
@@ -115,7 +115,7 @@ extern unsigned long uml_physmem;
 #define pfn_valid(pfn) ((pfn) < max_mapnr)
 #define virt_addr_valid(v) pfn_valid(phys_to_pfn(__pa(v)))
 
-extern struct page *arch_validate(struct page *page, int mask, int order);
+extern struct page *arch_validate(struct page *page, gfp_t mask, int order);
 #define HAVE_ARCH_VALIDATE
 
 extern void arch_free_page(struct page *page, int order);
index e784fdc524f1ac7be2dce7930995cccab58dc0f6..54a380efed413fda6d8c0bf155d4f2ace1a6753c 100644 (file)
@@ -17,7 +17,7 @@ extern dma_addr_t bad_dma_address;
        (swiotlb ? swiotlb_dma_mapping_error(x) : ((x) == bad_dma_address))
 
 void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
-                        unsigned gfp);
+                        gfp_t gfp);
 void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
                         dma_addr_t dma_handle);
 
index 36293061f4ed6b1416aac1604417d73fbd157765..7cbfd10ecc3c1c49ba70fde51d1a7efefeb264cf 100644 (file)
@@ -27,7 +27,7 @@ extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg,
                         int nents, int direction);
 extern int swiotlb_dma_mapping_error(dma_addr_t dma_addr);
 extern void *swiotlb_alloc_coherent (struct device *hwdev, size_t size,
-                                    dma_addr_t *dma_handle, int flags);
+                                    dma_addr_t *dma_handle, gfp_t flags);
 extern void swiotlb_free_coherent (struct device *hwdev, size_t size,
                                   void *vaddr, dma_addr_t dma_handle);
 
index e86a206f12093313335e326af2fb9af63fb24d42..c425f10d086a500c9ca45ca63df857bef16e3f09 100644 (file)
@@ -28,7 +28,7 @@ extern void consistent_sync(void*, size_t, int);
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
 
 void *dma_alloc_coherent(struct device *dev, size_t size,
-                          dma_addr_t *dma_handle, int flag);
+                          dma_addr_t *dma_handle, gfp_t flag);
 
 void dma_free_coherent(struct device *dev, size_t size,
                         void *vaddr, dma_addr_t dma_handle);
index b2a2509bd7ea35b02874d034e5928fbea18ac8c1..da3c01955f3d8eea8cacd69d9ef9485517493bf2 100644 (file)
@@ -260,11 +260,11 @@ extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
 #ifdef CONFIG_AUDIT
 /* These are defined in audit.c */
                                /* Public API */
-extern void                audit_log(struct audit_context *ctx, int gfp_mask,
+extern void                audit_log(struct audit_context *ctx, gfp_t gfp_mask,
                                      int type, const char *fmt, ...)
                                      __attribute__((format(printf,4,5)));
 
-extern struct audit_buffer *audit_log_start(struct audit_context *ctx, int gfp_mask, int type);
+extern struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type);
 extern void                audit_log_format(struct audit_buffer *ab,
                                             const char *fmt, ...)
                            __attribute__((format(printf,2,3)));
index 3344b4e8e43a1acc8e90e6de6600c6269aa14ff2..685fd3720df5b2105c86d3be588eb9cf0061b360 100644 (file)
@@ -301,7 +301,7 @@ extern struct bio *bio_map_user_iov(struct request_queue *,
                                    struct sg_iovec *, int, int);
 extern void bio_unmap_user(struct bio *);
 extern struct bio *bio_map_kern(struct request_queue *, void *, unsigned int,
-                               unsigned int);
+                               gfp_t);
 extern void bio_set_pages_dirty(struct bio *bio);
 extern void bio_check_pages_dirty(struct bio *bio);
 extern struct bio *bio_copy_user(struct request_queue *, unsigned long, unsigned int, int);
index efdc9b5bc05c8687380200f8a871975c91709860..1afbdb2d752c972df6fc986bee0b2c9bbc1fb9b5 100644 (file)
@@ -96,8 +96,8 @@ struct io_context {
 
 void put_io_context(struct io_context *ioc);
 void exit_io_context(void);
-struct io_context *current_io_context(int gfp_flags);
-struct io_context *get_io_context(int gfp_flags);
+struct io_context *current_io_context(gfp_t gfp_flags);
+struct io_context *get_io_context(gfp_t gfp_flags);
 void copy_io_context(struct io_context **pdst, struct io_context **psrc);
 void swap_io_context(struct io_context **ioc1, struct io_context **ioc2);
 
@@ -354,7 +354,7 @@ struct request_queue
         * queue needs bounce pages for pages above this limit
         */
        unsigned long           bounce_pfn;
-       unsigned int            bounce_gfp;
+       gfp_t                   bounce_gfp;
 
        /*
         * various queue flags, see QUEUE_* below
@@ -550,7 +550,7 @@ extern void generic_make_request(struct bio *bio);
 extern void blk_put_request(struct request *);
 extern void blk_end_sync_rq(struct request *rq);
 extern void blk_attempt_remerge(request_queue_t *, struct request *);
-extern struct request *blk_get_request(request_queue_t *, int, int);
+extern struct request *blk_get_request(request_queue_t *, int, gfp_t);
 extern void blk_insert_request(request_queue_t *, struct request *, int, void *);
 extern void blk_requeue_request(request_queue_t *, struct request *);
 extern void blk_plug_device(request_queue_t *);
@@ -565,7 +565,7 @@ extern void blk_run_queue(request_queue_t *);
 extern void blk_queue_activity_fn(request_queue_t *, activity_fn *, void *);
 extern int blk_rq_map_user(request_queue_t *, struct request *, void __user *, unsigned int);
 extern int blk_rq_unmap_user(struct bio *, unsigned int);
-extern int blk_rq_map_kern(request_queue_t *, struct request *, void *, unsigned int, unsigned int);
+extern int blk_rq_map_kern(request_queue_t *, struct request *, void *, unsigned int, gfp_t);
 extern int blk_rq_map_user_iov(request_queue_t *, struct request *, struct sg_iovec *, int);
 extern int blk_execute_rq(request_queue_t *, struct gendisk *,
                          struct request *, int);
@@ -654,8 +654,8 @@ extern void blk_wait_queue_drained(request_queue_t *, int);
 extern void blk_finish_queue_drain(request_queue_t *);
 
 int blk_get_queue(request_queue_t *);
-request_queue_t *blk_alloc_queue(int gfp_mask);
-request_queue_t *blk_alloc_queue_node(int,int);
+request_queue_t *blk_alloc_queue(gfp_t);
+request_queue_t *blk_alloc_queue_node(gfp_t, int);
 #define blk_put_queue(q) blk_cleanup_queue((q))
 
 /*
index 6a1d154c082523dc934021afe1e36445a5fc75ac..88af42f5e04a8fc6ebdc963f4ccf51a01f689dae 100644 (file)
@@ -188,7 +188,7 @@ extern int buffer_heads_over_limit;
  * Generic address_space_operations implementations for buffer_head-backed
  * address_spaces.
  */
-int try_to_release_page(struct page * page, int gfp_mask);
+int try_to_release_page(struct page * page, gfp_t gfp_mask);
 int block_invalidatepage(struct page *page, unsigned long offset);
 int block_write_full_page(struct page *page, get_block_t *get_block,
                                struct writeback_control *wbc);
index ea6bbc2d7407e9fb48de7c67756e4463bba82970..ed93125c1db5b6bc0f0e72f6baba89ddb7c501f8 100644 (file)
@@ -18,7 +18,7 @@ typedef struct request *(elevator_request_list_fn) (request_queue_t *, struct re
 typedef void (elevator_completed_req_fn) (request_queue_t *, struct request *);
 typedef int (elevator_may_queue_fn) (request_queue_t *, int, struct bio *);
 
-typedef int (elevator_set_req_fn) (request_queue_t *, struct request *, struct bio *, int);
+typedef int (elevator_set_req_fn) (request_queue_t *, struct request *, struct bio *, gfp_t);
 typedef void (elevator_put_req_fn) (request_queue_t *, struct request *);
 typedef void (elevator_deactivate_req_fn) (request_queue_t *, struct request *);
 
@@ -98,7 +98,7 @@ extern int elv_register_queue(request_queue_t *q);
 extern void elv_unregister_queue(request_queue_t *q);
 extern int elv_may_queue(request_queue_t *, int, struct bio *);
 extern void elv_completed_request(request_queue_t *, struct request *);
-extern int elv_set_request(request_queue_t *, struct request *, struct bio *, int);
+extern int elv_set_request(request_queue_t *, struct request *, struct bio *, gfp_t);
 extern void elv_put_request(request_queue_t *, struct request *);
 
 /*
index e0b77c5af9a02aadab2a1fcd2e967c92c402ce16..f83d997c55820101385553e780fa5216d2be25fc 100644 (file)
@@ -320,7 +320,7 @@ struct address_space_operations {
        /* Unfortunately this kludge is needed for FIBMAP. Don't use it */
        sector_t (*bmap)(struct address_space *, sector_t);
        int (*invalidatepage) (struct page *, unsigned long);
-       int (*releasepage) (struct page *, int);
+       int (*releasepage) (struct page *, gfp_t);
        ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
                        loff_t offset, unsigned long nr_segs);
        struct page* (*get_xip_page)(struct address_space *, sector_t,
index 3010e172394dc148539fdb3c5476310d16012769..c3779432a7239b5e2b85494f594d69db3adb6fb8 100644 (file)
@@ -12,8 +12,8 @@ struct vm_area_struct;
  * GFP bitmasks..
  */
 /* Zone modifiers in GFP_ZONEMASK (see linux/mmzone.h - low two bits) */
-#define __GFP_DMA      0x01u
-#define __GFP_HIGHMEM  0x02u
+#define __GFP_DMA      ((__force gfp_t)0x01u)
+#define __GFP_HIGHMEM  ((__force gfp_t)0x02u)
 
 /*
  * Action modifiers - doesn't change the zoning
@@ -26,24 +26,24 @@ struct vm_area_struct;
  *
  * __GFP_NORETRY: The VM implementation must not retry indefinitely.
  */
-#define __GFP_WAIT     0x10u   /* Can wait and reschedule? */
-#define __GFP_HIGH     0x20u   /* Should access emergency pools? */
-#define __GFP_IO       0x40u   /* Can start physical IO? */
-#define __GFP_FS       0x80u   /* Can call down to low-level FS? */
-#define __GFP_COLD     0x100u  /* Cache-cold page required */
-#define __GFP_NOWARN   0x200u  /* Suppress page allocation failure warning */
-#define __GFP_REPEAT   0x400u  /* Retry the allocation.  Might fail */
-#define __GFP_NOFAIL   0x800u  /* Retry for ever.  Cannot fail */
-#define __GFP_NORETRY  0x1000u /* Do not retry.  Might fail */
-#define __GFP_NO_GROW  0x2000u /* Slab internal usage */
-#define __GFP_COMP     0x4000u /* Add compound page metadata */
-#define __GFP_ZERO     0x8000u /* Return zeroed page on success */
-#define __GFP_NOMEMALLOC 0x10000u /* Don't use emergency reserves */
-#define __GFP_NORECLAIM  0x20000u /* No realy zone reclaim during allocation */
-#define __GFP_HARDWALL   0x40000u /* Enforce hardwall cpuset memory allocs */
+#define __GFP_WAIT     ((__force gfp_t)0x10u)  /* Can wait and reschedule? */
+#define __GFP_HIGH     ((__force gfp_t)0x20u)  /* Should access emergency pools? */
+#define __GFP_IO       ((__force gfp_t)0x40u)  /* Can start physical IO? */
+#define __GFP_FS       ((__force gfp_t)0x80u)  /* Can call down to low-level FS? */
+#define __GFP_COLD     ((__force gfp_t)0x100u) /* Cache-cold page required */
+#define __GFP_NOWARN   ((__force gfp_t)0x200u) /* Suppress page allocation failure warning */
+#define __GFP_REPEAT   ((__force gfp_t)0x400u) /* Retry the allocation.  Might fail */
+#define __GFP_NOFAIL   ((__force gfp_t)0x800u) /* Retry for ever.  Cannot fail */
+#define __GFP_NORETRY  ((__force gfp_t)0x1000u)/* Do not retry.  Might fail */
+#define __GFP_NO_GROW  ((__force gfp_t)0x2000u)/* Slab internal usage */
+#define __GFP_COMP     ((__force gfp_t)0x4000u)/* Add compound page metadata */
+#define __GFP_ZERO     ((__force gfp_t)0x8000u)/* Return zeroed page on success */
+#define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */
+#define __GFP_NORECLAIM  ((__force gfp_t)0x20000u) /* No realy zone reclaim during allocation */
+#define __GFP_HARDWALL   ((__force gfp_t)0x40000u) /* Enforce hardwall cpuset memory allocs */
 
 #define __GFP_BITS_SHIFT 20    /* Room for 20 __GFP_FOO bits */
-#define __GFP_BITS_MASK ((1 << __GFP_BITS_SHIFT) - 1)
+#define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
 
 /* if you forget to add the bitmask here kernel will crash, period */
 #define GFP_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS| \
@@ -64,6 +64,7 @@ struct vm_area_struct;
 
 #define GFP_DMA                __GFP_DMA
 
+#define gfp_zone(mask) ((__force int)((mask) & (__force gfp_t)GFP_ZONEMASK))
 
 /*
  * There is only one page-allocator function, and two main namespaces to
@@ -94,7 +95,7 @@ static inline struct page *alloc_pages_node(int nid, gfp_t gfp_mask,
                return NULL;
 
        return __alloc_pages(gfp_mask, order,
-               NODE_DATA(nid)->node_zonelists + (gfp_mask & GFP_ZONEMASK));
+               NODE_DATA(nid)->node_zonelists + gfp_zone(gfp_mask));
 }
 
 #ifdef CONFIG_NUMA
index bdc286ec947c13b2017a9dcc3dd5f49f0ed60533..b4af45aad25df5bf8fb669983bae3eacf76c9d62 100644 (file)
@@ -492,7 +492,7 @@ static inline int i2o_dma_map_sg(struct i2o_controller *c,
  *     Returns 0 on success or -ENOMEM on failure.
  */
 static inline int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr,
-                               size_t len, unsigned int gfp_mask)
+                               size_t len, gfp_t gfp_mask)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
        int dma_64 = 0;
@@ -551,7 +551,7 @@ static inline void i2o_dma_free(struct device *dev, struct i2o_dma *addr)
  *     Returns the 0 on success or negative error code on failure.
  */
 static inline int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr,
-                                 size_t len, unsigned int gfp_mask)
+                                 size_t len, gfp_t gfp_mask)
 {
        i2o_dma_free(dev, addr);
 
index 3d5de45f961b050d9780795c0bb07a34c866911c..7fb3ff9c7b0e4763b15b3ebf1aad0148a64f8e00 100644 (file)
@@ -71,7 +71,7 @@ struct idr {
  */
 
 void *idr_find(struct idr *idp, int id);
-int idr_pre_get(struct idr *idp, unsigned gfp_mask);
+int idr_pre_get(struct idr *idp, gfp_t gfp_mask);
 int idr_get_new(struct idr *idp, void *ptr, int *id);
 int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id);
 void idr_remove(struct idr *idp, int id);
index ff853b3173c6545a189da4c1ddd04a055c5218a0..be197eb900777167fedecdce824be0c2275a78d5 100644 (file)
@@ -69,7 +69,7 @@ extern int journal_enable_debug;
 #define jbd_debug(f, a...)     /**/
 #endif
 
-extern void * __jbd_kmalloc (const char *where, size_t size, int flags, int retry);
+extern void * __jbd_kmalloc (const char *where, size_t size, gfp_t flags, int retry);
 #define jbd_kmalloc(size, flags) \
        __jbd_kmalloc(__FUNCTION__, (size), (flags), journal_oom_retry)
 #define jbd_rep_kmalloc(size, flags) \
@@ -890,7 +890,7 @@ extern int   journal_forget (handle_t *, struct buffer_head *);
 extern void     journal_sync_buffer (struct buffer_head *);
 extern int      journal_invalidatepage(journal_t *,
                                struct page *, unsigned long);
-extern int      journal_try_to_free_buffers(journal_t *, struct page *, int);
+extern int      journal_try_to_free_buffers(journal_t *, struct page *, gfp_t);
 extern int      journal_stop(handle_t *);
 extern int      journal_flush (journal_t *);
 extern void     journal_lock_updates (journal_t *);
index 3b22304f12fd9f542f9a09f10e7bcde9531a9fd7..7f7403aa4a417c4fbf7ab8ad5740dff8aadb61f8 100644 (file)
@@ -65,7 +65,7 @@ extern void kobject_unregister(struct kobject *);
 extern struct kobject * kobject_get(struct kobject *);
 extern void kobject_put(struct kobject *);
 
-extern char * kobject_get_path(struct kobject *, int);
+extern char * kobject_get_path(struct kobject *, gfp_t);
 
 struct kobj_type {
        void (*release)(struct kobject *);
index 53fa51595443e81d2878ab22902f0815d1933844..40f63c9879d26798bbfc073753cc58ecd9de306b 100644 (file)
@@ -52,7 +52,7 @@ struct loop_device {
        unsigned        lo_blocksize;
        void            *key_data; 
 
-       int             old_gfp_mask;
+       gfp_t           old_gfp_mask;
 
        spinlock_t              lo_lock;
        struct bio              *lo_bio;
index 9263d2db2d670f41d24a2c9ec707c6a98db09ee8..99e044b4efc6d62ea92e79f79a2b74ec8b8559ad 100644 (file)
@@ -22,7 +22,7 @@ struct mb_cache_entry {
 };
 
 struct mb_cache_op {
-       int (*free)(struct mb_cache_entry *, int);
+       int (*free)(struct mb_cache_entry *, gfp_t);
 };
 
 /* Functions on caches */
index 097b3a3c693d58c924dd7409db1dd295ebfe8a23..e1649578fb0ca4cec40f93d1b358993f8bb69d23 100644 (file)
@@ -747,7 +747,7 @@ extern unsigned long do_mremap(unsigned long addr,
  * The callback will be passed nr_to_scan == 0 when the VM is querying the
  * cache size, so a fastpath for that case is appropriate.
  */
-typedef int (*shrinker_t)(int nr_to_scan, unsigned int gfp_mask);
+typedef int (*shrinker_t)(int nr_to_scan, gfp_t gfp_mask);
 
 /*
  * Add an aging callback.  The int is the number of 'seeks' it takes
index 5ed471b58f4f0c83904101ee6cb734bb104a47ad..7519eb4191e7d962e6a34e9831cb86441531ffdb 100644 (file)
@@ -302,7 +302,7 @@ void get_zone_counts(unsigned long *active, unsigned long *inactive,
 void build_all_zonelists(void);
 void wakeup_kswapd(struct zone *zone, int order);
 int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
-               int alloc_type, int can_try_harder, int gfp_high);
+               int alloc_type, int can_try_harder, gfp_t gfp_high);
 
 #ifdef CONFIG_HAVE_MEMORY_PRESENT
 void memory_present(int nid, unsigned long start, unsigned long end);
index 7db67b008cac425a089de3777a95210ccc50e586..1c975d0d9e949b628eb4fa35ef5001c763fb529c 100644 (file)
@@ -8,6 +8,7 @@ struct vfsmount;
 struct open_intent {
        int     flags;
        int     create_mode;
+       struct file *file;
 };
 
 enum { MAX_NESTED_LINKS = 5 };
@@ -65,6 +66,13 @@ extern int FASTCALL(link_path_walk(const char *, struct nameidata *));
 extern void path_release(struct nameidata *);
 extern void path_release_on_umount(struct nameidata *);
 
+extern int __user_path_lookup_open(const char __user *, unsigned lookup_flags, struct nameidata *nd, int open_flags);
+extern int path_lookup_open(const char *, unsigned lookup_flags, struct nameidata *, int open_flags);
+extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
+               int (*open)(struct inode *, struct file *));
+extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
+extern void release_open_intent(struct nameidata *);
+
 extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
 extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
 
index 9a6047ff1b25b198a869678463ed0561cbf417cc..325fe7ae49bb7be58270b261c52640de10085535 100644 (file)
 #define NFS_MAX_FILE_IO_BUFFER_SIZE    32768
 #define NFS_DEF_FILE_IO_BUFFER_SIZE    4096
 
+/* Default timeout values */
+#define NFS_MAX_UDP_TIMEOUT    (60*HZ)
+#define NFS_MAX_TCP_TIMEOUT    (600*HZ)
+
 /*
  * superblock magic number for NFS
  */
@@ -137,6 +141,7 @@ struct nfs_inode {
        unsigned long           attrtimeo_timestamp;
        __u64                   change_attr;            /* v4 only */
 
+       unsigned long           last_updated;
        /* "Generation counter" for the attribute cache. This is
         * bumped whenever we update the metadata on the
         * server.
@@ -236,13 +241,17 @@ static inline int nfs_caches_unstable(struct inode *inode)
        return atomic_read(&NFS_I(inode)->data_updates) != 0;
 }
 
+static inline void nfs_mark_for_revalidate(struct inode *inode)
+{
+       spin_lock(&inode->i_lock);
+       NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS;
+       spin_unlock(&inode->i_lock);
+}
+
 static inline void NFS_CACHEINV(struct inode *inode)
 {
-       if (!nfs_caches_unstable(inode)) {
-               spin_lock(&inode->i_lock);
-               NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS;
-               spin_unlock(&inode->i_lock);
-       }
+       if (!nfs_caches_unstable(inode))
+               nfs_mark_for_revalidate(inode);
 }
 
 static inline int nfs_server_capable(struct inode *inode, int cap)
@@ -276,7 +285,7 @@ static inline long nfs_save_change_attribute(struct inode *inode)
 static inline int nfs_verify_change_attribute(struct inode *inode, unsigned long chattr)
 {
        return !nfs_caches_unstable(inode)
-               && chattr == NFS_I(inode)->cache_change_attribute;
+               && time_after_eq(chattr, NFS_I(inode)->cache_change_attribute);
 }
 
 /*
@@ -286,6 +295,7 @@ extern void nfs_zap_caches(struct inode *);
 extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *,
                                struct nfs_fattr *);
 extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
+extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr);
 extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 extern int nfs_permission(struct inode *, int, struct nameidata *);
 extern int nfs_access_get_cached(struct inode *, struct rpc_cred *, struct nfs_access_entry *);
@@ -312,6 +322,12 @@ extern void nfs_file_clear_open_context(struct file *filp);
 /* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */
 extern u32 root_nfs_parse_addr(char *name); /*__init*/
 
+static inline void nfs_fattr_init(struct nfs_fattr *fattr)
+{
+       fattr->valid = 0;
+       fattr->time_start = jiffies;
+}
+
 /*
  * linux/fs/nfs/file.c
  */
index a2bf6914ff1b3aa1c444ef1478ac078a44070db6..40718669b9c896e45939e6490f38d843d67623ea 100644 (file)
@@ -41,7 +41,7 @@ struct nfs_fattr {
        __u32                   bitmap[2];      /* NFSv4 returned attribute bitmap */
        __u64                   change_attr;    /* NFSv4 change attribute */
        __u64                   pre_change_attr;/* pre-op NFSv4 change attribute */
-       unsigned long           timestamp;
+       unsigned long           time_start;
 };
 
 #define NFS_ATTR_WCC           0x0001          /* pre-op WCC data    */
@@ -96,12 +96,13 @@ struct nfs4_change_info {
        u64                     after;
 };
 
+struct nfs_seqid;
 /*
  * Arguments to the open call.
  */
 struct nfs_openargs {
        const struct nfs_fh *   fh;
-       __u32                   seqid;
+       struct nfs_seqid *      seqid;
        int                     open_flags;
        __u64                   clientid;
        __u32                   id;
@@ -123,6 +124,7 @@ struct nfs_openres {
        struct nfs4_change_info cinfo;
        __u32                   rflags;
        struct nfs_fattr *      f_attr;
+       struct nfs_fattr *      dir_attr;
        const struct nfs_server *server;
        int                     delegation_type;
        nfs4_stateid            delegation;
@@ -136,7 +138,7 @@ struct nfs_openres {
 struct nfs_open_confirmargs {
        const struct nfs_fh *   fh;
        nfs4_stateid            stateid;
-       __u32                   seqid;
+       struct nfs_seqid *      seqid;
 };
 
 struct nfs_open_confirmres {
@@ -148,13 +150,16 @@ struct nfs_open_confirmres {
  */
 struct nfs_closeargs {
        struct nfs_fh *         fh;
-       nfs4_stateid            stateid;
-       __u32                   seqid;
+       nfs4_stateid *          stateid;
+       struct nfs_seqid *      seqid;
        int                     open_flags;
+       const u32 *             bitmask;
 };
 
 struct nfs_closeres {
        nfs4_stateid            stateid;
+       struct nfs_fattr *      fattr;
+       const struct nfs_server *server;
 };
 /*
  *  * Arguments to the lock,lockt, and locku call.
@@ -164,30 +169,19 @@ struct nfs_lowner {
        u32                     id;
 };
 
-struct nfs_open_to_lock {
-       __u32                   open_seqid;
-       nfs4_stateid            open_stateid;
-       __u32                   lock_seqid;
-       struct nfs_lowner       lock_owner;
-};
-
-struct nfs_exist_lock {
-       nfs4_stateid            stateid;
-       __u32                   seqid;
-};
-
 struct nfs_lock_opargs {
+       struct nfs_seqid *      lock_seqid;
+       nfs4_stateid *          lock_stateid;
+       struct nfs_seqid *      open_seqid;
+       nfs4_stateid *          open_stateid;
+       struct nfs_lowner       lock_owner;
        __u32                   reclaim;
        __u32                   new_lock_owner;
-       union {
-               struct nfs_open_to_lock *open_lock;
-               struct nfs_exist_lock   *exist_lock;
-       } u;
 };
 
 struct nfs_locku_opargs {
-       __u32                   seqid;
-       nfs4_stateid            stateid;
+       struct nfs_seqid *      seqid;
+       nfs4_stateid *          stateid;
 };
 
 struct nfs_lockargs {
@@ -262,6 +256,7 @@ struct nfs_writeargs {
        enum nfs3_stable_how    stable;
        unsigned int            pgbase;
        struct page **          pages;
+       const u32 *             bitmask;
 };
 
 struct nfs_writeverf {
@@ -273,6 +268,7 @@ struct nfs_writeres {
        struct nfs_fattr *      fattr;
        struct nfs_writeverf *  verf;
        __u32                   count;
+       const struct nfs_server *server;
 };
 
 /*
@@ -550,6 +546,7 @@ struct nfs4_create_res {
        struct nfs_fh *                 fh;
        struct nfs_fattr *              fattr;
        struct nfs4_change_info         dir_cinfo;
+       struct nfs_fattr *              dir_fattr;
 };
 
 struct nfs4_fsinfo_arg {
@@ -571,8 +568,17 @@ struct nfs4_link_arg {
        const struct nfs_fh *           fh;
        const struct nfs_fh *           dir_fh;
        const struct qstr *             name;
+       const u32 *                     bitmask;
+};
+
+struct nfs4_link_res {
+       const struct nfs_server *       server;
+       struct nfs_fattr *              fattr;
+       struct nfs4_change_info         cinfo;
+       struct nfs_fattr *              dir_attr;
 };
 
+
 struct nfs4_lookup_arg {
        const struct nfs_fh *           dir_fh;
        const struct qstr *             name;
@@ -619,6 +625,13 @@ struct nfs4_readlink {
 struct nfs4_remove_arg {
        const struct nfs_fh *           fh;
        const struct qstr *             name;
+       const u32 *                     bitmask;
+};
+
+struct nfs4_remove_res {
+       const struct nfs_server *       server;
+       struct nfs4_change_info         cinfo;
+       struct nfs_fattr *              dir_attr;
 };
 
 struct nfs4_rename_arg {
@@ -626,11 +639,15 @@ struct nfs4_rename_arg {
        const struct nfs_fh *           new_dir;
        const struct qstr *             old_name;
        const struct qstr *             new_name;
+       const u32 *                     bitmask;
 };
 
 struct nfs4_rename_res {
+       const struct nfs_server *       server;
        struct nfs4_change_info         old_cinfo;
+       struct nfs_fattr *              old_fattr;
        struct nfs4_change_info         new_cinfo;
+       struct nfs_fattr *              new_fattr;
 };
 
 struct nfs4_setclientid {
@@ -722,7 +739,7 @@ struct nfs_rpc_ops {
        int     (*write)   (struct nfs_write_data *);
        int     (*commit)  (struct nfs_write_data *);
        int     (*create)  (struct inode *, struct dentry *,
-                           struct iattr *, int);
+                           struct iattr *, int, struct nameidata *);
        int     (*remove)  (struct inode *, struct qstr *);
        int     (*unlink_setup)  (struct rpc_message *,
                            struct dentry *, struct qstr *);
index acbf31c154f8576a6658c9f848c2bf234ba789f0..ba6c310a055fa123c0169dfd47ecdbdd11dcfb19 100644 (file)
 
 static inline gfp_t mapping_gfp_mask(struct address_space * mapping)
 {
-       return mapping->flags & __GFP_BITS_MASK;
+       return (__force gfp_t)mapping->flags & __GFP_BITS_MASK;
 }
 
 /*
  * This is non-atomic.  Only to be used before the mapping is activated.
  * Probably needs a barrier...
  */
-static inline void mapping_set_gfp_mask(struct address_space *m, int mask)
+static inline void mapping_set_gfp_mask(struct address_space *m, gfp_t mask)
 {
-       m->flags = (m->flags & ~__GFP_BITS_MASK) | mask;
+       m->flags = (m->flags & ~(__force unsigned long)__GFP_BITS_MASK) |
+                               (__force unsigned long)mask;
 }
 
 /*
@@ -69,7 +70,7 @@ extern struct page * find_lock_page(struct address_space *mapping,
 extern struct page * find_trylock_page(struct address_space *mapping,
                                unsigned long index);
 extern struct page * find_or_create_page(struct address_space *mapping,
-                               unsigned long index, unsigned int gfp_mask);
+                               unsigned long index, gfp_t gfp_mask);
 unsigned find_get_pages(struct address_space *mapping, pgoff_t start,
                        unsigned int nr_pages, struct page **pages);
 unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index,
@@ -92,9 +93,9 @@ extern int read_cache_pages(struct address_space *mapping,
                struct list_head *pages, filler_t *filler, void *data);
 
 int add_to_page_cache(struct page *page, struct address_space *mapping,
-                               unsigned long index, int gfp_mask);
+                               unsigned long index, gfp_t gfp_mask);
 int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
-                               unsigned long index, int gfp_mask);
+                               unsigned long index, gfp_t gfp_mask);
 extern void remove_from_page_cache(struct page *page);
 extern void __remove_from_page_cache(struct page *page);
 
index 045d4761febce8557b542cbffb9cfc04776b65f8..9f0f9281f42a01628adbdb80f317172486eca583 100644 (file)
@@ -24,7 +24,7 @@
 
 struct radix_tree_root {
        unsigned int            height;
-       unsigned int            gfp_mask;
+       gfp_t                   gfp_mask;
        struct radix_tree_node  *rnode;
 };
 
index af00b10294cde3abfc57b09a4d6c6867413575b3..001ab82df051dd21ba5697f5b258ff8a13731e8f 100644 (file)
@@ -1972,7 +1972,7 @@ extern struct address_space_operations reiserfs_address_space_operations;
 
 /* fix_nodes.c */
 #ifdef CONFIG_REISERFS_CHECK
-void *reiserfs_kmalloc(size_t size, int flags, struct super_block *s);
+void *reiserfs_kmalloc(size_t size, gfp_t flags, struct super_block *s);
 void reiserfs_kfree(const void *vp, size_t size, struct super_block *s);
 #else
 static inline void *reiserfs_kmalloc(size_t size, int flags,
index 627382e7405779464e5475040a1cf1ca084b7b49..dac956ed98f0a11c217e58512e37a8e1085ffd7a 100644 (file)
@@ -1210,7 +1210,7 @@ struct security_operations {
        int (*socket_shutdown) (struct socket * sock, int how);
        int (*socket_sock_rcv_skb) (struct sock * sk, struct sk_buff * skb);
        int (*socket_getpeersec) (struct socket *sock, char __user *optval, int __user *optlen, unsigned len);
-       int (*sk_alloc_security) (struct sock *sk, int family, int priority);
+       int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority);
        void (*sk_free_security) (struct sock *sk);
 #endif /* CONFIG_SECURITY_NETWORK */
 };
index 8f5d9e7f8734abf0307483998c27f4faca71f47c..b756935da9c8ce1b7a05fbf7d3d371a0f05c0852 100644 (file)
@@ -171,7 +171,6 @@ enum {
  *     struct sk_buff - socket buffer
  *     @next: Next buffer in list
  *     @prev: Previous buffer in list
- *     @list: List we are on
  *     @sk: Socket we are owned by
  *     @tstamp: Time we arrived
  *     @dev: Device we arrived on/are leaving by
@@ -190,6 +189,7 @@ enum {
  *     @cloned: Head may be cloned (check refcnt to be sure)
  *     @nohdr: Payload reference only, must not modify header
  *     @pkt_type: Packet class
+ *     @fclone: skbuff clone status
  *     @ip_summed: Driver fed us an IP checksum
  *     @priority: Packet queueing priority
  *     @users: User count - see {datagram,tcp}.c
@@ -202,6 +202,7 @@ enum {
  *     @destructor: Destruct function
  *     @nfmark: Can be used for communication between hooks
  *     @nfct: Associated connection, if any
+ *     @ipvs_property: skbuff is owned by ipvs
  *     @nfctinfo: Relationship of this skb to the connection
  *     @nf_bridge: Saved data about a bridged frame - see br_netfilter.c
  *     @tc_index: Traffic control index
index 5fc04a16ecb09adbce015ca6a7bb5632dae19b29..09b9aa60063dda9d56d062f9e44e2042df72f744 100644 (file)
@@ -121,7 +121,7 @@ extern unsigned int ksize(const void *);
 extern void *kmem_cache_alloc_node(kmem_cache_t *, gfp_t flags, int node);
 extern void *kmalloc_node(size_t size, gfp_t flags, int node);
 #else
-static inline void *kmem_cache_alloc_node(kmem_cache_t *cachep, int flags, int node)
+static inline void *kmem_cache_alloc_node(kmem_cache_t *cachep, gfp_t flags, int node)
 {
        return kmem_cache_alloc(cachep, flags);
 }
index 04ebc24db34879ffa70797e30f26e31b98ae8e0b..b68c11a2d6dd912274b146df30d17bc4045800a9 100644 (file)
@@ -66,7 +66,12 @@ struct rpc_cred_cache {
 
 struct rpc_auth {
        unsigned int            au_cslack;      /* call cred size estimate */
-       unsigned int            au_rslack;      /* reply verf size guess */
+                               /* guess at number of u32's auth adds before
+                                * reply data; normally the verifier size: */
+       unsigned int            au_rslack;
+                               /* for gss, used to calculate au_rslack: */
+       unsigned int            au_verfsize;
+
        unsigned int            au_flags;       /* various flags */
        struct rpc_authops *    au_ops;         /* operations */
        rpc_authflavor_t        au_flavor;      /* pseudoflavor (note may
index eadb31e3c1983b850ad3b824ac6a3d0b35617d73..1a42d902bc11e0bb9976177765a8ebcc0263648d 100644 (file)
@@ -32,6 +32,7 @@
 #define RPCDBG_AUTH            0x0010
 #define RPCDBG_PMAP            0x0020
 #define RPCDBG_SCHED           0x0040
+#define RPCDBG_TRANS           0x0080
 #define RPCDBG_SVCSOCK         0x0100
 #define RPCDBG_SVCDSP          0x0200
 #define RPCDBG_MISC            0x0400
@@ -94,6 +95,8 @@ enum {
        CTL_NLMDEBUG,
        CTL_SLOTTABLE_UDP,
        CTL_SLOTTABLE_TCP,
+       CTL_MIN_RESVPORT,
+       CTL_MAX_RESVPORT,
 };
 
 #endif /* _LINUX_SUNRPC_DEBUG_H_ */
index 689262f6305987183568e3f919121eea01bf7208..9b8bcf125c18e79332d9c13762dacb85d8eec8b7 100644 (file)
@@ -40,14 +40,21 @@ int gss_import_sec_context(
                struct gss_ctx          **ctx_id);
 u32 gss_get_mic(
                struct gss_ctx          *ctx_id,
-               u32                     qop,
                struct xdr_buf          *message,
                struct xdr_netobj       *mic_token);
 u32 gss_verify_mic(
                struct gss_ctx          *ctx_id,
                struct xdr_buf          *message,
-               struct xdr_netobj       *mic_token,
-               u32                     *qstate);
+               struct xdr_netobj       *mic_token);
+u32 gss_wrap(
+               struct gss_ctx          *ctx_id,
+               int                     offset,
+               struct xdr_buf          *outbuf,
+               struct page             **inpages);
+u32 gss_unwrap(
+               struct gss_ctx          *ctx_id,
+               int                     offset,
+               struct xdr_buf          *inbuf);
 u32 gss_delete_sec_context(
                struct gss_ctx          **ctx_id);
 
@@ -56,7 +63,6 @@ char *gss_service_to_auth_domain_name(struct gss_api_mech *, u32 service);
 
 struct pf_desc {
        u32     pseudoflavor;
-       u32     qop;
        u32     service;
        char    *name;
        char    *auth_domain_name;
@@ -85,14 +91,21 @@ struct gss_api_ops {
                        struct gss_ctx          *ctx_id);
        u32 (*gss_get_mic)(
                        struct gss_ctx          *ctx_id,
-                       u32                     qop, 
                        struct xdr_buf          *message,
                        struct xdr_netobj       *mic_token);
        u32 (*gss_verify_mic)(
                        struct gss_ctx          *ctx_id,
                        struct xdr_buf          *message,
-                       struct xdr_netobj       *mic_token,
-                       u32                     *qstate);
+                       struct xdr_netobj       *mic_token);
+       u32 (*gss_wrap)(
+                       struct gss_ctx          *ctx_id,
+                       int                     offset,
+                       struct xdr_buf          *outbuf,
+                       struct page             **inpages);
+       u32 (*gss_unwrap)(
+                       struct gss_ctx          *ctx_id,
+                       int                     offset,
+                       struct xdr_buf          *buf);
        void (*gss_delete_sec_context)(
                        void                    *internal_ctx_id);
 };
index 92608a2e574c88b8f548d537f6343f64c52b4766..a6807867bd2105e93af78841e4bb5e8796c2d198 100644 (file)
@@ -65,16 +65,6 @@ typedef unsigned int OM_uint32;
 #define GSS_C_MECH_CODE 2
 
 
-/*
- * Define the default Quality of Protection for per-message services.  Note
- * that an implementation that offers multiple levels of QOP may either reserve
- * a value (for example zero, as assumed here) to mean "default protection", or
- * alternatively may simply equate GSS_C_QOP_DEFAULT to a specific explicit
- * QOP value.  However a value of 0 should always be interpreted by a GSSAPI
- * implementation as a request for the default protection level.
- */
-#define GSS_C_QOP_DEFAULT 0
-
 /*
  * Expiration time of 2^32-1 seconds means infinite lifetime for a
  * credential or security context
index ffe31d2eb9ec5e49a45f012dfa9c33f3baf55041..2c3601d3104503422c970c4aa58ed63dee68e5a8 100644 (file)
@@ -116,18 +116,22 @@ enum seal_alg {
 
 s32
 make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
-                  struct xdr_netobj *cksum);
+                  int body_offset, struct xdr_netobj *cksum);
+
+u32 gss_get_mic_kerberos(struct gss_ctx *, struct xdr_buf *,
+               struct xdr_netobj *);
+
+u32 gss_verify_mic_kerberos(struct gss_ctx *, struct xdr_buf *,
+               struct xdr_netobj *);
 
 u32
-krb5_make_token(struct krb5_ctx *context_handle, int qop_req,
-       struct xdr_buf *input_message_buffer,
-       struct xdr_netobj *output_message_buffer, int toktype);
+gss_wrap_kerberos(struct gss_ctx *ctx_id, int offset,
+               struct xdr_buf *outbuf, struct page **pages);
 
 u32
-krb5_read_token(struct krb5_ctx *context_handle,
-         struct xdr_netobj *input_token_buffer,
-         struct xdr_buf *message_buffer,
-         int *qop_state, int toktype);
+gss_unwrap_kerberos(struct gss_ctx *ctx_id, int offset,
+               struct xdr_buf *buf);
+
 
 u32
 krb5_encrypt(struct crypto_tfm * key,
@@ -137,6 +141,13 @@ u32
 krb5_decrypt(struct crypto_tfm * key,
             void *iv, void *in, void *out, int length); 
 
+int
+gss_encrypt_xdr_buf(struct crypto_tfm *tfm, struct xdr_buf *outbuf, int offset,
+               struct page **pages);
+
+int
+gss_decrypt_xdr_buf(struct crypto_tfm *tfm, struct xdr_buf *inbuf, int offset);
+
 s32
 krb5_make_seq_num(struct crypto_tfm * key,
                int direction,
index b5c9968c3c171b55223f3806fc03dbaf49a7fb64..0beb2cf00a8401b55bd6bad5430cb85960815cb1 100644 (file)
@@ -41,9 +41,9 @@ struct spkm3_ctx {
 #define SPKM_WRAP_TOK  5
 #define SPKM_DEL_TOK   6
 
-u32 spkm3_make_token(struct spkm3_ctx *ctx, int qop_req, struct xdr_buf * text, struct xdr_netobj * token, int toktype);
+u32 spkm3_make_token(struct spkm3_ctx *ctx, struct xdr_buf * text, struct xdr_netobj * token, int toktype);
 
-u32 spkm3_read_token(struct spkm3_ctx *ctx, struct xdr_netobj *read_token, struct xdr_buf *message_buffer, int *qop_state, int toktype);
+u32 spkm3_read_token(struct spkm3_ctx *ctx, struct xdr_netobj *read_token, struct xdr_buf *message_buffer, int toktype);
 
 #define CKSUMTYPE_RSA_MD5            0x0007
 
index 15f115332389af86f9d56ba6a8ec74da6d7fdf88..f43f237360ae62099997c803b440e2efece721b5 100644 (file)
@@ -76,5 +76,30 @@ enum rpc_auth_stat {
 
 #define RPC_MAXNETNAMELEN      256
 
+/*
+ * From RFC 1831:
+ *
+ * "A record is composed of one or more record fragments.  A record
+ *  fragment is a four-byte header followed by 0 to (2**31) - 1 bytes of
+ *  fragment data.  The bytes encode an unsigned binary number; as with
+ *  XDR integers, the byte order is from highest to lowest.  The number
+ *  encodes two values -- a boolean which indicates whether the fragment
+ *  is the last fragment of the record (bit value 1 implies the fragment
+ *  is the last fragment) and a 31-bit unsigned binary value which is the
+ *  length in bytes of the fragment's data.  The boolean value is the
+ *  highest-order bit of the header; the length is the 31 low-order bits.
+ *  (Note that this record specification is NOT in XDR standard form!)"
+ *
+ * The Linux RPC client always sends its requests in a single record
+ * fragment, limiting the maximum payload size for stream transports to
+ * 2GB.
+ */
+
+typedef u32    rpc_fraghdr;
+
+#define        RPC_LAST_STREAM_FRAGMENT        (1U << 31)
+#define        RPC_FRAGMENT_SIZE_MASK          (~RPC_LAST_STREAM_FRAGMENT)
+#define        RPC_MAX_FRAGMENT_SIZE           ((1U << 31) - 1)
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SUNRPC_MSGPROT_H_ */
index 23448d0fb5bc522324f176859170874c6f2d0a1a..5da968729cf820c9028a9d6202325002c44933aa 100644 (file)
@@ -161,14 +161,10 @@ typedef struct {
 
 typedef size_t (*skb_read_actor_t)(skb_reader_t *desc, void *to, size_t len);
 
+extern int csum_partial_copy_to_xdr(struct xdr_buf *, struct sk_buff *);
 extern ssize_t xdr_partial_copy_from_skb(struct xdr_buf *, unsigned int,
                skb_reader_t *, skb_read_actor_t);
 
-struct socket;
-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 *);
 
index e618c164981403ad8c2fb2e7aef6c7f134a11599..3b8b6e823c70eab0083330be5dd8b25727b037c0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/include/linux/sunrpc/clnt_xprt.h
+ *  linux/include/linux/sunrpc/xprt.h
  *
  *  Declarations for the RPC transport interface.
  *
 #include <linux/sunrpc/sched.h>
 #include <linux/sunrpc/xdr.h>
 
-/*
- * The transport code maintains an estimate on the maximum number of out-
- * standing RPC requests, using a smoothed version of the congestion
- * avoidance implemented in 44BSD. This is basically the Van Jacobson
- * congestion algorithm: If a retransmit occurs, the congestion window is
- * halved; otherwise, it is incremented by 1/cwnd when
- *
- *     -       a reply is received and
- *     -       a full number of requests are outstanding and
- *     -       the congestion window hasn't been updated recently.
- *
- * Upper procedures may check whether a request would block waiting for
- * a free RPC slot by using the RPC_CONGESTED() macro.
- */
 extern unsigned int xprt_udp_slot_table_entries;
 extern unsigned int xprt_tcp_slot_table_entries;
 
@@ -36,34 +22,23 @@ extern unsigned int xprt_tcp_slot_table_entries;
 #define RPC_DEF_SLOT_TABLE     (16U)
 #define RPC_MAX_SLOT_TABLE     (128U)
 
-#define RPC_CWNDSHIFT          (8U)
-#define RPC_CWNDSCALE          (1U << RPC_CWNDSHIFT)
-#define RPC_INITCWND           RPC_CWNDSCALE
-#define RPC_MAXCWND(xprt)      ((xprt)->max_reqs << RPC_CWNDSHIFT)
-#define RPCXPRT_CONGESTED(xprt) ((xprt)->cong >= (xprt)->cwnd)
-
-/* Default timeout values */
-#define RPC_MAX_UDP_TIMEOUT    (60*HZ)
-#define RPC_MAX_TCP_TIMEOUT    (600*HZ)
-
 /*
- * Wait duration for an RPC TCP connection to be established.  Solaris
- * NFS over TCP uses 60 seconds, for example, which is in line with how
- * long a server takes to reboot.
+ * RPC call and reply header size as number of 32bit words (verifier
+ * size computed separately)
  */
-#define RPC_CONNECT_TIMEOUT    (60*HZ)
+#define RPC_CALLHDRSIZE                6
+#define RPC_REPHDRSIZE         4
 
 /*
- * Delay an arbitrary number of seconds before attempting to reconnect
- * after an error.
+ * Parameters for choosing a free port
  */
-#define RPC_REESTABLISH_TIMEOUT        (15*HZ)
+extern unsigned int xprt_min_resvport;
+extern unsigned int xprt_max_resvport;
 
-/* RPC call and reply header size as number of 32bit words (verifier
- * size computed separately)
- */
-#define RPC_CALLHDRSIZE                6
-#define RPC_REPHDRSIZE         4
+#define RPC_MIN_RESVPORT       (1U)
+#define RPC_MAX_RESVPORT       (65535U)
+#define RPC_DEF_MIN_RESVPORT   (650U)
+#define RPC_DEF_MAX_RESVPORT   (1023U)
 
 /*
  * This describes a timeout strategy
@@ -76,6 +51,9 @@ struct rpc_timeout {
        unsigned char           to_exponential;
 };
 
+struct rpc_task;
+struct rpc_xprt;
+
 /*
  * This describes a complete RPC request
  */
@@ -95,7 +73,10 @@ struct rpc_rqst {
        int                     rq_cong;        /* has incremented xprt->cong */
        int                     rq_received;    /* receive completed */
        u32                     rq_seqno;       /* gss seq no. used on req. */
-
+       int                     rq_enc_pages_num;
+       struct page             **rq_enc_pages; /* scratch pages for use by
+                                                  gss privacy code */
+       void (*rq_release_snd_buf)(struct rpc_rqst *); /* release rq_enc_pages */
        struct list_head        rq_list;
 
        struct xdr_buf          rq_private_buf;         /* The receive buffer
@@ -121,12 +102,21 @@ struct rpc_rqst {
 #define rq_svec                        rq_snd_buf.head
 #define rq_slen                        rq_snd_buf.len
 
-#define XPRT_LAST_FRAG         (1 << 0)
-#define XPRT_COPY_RECM         (1 << 1)
-#define XPRT_COPY_XID          (1 << 2)
-#define XPRT_COPY_DATA         (1 << 3)
+struct rpc_xprt_ops {
+       void            (*set_buffer_size)(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize);
+       int             (*reserve_xprt)(struct rpc_task *task);
+       void            (*release_xprt)(struct rpc_xprt *xprt, struct rpc_task *task);
+       void            (*connect)(struct rpc_task *task);
+       int             (*send_request)(struct rpc_task *task);
+       void            (*set_retrans_timeout)(struct rpc_task *task);
+       void            (*timer)(struct rpc_task *task);
+       void            (*release_request)(struct rpc_task *task);
+       void            (*close)(struct rpc_xprt *xprt);
+       void            (*destroy)(struct rpc_xprt *xprt);
+};
 
 struct rpc_xprt {
+       struct rpc_xprt_ops *   ops;            /* transport methods */
        struct socket *         sock;           /* BSD socket layer */
        struct sock *           inet;           /* INET layer */
 
@@ -137,11 +127,13 @@ struct rpc_xprt {
        unsigned long           cong;           /* current congestion */
        unsigned long           cwnd;           /* congestion window */
 
-       unsigned int            rcvsize,        /* socket receive buffer size */
-                               sndsize;        /* socket send buffer size */
+       size_t                  rcvsize,        /* transport rcv buffer size */
+                               sndsize;        /* transport send buffer size */
 
        size_t                  max_payload;    /* largest RPC payload size,
                                                   in bytes */
+       unsigned int            tsh_size;       /* size of transport specific
+                                                  header */
 
        struct rpc_wait_queue   sending;        /* requests waiting to send */
        struct rpc_wait_queue   resend;         /* requests waiting to resend */
@@ -150,11 +142,9 @@ struct rpc_xprt {
        struct list_head        free;           /* free slots */
        struct rpc_rqst *       slot;           /* slot table storage */
        unsigned int            max_reqs;       /* total slots */
-       unsigned long           sockstate;      /* Socket state */
+       unsigned long           state;          /* transport state */
        unsigned char           shutdown   : 1, /* being shut down */
-                               nocong     : 1, /* no congestion control */
-                               resvport   : 1, /* use a reserved port */
-                               stream     : 1; /* TCP */
+                               resvport   : 1; /* use a reserved port */
 
        /*
         * XID
@@ -171,22 +161,27 @@ struct rpc_xprt {
        unsigned long           tcp_copied,     /* copied to request */
                                tcp_flags;
        /*
-        * Connection of sockets
+        * Connection of transports
         */
-       struct work_struct      sock_connect;
+       unsigned long           connect_timeout,
+                               bind_timeout,
+                               reestablish_timeout;
+       struct work_struct      connect_worker;
        unsigned short          port;
+
        /*
-        * Disconnection of idle sockets
+        * Disconnection of idle transports
         */
        struct work_struct      task_cleanup;
        struct timer_list       timer;
-       unsigned long           last_used;
+       unsigned long           last_used,
+                               idle_timeout;
 
        /*
         * Send stuff
         */
-       spinlock_t              sock_lock;      /* lock socket info */
-       spinlock_t              xprt_lock;      /* lock xprt info */
+       spinlock_t              transport_lock; /* lock transport info */
+       spinlock_t              reserve_lock;   /* lock slot table */
        struct rpc_task *       snd_task;       /* Task blocked in send */
 
        struct list_head        recv;
@@ -195,37 +190,111 @@ struct rpc_xprt {
        void                    (*old_data_ready)(struct sock *, int);
        void                    (*old_state_change)(struct sock *);
        void                    (*old_write_space)(struct sock *);
-
-       wait_queue_head_t       cong_wait;
 };
 
+#define XPRT_LAST_FRAG         (1 << 0)
+#define XPRT_COPY_RECM         (1 << 1)
+#define XPRT_COPY_XID          (1 << 2)
+#define XPRT_COPY_DATA         (1 << 3)
+
 #ifdef __KERNEL__
 
-struct rpc_xprt *      xprt_create_proto(int proto, struct sockaddr_in *addr,
-                                       struct rpc_timeout *toparms);
-int                    xprt_destroy(struct rpc_xprt *);
-void                   xprt_set_timeout(struct rpc_timeout *, unsigned int,
-                                       unsigned long);
+/*
+ * Transport operations used by ULPs
+ */
+struct rpc_xprt *      xprt_create_proto(int proto, struct sockaddr_in *addr, struct rpc_timeout *to);
+void                   xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr);
 
-void                   xprt_reserve(struct rpc_task *);
-int                    xprt_prepare_transmit(struct rpc_task *);
-void                   xprt_transmit(struct rpc_task *);
-void                   xprt_receive(struct rpc_task *);
+/*
+ * Generic internal transport functions
+ */
+void                   xprt_connect(struct rpc_task *task);
+void                   xprt_reserve(struct rpc_task *task);
+int                    xprt_reserve_xprt(struct rpc_task *task);
+int                    xprt_reserve_xprt_cong(struct rpc_task *task);
+int                    xprt_prepare_transmit(struct rpc_task *task);
+void                   xprt_transmit(struct rpc_task *task);
+void                   xprt_abort_transmit(struct rpc_task *task);
 int                    xprt_adjust_timeout(struct rpc_rqst *req);
-void                   xprt_release(struct rpc_task *);
-void                   xprt_connect(struct rpc_task *);
-void                   xprt_sock_setbufsize(struct rpc_xprt *);
-
-#define XPRT_LOCKED    0
-#define XPRT_CONNECT   1
-#define XPRT_CONNECTING        2
-
-#define xprt_connected(xp)             (test_bit(XPRT_CONNECT, &(xp)->sockstate))
-#define xprt_set_connected(xp)         (set_bit(XPRT_CONNECT, &(xp)->sockstate))
-#define xprt_test_and_set_connected(xp)        (test_and_set_bit(XPRT_CONNECT, &(xp)->sockstate))
-#define xprt_test_and_clear_connected(xp) \
-                                       (test_and_clear_bit(XPRT_CONNECT, &(xp)->sockstate))
-#define xprt_clear_connected(xp)       (clear_bit(XPRT_CONNECT, &(xp)->sockstate))
+void                   xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task);
+void                   xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);
+void                   xprt_release(struct rpc_task *task);
+int                    xprt_destroy(struct rpc_xprt *xprt);
+
+static inline u32 *xprt_skip_transport_header(struct rpc_xprt *xprt, u32 *p)
+{
+       return p + xprt->tsh_size;
+}
+
+/*
+ * Transport switch helper functions
+ */
+void                   xprt_set_retrans_timeout_def(struct rpc_task *task);
+void                   xprt_set_retrans_timeout_rtt(struct rpc_task *task);
+void                   xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status);
+void                   xprt_wait_for_buffer_space(struct rpc_task *task);
+void                   xprt_write_space(struct rpc_xprt *xprt);
+void                   xprt_update_rtt(struct rpc_task *task);
+void                   xprt_adjust_cwnd(struct rpc_task *task, int result);
+struct rpc_rqst *      xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid);
+void                   xprt_complete_rqst(struct rpc_task *task, int copied);
+void                   xprt_release_rqst_cong(struct rpc_task *task);
+void                   xprt_disconnect(struct rpc_xprt *xprt);
+
+/*
+ * Socket transport setup operations
+ */
+int                    xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to);
+int                    xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to);
+
+/*
+ * Reserved bit positions in xprt->state
+ */
+#define XPRT_LOCKED            (0)
+#define XPRT_CONNECTED         (1)
+#define XPRT_CONNECTING                (2)
+
+static inline void xprt_set_connected(struct rpc_xprt *xprt)
+{
+       set_bit(XPRT_CONNECTED, &xprt->state);
+}
+
+static inline void xprt_clear_connected(struct rpc_xprt *xprt)
+{
+       clear_bit(XPRT_CONNECTED, &xprt->state);
+}
+
+static inline int xprt_connected(struct rpc_xprt *xprt)
+{
+       return test_bit(XPRT_CONNECTED, &xprt->state);
+}
+
+static inline int xprt_test_and_set_connected(struct rpc_xprt *xprt)
+{
+       return test_and_set_bit(XPRT_CONNECTED, &xprt->state);
+}
+
+static inline int xprt_test_and_clear_connected(struct rpc_xprt *xprt)
+{
+       return test_and_clear_bit(XPRT_CONNECTED, &xprt->state);
+}
+
+static inline void xprt_clear_connecting(struct rpc_xprt *xprt)
+{
+       smp_mb__before_clear_bit();
+       clear_bit(XPRT_CONNECTING, &xprt->state);
+       smp_mb__after_clear_bit();
+}
+
+static inline int xprt_connecting(struct rpc_xprt *xprt)
+{
+       return test_bit(XPRT_CONNECTING, &xprt->state);
+}
+
+static inline int xprt_test_and_set_connecting(struct rpc_xprt *xprt)
+{
+       return test_and_set_bit(XPRT_CONNECTING, &xprt->state);
+}
 
 #endif /* __KERNEL__*/
 
index ad15a54806d8134342d195e7b120e11fb584f7ac..ba448c760168a8e48cbb2ab59005095ebd1fb6b2 100644 (file)
@@ -71,7 +71,7 @@ void restore_processor_state(void);
 struct saved_context;
 void __save_processor_state(struct saved_context *ctxt);
 void __restore_processor_state(struct saved_context *ctxt);
-extern unsigned long get_usable_page(unsigned gfp_mask);
+extern unsigned long get_usable_page(gfp_t gfp_mask);
 extern void free_eaten_memory(void);
 
 #endif /* _LINUX_SWSUSP_H */
index a7bf1a3b149624398413fa64a31bb886c4ec35b4..20c975642cab4c7f17e1cd9c8b2a6b9a2938aa03 100644 (file)
@@ -171,8 +171,8 @@ extern int rotate_reclaimable_page(struct page *page);
 extern void swap_setup(void);
 
 /* linux/mm/vmscan.c */
-extern int try_to_free_pages(struct zone **, unsigned int);
-extern int zone_reclaim(struct zone *, unsigned int, unsigned int);
+extern int try_to_free_pages(struct zone **, gfp_t);
+extern int zone_reclaim(struct zone *, gfp_t, unsigned int);
 extern int shrink_all_memory(int);
 extern int vm_swappiness;
 
index 515046d1b2f42825efaef6959abf91893fcf0bb1..fc5bb4e91a5846303ecb9be8a8058768d000d7e1 100644 (file)
@@ -40,7 +40,7 @@ struct ts_state
 struct ts_ops
 {
        const char              *name;
-       struct ts_config *      (*init)(const void *, unsigned int, int);
+       struct ts_config *      (*init)(const void *, unsigned int, gfp_t);
        unsigned int            (*find)(struct ts_config *,
                                        struct ts_state *);
        void                    (*destroy)(struct ts_config *);
@@ -148,7 +148,7 @@ static inline unsigned int textsearch_get_pattern_len(struct ts_config *conf)
 extern int textsearch_register(struct ts_ops *);
 extern int textsearch_unregister(struct ts_ops *);
 extern struct ts_config *textsearch_prepare(const char *, const void *,
-                                           unsigned int, int, int);
+                                           unsigned int, gfp_t, int);
 extern void textsearch_destroy(struct ts_config *conf);
 extern unsigned int textsearch_find_continuous(struct ts_config *,
                                               struct ts_state *,
index 0aee34f9da9f8bf7f267d957d5be7ba9faf281f5..21b9ce80364429abd04e9ef718834d0a6427eb15 100644 (file)
@@ -151,7 +151,12 @@ typedef unsigned long sector_t;
  */
 
 #ifdef __CHECKER__
-#define __bitwise __attribute__((bitwise))
+#define __bitwise__ __attribute__((bitwise))
+#else
+#define __bitwise__
+#endif
+#ifdef __CHECK_ENDIAN__
+#define __bitwise __bitwise__
 #else
 #define __bitwise
 #endif
@@ -166,7 +171,7 @@ typedef __u64 __bitwise __be64;
 #endif
 
 #ifdef __KERNEL__
-typedef unsigned __nocast gfp_t;
+typedef unsigned __bitwise__ gfp_t;
 #endif
 
 struct ustat {
index 4dbe580f9335833eb5fe78be9e241db64e5ef0fb..8f731e8f28215cd938e29fe54fca4ae47477c85c 100644 (file)
@@ -933,17 +933,17 @@ static inline void usb_fill_int_urb (struct urb *urb,
 }
 
 extern void usb_init_urb(struct urb *urb);
-extern struct urb *usb_alloc_urb(int iso_packets, unsigned mem_flags);
+extern struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags);
 extern void usb_free_urb(struct urb *urb);
 #define usb_put_urb usb_free_urb
 extern struct urb *usb_get_urb(struct urb *urb);
-extern int usb_submit_urb(struct urb *urb, unsigned mem_flags);
+extern int usb_submit_urb(struct urb *urb, gfp_t mem_flags);
 extern int usb_unlink_urb(struct urb *urb);
 extern void usb_kill_urb(struct urb *urb);
 
 #define HAVE_USB_BUFFERS
 void *usb_buffer_alloc (struct usb_device *dev, size_t size,
-       unsigned mem_flags, dma_addr_t *dma);
+       gfp_t mem_flags, dma_addr_t *dma);
 void usb_buffer_free (struct usb_device *dev, size_t size,
        void *addr, dma_addr_t dma);
 
@@ -1050,7 +1050,7 @@ int usb_sg_init (
        struct scatterlist      *sg,
        int                     nents,
        size_t                  length,
-       unsigned                mem_flags
+       gfp_t                   mem_flags
 );
 void usb_sg_cancel (struct usb_sg_request *io);
 void usb_sg_wait (struct usb_sg_request *io);
index 71e60860732467955f9d078ef62d684ab5579f84..ff81117eb733f772aea4fd33ca8e2e2267f88503 100644 (file)
@@ -107,18 +107,18 @@ struct usb_ep_ops {
        int (*disable) (struct usb_ep *ep);
 
        struct usb_request *(*alloc_request) (struct usb_ep *ep,
-               unsigned gfp_flags);
+               gfp_t gfp_flags);
        void (*free_request) (struct usb_ep *ep, struct usb_request *req);
 
        void *(*alloc_buffer) (struct usb_ep *ep, unsigned bytes,
-               dma_addr_t *dma, unsigned gfp_flags);
+               dma_addr_t *dma, gfp_t gfp_flags);
        void (*free_buffer) (struct usb_ep *ep, void *buf, dma_addr_t dma,
                unsigned bytes);
        // NOTE:  on 2.6, drivers may also use dma_map() and
        // dma_sync_single_*() to directly manage dma overhead. 
 
        int (*queue) (struct usb_ep *ep, struct usb_request *req,
-               unsigned gfp_flags);
+               gfp_t gfp_flags);
        int (*dequeue) (struct usb_ep *ep, struct usb_request *req);
 
        int (*set_halt) (struct usb_ep *ep, int value);
@@ -214,7 +214,7 @@ usb_ep_disable (struct usb_ep *ep)
  * Returns the request, or null if one could not be allocated.
  */
 static inline struct usb_request *
-usb_ep_alloc_request (struct usb_ep *ep, unsigned gfp_flags)
+usb_ep_alloc_request (struct usb_ep *ep, gfp_t gfp_flags)
 {
        return ep->ops->alloc_request (ep, gfp_flags);
 }
@@ -254,7 +254,7 @@ usb_ep_free_request (struct usb_ep *ep, struct usb_request *req)
  */
 static inline void *
 usb_ep_alloc_buffer (struct usb_ep *ep, unsigned len, dma_addr_t *dma,
-       unsigned gfp_flags)
+       gfp_t gfp_flags)
 {
        return ep->ops->alloc_buffer (ep, len, dma, gfp_flags);
 }
@@ -330,7 +330,7 @@ usb_ep_free_buffer (struct usb_ep *ep, void *buf, dma_addr_t dma, unsigned len)
  * reported when the usb peripheral is disconnected.
  */
 static inline int
-usb_ep_queue (struct usb_ep *ep, struct usb_request *req, unsigned gfp_flags)
+usb_ep_queue (struct usb_ep *ep, struct usb_request *req, gfp_t gfp_flags)
 {
        return ep->ops->queue (ep, req, gfp_flags);
 }
index 4a056a68243540fa610a9363bef13c6a0b59c7ef..6c196a5baf24bda85e3789163ebe4a6cdf74eb31 100644 (file)
@@ -94,7 +94,6 @@ struct dst_ops
        struct dst_entry *      (*negative_advice)(struct dst_entry *);
        void                    (*link_failure)(struct sk_buff *);
        void                    (*update_pmtu)(struct dst_entry *dst, u32 mtu);
-       int                     (*get_mss)(struct dst_entry *dst, u32 mtu);
        int                     entry_size;
 
        atomic_t                entries;
index ecb75526cba09d817bff41df4413f748a0e19662..e0498bd360042121d99fa0aea7ec77b8ebb2a03b 100644 (file)
@@ -207,7 +207,7 @@ struct sock {
        struct sk_buff_head     sk_write_queue;
        int                     sk_wmem_queued;
        int                     sk_forward_alloc;
-       unsigned int            sk_allocation;
+       gfp_t                   sk_allocation;
        int                     sk_sndbuf;
        int                     sk_route_caps;
        unsigned long           sk_flags;
index bed4b7c9be99342b51203e43586dd50580825250..e6b61fab66ddf69a66adc5f81f6647fe2ad11da9 100644 (file)
@@ -146,7 +146,7 @@ struct scsi_cmnd {
 #define SCSI_STATE_MLQUEUE         0x100b
 
 
-extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, int);
+extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t);
 extern void scsi_put_command(struct scsi_cmnd *);
 extern void scsi_io_completion(struct scsi_cmnd *, unsigned int, unsigned int);
 extern void scsi_finish_command(struct scsi_cmnd *cmd);
index 6a140020d7cb0538ce69578488ba4b6eadb08adb..2539debb7993cf91c687ebd9f6656e5a790eee07 100644 (file)
@@ -45,7 +45,7 @@ struct scsi_request {
                                           level driver) of this request */
 };
 
-extern struct scsi_request *scsi_allocate_request(struct scsi_device *, int);
+extern struct scsi_request *scsi_allocate_request(struct scsi_device *, gfp_t);
 extern void scsi_release_request(struct scsi_request *);
 extern void scsi_wait_req(struct scsi_request *, const void *cmnd,
                          void *buffer, unsigned bufflen,
index 3a2fd2cc9f193096c1426a1050c77b1c353839ca..83489c3abbaf5f048293c4aea3041da63143a879 100644 (file)
@@ -111,7 +111,7 @@ size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id);
 int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id);
 
 /* basic memory allocation functions */
-void *snd_malloc_pages(size_t size, unsigned int gfp_flags);
+void *snd_malloc_pages(size_t size, gfp_t gfp_flags);
 void snd_free_pages(void *ptr, size_t size);
 
 #endif /* __SOUND_MEMALLOC_H */
index aefa73a8a586c50383ab22f6432186d21f5d2f08..0c56320d38dc38eac05fb4eb04b5d0e626352019 100644 (file)
@@ -133,7 +133,7 @@ struct audit_buffer {
        struct list_head     list;
        struct sk_buff       *skb;      /* formatted skb ready to send */
        struct audit_context *ctx;      /* NULL or associated context */
-       int                  gfp_mask;
+       gfp_t                gfp_mask;
 };
 
 static void audit_set_pid(struct audit_buffer *ab, pid_t pid)
@@ -647,7 +647,7 @@ static inline void audit_get_stamp(struct audit_context *ctx,
  * will be written at syscall exit.  If there is no associated task, tsk
  * should be NULL. */
 
-struct audit_buffer *audit_log_start(struct audit_context *ctx, int gfp_mask,
+struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
                                     int type)
 {
        struct audit_buffer     *ab     = NULL;
@@ -879,7 +879,7 @@ void audit_log_end(struct audit_buffer *ab)
 /* Log an audit record.  This is a convenience function that calls
  * audit_log_start, audit_log_vformat, and audit_log_end.  It may be
  * called in any context. */
-void audit_log(struct audit_context *ctx, int gfp_mask, int type, 
+void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type, 
               const char *fmt, ...)
 {
        struct audit_buffer *ab;
index 88696f639aab890140657aba7fcd2956ddfe6623..d8a68509e7299df13233c98134c9431e994faa41 100644 (file)
@@ -803,7 +803,7 @@ static void audit_log_task_info(struct audit_buffer *ab)
        up_read(&mm->mmap_sem);
 }
 
-static void audit_log_exit(struct audit_context *context, unsigned int gfp_mask)
+static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
 {
        int i;
        struct audit_buffer *ab;
index cdd4dcd8fb630be76f35246cb3196f327fef252b..36c5d9cd4cc14b8b0f342600c69b7a653132f1f1 100644 (file)
@@ -90,7 +90,7 @@ int kexec_should_crash(struct task_struct *p)
 static int kimage_is_destination_range(struct kimage *image,
                                       unsigned long start, unsigned long end);
 static struct page *kimage_alloc_page(struct kimage *image,
-                                      unsigned int gfp_mask,
+                                      gfp_t gfp_mask,
                                       unsigned long dest);
 
 static int do_kimage_alloc(struct kimage **rimage, unsigned long entry,
@@ -326,8 +326,7 @@ static int kimage_is_destination_range(struct kimage *image,
        return 0;
 }
 
-static struct page *kimage_alloc_pages(unsigned int gfp_mask,
-                                       unsigned int order)
+static struct page *kimage_alloc_pages(gfp_t gfp_mask, unsigned int order)
 {
        struct page *pages;
 
@@ -654,7 +653,7 @@ static kimage_entry_t *kimage_dst_used(struct kimage *image,
 }
 
 static struct page *kimage_alloc_page(struct kimage *image,
-                                       unsigned int gfp_mask,
+                                       gfp_t gfp_mask,
                                        unsigned long destination)
 {
        /*
index 2d5c4567644279d3f73c6d0563b0b72ee4b40dc2..10bc5ec496d72a25e70b42785cfaee781312dddb 100644 (file)
@@ -1095,7 +1095,7 @@ static inline void eat_page(void *page)
        *eaten_memory = c;
 }
 
-unsigned long get_usable_page(unsigned gfp_mask)
+unsigned long get_usable_page(gfp_t gfp_mask)
 {
        unsigned long m;
 
index d4df21debc4ddb77948206f6091fb27c569e9909..6414b2fb482d48255e0e54e23dcead7ee849658c 100644 (file)
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -72,7 +72,7 @@ static void free_layer(struct idr *idp, struct idr_layer *p)
  * If the system is REALLY out of memory this function returns 0,
  * otherwise 1.
  */
-int idr_pre_get(struct idr *idp, unsigned gfp_mask)
+int idr_pre_get(struct idr *idp, gfp_t gfp_mask)
 {
        while (idp->id_free_cnt < IDR_FREE_MAX) {
                struct idr_layer *new;
index dd0917dd9fa9df9274b24e6acbe3abddaa3b17ed..253d3004ace90edae789bb23f16c2919a4e6830c 100644 (file)
@@ -100,7 +100,7 @@ static void fill_kobj_path(struct kobject *kobj, char *path, int length)
  * @kobj:      kobject in question, with which to build the path
  * @gfp_mask:  the allocation type used to allocate the path
  */
-char *kobject_get_path(struct kobject *kobj, int gfp_mask)
+char *kobject_get_path(struct kobject *kobj, gfp_t gfp_mask)
 {
        char *path;
        int len;
index 04ca4429ddfaf4a077f48c45bb2b718d647b4e42..7ef6f6a17aa65a667a01417a0fcdc2265021482b 100644 (file)
@@ -62,7 +62,7 @@ static struct sock *uevent_sock;
  * @gfp_mask:
  */
 static int send_uevent(const char *signal, const char *obj,
-                      char **envp, int gfp_mask)
+                      char **envp, gfp_t gfp_mask)
 {
        struct sk_buff *skb;
        char *pos;
@@ -98,7 +98,7 @@ static int send_uevent(const char *signal, const char *obj,
 }
 
 static int do_kobject_uevent(struct kobject *kobj, enum kobject_action action, 
-                            struct attribute *attr, int gfp_mask)
+                            struct attribute *attr, gfp_t gfp_mask)
 {
        char *path;
        char *attrpath;
index 1e934c196f0f1f8dbd7e69a2701f0ecc7ac1a1c7..6f3093efbd7b0f084edc5b3a85e6b71bbb357783 100644 (file)
@@ -254,7 +254,7 @@ unsigned int textsearch_find_continuous(struct ts_config *conf,
  *         parameters or a ERR_PTR().
  */
 struct ts_config *textsearch_prepare(const char *algo, const void *pattern,
-                                    unsigned int len, int gfp_mask, int flags)
+                                    unsigned int len, gfp_t gfp_mask, int flags)
 {
        int err = -ENOENT;
        struct ts_config *conf;
index b5346576e58d252ea63224606bd2564cb2f088fa..1c31b2fd2ca5afdfb5e7f6bc79cc5f5eb91498ac 100644 (file)
@@ -377,7 +377,7 @@ int filemap_write_and_wait_range(struct address_space *mapping,
  * This function does not add the page to the LRU.  The caller must do that.
  */
 int add_to_page_cache(struct page *page, struct address_space *mapping,
-               pgoff_t offset, int gfp_mask)
+               pgoff_t offset, gfp_t gfp_mask)
 {
        int error = radix_tree_preload(gfp_mask & ~__GFP_HIGHMEM);
 
@@ -401,7 +401,7 @@ int add_to_page_cache(struct page *page, struct address_space *mapping,
 EXPORT_SYMBOL(add_to_page_cache);
 
 int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
-                               pgoff_t offset, int gfp_mask)
+                               pgoff_t offset, gfp_t gfp_mask)
 {
        int ret = add_to_page_cache(page, mapping, offset, gfp_mask);
        if (ret == 0)
@@ -591,7 +591,7 @@ EXPORT_SYMBOL(find_lock_page);
  * memory exhaustion.
  */
 struct page *find_or_create_page(struct address_space *mapping,
-               unsigned long index, unsigned int gfp_mask)
+               unsigned long index, gfp_t gfp_mask)
 {
        struct page *page, *cached_page = NULL;
        int err;
@@ -683,7 +683,7 @@ struct page *
 grab_cache_page_nowait(struct address_space *mapping, unsigned long index)
 {
        struct page *page = find_get_page(mapping, index);
-       unsigned int gfp_mask;
+       gfp_t gfp_mask;
 
        if (page) {
                if (!TestSetPageLocked(page))
index 90e1861e2da0defa1a9b8514a9f781b8529a6197..ce2e7e8bbfa7102a78473d1a47c24a41f7788b83 100644 (file)
 
 static mempool_t *page_pool, *isa_page_pool;
 
-static void *page_pool_alloc(gfp_t gfp_mask, void *data)
+static void *page_pool_alloc_isa(gfp_t gfp_mask, void *data)
 {
-       unsigned int gfp = gfp_mask | (unsigned int) (long) data;
-
-       return alloc_page(gfp);
+       return alloc_page(gfp_mask | GFP_DMA);
 }
 
 static void page_pool_free(void *page, void *data)
@@ -51,6 +49,12 @@ static void page_pool_free(void *page, void *data)
  *  n means that there are (n-1) current users of it.
  */
 #ifdef CONFIG_HIGHMEM
+
+static void *page_pool_alloc(gfp_t gfp_mask, void *data)
+{
+       return alloc_page(gfp_mask);
+}
+
 static int pkmap_count[LAST_PKMAP];
 static unsigned int last_pkmap_nr;
 static  __cacheline_aligned_in_smp DEFINE_SPINLOCK(kmap_lock);
@@ -267,7 +271,7 @@ int init_emergency_isa_pool(void)
        if (isa_page_pool)
                return 0;
 
-       isa_page_pool = mempool_create(ISA_POOL_SIZE, page_pool_alloc, page_pool_free, (void *) __GFP_DMA);
+       isa_page_pool = mempool_create(ISA_POOL_SIZE, page_pool_alloc_isa, page_pool_free, NULL);
        if (!isa_page_pool)
                BUG();
 
index 37af443eb0944e5e81b4094bf5b7312540ce170d..1d5c64df1653bf6f1c4a232477099ae4fd1112e3 100644 (file)
@@ -700,7 +700,7 @@ static struct zonelist *zonelist_policy(gfp_t gfp, struct mempolicy *policy)
        case MPOL_BIND:
                /* Lower zones don't get a policy applied */
                /* Careful: current->mems_allowed might have moved */
-               if ((gfp & GFP_ZONEMASK) >= policy_zone)
+               if (gfp_zone(gfp) >= policy_zone)
                        if (cpuset_zonelist_valid_mems_allowed(policy->v.zonelist))
                                return policy->v.zonelist;
                /*FALL THROUGH*/
@@ -712,7 +712,7 @@ static struct zonelist *zonelist_policy(gfp_t gfp, struct mempolicy *policy)
                nd = 0;
                BUG();
        }
-       return NODE_DATA(nd)->node_zonelists + (gfp & GFP_ZONEMASK);
+       return NODE_DATA(nd)->node_zonelists + gfp_zone(gfp);
 }
 
 /* Do dynamic interleaving for a process */
@@ -757,7 +757,7 @@ static struct page *alloc_page_interleave(gfp_t gfp, unsigned order, unsigned ni
        struct page *page;
 
        BUG_ON(!node_online(nid));
-       zl = NODE_DATA(nid)->node_zonelists + (gfp & GFP_ZONEMASK);
+       zl = NODE_DATA(nid)->node_zonelists + gfp_zone(gfp);
        page = __alloc_pages(gfp, order, zl);
        if (page && page_zone(page) == zl->zones[0]) {
                zone_pcp(zl->zones[0],get_cpu())->interleave_hit++;
index 9e377ea700b2bd84c05a6661a53058444bbe7ee9..1a99b80480d3da562117c14db409149abdfd7e61 100644 (file)
@@ -205,7 +205,7 @@ void * mempool_alloc(mempool_t *pool, gfp_t gfp_mask)
        void *element;
        unsigned long flags;
        wait_queue_t wait;
-       unsigned int gfp_temp;
+       gfp_t gfp_temp;
 
        might_sleep_if(gfp_mask & __GFP_WAIT);
 
index e1d3d77f4aeef89259d9e3b09e500042a42d7a87..94c864eac9c48e26577d46f5e68cb5b9b3bcba61 100644 (file)
@@ -734,7 +734,7 @@ buffered_rmqueue(struct zone *zone, int order, gfp_t gfp_flags)
  * of the allocation.
  */
 int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
-                     int classzone_idx, int can_try_harder, int gfp_high)
+                     int classzone_idx, int can_try_harder, gfp_t gfp_high)
 {
        /* free_pages my go negative - that's OK */
        long min = mark, free_pages = z->free_pages - (1 << order) + 1;
@@ -777,7 +777,7 @@ struct page * fastcall
 __alloc_pages(gfp_t gfp_mask, unsigned int order,
                struct zonelist *zonelist)
 {
-       const int wait = gfp_mask & __GFP_WAIT;
+       const gfp_t wait = gfp_mask & __GFP_WAIT;
        struct zone **zones, *z;
        struct page *page;
        struct reclaim_state reclaim_state;
@@ -996,7 +996,7 @@ fastcall unsigned long get_zeroed_page(gfp_t gfp_mask)
         * get_zeroed_page() returns a 32-bit address, which cannot represent
         * a highmem page
         */
-       BUG_ON(gfp_mask & __GFP_HIGHMEM);
+       BUG_ON((gfp_mask & __GFP_HIGHMEM) != 0);
 
        page = alloc_pages(gfp_mask | __GFP_ZERO, 0);
        if (page)
@@ -1089,7 +1089,7 @@ static unsigned int nr_free_zone_pages(int offset)
  */
 unsigned int nr_free_buffer_pages(void)
 {
-       return nr_free_zone_pages(GFP_USER & GFP_ZONEMASK);
+       return nr_free_zone_pages(gfp_zone(GFP_USER));
 }
 
 /*
@@ -1097,7 +1097,7 @@ unsigned int nr_free_buffer_pages(void)
  */
 unsigned int nr_free_pagecache_pages(void)
 {
-       return nr_free_zone_pages(GFP_HIGHUSER & GFP_ZONEMASK);
+       return nr_free_zone_pages(gfp_zone(GFP_HIGHUSER));
 }
 
 #ifdef CONFIG_HIGHMEM
@@ -1428,6 +1428,16 @@ static int __init build_zonelists_node(pg_data_t *pgdat, struct zonelist *zoneli
        return j;
 }
 
+static inline int highest_zone(int zone_bits)
+{
+       int res = ZONE_NORMAL;
+       if (zone_bits & (__force int)__GFP_HIGHMEM)
+               res = ZONE_HIGHMEM;
+       if (zone_bits & (__force int)__GFP_DMA)
+               res = ZONE_DMA;
+       return res;
+}
+
 #ifdef CONFIG_NUMA
 #define MAX_NODE_LOAD (num_online_nodes())
 static int __initdata node_load[MAX_NUMNODES];
@@ -1524,11 +1534,7 @@ static void __init build_zonelists(pg_data_t *pgdat)
                        zonelist = pgdat->node_zonelists + i;
                        for (j = 0; zonelist->zones[j] != NULL; j++);
 
-                       k = ZONE_NORMAL;
-                       if (i & __GFP_HIGHMEM)
-                               k = ZONE_HIGHMEM;
-                       if (i & __GFP_DMA)
-                               k = ZONE_DMA;
+                       k = highest_zone(i);
 
                        j = build_zonelists_node(NODE_DATA(node), zonelist, j, k);
                        zonelist->zones[j] = NULL;
@@ -1549,12 +1555,7 @@ static void __init build_zonelists(pg_data_t *pgdat)
                zonelist = pgdat->node_zonelists + i;
 
                j = 0;
-               k = ZONE_NORMAL;
-               if (i & __GFP_HIGHMEM)
-                       k = ZONE_HIGHMEM;
-               if (i & __GFP_DMA)
-                       k = ZONE_DMA;
-
+               k = highest_zone(i);
                j = build_zonelists_node(pgdat, zonelist, j, k);
                /*
                 * Now we build the zonelist so that it contains the zones
index ea064d89cda9510d16755ab95127eae62badf94b..55e04a0734c19869d12fd07e5df398c207de121b 100644 (file)
@@ -85,7 +85,7 @@ enum sgp_type {
 static int shmem_getpage(struct inode *inode, unsigned long idx,
                         struct page **pagep, enum sgp_type sgp, int *type);
 
-static inline struct page *shmem_dir_alloc(unsigned int gfp_mask)
+static inline struct page *shmem_dir_alloc(gfp_t gfp_mask)
 {
        /*
         * The above definition of ENTRIES_PER_PAGE, and the use of
@@ -898,7 +898,7 @@ struct page *shmem_swapin(struct shmem_inode_info *info, swp_entry_t entry,
 }
 
 static struct page *
-shmem_alloc_page(unsigned long gfp, struct shmem_inode_info *info,
+shmem_alloc_page(gfp_t gfp, struct shmem_inode_info *info,
                 unsigned long idx)
 {
        struct vm_area_struct pvma;
index d05c678bceb3de1f23ef3ae91170299e2c1372e5..d30423f167a2c0a5c4c4d13b0678495fffa86189 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -386,7 +386,7 @@ struct kmem_cache_s {
        unsigned int            gfporder;
 
        /* force GFP flags, e.g. GFP_DMA */
-       unsigned int            gfpflags;
+       gfp_t                   gfpflags;
 
        size_t                  colour;         /* cache colouring range */
        unsigned int            colour_off;     /* colour offset */
@@ -2117,7 +2117,7 @@ static void cache_init_objs(kmem_cache_t *cachep,
        slabp->free = 0;
 }
 
-static void kmem_flagcheck(kmem_cache_t *cachep, unsigned int flags)
+static void kmem_flagcheck(kmem_cache_t *cachep, gfp_t flags)
 {
        if (flags & SLAB_DMA) {
                if (!(cachep->gfpflags & GFP_DMA))
@@ -2152,7 +2152,7 @@ static int cache_grow(kmem_cache_t *cachep, gfp_t flags, int nodeid)
        struct slab     *slabp;
        void            *objp;
        size_t           offset;
-       unsigned int     local_flags;
+       gfp_t            local_flags;
        unsigned long    ctor_flags;
        struct kmem_list3 *l3;
 
@@ -2546,7 +2546,7 @@ static inline void *__cache_alloc(kmem_cache_t *cachep, gfp_t flags)
 /*
  * A interface to enable slab creation on nodeid
  */
-static void *__cache_alloc_node(kmem_cache_t *cachep, int flags, int nodeid)
+static void *__cache_alloc_node(kmem_cache_t *cachep, gfp_t flags, int nodeid)
 {
        struct list_head *entry;
        struct slab *slabp;
index 64f9570cff568103c8031706322c0e78b8f93029..843c87d1e61f5f63e68aa53a903567a3802958f8 100644 (file)
@@ -70,7 +70,7 @@ struct scan_control {
        unsigned int priority;
 
        /* This context's GFP mask */
-       unsigned int gfp_mask;
+       gfp_t gfp_mask;
 
        int may_writepage;
 
@@ -186,7 +186,7 @@ EXPORT_SYMBOL(remove_shrinker);
  *
  * Returns the number of slab objects which we shrunk.
  */
-static int shrink_slab(unsigned long scanned, unsigned int gfp_mask,
+static int shrink_slab(unsigned long scanned, gfp_t gfp_mask,
                        unsigned long lru_pages)
 {
        struct shrinker *shrinker;
@@ -926,7 +926,7 @@ shrink_caches(struct zone **zones, struct scan_control *sc)
  * holds filesystem locks which prevent writeout this might not work, and the
  * allocation attempt will fail.
  */
-int try_to_free_pages(struct zone **zones, unsigned int gfp_mask)
+int try_to_free_pages(struct zone **zones, gfp_t gfp_mask)
 {
        int priority;
        int ret = 0;
@@ -1338,7 +1338,7 @@ module_init(kswapd_init)
 /*
  * Try to free up some pages from this zone through reclaim.
  */
-int zone_reclaim(struct zone *zone, unsigned int gfp_mask, unsigned int order)
+int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
 {
        struct scan_control sc;
        int nr_pages = 1 << order;
index 1dcf7fa1f0fead6dc2469d0a478025284921e804..e68700f950a55d3cff784a54d655001a7da30dec 100644 (file)
@@ -1625,12 +1625,9 @@ static int neightbl_fill_info(struct neigh_table *tbl, struct sk_buff *skb,
 
                memset(&ndst, 0, sizeof(ndst));
 
-               for (cpu = 0; cpu < NR_CPUS; cpu++) {
+               for_each_cpu(cpu) {
                        struct neigh_statistics *st;
 
-                       if (!cpu_possible(cpu))
-                               continue;
-
                        st = per_cpu_ptr(tbl->stats, cpu);
                        ndst.ndts_allocs                += st->allocs;
                        ndst.ndts_destroys              += st->destroys;
index 5f043d346694dc012ba3403b82d875cd6a0133f1..7fc3e9e28c34c3353b3e48082916d4cb737ad5e8 100644 (file)
@@ -75,7 +75,7 @@
  * By design there should only be *one* "controlling" process. In practice 
  * multiple write accesses gives unpredictable result. Understood by "write" 
  * to /proc gives result code thats should be read be the "writer".
- * For pratical use this should be no problem.
+ * For practical use this should be no problem.
  *
  * Note when adding devices to a specific CPU there good idea to also assign 
  * /proc/irq/XX/smp_affinity so TX-interrupts gets bound to the same CPU. 
@@ -96,7 +96,7 @@
  * New xmit() return, do_div and misc clean up by Stephen Hemminger 
  * <shemminger@osdl.org> 040923
  *
- * Rany Dunlap fixed u64 printk compiler waring 
+ * Randy Dunlap fixed u64 printk compiler waring 
  *
  * Remove FCS from BW calculation.  Lennert Buytenhek <buytenh@wantstofly.org>
  * New time handling. Lennert Buytenhek <buytenh@wantstofly.org> 041213
 #include <linux/ipv6.h>
 #include <linux/udp.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/wait.h>
 #include <net/checksum.h>
 #include <net/ipv6.h>
 #include <asm/timex.h>
 
 
-#define VERSION  "pktgen v2.62: Packet Generator for packet performance testing.\n"
+#define VERSION  "pktgen v2.63: Packet Generator for packet performance testing.\n"
 
 /* #define PG_DEBUG(a) a */
 #define PG_DEBUG(a) 
 #define T_REMDEV      (1<<3)  /* Remove all devs */
 
 /* Locks */
-#define   thread_lock()        spin_lock(&_thread_lock)
-#define   thread_unlock()      spin_unlock(&_thread_lock)
+#define   thread_lock()        down(&pktgen_sem)
+#define   thread_unlock()      up(&pktgen_sem)
 
 /* If lock -- can be removed after some work */
 #define   if_lock(t)           spin_lock(&(t->if_lock));
 
 /* Used to help with determining the pkts on receive */
 #define PKTGEN_MAGIC 0xbe9be955
-#define PG_PROC_DIR "net/pktgen"
+#define PG_PROC_DIR "pktgen"
+#define PGCTRL     "pgctrl"
+static struct proc_dir_entry *pg_proc_dir = NULL;
 
 #define MAX_CFLOWS  65536
 
@@ -202,11 +205,8 @@ struct pktgen_dev {
         * Try to keep frequent/infrequent used vars. separated.
         */
 
-        char ifname[32];
-        struct proc_dir_entry *proc_ent;
+        char ifname[IFNAMSIZ];
         char result[512];
-        /* proc file names */
-        char fname[80];
 
         struct pktgen_thread* pg_thread; /* the owner */
         struct pktgen_dev *next; /* Used for chaining in the thread's run-queue */
@@ -244,7 +244,7 @@ struct pktgen_dev {
         __u32 seq_num;
         
         int clone_skb; /* Use multiple SKBs during packet gen.  If this number
-                          * is greater than 1, then that many coppies of the same
+                          * is greater than 1, then that many copies of the same
                           * packet will be sent before a new packet is allocated.
                           * For instance, if you want to send 1024 identical packets
                           * before creating a new packet, set clone_skb to 1024.
@@ -330,8 +330,6 @@ struct pktgen_thread {
         struct pktgen_dev *if_list;           /* All device here */
         struct pktgen_thread* next;
         char name[32];
-        char fname[128]; /* name of proc file */
-        struct proc_dir_entry *proc_ent;
         char result[512];
         u32 max_before_softirq; /* We'll call do_softirq to prevent starvation. */
         
@@ -396,7 +394,7 @@ static inline s64 divremdi3(s64 x, s64 y, int type)
 
 /* End of hacks to deal with 64-bit math on x86 */
 
-/** Convert to miliseconds */
+/** Convert to milliseconds */
 static inline __u64 tv_to_ms(const struct timeval* tv) 
 {
         __u64 ms = tv->tv_usec / 1000;
@@ -425,7 +423,7 @@ static inline __u64 pg_div64(__u64 n, __u64 base)
 {
         __u64 tmp = n;
 /*
- * How do we know if the architectrure we are running on
+ * How do we know if the architecture we are running on
  * supports division with 64 bit base?
  * 
  */
@@ -473,16 +471,6 @@ static inline __u64 tv_diff(const struct timeval* a, const struct timeval* b)
 
 static char version[] __initdata = VERSION;
 
-static ssize_t proc_pgctrl_read(struct file* file, char __user * buf, size_t count, loff_t *ppos);
-static ssize_t proc_pgctrl_write(struct file* file, const char __user * buf, size_t count, loff_t *ppos);
-static int proc_if_read(char *buf , char **start, off_t offset, int len, int *eof, void *data);
-
-static int proc_thread_read(char *buf , char **start, off_t offset, int len, int *eof, void *data);
-static int proc_if_write(struct file *file, const char __user *user_buffer, unsigned long count, void *data);
-static int proc_thread_write(struct file *file, const char __user *user_buffer, unsigned long count, void *data);
-static int create_proc_dir(void);
-static int remove_proc_dir(void);
-
 static int pktgen_remove_device(struct pktgen_thread* t, struct pktgen_dev *i);
 static int pktgen_add_device(struct pktgen_thread* t, const char* ifname);
 static struct pktgen_thread* pktgen_find_thread(const char* name);
@@ -503,83 +491,41 @@ static int pg_delay_d = 0;
 static int pg_clone_skb_d = 0;
 static int debug = 0;
 
-static DEFINE_SPINLOCK(_thread_lock);
+static DECLARE_MUTEX(pktgen_sem);
 static struct pktgen_thread *pktgen_threads = NULL;
 
-static char module_fname[128];
-static struct proc_dir_entry *module_proc_ent = NULL;
-
 static struct notifier_block pktgen_notifier_block = {
        .notifier_call = pktgen_device_event,
 };
 
-static struct file_operations pktgen_fops = {
-        .read     = proc_pgctrl_read,
-        .write    = proc_pgctrl_write,
-       /*  .ioctl    = pktgen_ioctl, later maybe */
-};
-
 /*
  * /proc handling functions 
  *
  */
 
-static struct proc_dir_entry *pg_proc_dir = NULL;
-static int proc_pgctrl_read_eof=0;
-
-static ssize_t proc_pgctrl_read(struct file* file, char __user * buf,
-                                 size_t count, loff_t *ppos)
+static int pgctrl_show(struct seq_file *seq, void *v)
 { 
-       char data[200];
-       int len = 0;
-
-       if(proc_pgctrl_read_eof) {
-               proc_pgctrl_read_eof=0;
-               len = 0;
-               goto out;
-       }
-
-       sprintf(data, "%s", VERSION); 
-
-       len = strlen(data);
-
-       if(len > count) {
-               len =-EFAULT;
-               goto out;
-       }       
-
-       if (copy_to_user(buf, data, len)) {
-               len =-EFAULT;
-               goto out;
-       }  
-
-       *ppos += len;
-       proc_pgctrl_read_eof=1; /* EOF next call */
-
- out:
-       return len;
+       seq_puts(seq, VERSION);
+       return 0;
 }
 
-static ssize_t proc_pgctrl_write(struct file* file,const char __user * buf,
-                                size_t count, loff_t *ppos)
+static ssize_t pgctrl_write(struct file* file,const char __user * buf,
+                           size_t count, loff_t *ppos)
 {
-       char *data = NULL;
        int err = 0;
+       char data[128];
 
         if (!capable(CAP_NET_ADMIN)){
                 err = -EPERM;
                goto out;
         }
 
-       data = (void*)vmalloc ((unsigned int)count);
+       if (count > sizeof(data))
+               count = sizeof(data);
 
-       if(!data) {
-               err = -ENOMEM;
-               goto out;
-       }
        if (copy_from_user(data, buf, count)) {
-               err =-EFAULT;
-               goto out_free;
+               err = -EFAULT;
+               goto out;
        }  
        data[count-1] = 0; /* Make string */
 
@@ -594,31 +540,40 @@ static ssize_t proc_pgctrl_write(struct file* file,const char __user * buf,
 
        err = count;
 
- out_free:
-       vfree (data);
  out:
         return err;
 }
 
-static int proc_if_read(char *buf , char **start, off_t offset,
-                           int len, int *eof, void *data)
+static int pgctrl_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, pgctrl_show, PDE(inode)->data);
+}
+
+static struct file_operations pktgen_fops = {
+       .owner    = THIS_MODULE,
+       .open     = pgctrl_open,
+        .read     = seq_read,
+       .llseek   = seq_lseek,
+        .write    = pgctrl_write,
+       .release  = single_release,
+};
+
+static int pktgen_if_show(struct seq_file *seq, void *v)
 {
-       char *p;
        int i;
-        struct pktgen_dev *pkt_dev = (struct pktgen_dev*)(data);
+        struct pktgen_dev *pkt_dev = seq->private;
         __u64 sa;
         __u64 stopped;
         __u64 now = getCurUs();
         
-       p = buf;
-       p += sprintf(p, "Params: count %llu  min_pkt_size: %u  max_pkt_size: %u\n",
-                    (unsigned long long) pkt_dev->count,
-                    pkt_dev->min_pkt_size, pkt_dev->max_pkt_size);
+       seq_printf(seq, "Params: count %llu  min_pkt_size: %u  max_pkt_size: %u\n",
+                  (unsigned long long) pkt_dev->count,
+                  pkt_dev->min_pkt_size, pkt_dev->max_pkt_size);
 
-       p += sprintf(p, "     frags: %d  delay: %u  clone_skb: %d  ifname: %s\n",
-                     pkt_dev->nfrags, 1000*pkt_dev->delay_us+pkt_dev->delay_ns, pkt_dev->clone_skb, pkt_dev->ifname);
+       seq_printf(seq, "     frags: %d  delay: %u  clone_skb: %d  ifname: %s\n",
+                  pkt_dev->nfrags, 1000*pkt_dev->delay_us+pkt_dev->delay_ns, pkt_dev->clone_skb, pkt_dev->ifname);
 
-       p += sprintf(p, "     flows: %u flowlen: %u\n", pkt_dev->cflows, pkt_dev->lflow);
+       seq_printf(seq, "     flows: %u flowlen: %u\n", pkt_dev->cflows, pkt_dev->lflow);
 
 
        if(pkt_dev->flags & F_IPV6) {
@@ -626,19 +581,19 @@ static int proc_if_read(char *buf , char **start, off_t offset,
                fmt_ip6(b1,  pkt_dev->in6_saddr.s6_addr);
                fmt_ip6(b2,  pkt_dev->min_in6_saddr.s6_addr);
                fmt_ip6(b3,  pkt_dev->max_in6_saddr.s6_addr);
-               p += sprintf(p, "     saddr: %s  min_saddr: %s  max_saddr: %s\n", b1, b2, b3);
+               seq_printf(seq, "     saddr: %s  min_saddr: %s  max_saddr: %s\n", b1, b2, b3);
 
                fmt_ip6(b1,  pkt_dev->in6_daddr.s6_addr);
                fmt_ip6(b2,  pkt_dev->min_in6_daddr.s6_addr);
                fmt_ip6(b3,  pkt_dev->max_in6_daddr.s6_addr);
-               p += sprintf(p, "     daddr: %s  min_daddr: %s  max_daddr: %s\n", b1, b2, b3);
+               seq_printf(seq, "     daddr: %s  min_daddr: %s  max_daddr: %s\n", b1, b2, b3);
 
        } 
        else 
-               p += sprintf(p, "     dst_min: %s  dst_max: %s\n     src_min: %s  src_max: %s\n",
-                     pkt_dev->dst_min, pkt_dev->dst_max, pkt_dev->src_min, pkt_dev->src_max);
+               seq_printf(seq,"     dst_min: %s  dst_max: %s\n     src_min: %s  src_max: %s\n",
+                          pkt_dev->dst_min, pkt_dev->dst_max, pkt_dev->src_min, pkt_dev->src_max);
 
-        p += sprintf(p, "     src_mac: ");
+       seq_puts(seq, "     src_mac: ");
 
        if ((pkt_dev->src_mac[0] == 0) && 
            (pkt_dev->src_mac[1] == 0) && 
@@ -648,89 +603,89 @@ static int proc_if_read(char *buf , char **start, off_t offset,
            (pkt_dev->src_mac[5] == 0)) 
 
                for (i = 0; i < 6; i++) 
-                       p += sprintf(p, "%02X%s", pkt_dev->odev->dev_addr[i], i == 5 ? "  " : ":");
+                       seq_printf(seq,  "%02X%s", pkt_dev->odev->dev_addr[i], i == 5 ? "  " : ":");
 
        else 
                for (i = 0; i < 6; i++) 
-                       p += sprintf(p, "%02X%s", pkt_dev->src_mac[i], i == 5 ? "  " : ":");
+                       seq_printf(seq,  "%02X%s", pkt_dev->src_mac[i], i == 5 ? "  " : ":");
 
-        p += sprintf(p, "dst_mac: ");
+        seq_printf(seq,  "dst_mac: ");
        for (i = 0; i < 6; i++) 
-               p += sprintf(p, "%02X%s", pkt_dev->dst_mac[i], i == 5 ? "\n" : ":");
+               seq_printf(seq,  "%02X%s", pkt_dev->dst_mac[i], i == 5 ? "\n" : ":");
 
-        p += sprintf(p, "     udp_src_min: %d  udp_src_max: %d  udp_dst_min: %d  udp_dst_max: %d\n",
-                     pkt_dev->udp_src_min, pkt_dev->udp_src_max, pkt_dev->udp_dst_min,
-                     pkt_dev->udp_dst_max);
+        seq_printf(seq,  "     udp_src_min: %d  udp_src_max: %d  udp_dst_min: %d  udp_dst_max: %d\n",
+                  pkt_dev->udp_src_min, pkt_dev->udp_src_max, pkt_dev->udp_dst_min,
+                  pkt_dev->udp_dst_max);
 
-        p += sprintf(p, "     src_mac_count: %d  dst_mac_count: %d \n     Flags: ",
-                     pkt_dev->src_mac_count, pkt_dev->dst_mac_count);
+        seq_printf(seq,  "     src_mac_count: %d  dst_mac_count: %d \n     Flags: ",
+                  pkt_dev->src_mac_count, pkt_dev->dst_mac_count);
 
 
         if (pkt_dev->flags &  F_IPV6) 
-                p += sprintf(p, "IPV6  ");
+                seq_printf(seq,  "IPV6  ");
 
         if (pkt_dev->flags &  F_IPSRC_RND) 
-                p += sprintf(p, "IPSRC_RND  ");
+                seq_printf(seq,  "IPSRC_RND  ");
 
         if (pkt_dev->flags & F_IPDST_RND) 
-                p += sprintf(p, "IPDST_RND  ");
+                seq_printf(seq,  "IPDST_RND  ");
         
         if (pkt_dev->flags & F_TXSIZE_RND) 
-                p += sprintf(p, "TXSIZE_RND  ");
+                seq_printf(seq,  "TXSIZE_RND  ");
         
         if (pkt_dev->flags & F_UDPSRC_RND) 
-                p += sprintf(p, "UDPSRC_RND  ");
+                seq_printf(seq,  "UDPSRC_RND  ");
         
         if (pkt_dev->flags & F_UDPDST_RND) 
-                p += sprintf(p, "UDPDST_RND  ");
+                seq_printf(seq,  "UDPDST_RND  ");
         
         if (pkt_dev->flags & F_MACSRC_RND) 
-                p += sprintf(p, "MACSRC_RND  ");
+                seq_printf(seq,  "MACSRC_RND  ");
         
         if (pkt_dev->flags & F_MACDST_RND) 
-                p += sprintf(p, "MACDST_RND  ");
+                seq_printf(seq,  "MACDST_RND  ");
 
         
-        p += sprintf(p, "\n");
+        seq_puts(seq,  "\n");
         
         sa = pkt_dev->started_at;
         stopped = pkt_dev->stopped_at;
         if (pkt_dev->running) 
                 stopped = now; /* not really stopped, more like last-running-at */
         
-        p += sprintf(p, "Current:\n     pkts-sofar: %llu  errors: %llu\n     started: %lluus  stopped: %lluus idle: %lluus\n",
-                    (unsigned long long) pkt_dev->sofar,
-                    (unsigned long long) pkt_dev->errors,
-                    (unsigned long long) sa,
-                    (unsigned long long) stopped, 
-                    (unsigned long long) pkt_dev->idle_acc);
+        seq_printf(seq,  "Current:\n     pkts-sofar: %llu  errors: %llu\n     started: %lluus  stopped: %lluus idle: %lluus\n",
+                  (unsigned long long) pkt_dev->sofar,
+                  (unsigned long long) pkt_dev->errors,
+                  (unsigned long long) sa,
+                  (unsigned long long) stopped,
+                  (unsigned long long) pkt_dev->idle_acc);
 
-        p += sprintf(p, "     seq_num: %d  cur_dst_mac_offset: %d  cur_src_mac_offset: %d\n",
-                     pkt_dev->seq_num, pkt_dev->cur_dst_mac_offset, pkt_dev->cur_src_mac_offset);
+        seq_printf(seq,  "     seq_num: %d  cur_dst_mac_offset: %d  cur_src_mac_offset: %d\n",
+                  pkt_dev->seq_num, pkt_dev->cur_dst_mac_offset,
+                  pkt_dev->cur_src_mac_offset);
 
        if(pkt_dev->flags & F_IPV6) {
                char b1[128], b2[128];
                fmt_ip6(b1,  pkt_dev->cur_in6_daddr.s6_addr);
                fmt_ip6(b2,  pkt_dev->cur_in6_saddr.s6_addr);
-               p += sprintf(p, "     cur_saddr: %s  cur_daddr: %s\n", b2, b1);
+               seq_printf(seq,  "     cur_saddr: %s  cur_daddr: %s\n", b2, b1);
        } 
        else 
-               p += sprintf(p, "     cur_saddr: 0x%x  cur_daddr: 0x%x\n",
-                     pkt_dev->cur_saddr, pkt_dev->cur_daddr);
+               seq_printf(seq,  "     cur_saddr: 0x%x  cur_daddr: 0x%x\n",
+                          pkt_dev->cur_saddr, pkt_dev->cur_daddr);
 
 
-       p += sprintf(p, "     cur_udp_dst: %d  cur_udp_src: %d\n",
-                     pkt_dev->cur_udp_dst, pkt_dev->cur_udp_src);
+       seq_printf(seq,  "     cur_udp_dst: %d  cur_udp_src: %d\n",
+                  pkt_dev->cur_udp_dst, pkt_dev->cur_udp_src);
 
-       p += sprintf(p, "     flows: %u\n", pkt_dev->nflows);
+       seq_printf(seq,  "     flows: %u\n", pkt_dev->nflows);
 
        if (pkt_dev->result[0])
-               p += sprintf(p, "Result: %s\n", pkt_dev->result);
+               seq_printf(seq,  "Result: %s\n", pkt_dev->result);
        else
-               p += sprintf(p, "Result: Idle\n");
-       *eof = 1;
+               seq_printf(seq,  "Result: Idle\n");
 
-       return p - buf;
+       return 0;
 }
 
 
@@ -802,13 +757,14 @@ done_str:
        return i;
 }
 
-static int proc_if_write(struct file *file, const char __user *user_buffer,
-                            unsigned long count, void *data)
+static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer,
+                              size_t count, loff_t *offset)
 {
+       struct seq_file *seq = (struct seq_file *) file->private_data;
+        struct pktgen_dev *pkt_dev = seq->private;
        int i = 0, max, len;
        char name[16], valstr[32];
        unsigned long value = 0;
-        struct pktgen_dev *pkt_dev = (struct pktgen_dev*)(data);
         char* pg_result = NULL;
         int tmp = 0;
        char buf[128];
@@ -849,7 +805,8 @@ static int proc_if_write(struct file *file, const char __user *user_buffer,
                 if (copy_from_user(tb, user_buffer, count))
                        return -EFAULT;
                 tb[count] = 0;
-               printk("pktgen: %s,%lu  buffer -:%s:-\n", name, count, tb);
+               printk("pktgen: %s,%lu  buffer -:%s:-\n", name,
+                      (unsigned long) count, tb);
         }
 
        if (!strcmp(name, "min_pkt_size")) {
@@ -1335,92 +1292,98 @@ static int proc_if_write(struct file *file, const char __user *user_buffer,
        return -EINVAL;
 }
 
-static int proc_thread_read(char *buf , char **start, off_t offset,
-                               int len, int *eof, void *data)
+static int pktgen_if_open(struct inode *inode, struct file *file)
 {
-       char *p;
-        struct pktgen_thread *t = (struct pktgen_thread*)(data);
-        struct pktgen_dev *pkt_dev = NULL;
+       return single_open(file, pktgen_if_show, PDE(inode)->data);
+}
 
+static struct file_operations pktgen_if_fops = {
+       .owner    = THIS_MODULE,
+       .open     = pktgen_if_open,
+        .read     = seq_read,
+       .llseek   = seq_lseek,
+        .write    = pktgen_if_write,
+       .release  = single_release,
+};
 
-        if (!t) {
-                printk("pktgen: ERROR: could not find thread in proc_thread_read\n");
-                return -EINVAL;
-        }
+static int pktgen_thread_show(struct seq_file *seq, void *v)
+{
+        struct pktgen_thread *t = seq->private;
+        struct pktgen_dev *pkt_dev = NULL;
+
+       BUG_ON(!t);
 
-       p = buf;
-       p += sprintf(p, "Name: %s  max_before_softirq: %d\n",
+       seq_printf(seq, "Name: %s  max_before_softirq: %d\n",
                      t->name, t->max_before_softirq);
 
-        p += sprintf(p, "Running: ");
+        seq_printf(seq, "Running: ");
         
         if_lock(t);
         for(pkt_dev = t->if_list;pkt_dev; pkt_dev = pkt_dev->next) 
                if(pkt_dev->running)
-                       p += sprintf(p, "%s ", pkt_dev->ifname);
+                       seq_printf(seq, "%s ", pkt_dev->ifname);
         
-        p += sprintf(p, "\nStopped: ");
+        seq_printf(seq, "\nStopped: ");
 
         for(pkt_dev = t->if_list;pkt_dev; pkt_dev = pkt_dev->next) 
                if(!pkt_dev->running)
-                       p += sprintf(p, "%s ", pkt_dev->ifname);
+                       seq_printf(seq, "%s ", pkt_dev->ifname);
 
        if (t->result[0])
-               p += sprintf(p, "\nResult: %s\n", t->result);
+               seq_printf(seq, "\nResult: %s\n", t->result);
        else
-               p += sprintf(p, "\nResult: NA\n");
-
-       *eof = 1;
+               seq_printf(seq, "\nResult: NA\n");
 
         if_unlock(t);
 
-       return p - buf;
+       return 0;
 }
 
-static int proc_thread_write(struct file *file, const char __user *user_buffer,
-                                unsigned long count, void *data)
+static ssize_t pktgen_thread_write(struct file *file,
+                                  const char __user *user_buffer,
+                                  size_t count, loff_t *offset)
 {
+       struct seq_file *seq = (struct seq_file *) file->private_data;
+        struct pktgen_thread *t = seq->private;
        int i = 0, max, len, ret;
        char name[40];
-        struct pktgen_thread *t;
         char *pg_result;
         unsigned long value = 0;
-        
+
        if (count < 1) {
                //      sprintf(pg_result, "Wrong command format");
                return -EINVAL;
        }
-  
+
        max = count - i;
         len = count_trail_chars(&user_buffer[i], max);
-        if (len < 0) 
-               return len; 
-     
+        if (len < 0)
+               return len;
+
        i += len;
-  
+
        /* Read variable name */
 
        len = strn_len(&user_buffer[i], sizeof(name) - 1);
-        if (len < 0)  
-               return len; 
+        if (len < 0)
+               return len;
        
        memset(name, 0, sizeof(name));
        if (copy_from_user(name, &user_buffer[i], len))
                return -EFAULT;
        i += len;
-  
+
        max = count -i;
        len = count_trail_chars(&user_buffer[i], max);
-        if (len < 0)  
-               return len; 
-       
+        if (len < 0)
+               return len;
+
        i += len;
 
-       if (debug) 
-               printk("pktgen: t=%s, count=%lu\n", name, count);
-        
+       if (debug)
+               printk("pktgen: t=%s, count=%lu\n", name,
+                      (unsigned long) count);
 
-        t = (struct pktgen_thread*)(data);
        if(!t) {
                printk("pktgen: ERROR: No thread\n");
                ret = -EINVAL;
@@ -1474,21 +1437,19 @@ static int proc_thread_write(struct file *file, const char __user *user_buffer,
        return ret;
 }
 
-static int create_proc_dir(void)
+static int pktgen_thread_open(struct inode *inode, struct file *file)
 {
-       pg_proc_dir = proc_mkdir(PG_PROC_DIR, NULL);
-        
-        if (!pg_proc_dir) 
-                return -ENODEV;
-        
-        return 0;
+       return single_open(file, pktgen_thread_show, PDE(inode)->data);
 }
 
-static int remove_proc_dir(void)
-{
-        remove_proc_entry(PG_PROC_DIR, NULL);
-        return 0;
-}
+static struct file_operations pktgen_thread_fops = {
+       .owner    = THIS_MODULE,
+       .open     = pktgen_thread_open,
+        .read     = seq_read,
+       .llseek   = seq_lseek,
+        .write    = pktgen_thread_write,
+       .release  = single_release,
+};
 
 /* Think find or remove for NN */
 static struct pktgen_dev *__pktgen_NN_threads(const char* ifname, int remove) 
@@ -1702,7 +1663,7 @@ static void spin(struct pktgen_dev *pkt_dev, __u64 spin_until_us)
        start = now = getCurUs();
        printk(KERN_INFO "sleeping for %d\n", (int)(spin_until_us - now));
        while (now < spin_until_us) {
-               /* TODO: optimise sleeping behavior */
+               /* TODO: optimize sleeping behavior */
                if (spin_until_us - now > jiffies_to_usecs(1)+1)
                        schedule_timeout_interruptible(1);
                else if (spin_until_us - now > 100) {
@@ -2361,7 +2322,7 @@ static void pktgen_stop_all_threads_ifs(void)
                pktgen_stop(t);
                t = t->next;
        }
-       thread_unlock();
+       thread_unlock();
 }
 
 static int thread_is_running(struct pktgen_thread *t )
@@ -2552,10 +2513,9 @@ static void pktgen_rem_thread(struct pktgen_thread *t)
 
        struct pktgen_thread *tmp = pktgen_threads;
 
-        if (strlen(t->fname))
-                remove_proc_entry(t->fname, NULL);
+       remove_proc_entry(t->name, pg_proc_dir);
 
-       thread_lock();
+       thread_lock();
 
        if (tmp == t)
                pktgen_threads = tmp->next;
@@ -2825,7 +2785,7 @@ static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t, const char* i
         if_lock(t);
 
         for(pkt_dev=t->if_list; pkt_dev; pkt_dev = pkt_dev->next ) {
-                if (strcmp(pkt_dev->ifname, ifname) == 0) {
+                if (strncmp(pkt_dev->ifname, ifname, IFNAMSIZ) == 0) {
                         break;
                 }
         }
@@ -2864,74 +2824,70 @@ static int add_dev_to_thread(struct pktgen_thread *t, struct pktgen_dev *pkt_dev
 static int pktgen_add_device(struct pktgen_thread *t, const char* ifname) 
 {
         struct pktgen_dev *pkt_dev;
+       struct proc_dir_entry *pe;
        
        /* We don't allow a device to be on several threads */
 
-       if( (pkt_dev = __pktgen_NN_threads(ifname, FIND)) == NULL) {
-                                                  
-               pkt_dev = kmalloc(sizeof(struct pktgen_dev), GFP_KERNEL);
-                if (!pkt_dev) 
-                        return -ENOMEM;
+       pkt_dev = __pktgen_NN_threads(ifname, FIND);
+       if (pkt_dev) {
+                printk("pktgen: ERROR: interface already used.\n");
+                return -EBUSY;
+        }
 
-                memset(pkt_dev, 0, sizeof(struct pktgen_dev));
+       pkt_dev = kzalloc(sizeof(struct pktgen_dev), GFP_KERNEL);
+       if (!pkt_dev)
+               return -ENOMEM;
 
-               pkt_dev->flows = vmalloc(MAX_CFLOWS*sizeof(struct flow_state));
-               if (pkt_dev->flows == NULL) {
-                       kfree(pkt_dev);
-                       return -ENOMEM;
-               }
-               memset(pkt_dev->flows, 0, MAX_CFLOWS*sizeof(struct flow_state));
-
-               pkt_dev->min_pkt_size = ETH_ZLEN;
-                pkt_dev->max_pkt_size = ETH_ZLEN;
-                pkt_dev->nfrags = 0;
-                pkt_dev->clone_skb = pg_clone_skb_d;
-                pkt_dev->delay_us = pg_delay_d / 1000;
-                pkt_dev->delay_ns = pg_delay_d % 1000;
-                pkt_dev->count = pg_count_d;
-                pkt_dev->sofar = 0;
-                pkt_dev->udp_src_min = 9; /* sink port */
-                pkt_dev->udp_src_max = 9;
-                pkt_dev->udp_dst_min = 9;
-                pkt_dev->udp_dst_max = 9;
-
-                strncpy(pkt_dev->ifname, ifname, 31);
-                sprintf(pkt_dev->fname, "%s/%s", PG_PROC_DIR, ifname);
-
-                if (! pktgen_setup_dev(pkt_dev)) {
-                        printk("pktgen: ERROR: pktgen_setup_dev failed.\n");
-                       if (pkt_dev->flows)
-                               vfree(pkt_dev->flows);
-                        kfree(pkt_dev);
-                        return -ENODEV;
-                }
+       pkt_dev->flows = vmalloc(MAX_CFLOWS*sizeof(struct flow_state));
+       if (pkt_dev->flows == NULL) {
+               kfree(pkt_dev);
+               return -ENOMEM;
+       }
+       memset(pkt_dev->flows, 0, MAX_CFLOWS*sizeof(struct flow_state));
 
-                pkt_dev->proc_ent = create_proc_entry(pkt_dev->fname, 0600, NULL);
-                if (!pkt_dev->proc_ent) {
-                        printk("pktgen: cannot create %s procfs entry.\n", pkt_dev->fname);
-                       if (pkt_dev->flows)
-                               vfree(pkt_dev->flows);
-                        kfree(pkt_dev);
-                        return -EINVAL;
-                }
-                pkt_dev->proc_ent->read_proc = proc_if_read;
-                pkt_dev->proc_ent->write_proc = proc_if_write;
-                pkt_dev->proc_ent->data = (void*)(pkt_dev);
-               pkt_dev->proc_ent->owner = THIS_MODULE;
+       pkt_dev->min_pkt_size = ETH_ZLEN;
+       pkt_dev->max_pkt_size = ETH_ZLEN;
+       pkt_dev->nfrags = 0;
+       pkt_dev->clone_skb = pg_clone_skb_d;
+       pkt_dev->delay_us = pg_delay_d / 1000;
+       pkt_dev->delay_ns = pg_delay_d % 1000;
+       pkt_dev->count = pg_count_d;
+       pkt_dev->sofar = 0;
+       pkt_dev->udp_src_min = 9; /* sink port */
+       pkt_dev->udp_src_max = 9;
+       pkt_dev->udp_dst_min = 9;
+       pkt_dev->udp_dst_max = 9;
+
+       strncpy(pkt_dev->ifname, ifname, IFNAMSIZ);
+
+       if (! pktgen_setup_dev(pkt_dev)) {
+               printk("pktgen: ERROR: pktgen_setup_dev failed.\n");
+               if (pkt_dev->flows)
+                       vfree(pkt_dev->flows);
+               kfree(pkt_dev);
+               return -ENODEV;
+       }
+
+       pe = create_proc_entry(ifname, 0600, pg_proc_dir);
+       if (!pe) {
+               printk("pktgen: cannot create %s/%s procfs entry.\n",
+                      PG_PROC_DIR, ifname);
+               if (pkt_dev->flows)
+                       vfree(pkt_dev->flows);
+               kfree(pkt_dev);
+               return -EINVAL;
+       }
+       pe->proc_fops = &pktgen_if_fops;
+       pe->data = pkt_dev;
 
-                return add_dev_to_thread(t, pkt_dev);
-        }
-        else {
-                printk("pktgen: ERROR: interface already used.\n");
-                return -EBUSY;
-        }
+       return add_dev_to_thread(t, pkt_dev);
 }
 
 static struct pktgen_thread *pktgen_find_thread(const char* name) 
 {
         struct pktgen_thread *t = NULL;
 
-       thread_lock();
+       thread_lock();
 
         t = pktgen_threads;
         while (t) {
@@ -2947,6 +2903,7 @@ static struct pktgen_thread *pktgen_find_thread(const char* name)
 static int pktgen_create_thread(const char* name, int cpu) 
 {
         struct pktgen_thread *t = NULL;
+       struct proc_dir_entry *pe;
 
         if (strlen(name) > 31) {
                 printk("pktgen: ERROR:  Thread name cannot be more than 31 characters.\n");
@@ -2958,28 +2915,26 @@ static int pktgen_create_thread(const char* name, int cpu)
                 return -EINVAL;
         }
 
-        t = (struct pktgen_thread*)(kmalloc(sizeof(struct pktgen_thread), GFP_KERNEL));
+        t = kzalloc(sizeof(struct pktgen_thread), GFP_KERNEL);
         if (!t) {
                 printk("pktgen: ERROR: out of memory, can't create new thread.\n");
                 return -ENOMEM;
         }
 
-        memset(t, 0, sizeof(struct pktgen_thread));
         strcpy(t->name, name);
         spin_lock_init(&t->if_lock);
        t->cpu = cpu;
         
-        sprintf(t->fname, "%s/%s", PG_PROC_DIR, t->name);
-        t->proc_ent = create_proc_entry(t->fname, 0600, NULL);
-        if (!t->proc_ent) {
-                printk("pktgen: cannot create %s procfs entry.\n", t->fname);
+        pe = create_proc_entry(t->name, 0600, pg_proc_dir);
+        if (!pe) {
+                printk("pktgen: cannot create %s/%s procfs entry.\n",
+                      PG_PROC_DIR, t->name);
                 kfree(t);
                 return -EINVAL;
         }
-        t->proc_ent->read_proc = proc_thread_read;
-        t->proc_ent->write_proc = proc_thread_write;
-        t->proc_ent->data = (void*)(t);
-        t->proc_ent->owner = THIS_MODULE;
+
+       pe->proc_fops = &pktgen_thread_fops;
+       pe->data = t;
 
         t->next = pktgen_threads;
         pktgen_threads = t;
@@ -3034,8 +2989,7 @@ static int pktgen_remove_device(struct pktgen_thread *t, struct pktgen_dev *pkt_
 
         /* Clean up proc file system */
 
-        if (strlen(pkt_dev->fname)) 
-                remove_proc_entry(pkt_dev->fname, NULL);
+       remove_proc_entry(pkt_dev->ifname, pg_proc_dir);
 
        if (pkt_dev->flows)
                vfree(pkt_dev->flows);
@@ -3046,31 +3000,31 @@ static int pktgen_remove_device(struct pktgen_thread *t, struct pktgen_dev *pkt_
 static int __init pg_init(void) 
 {
        int cpu;
-       printk(version);
+       struct proc_dir_entry *pe;
 
-        module_fname[0] = 0;
+       printk(version);
 
-       create_proc_dir();
+       pg_proc_dir = proc_mkdir(PG_PROC_DIR, proc_net);
+       if (!pg_proc_dir)
+               return -ENODEV;
+       pg_proc_dir->owner = THIS_MODULE;
 
-        sprintf(module_fname, "%s/pgctrl", PG_PROC_DIR);
-        module_proc_ent = create_proc_entry(module_fname, 0600, NULL);
-        if (!module_proc_ent) {
-                printk("pktgen: ERROR: cannot create %s procfs entry.\n", module_fname);
+       pe = create_proc_entry(PGCTRL, 0600, pg_proc_dir);
+        if (pe == NULL) {
+               printk("pktgen: ERROR: cannot create %s procfs entry.\n", PGCTRL);
+               proc_net_remove(PG_PROC_DIR);
                 return -EINVAL;
         }
 
-        module_proc_ent->proc_fops =  &pktgen_fops;
-        module_proc_ent->data = NULL;
+        pe->proc_fops = &pktgen_fops;
+        pe->data      = NULL;
 
        /* Register us to receive netdevice events */
        register_netdevice_notifier(&pktgen_notifier_block);
         
-       for (cpu = 0; cpu < NR_CPUS ; cpu++) {
+       for_each_online_cpu(cpu) {
                char buf[30];
 
-               if (!cpu_online(cpu))
-                       continue;
-
                 sprintf(buf, "kpktgend_%i", cpu);
                 pktgen_create_thread(buf, cpu);
         }
@@ -3095,10 +3049,8 @@ static void __exit pg_cleanup(void)
        unregister_netdevice_notifier(&pktgen_notifier_block);
 
         /* Clean up proc file system */
-
-        remove_proc_entry(module_fname, NULL);
-        
-       remove_proc_dir();
+       remove_proc_entry(PGCTRL, pg_proc_dir);
+       proc_net_remove(PG_PROC_DIR);
 }
 
 
index 02cd4cde2112a6456e1da188873b708af9bc1338..ef9d46b91eb9200fa3eaf9fbc428808fcf1663c4 100644 (file)
@@ -122,6 +122,8 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here)
  *     __alloc_skb     -       allocate a network buffer
  *     @size: size to allocate
  *     @gfp_mask: allocation mask
+ *     @fclone: allocate from fclone cache instead of head cache
+ *             and allocate a cloned (child) skb
  *
  *     Allocate a new &sk_buff. The returned buffer has no headroom and a
  *     tail room of size bytes. The object has a reference count of one.
index 1c52fe809edad0a79038748f589c915ec96f6a6f..9602ceb3bac9a2d33eec5ce1bc0cb8a55340203b 100644 (file)
@@ -940,7 +940,7 @@ static struct sk_buff *sock_alloc_send_pskb(struct sock *sk,
                                            int noblock, int *errcode)
 {
        struct sk_buff *skb;
-       unsigned int gfp_mask;
+       gfp_t gfp_mask;
        long timeo;
        int err;
 
index 29250749f16f86044d1f5fec4a592271fa12f856..d59f86f7ceabbdd21a66a3910fd1f2ac16e52a35 100644 (file)
@@ -495,7 +495,7 @@ void dccp_send_close(struct sock *sk, const int active)
 {
        struct dccp_sock *dp = dccp_sk(sk);
        struct sk_buff *skb;
-       const unsigned int prio = active ? GFP_KERNEL : GFP_ATOMIC;
+       const gfp_t prio = active ? GFP_KERNEL : GFP_ATOMIC;
 
        skb = alloc_skb(sk->sk_prot->max_header, prio);
        if (skb == NULL)
index 1186dc44cdff2ad8d459167e16e6103cec017a24..3f25cadccddd4f048cdbf36d2fa5e92a8a176116 100644 (file)
@@ -719,22 +719,9 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        if (saddr->sdn_flags & ~SDF_WILD)
                return -EINVAL;
 
-#if 1
        if (!capable(CAP_NET_BIND_SERVICE) && (saddr->sdn_objnum ||
            (saddr->sdn_flags & SDF_WILD)))
                return -EACCES;
-#else
-       /*
-        * Maybe put the default actions in the default security ops for
-        * dn_prot_sock ? Would be nice if the capable call would go there
-        * too.
-        */
-       if (security_dn_prot_sock(saddr) &&
-           !capable(CAP_NET_BIND_SERVICE) || 
-           saddr->sdn_objnum || (saddr->sdn_flags & SDF_WILD))
-               return -EACCES;
-#endif
-
 
        if (!(saddr->sdn_flags & SDF_WILD)) {
                if (dn_ntohs(saddr->sdn_nodeaddrl)) {
index 74f2207e131ae06b165f6203eb55b7d7e9b9456f..4ec4b2ca6ab15440eabc8f9e22b80a592d0067d1 100644 (file)
@@ -715,6 +715,7 @@ int devinet_ioctl(unsigned int cmd, void __user *arg)
                        break;
                ret = 0;
                if (ifa->ifa_mask != sin->sin_addr.s_addr) {
+                       u32 old_mask = ifa->ifa_mask;
                        inet_del_ifa(in_dev, ifap, 0);
                        ifa->ifa_mask = sin->sin_addr.s_addr;
                        ifa->ifa_prefixlen = inet_mask_len(ifa->ifa_mask);
@@ -728,7 +729,7 @@ int devinet_ioctl(unsigned int cmd, void __user *arg)
                        if ((dev->flags & IFF_BROADCAST) &&
                            (ifa->ifa_prefixlen < 31) &&
                            (ifa->ifa_broadcast ==
-                            (ifa->ifa_local|~ifa->ifa_mask))) {
+                            (ifa->ifa_local|~old_mask))) {
                                ifa->ifa_broadcast = (ifa->ifa_local |
                                                      ~sin->sin_addr.s_addr);
                        }
index 0093ea08c7f5378c8bbd80e966007c9eaf87f382..66247f38b3716193637ab4c79020e22d9f65e1dd 100644 (file)
@@ -2404,7 +2404,7 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
                prefix = htonl(l->key);
 
                list_for_each_entry_rcu(fa, &li->falh, fa_list) {
-                       const struct fib_info *fi = rcu_dereference(fa->fa_info);
+                       const struct fib_info *fi = fa->fa_info;
                        unsigned flags = fib_flag_trans(fa->fa_type, mask, fi);
 
                        if (fa->fa_type == RTN_BROADCAST
index 90dca711ac9f3061d8b247d1e9f1b50e40419e40..175e093ec5645209ab809dd52ccce0667a020e82 100644 (file)
@@ -1108,12 +1108,9 @@ void __init icmp_init(struct net_proto_family *ops)
        struct inet_sock *inet;
        int i;
 
-       for (i = 0; i < NR_CPUS; i++) {
+       for_each_cpu(i) {
                int err;
 
-               if (!cpu_possible(i))
-                       continue;
-
                err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP,
                                       &per_cpu(__icmp_socket, i));
 
index 1ad5202e556b5d1862f5c0b1c9895c45e81e4c04..87e350069abb1cf8a2654bb652c609a4a429cb96 100644 (file)
@@ -1023,10 +1023,7 @@ ssize_t  ip_append_page(struct sock *sk, struct page *page,
                        int alloclen;
 
                        skb_prev = skb;
-                       if (skb_prev)
-                               fraggap = skb_prev->len - maxfraglen;
-                       else
-                               fraggap = 0;
+                       fraggap = skb_prev->len - maxfraglen;
 
                        alloclen = fragheaderlen + hh_len + fraggap + 15;
                        skb = sock_wmalloc(sk, alloclen, 1, sk->sk_allocation);
index 07a80b56e8dce24f421e98d4efb89589748bed3a..422ab68ee7fb62599cb410c0b8aac61bda4647d6 100644 (file)
@@ -50,7 +50,7 @@
 #include <linux/netfilter_ipv4/ip_conntrack_core.h>
 #include <linux/netfilter_ipv4/listhelp.h>
 
-#define IP_CONNTRACK_VERSION   "2.3"
+#define IP_CONNTRACK_VERSION   "2.4"
 
 #if 0
 #define DEBUGP printk
@@ -148,16 +148,20 @@ DEFINE_PER_CPU(struct ip_conntrack_stat, ip_conntrack_stat);
 static int ip_conntrack_hash_rnd_initted;
 static unsigned int ip_conntrack_hash_rnd;
 
-static u_int32_t
-hash_conntrack(const struct ip_conntrack_tuple *tuple)
+static u_int32_t __hash_conntrack(const struct ip_conntrack_tuple *tuple,
+                           unsigned int size, unsigned int rnd)
 {
-#if 0
-       dump_tuple(tuple);
-#endif
        return (jhash_3words(tuple->src.ip,
                             (tuple->dst.ip ^ tuple->dst.protonum),
                             (tuple->src.u.all | (tuple->dst.u.all << 16)),
-                            ip_conntrack_hash_rnd) % ip_conntrack_htable_size);
+                            rnd) % size);
+}
+
+static u_int32_t
+hash_conntrack(const struct ip_conntrack_tuple *tuple)
+{
+       return __hash_conntrack(tuple, ip_conntrack_htable_size,
+                               ip_conntrack_hash_rnd);
 }
 
 int
@@ -1341,14 +1345,13 @@ static int kill_all(struct ip_conntrack *i, void *data)
        return 1;
 }
 
-static void free_conntrack_hash(void)
+static void free_conntrack_hash(struct list_head *hash, int vmalloced,int size)
 {
-       if (ip_conntrack_vmalloc)
-               vfree(ip_conntrack_hash);
+       if (vmalloced)
+               vfree(hash);
        else
-               free_pages((unsigned long)ip_conntrack_hash, 
-                          get_order(sizeof(struct list_head)
-                                    * ip_conntrack_htable_size));
+               free_pages((unsigned long)hash, 
+                          get_order(sizeof(struct list_head) * size));
 }
 
 void ip_conntrack_flush()
@@ -1378,12 +1381,83 @@ void ip_conntrack_cleanup(void)
        ip_conntrack_flush();
        kmem_cache_destroy(ip_conntrack_cachep);
        kmem_cache_destroy(ip_conntrack_expect_cachep);
-       free_conntrack_hash();
+       free_conntrack_hash(ip_conntrack_hash, ip_conntrack_vmalloc,
+                           ip_conntrack_htable_size);
        nf_unregister_sockopt(&so_getorigdst);
 }
 
-static int hashsize;
-module_param(hashsize, int, 0400);
+static struct list_head *alloc_hashtable(int size, int *vmalloced)
+{
+       struct list_head *hash;
+       unsigned int i;
+
+       *vmalloced = 0; 
+       hash = (void*)__get_free_pages(GFP_KERNEL, 
+                                      get_order(sizeof(struct list_head)
+                                                * size));
+       if (!hash) { 
+               *vmalloced = 1;
+               printk(KERN_WARNING"ip_conntrack: falling back to vmalloc.\n");
+               hash = vmalloc(sizeof(struct list_head) * size);
+       }
+
+       if (hash)
+               for (i = 0; i < size; i++)
+                       INIT_LIST_HEAD(&hash[i]);
+
+       return hash;
+}
+
+int set_hashsize(const char *val, struct kernel_param *kp)
+{
+       int i, bucket, hashsize, vmalloced;
+       int old_vmalloced, old_size;
+       int rnd;
+       struct list_head *hash, *old_hash;
+       struct ip_conntrack_tuple_hash *h;
+
+       /* On boot, we can set this without any fancy locking. */
+       if (!ip_conntrack_htable_size)
+               return param_set_int(val, kp);
+
+       hashsize = simple_strtol(val, NULL, 0);
+       if (!hashsize)
+               return -EINVAL;
+
+       hash = alloc_hashtable(hashsize, &vmalloced);
+       if (!hash)
+               return -ENOMEM;
+
+       /* We have to rehash for the new table anyway, so we also can 
+        * use a new random seed */
+       get_random_bytes(&rnd, 4);
+
+       write_lock_bh(&ip_conntrack_lock);
+       for (i = 0; i < ip_conntrack_htable_size; i++) {
+               while (!list_empty(&ip_conntrack_hash[i])) {
+                       h = list_entry(ip_conntrack_hash[i].next,
+                                      struct ip_conntrack_tuple_hash, list);
+                       list_del(&h->list);
+                       bucket = __hash_conntrack(&h->tuple, hashsize, rnd);
+                       list_add_tail(&h->list, &hash[bucket]);
+               }
+       }
+       old_size = ip_conntrack_htable_size;
+       old_vmalloced = ip_conntrack_vmalloc;
+       old_hash = ip_conntrack_hash;
+
+       ip_conntrack_htable_size = hashsize;
+       ip_conntrack_vmalloc = vmalloced;
+       ip_conntrack_hash = hash;
+       ip_conntrack_hash_rnd = rnd;
+       write_unlock_bh(&ip_conntrack_lock);
+
+       free_conntrack_hash(old_hash, old_vmalloced, old_size);
+       return 0;
+}
+
+module_param_call(hashsize, set_hashsize, param_get_uint,
+                 &ip_conntrack_htable_size, 0600);
 
 int __init ip_conntrack_init(void)
 {
@@ -1392,9 +1466,7 @@ int __init ip_conntrack_init(void)
 
        /* Idea from tcp.c: use 1/16384 of memory.  On i386: 32MB
         * machine has 256 buckets.  >= 1GB machines have 8192 buckets. */
-       if (hashsize) {
-               ip_conntrack_htable_size = hashsize;
-       } else {
+       if (!ip_conntrack_htable_size) {
                ip_conntrack_htable_size
                        = (((num_physpages << PAGE_SHIFT) / 16384)
                           / sizeof(struct list_head));
@@ -1416,20 +1488,8 @@ int __init ip_conntrack_init(void)
                return ret;
        }
 
-       /* AK: the hash table is twice as big than needed because it
-          uses list_head.  it would be much nicer to caches to use a
-          single pointer list head here. */
-       ip_conntrack_vmalloc = 0; 
-       ip_conntrack_hash 
-               =(void*)__get_free_pages(GFP_KERNEL, 
-                                        get_order(sizeof(struct list_head)
-                                                  *ip_conntrack_htable_size));
-       if (!ip_conntrack_hash) { 
-               ip_conntrack_vmalloc = 1;
-               printk(KERN_WARNING "ip_conntrack: falling back to vmalloc.\n");
-               ip_conntrack_hash = vmalloc(sizeof(struct list_head)
-                                           * ip_conntrack_htable_size);
-       }
+       ip_conntrack_hash = alloc_hashtable(ip_conntrack_htable_size,
+                                           &ip_conntrack_vmalloc);
        if (!ip_conntrack_hash) {
                printk(KERN_ERR "Unable to create ip_conntrack_hash\n");
                goto err_unreg_sockopt;
@@ -1461,9 +1521,6 @@ int __init ip_conntrack_init(void)
        ip_ct_protos[IPPROTO_ICMP] = &ip_conntrack_protocol_icmp;
        write_unlock_bh(&ip_conntrack_lock);
 
-       for (i = 0; i < ip_conntrack_htable_size; i++)
-               INIT_LIST_HEAD(&ip_conntrack_hash[i]);
-
        /* For use by ipt_REJECT */
        ip_ct_attach = ip_conntrack_attach;
 
@@ -1478,7 +1535,8 @@ int __init ip_conntrack_init(void)
 err_free_conntrack_slab:
        kmem_cache_destroy(ip_conntrack_cachep);
 err_free_hash:
-       free_conntrack_hash();
+       free_conntrack_hash(ip_conntrack_hash, ip_conntrack_vmalloc,
+                           ip_conntrack_htable_size);
 err_unreg_sockopt:
        nf_unregister_sockopt(&so_getorigdst);
 
index f7943ba1f43c42d3d8c6546730c283ae134f53e6..a65e508fbd40e4681bb9b5649c36d5ed8959b913 100644 (file)
@@ -90,9 +90,7 @@ fold_field(void *mib[], int offt)
        unsigned long res = 0;
        int i;
 
-       for (i = 0; i < NR_CPUS; i++) {
-               if (!cpu_possible(i))
-                       continue;
+       for_each_cpu(i) {
                res += *(((unsigned long *) per_cpu_ptr(mib[0], i)) + offt);
                res += *(((unsigned long *) per_cpu_ptr(mib[1], i)) + offt);
        }
index b7185fb3377ce08105d46e34741cea01b85610a7..23e540365a143fde637aa72bd8697113cab444d6 100644 (file)
@@ -700,10 +700,7 @@ int __init icmpv6_init(struct net_proto_family *ops)
        struct sock *sk;
        int err, i, j;
 
-       for (i = 0; i < NR_CPUS; i++) {
-               if (!cpu_possible(i))
-                       continue;
-
+       for_each_cpu(i) {
                err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6,
                                       &per_cpu(__icmpv6_socket, i));
                if (err < 0) {
@@ -749,9 +746,7 @@ void icmpv6_cleanup(void)
 {
        int i;
 
-       for (i = 0; i < NR_CPUS; i++) {
-               if (!cpu_possible(i))
-                       continue;
+       for_each_cpu(i) {
                sock_release(per_cpu(__icmpv6_socket, i));
        }
        inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6);
index 334a5967831e061c7dca3ce1532d7f33e742a17d..50a13e75d70ec5fecd20269c8c4e90bc523164cc 100644 (file)
@@ -140,9 +140,7 @@ fold_field(void *mib[], int offt)
         unsigned long res = 0;
         int i;
  
-        for (i = 0; i < NR_CPUS; i++) {
-                if (!cpu_possible(i))
-                        continue;
+        for_each_cpu(i) {
                 res += *(((unsigned long *)per_cpu_ptr(mib[0], i)) + offt);
                 res += *(((unsigned long *)per_cpu_ptr(mib[1], i)) + offt);
         }
index 678c3f2c0d0bdd9abad85d3eeb16acf38c8a01d3..5ca283537bc66e9344c2e0295b6139d0628454a9 100644 (file)
@@ -740,11 +740,8 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, long t
 
 int netlink_sendskb(struct sock *sk, struct sk_buff *skb, int protocol)
 {
-       struct netlink_sock *nlk;
        int len = skb->len;
 
-       nlk = nlk_sk(sk);
-
        skb_queue_tail(&sk->sk_receive_queue, skb);
        sk->sk_data_ready(sk, len);
        sock_put(sk);
@@ -827,7 +824,7 @@ struct netlink_broadcast_data {
        int failure;
        int congested;
        int delivered;
-       unsigned int allocation;
+       gfp_t allocation;
        struct sk_buff *skb, *skb2;
 };
 
index e556d92c0bc4d2eb5883acda48b051a608a10d9f..b18fe504301944d8514816df8d6eb90f715b048d 100644 (file)
@@ -727,7 +727,7 @@ int rose_rt_ioctl(unsigned int cmd, void __user *arg)
                }
                if (rose_route.mask > 10) /* Mask can't be more than 10 digits */
                        return -EINVAL;
-               if (rose_route.ndigis > 8) /* No more than 8 digipeats */
+               if (rose_route.ndigis > AX25_MAX_DIGIS)
                        return -EINVAL;
                err = rose_add_node(&rose_route, dev);
                dev_put(dev);
index b74f7772b576b131b34b25c33fa544d4d6b84c8d..6e4dc28874d7690884753d32542fb039ed5e0b6d 100644 (file)
@@ -69,9 +69,7 @@ fold_field(void *mib[], int nr)
        unsigned long res = 0;
        int i;
 
-       for (i = 0; i < NR_CPUS; i++) {
-               if (!cpu_possible(i))
-                       continue;
+       for_each_cpu(i) {
                res +=
                    *((unsigned long *) (((void *) per_cpu_ptr(mib[0], i)) +
                                         sizeof (unsigned long) * nr));
index 46a2ce00a29b8af7ca0ac4a67fd082eda541bf00..cdcab9ca4c60fed14b460da6a4c93794b18bf938 100644 (file)
@@ -6,7 +6,7 @@
 obj-$(CONFIG_SUNRPC) += sunrpc.o
 obj-$(CONFIG_SUNRPC_GSS) += auth_gss/
 
-sunrpc-y := clnt.o xprt.o sched.o \
+sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \
            auth.o auth_null.o auth_unix.o \
            svc.o svcsock.o svcauth.o svcauth_unix.o \
            pmap_clnt.o timer.o xdr.o \
index 505e2d4b3d6259e3363c8a1c428da3535533132a..a415d99c394dee1cc4f008c85a60b28a9bae354f 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
-#include <linux/socket.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/spinlock.h>
 
index fe1b874084bc6d9df9631eb497764ca63fa44aca..f3431a7e33da6603af6076116dfcfa7b5e5b6760 100644 (file)
@@ -10,7 +10,7 @@ auth_rpcgss-objs := auth_gss.o gss_generic_token.o \
 obj-$(CONFIG_RPCSEC_GSS_KRB5) += rpcsec_gss_krb5.o
 
 rpcsec_gss_krb5-objs := gss_krb5_mech.o gss_krb5_seal.o gss_krb5_unseal.o \
-       gss_krb5_seqnum.o
+       gss_krb5_seqnum.o gss_krb5_wrap.o
 
 obj-$(CONFIG_RPCSEC_GSS_SPKM3) += rpcsec_gss_spkm3.o
 
index 2f7b867161d254cc6251dbe994fa90017a02e7a8..f44f46f1d8e053c0d330b442c2f3788cf4073dd4 100644 (file)
@@ -42,9 +42,8 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/slab.h>
-#include <linux/socket.h>
-#include <linux/in.h>
 #include <linux/sched.h>
+#include <linux/pagemap.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/auth.h>
 #include <linux/sunrpc/auth_gss.h>
@@ -846,10 +845,8 @@ gss_marshal(struct rpc_task *task, u32 *p)
 
        /* We compute the checksum for the verifier over the xdr-encoded bytes
         * starting with the xid and ending at the end of the credential: */
-       iov.iov_base = req->rq_snd_buf.head[0].iov_base;
-       if (task->tk_client->cl_xprt->stream)
-               /* See clnt.c:call_header() */
-               iov.iov_base += 4;
+       iov.iov_base = xprt_skip_transport_header(task->tk_xprt,
+                                       req->rq_snd_buf.head[0].iov_base);
        iov.iov_len = (u8 *)p - (u8 *)iov.iov_base;
        xdr_buf_from_iov(&iov, &verf_buf);
 
@@ -857,9 +854,7 @@ gss_marshal(struct rpc_task *task, u32 *p)
        *p++ = htonl(RPC_AUTH_GSS);
 
        mic.data = (u8 *)(p + 1);
-       maj_stat = gss_get_mic(ctx->gc_gss_ctx,
-                              GSS_C_QOP_DEFAULT, 
-                              &verf_buf, &mic);
+       maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
        if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
                cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
        } else if (maj_stat != 0) {
@@ -890,10 +885,8 @@ static u32 *
 gss_validate(struct rpc_task *task, u32 *p)
 {
        struct rpc_cred *cred = task->tk_msg.rpc_cred;
-       struct gss_cred *gss_cred = container_of(cred, struct gss_cred,
-                                               gc_base);
        struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
-       u32             seq, qop_state;
+       u32             seq;
        struct kvec     iov;
        struct xdr_buf  verf_buf;
        struct xdr_netobj mic;
@@ -914,23 +907,14 @@ gss_validate(struct rpc_task *task, u32 *p)
        mic.data = (u8 *)p;
        mic.len = len;
 
-       maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic, &qop_state);
+       maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
        if (maj_stat == GSS_S_CONTEXT_EXPIRED)
                cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
        if (maj_stat)
                goto out_bad;
-       switch (gss_cred->gc_service) {
-       case RPC_GSS_SVC_NONE:
-              /* verifier data, flavor, length: */
-              task->tk_auth->au_rslack = XDR_QUADLEN(len) + 2;
-              break;
-       case RPC_GSS_SVC_INTEGRITY:
-              /* verifier data, flavor, length, length, sequence number: */
-              task->tk_auth->au_rslack = XDR_QUADLEN(len) + 4;
-              break;
-       case RPC_GSS_SVC_PRIVACY:
-              goto out_bad;
-       }
+       /* We leave it to unwrap to calculate au_rslack. For now we just
+        * calculate the length of the verifier: */
+       task->tk_auth->au_verfsize = XDR_QUADLEN(len) + 2;
        gss_put_ctx(ctx);
        dprintk("RPC: %4u GSS gss_validate: gss_verify_mic succeeded.\n",
                        task->tk_pid);
@@ -975,8 +959,7 @@ gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
        p = iov->iov_base + iov->iov_len;
        mic.data = (u8 *)(p + 1);
 
-       maj_stat = gss_get_mic(ctx->gc_gss_ctx,
-                       GSS_C_QOP_DEFAULT, &integ_buf, &mic);
+       maj_stat = gss_get_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
        status = -EIO; /* XXX? */
        if (maj_stat == GSS_S_CONTEXT_EXPIRED)
                cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
@@ -990,6 +973,113 @@ gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
        return 0;
 }
 
+static void
+priv_release_snd_buf(struct rpc_rqst *rqstp)
+{
+       int i;
+
+       for (i=0; i < rqstp->rq_enc_pages_num; i++)
+               __free_page(rqstp->rq_enc_pages[i]);
+       kfree(rqstp->rq_enc_pages);
+}
+
+static int
+alloc_enc_pages(struct rpc_rqst *rqstp)
+{
+       struct xdr_buf *snd_buf = &rqstp->rq_snd_buf;
+       int first, last, i;
+
+       if (snd_buf->page_len == 0) {
+               rqstp->rq_enc_pages_num = 0;
+               return 0;
+       }
+
+       first = snd_buf->page_base >> PAGE_CACHE_SHIFT;
+       last = (snd_buf->page_base + snd_buf->page_len - 1) >> PAGE_CACHE_SHIFT;
+       rqstp->rq_enc_pages_num = last - first + 1 + 1;
+       rqstp->rq_enc_pages
+               = kmalloc(rqstp->rq_enc_pages_num * sizeof(struct page *),
+                               GFP_NOFS);
+       if (!rqstp->rq_enc_pages)
+               goto out;
+       for (i=0; i < rqstp->rq_enc_pages_num; i++) {
+               rqstp->rq_enc_pages[i] = alloc_page(GFP_NOFS);
+               if (rqstp->rq_enc_pages[i] == NULL)
+                       goto out_free;
+       }
+       rqstp->rq_release_snd_buf = priv_release_snd_buf;
+       return 0;
+out_free:
+       for (i--; i >= 0; i--) {
+               __free_page(rqstp->rq_enc_pages[i]);
+       }
+out:
+       return -EAGAIN;
+}
+
+static inline int
+gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
+               kxdrproc_t encode, struct rpc_rqst *rqstp, u32 *p, void *obj)
+{
+       struct xdr_buf  *snd_buf = &rqstp->rq_snd_buf;
+       u32             offset;
+       u32             maj_stat;
+       int             status;
+       u32             *opaque_len;
+       struct page     **inpages;
+       int             first;
+       int             pad;
+       struct kvec     *iov;
+       char            *tmp;
+
+       opaque_len = p++;
+       offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base;
+       *p++ = htonl(rqstp->rq_seqno);
+
+       status = encode(rqstp, p, obj);
+       if (status)
+               return status;
+
+       status = alloc_enc_pages(rqstp);
+       if (status)
+               return status;
+       first = snd_buf->page_base >> PAGE_CACHE_SHIFT;
+       inpages = snd_buf->pages + first;
+       snd_buf->pages = rqstp->rq_enc_pages;
+       snd_buf->page_base -= first << PAGE_CACHE_SHIFT;
+       /* Give the tail its own page, in case we need extra space in the
+        * head when wrapping: */
+       if (snd_buf->page_len || snd_buf->tail[0].iov_len) {
+               tmp = page_address(rqstp->rq_enc_pages[rqstp->rq_enc_pages_num - 1]);
+               memcpy(tmp, snd_buf->tail[0].iov_base, snd_buf->tail[0].iov_len);
+               snd_buf->tail[0].iov_base = tmp;
+       }
+       maj_stat = gss_wrap(ctx->gc_gss_ctx, offset, snd_buf, inpages);
+       /* RPC_SLACK_SPACE should prevent this ever happening: */
+       BUG_ON(snd_buf->len > snd_buf->buflen);
+        status = -EIO;
+       /* We're assuming that when GSS_S_CONTEXT_EXPIRED, the encryption was
+        * done anyway, so it's safe to put the request on the wire: */
+       if (maj_stat == GSS_S_CONTEXT_EXPIRED)
+               cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+       else if (maj_stat)
+               return status;
+
+       *opaque_len = htonl(snd_buf->len - offset);
+       /* guess whether we're in the head or the tail: */
+       if (snd_buf->page_len || snd_buf->tail[0].iov_len)
+               iov = snd_buf->tail;
+       else
+               iov = snd_buf->head;
+       p = iov->iov_base + iov->iov_len;
+       pad = 3 - ((snd_buf->len - offset - 1) & 3);
+       memset(p, 0, pad);
+       iov->iov_len += pad;
+       snd_buf->len += pad;
+
+       return 0;
+}
+
 static int
 gss_wrap_req(struct rpc_task *task,
             kxdrproc_t encode, void *rqstp, u32 *p, void *obj)
@@ -1017,6 +1107,8 @@ gss_wrap_req(struct rpc_task *task,
                                                                rqstp, p, obj);
                        break;
                        case RPC_GSS_SVC_PRIVACY:
+                       status = gss_wrap_req_priv(cred, ctx, encode,
+                                       rqstp, p, obj);
                        break;
        }
 out:
@@ -1054,8 +1146,7 @@ gss_unwrap_resp_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
        if (xdr_buf_read_netobj(rcv_buf, &mic, mic_offset))
                return status;
 
-       maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf,
-                       &mic, NULL);
+       maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
        if (maj_stat == GSS_S_CONTEXT_EXPIRED)
                cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
        if (maj_stat != GSS_S_COMPLETE)
@@ -1063,6 +1154,35 @@ gss_unwrap_resp_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
        return 0;
 }
 
+static inline int
+gss_unwrap_resp_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
+               struct rpc_rqst *rqstp, u32 **p)
+{
+       struct xdr_buf  *rcv_buf = &rqstp->rq_rcv_buf;
+       u32 offset;
+       u32 opaque_len;
+       u32 maj_stat;
+       int status = -EIO;
+
+       opaque_len = ntohl(*(*p)++);
+       offset = (u8 *)(*p) - (u8 *)rcv_buf->head[0].iov_base;
+       if (offset + opaque_len > rcv_buf->len)
+               return status;
+       /* remove padding: */
+       rcv_buf->len = offset + opaque_len;
+
+       maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset, rcv_buf);
+       if (maj_stat == GSS_S_CONTEXT_EXPIRED)
+               cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+       if (maj_stat != GSS_S_COMPLETE)
+               return status;
+       if (ntohl(*(*p)++) != rqstp->rq_seqno)
+               return status;
+
+       return 0;
+}
+
+
 static int
 gss_unwrap_resp(struct rpc_task *task,
                kxdrproc_t decode, void *rqstp, u32 *p, void *obj)
@@ -1071,6 +1191,9 @@ gss_unwrap_resp(struct rpc_task *task,
        struct gss_cred *gss_cred = container_of(cred, struct gss_cred,
                        gc_base);
        struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
+       u32             *savedp = p;
+       struct kvec     *head = ((struct rpc_rqst *)rqstp)->rq_rcv_buf.head;
+       int             savedlen = head->iov_len;
        int             status = -EIO;
 
        if (ctx->gc_proc != RPC_GSS_PROC_DATA)
@@ -1084,8 +1207,14 @@ gss_unwrap_resp(struct rpc_task *task,
                                goto out;
                        break;
                        case RPC_GSS_SVC_PRIVACY:
+                       status = gss_unwrap_resp_priv(cred, ctx, rqstp, &p);
+                       if (status)
+                               goto out;
                        break;
        }
+       /* take into account extra slack for integrity and privacy cases: */
+       task->tk_auth->au_rslack = task->tk_auth->au_verfsize + (p - savedp)
+                                               + (savedlen - head->iov_len);
 out_decode:
        status = decode(rqstp, p, obj);
 out:
index ee6ae74cd1b226b2bb7d39655f2a1862e4507c21..3f3d5437f02d38309bbad8cfc9d343720b6f3d04 100644 (file)
@@ -139,17 +139,91 @@ buf_to_sg(struct scatterlist *sg, char *ptr, int len) {
        sg->length = len;
 }
 
+static int
+process_xdr_buf(struct xdr_buf *buf, int offset, int len,
+               int (*actor)(struct scatterlist *, void *), void *data)
+{
+       int i, page_len, thislen, page_offset, ret = 0;
+       struct scatterlist      sg[1];
+
+       if (offset >= buf->head[0].iov_len) {
+               offset -= buf->head[0].iov_len;
+       } else {
+               thislen = buf->head[0].iov_len - offset;
+               if (thislen > len)
+                       thislen = len;
+               buf_to_sg(sg, buf->head[0].iov_base + offset, thislen);
+               ret = actor(sg, data);
+               if (ret)
+                       goto out;
+               offset = 0;
+               len -= thislen;
+       }
+       if (len == 0)
+               goto out;
+
+       if (offset >= buf->page_len) {
+               offset -= buf->page_len;
+       } else {
+               page_len = buf->page_len - offset;
+               if (page_len > len)
+                       page_len = len;
+               len -= page_len;
+               page_offset = (offset + buf->page_base) & (PAGE_CACHE_SIZE - 1);
+               i = (offset + buf->page_base) >> PAGE_CACHE_SHIFT;
+               thislen = PAGE_CACHE_SIZE - page_offset;
+               do {
+                       if (thislen > page_len)
+                               thislen = page_len;
+                       sg->page = buf->pages[i];
+                       sg->offset = page_offset;
+                       sg->length = thislen;
+                       ret = actor(sg, data);
+                       if (ret)
+                               goto out;
+                       page_len -= thislen;
+                       i++;
+                       page_offset = 0;
+                       thislen = PAGE_CACHE_SIZE;
+               } while (page_len != 0);
+               offset = 0;
+       }
+       if (len == 0)
+               goto out;
+
+       if (offset < buf->tail[0].iov_len) {
+               thislen = buf->tail[0].iov_len - offset;
+               if (thislen > len)
+                       thislen = len;
+               buf_to_sg(sg, buf->tail[0].iov_base + offset, thislen);
+               ret = actor(sg, data);
+               len -= thislen;
+       }
+       if (len != 0)
+               ret = -EINVAL;
+out:
+       return ret;
+}
+
+static int
+checksummer(struct scatterlist *sg, void *data)
+{
+       struct crypto_tfm *tfm = (struct crypto_tfm *)data;
+
+       crypto_digest_update(tfm, sg, 1);
+
+       return 0;
+}
+
 /* checksum the plaintext data and hdrlen bytes of the token header */
 s32
 make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
-                  struct xdr_netobj *cksum)
+                  int body_offset, struct xdr_netobj *cksum)
 {
        char                            *cksumname;
        struct crypto_tfm               *tfm = NULL; /* XXX add to ctx? */
        struct scatterlist              sg[1];
        u32                             code = GSS_S_FAILURE;
-       int                             len, thislen, offset;
-       int                             i;
 
        switch (cksumtype) {
                case CKSUMTYPE_RSA_MD5:
@@ -169,33 +243,8 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
        crypto_digest_init(tfm);
        buf_to_sg(sg, header, hdrlen);
        crypto_digest_update(tfm, sg, 1);
-       if (body->head[0].iov_len) {
-               buf_to_sg(sg, body->head[0].iov_base, body->head[0].iov_len);
-               crypto_digest_update(tfm, sg, 1);
-       }
-
-       len = body->page_len;
-       if (len != 0) {
-               offset = body->page_base & (PAGE_CACHE_SIZE - 1);
-               i = body->page_base >> PAGE_CACHE_SHIFT;
-               thislen = PAGE_CACHE_SIZE - offset;
-               do {
-                       if (thislen > len)
-                               thislen = len;
-                       sg->page = body->pages[i];
-                       sg->offset = offset;
-                       sg->length = thislen;
-                       crypto_digest_update(tfm, sg, 1);
-                       len -= thislen;
-                       i++;
-                       offset = 0;
-                       thislen = PAGE_CACHE_SIZE;
-               } while(len != 0);
-       }
-       if (body->tail[0].iov_len) {
-               buf_to_sg(sg, body->tail[0].iov_base, body->tail[0].iov_len);
-               crypto_digest_update(tfm, sg, 1);
-       }
+       process_xdr_buf(body, body_offset, body->len - body_offset,
+                       checksummer, tfm);
        crypto_digest_final(tfm, cksum->data);
        code = 0;
 out:
@@ -204,3 +253,154 @@ out:
 }
 
 EXPORT_SYMBOL(make_checksum);
+
+struct encryptor_desc {
+       u8 iv[8]; /* XXX hard-coded blocksize */
+       struct crypto_tfm *tfm;
+       int pos;
+       struct xdr_buf *outbuf;
+       struct page **pages;
+       struct scatterlist infrags[4];
+       struct scatterlist outfrags[4];
+       int fragno;
+       int fraglen;
+};
+
+static int
+encryptor(struct scatterlist *sg, void *data)
+{
+       struct encryptor_desc *desc = data;
+       struct xdr_buf *outbuf = desc->outbuf;
+       struct page *in_page;
+       int thislen = desc->fraglen + sg->length;
+       int fraglen, ret;
+       int page_pos;
+
+       /* Worst case is 4 fragments: head, end of page 1, start
+        * of page 2, tail.  Anything more is a bug. */
+       BUG_ON(desc->fragno > 3);
+       desc->infrags[desc->fragno] = *sg;
+       desc->outfrags[desc->fragno] = *sg;
+
+       page_pos = desc->pos - outbuf->head[0].iov_len;
+       if (page_pos >= 0 && page_pos < outbuf->page_len) {
+               /* pages are not in place: */
+               int i = (page_pos + outbuf->page_base) >> PAGE_CACHE_SHIFT;
+               in_page = desc->pages[i];
+       } else {
+               in_page = sg->page;
+       }
+       desc->infrags[desc->fragno].page = in_page;
+       desc->fragno++;
+       desc->fraglen += sg->length;
+       desc->pos += sg->length;
+
+       fraglen = thislen & 7; /* XXX hardcoded blocksize */
+       thislen -= fraglen;
+
+       if (thislen == 0)
+               return 0;
+
+       ret = crypto_cipher_encrypt_iv(desc->tfm, desc->outfrags, desc->infrags,
+                                       thislen, desc->iv);
+       if (ret)
+               return ret;
+       if (fraglen) {
+               desc->outfrags[0].page = sg->page;
+               desc->outfrags[0].offset = sg->offset + sg->length - fraglen;
+               desc->outfrags[0].length = fraglen;
+               desc->infrags[0] = desc->outfrags[0];
+               desc->infrags[0].page = in_page;
+               desc->fragno = 1;
+               desc->fraglen = fraglen;
+       } else {
+               desc->fragno = 0;
+               desc->fraglen = 0;
+       }
+       return 0;
+}
+
+int
+gss_encrypt_xdr_buf(struct crypto_tfm *tfm, struct xdr_buf *buf, int offset,
+               struct page **pages)
+{
+       int ret;
+       struct encryptor_desc desc;
+
+       BUG_ON((buf->len - offset) % crypto_tfm_alg_blocksize(tfm) != 0);
+
+       memset(desc.iv, 0, sizeof(desc.iv));
+       desc.tfm = tfm;
+       desc.pos = offset;
+       desc.outbuf = buf;
+       desc.pages = pages;
+       desc.fragno = 0;
+       desc.fraglen = 0;
+
+       ret = process_xdr_buf(buf, offset, buf->len - offset, encryptor, &desc);
+       return ret;
+}
+
+EXPORT_SYMBOL(gss_encrypt_xdr_buf);
+
+struct decryptor_desc {
+       u8 iv[8]; /* XXX hard-coded blocksize */
+       struct crypto_tfm *tfm;
+       struct scatterlist frags[4];
+       int fragno;
+       int fraglen;
+};
+
+static int
+decryptor(struct scatterlist *sg, void *data)
+{
+       struct decryptor_desc *desc = data;
+       int thislen = desc->fraglen + sg->length;
+       int fraglen, ret;
+
+       /* Worst case is 4 fragments: head, end of page 1, start
+        * of page 2, tail.  Anything more is a bug. */
+       BUG_ON(desc->fragno > 3);
+       desc->frags[desc->fragno] = *sg;
+       desc->fragno++;
+       desc->fraglen += sg->length;
+
+       fraglen = thislen & 7; /* XXX hardcoded blocksize */
+       thislen -= fraglen;
+
+       if (thislen == 0)
+               return 0;
+
+       ret = crypto_cipher_decrypt_iv(desc->tfm, desc->frags, desc->frags,
+                                       thislen, desc->iv);
+       if (ret)
+               return ret;
+       if (fraglen) {
+               desc->frags[0].page = sg->page;
+               desc->frags[0].offset = sg->offset + sg->length - fraglen;
+               desc->frags[0].length = fraglen;
+               desc->fragno = 1;
+               desc->fraglen = fraglen;
+       } else {
+               desc->fragno = 0;
+               desc->fraglen = 0;
+       }
+       return 0;
+}
+
+int
+gss_decrypt_xdr_buf(struct crypto_tfm *tfm, struct xdr_buf *buf, int offset)
+{
+       struct decryptor_desc desc;
+
+       /* XXXJBF: */
+       BUG_ON((buf->len - offset) % crypto_tfm_alg_blocksize(tfm) != 0);
+
+       memset(desc.iv, 0, sizeof(desc.iv));
+       desc.tfm = tfm;
+       desc.fragno = 0;
+       desc.fraglen = 0;
+       return process_xdr_buf(buf, offset, buf->len - offset, decryptor, &desc);
+}
+
+EXPORT_SYMBOL(gss_decrypt_xdr_buf);
index 606a8a82cafbedc84545ec73def5ff2e54054b5c..5f1f806a0b1176401f0fb744eaa9b7d7579edc90 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/sunrpc/auth.h>
-#include <linux/in.h>
 #include <linux/sunrpc/gss_krb5.h>
 #include <linux/sunrpc/xdr.h>
 #include <linux/crypto.h>
@@ -191,43 +190,12 @@ gss_delete_sec_context_kerberos(void *internal_ctx) {
        kfree(kctx);
 }
 
-static u32
-gss_verify_mic_kerberos(struct gss_ctx         *ctx,
-                       struct xdr_buf          *message,
-                       struct xdr_netobj       *mic_token,
-                       u32                     *qstate) {
-       u32 maj_stat = 0;
-       int qop_state;
-       struct krb5_ctx *kctx = ctx->internal_ctx_id;
-
-       maj_stat = krb5_read_token(kctx, mic_token, message, &qop_state,
-                                  KG_TOK_MIC_MSG);
-       if (!maj_stat && qop_state)
-           *qstate = qop_state;
-
-       dprintk("RPC:      gss_verify_mic_kerberos returning %d\n", maj_stat);
-       return maj_stat;
-}
-
-static u32
-gss_get_mic_kerberos(struct gss_ctx    *ctx,
-                    u32                qop,
-                    struct xdr_buf     *message,
-                    struct xdr_netobj  *mic_token) {
-       u32 err = 0;
-       struct krb5_ctx *kctx = ctx->internal_ctx_id;
-
-       err = krb5_make_token(kctx, qop, message, mic_token, KG_TOK_MIC_MSG);
-
-       dprintk("RPC:      gss_get_mic_kerberos returning %d\n",err);
-
-       return err;
-}
-
 static struct gss_api_ops gss_kerberos_ops = {
        .gss_import_sec_context = gss_import_sec_context_kerberos,
        .gss_get_mic            = gss_get_mic_kerberos,
        .gss_verify_mic         = gss_verify_mic_kerberos,
+       .gss_wrap               = gss_wrap_kerberos,
+       .gss_unwrap             = gss_unwrap_kerberos,
        .gss_delete_sec_context = gss_delete_sec_context_kerberos,
 };
 
@@ -242,6 +210,11 @@ static struct pf_desc gss_kerberos_pfs[] = {
                .service = RPC_GSS_SVC_INTEGRITY,
                .name = "krb5i",
        },
+       [2] = {
+               .pseudoflavor = RPC_AUTH_GSS_KRB5P,
+               .service = RPC_GSS_SVC_PRIVACY,
+               .name = "krb5p",
+       },
 };
 
 static struct gss_api_mech gss_kerberos_mech = {
index afeeb8715a774c7e05d80a28112ced76753dac09..13f8ae9794542d436f82274bff2e38c0a7724f18 100644 (file)
 # define RPCDBG_FACILITY        RPCDBG_AUTH
 #endif
 
-static inline int
-gss_krb5_padding(int blocksize, int length) {
-       /* Most of the code is block-size independent but in practice we
-        * use only 8: */
-       BUG_ON(blocksize != 8);
-       return 8 - (length & 7);
-}
-
 u32
-krb5_make_token(struct krb5_ctx *ctx, int qop_req,
-                  struct xdr_buf *text, struct xdr_netobj *token,
-                  int toktype)
+gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
+               struct xdr_netobj *token)
 {
+       struct krb5_ctx         *ctx = gss_ctx->internal_ctx_id;
        s32                     checksum_type;
        struct xdr_netobj       md5cksum = {.len = 0, .data = NULL};
-       int                     blocksize = 0, tmsglen;
        unsigned char           *ptr, *krb5_hdr, *msg_start;
        s32                     now;
 
@@ -93,9 +84,6 @@ krb5_make_token(struct krb5_ctx *ctx, int qop_req,
 
        now = get_seconds();
 
-       if (qop_req != 0)
-               goto out_err;
-
        switch (ctx->signalg) {
                case SGN_ALG_DES_MAC_MD5:
                        checksum_type = CKSUMTYPE_RSA_MD5;
@@ -111,21 +99,13 @@ krb5_make_token(struct krb5_ctx *ctx, int qop_req,
                goto out_err;
        }
 
-       if (toktype == KG_TOK_WRAP_MSG) {
-               blocksize = crypto_tfm_alg_blocksize(ctx->enc);
-               tmsglen = blocksize + text->len
-                       + gss_krb5_padding(blocksize, blocksize + text->len);
-       } else {
-               tmsglen = 0;
-       }
-
-       token->len = g_token_size(&ctx->mech_used, 22 + tmsglen);
+       token->len = g_token_size(&ctx->mech_used, 22);
 
        ptr = token->data;
-       g_make_token_header(&ctx->mech_used, 22 + tmsglen, &ptr);
+       g_make_token_header(&ctx->mech_used, 22, &ptr);
 
-       *ptr++ = (unsigned char) ((toktype>>8)&0xff);
-       *ptr++ = (unsigned char) (toktype&0xff);
+       *ptr++ = (unsigned char) ((KG_TOK_MIC_MSG>>8)&0xff);
+       *ptr++ = (unsigned char) (KG_TOK_MIC_MSG&0xff);
 
        /* ptr now at byte 2 of header described in rfc 1964, section 1.2.1: */
        krb5_hdr = ptr - 2;
@@ -133,17 +113,9 @@ krb5_make_token(struct krb5_ctx *ctx, int qop_req,
 
        *(u16 *)(krb5_hdr + 2) = htons(ctx->signalg);
        memset(krb5_hdr + 4, 0xff, 4);
-       if (toktype == KG_TOK_WRAP_MSG)
-               *(u16 *)(krb5_hdr + 4) = htons(ctx->sealalg);
 
-       if (toktype == KG_TOK_WRAP_MSG) {
-               /* XXX removing support for now */
-               goto out_err;
-       } else { /* Sign only.  */
-               if (make_checksum(checksum_type, krb5_hdr, 8, text,
-                                      &md5cksum))
+       if (make_checksum(checksum_type, krb5_hdr, 8, text, 0, &md5cksum))
                        goto out_err;
-       }
 
        switch (ctx->signalg) {
        case SGN_ALG_DES_MAC_MD5:
index 8767fc53183d49c105a5d366bf03ff663ef6b775..2030475d98ed26b22632a6dc6f01068ef6f92947 100644 (file)
 #endif
 
 
-/* message_buffer is an input if toktype is MIC and an output if it is WRAP:
- * If toktype is MIC: read_token is a mic token, and message_buffer is the
- *   data that the mic was supposedly taken over.
- * If toktype is WRAP: read_token is a wrap token, and message_buffer is used
- *   to return the decrypted data.
- */
+/* read_token is a mic token, and message_buffer is the data that the mic was
+ * supposedly taken over. */
 
-/* XXX will need to change prototype and/or just split into a separate function
- * when we add privacy (because read_token will be in pages too). */
 u32
-krb5_read_token(struct krb5_ctx *ctx,
-               struct xdr_netobj *read_token,
-               struct xdr_buf *message_buffer,
-               int *qop_state, int toktype)
+gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
+               struct xdr_buf *message_buffer, struct xdr_netobj *read_token)
 {
+       struct krb5_ctx         *ctx = gss_ctx->internal_ctx_id;
        int                     signalg;
        int                     sealalg;
        s32                     checksum_type;
@@ -100,16 +93,12 @@ krb5_read_token(struct krb5_ctx *ctx,
                                        read_token->len))
                goto out;
 
-       if ((*ptr++ != ((toktype>>8)&0xff)) || (*ptr++ != (toktype&0xff)))
+       if ((*ptr++ != ((KG_TOK_MIC_MSG>>8)&0xff)) ||
+           (*ptr++ != ( KG_TOK_MIC_MSG    &0xff))   )
                goto out;
 
        /* XXX sanity-check bodysize?? */
 
-       if (toktype == KG_TOK_WRAP_MSG) {
-               /* XXX gone */
-               goto out;
-       }
-
        /* get the sign and seal algorithms */
 
        signalg = ptr[0] + (ptr[1] << 8);
@@ -120,14 +109,7 @@ krb5_read_token(struct krb5_ctx *ctx,
        if ((ptr[4] != 0xff) || (ptr[5] != 0xff))
                goto out;
 
-       if (((toktype != KG_TOK_WRAP_MSG) && (sealalg != 0xffff)) ||
-           ((toktype == KG_TOK_WRAP_MSG) && (sealalg == 0xffff)))
-               goto out;
-
-       /* in the current spec, there is only one valid seal algorithm per
-          key type, so a simple comparison is ok */
-
-       if ((toktype == KG_TOK_WRAP_MSG) && !(sealalg == ctx->sealalg))
+       if (sealalg != 0xffff)
                goto out;
 
        /* there are several mappings of seal algorithms to sign algorithms,
@@ -154,7 +136,7 @@ krb5_read_token(struct krb5_ctx *ctx,
        switch (signalg) {
        case SGN_ALG_DES_MAC_MD5:
                ret = make_checksum(checksum_type, ptr - 2, 8,
-                                        message_buffer, &md5cksum);
+                                        message_buffer, 0, &md5cksum);
                if (ret)
                        goto out;
 
@@ -175,9 +157,6 @@ krb5_read_token(struct krb5_ctx *ctx,
 
        /* it got through unscathed.  Make sure the context is unexpired */
 
-       if (qop_state)
-               *qop_state = GSS_C_QOP_DEFAULT;
-
        now = get_seconds();
 
        ret = GSS_S_CONTEXT_EXPIRED;
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
new file mode 100644 (file)
index 0000000..af777cf
--- /dev/null
@@ -0,0 +1,363 @@
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/sunrpc/gss_krb5.h>
+#include <linux/random.h>
+#include <linux/pagemap.h>
+#include <asm/scatterlist.h>
+#include <linux/crypto.h>
+
+#ifdef RPC_DEBUG
+# define RPCDBG_FACILITY       RPCDBG_AUTH
+#endif
+
+static inline int
+gss_krb5_padding(int blocksize, int length)
+{
+       /* Most of the code is block-size independent but currently we
+        * use only 8: */
+       BUG_ON(blocksize != 8);
+       return 8 - (length & 7);
+}
+
+static inline void
+gss_krb5_add_padding(struct xdr_buf *buf, int offset, int blocksize)
+{
+       int padding = gss_krb5_padding(blocksize, buf->len - offset);
+       char *p;
+       struct kvec *iov;
+
+       if (buf->page_len || buf->tail[0].iov_len)
+               iov = &buf->tail[0];
+       else
+               iov = &buf->head[0];
+       p = iov->iov_base + iov->iov_len;
+       iov->iov_len += padding;
+       buf->len += padding;
+       memset(p, padding, padding);
+}
+
+static inline int
+gss_krb5_remove_padding(struct xdr_buf *buf, int blocksize)
+{
+       u8 *ptr;
+       u8 pad;
+       int len = buf->len;
+
+       if (len <= buf->head[0].iov_len) {
+               pad = *(u8 *)(buf->head[0].iov_base + len - 1);
+               if (pad > buf->head[0].iov_len)
+                       return -EINVAL;
+               buf->head[0].iov_len -= pad;
+               goto out;
+       } else
+               len -= buf->head[0].iov_len;
+       if (len <= buf->page_len) {
+               int last = (buf->page_base + len - 1)
+                                       >>PAGE_CACHE_SHIFT;
+               int offset = (buf->page_base + len - 1)
+                                       & (PAGE_CACHE_SIZE - 1);
+               ptr = kmap_atomic(buf->pages[last], KM_SKB_SUNRPC_DATA);
+               pad = *(ptr + offset);
+               kunmap_atomic(ptr, KM_SKB_SUNRPC_DATA);
+               goto out;
+       } else
+               len -= buf->page_len;
+       BUG_ON(len > buf->tail[0].iov_len);
+       pad = *(u8 *)(buf->tail[0].iov_base + len - 1);
+out:
+       /* XXX: NOTE: we do not adjust the page lengths--they represent
+        * a range of data in the real filesystem page cache, and we need
+        * to know that range so the xdr code can properly place read data.
+        * However adjusting the head length, as we do above, is harmless.
+        * In the case of a request that fits into a single page, the server
+        * also uses length and head length together to determine the original
+        * start of the request to copy the request for deferal; so it's
+        * easier on the server if we adjust head and tail length in tandem.
+        * It's not really a problem that we don't fool with the page and
+        * tail lengths, though--at worst badly formed xdr might lead the
+        * server to attempt to parse the padding.
+        * XXX: Document all these weird requirements for gss mechanism
+        * wrap/unwrap functions. */
+       if (pad > blocksize)
+               return -EINVAL;
+       if (buf->len > pad)
+               buf->len -= pad;
+       else
+               return -EINVAL;
+       return 0;
+}
+
+static inline void
+make_confounder(char *p, int blocksize)
+{
+       static u64 i = 0;
+       u64 *q = (u64 *)p;
+
+       /* rfc1964 claims this should be "random".  But all that's really
+        * necessary is that it be unique.  And not even that is necessary in
+        * our case since our "gssapi" implementation exists only to support
+        * rpcsec_gss, so we know that the only buffers we will ever encrypt
+        * already begin with a unique sequence number.  Just to hedge my bets
+        * I'll make a half-hearted attempt at something unique, but ensuring
+        * uniqueness would mean worrying about atomicity and rollover, and I
+        * don't care enough. */
+
+       BUG_ON(blocksize != 8);
+       *q = i++;
+}
+
+/* Assumptions: the head and tail of inbuf are ours to play with.
+ * The pages, however, may be real pages in the page cache and we replace
+ * them with scratch pages from **pages before writing to them. */
+/* XXX: obviously the above should be documentation of wrap interface,
+ * and shouldn't be in this kerberos-specific file. */
+
+/* XXX factor out common code with seal/unseal. */
+
+u32
+gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
+               struct xdr_buf *buf, struct page **pages)
+{
+       struct krb5_ctx         *kctx = ctx->internal_ctx_id;
+       s32                     checksum_type;
+       struct xdr_netobj       md5cksum = {.len = 0, .data = NULL};
+       int                     blocksize = 0, plainlen;
+       unsigned char           *ptr, *krb5_hdr, *msg_start;
+       s32                     now;
+       int                     headlen;
+       struct page             **tmp_pages;
+
+       dprintk("RPC:     gss_wrap_kerberos\n");
+
+       now = get_seconds();
+
+       switch (kctx->signalg) {
+               case SGN_ALG_DES_MAC_MD5:
+                       checksum_type = CKSUMTYPE_RSA_MD5;
+                       break;
+               default:
+                       dprintk("RPC:      gss_krb5_seal: kctx->signalg %d not"
+                               " supported\n", kctx->signalg);
+                       goto out_err;
+       }
+       if (kctx->sealalg != SEAL_ALG_NONE && kctx->sealalg != SEAL_ALG_DES) {
+               dprintk("RPC:      gss_krb5_seal: kctx->sealalg %d not supported\n",
+                       kctx->sealalg);
+               goto out_err;
+       }
+
+       blocksize = crypto_tfm_alg_blocksize(kctx->enc);
+       gss_krb5_add_padding(buf, offset, blocksize);
+       BUG_ON((buf->len - offset) % blocksize);
+       plainlen = blocksize + buf->len - offset;
+
+       headlen = g_token_size(&kctx->mech_used, 22 + plainlen) -
+                                               (buf->len - offset);
+
+       ptr = buf->head[0].iov_base + offset;
+       /* shift data to make room for header. */
+       /* XXX Would be cleverer to encrypt while copying. */
+       /* XXX bounds checking, slack, etc. */
+       memmove(ptr + headlen, ptr, buf->head[0].iov_len - offset);
+       buf->head[0].iov_len += headlen;
+       buf->len += headlen;
+       BUG_ON((buf->len - offset - headlen) % blocksize);
+
+       g_make_token_header(&kctx->mech_used, 22 + plainlen, &ptr);
+
+
+       *ptr++ = (unsigned char) ((KG_TOK_WRAP_MSG>>8)&0xff);
+       *ptr++ = (unsigned char) (KG_TOK_WRAP_MSG&0xff);
+
+       /* ptr now at byte 2 of header described in rfc 1964, section 1.2.1: */
+       krb5_hdr = ptr - 2;
+       msg_start = krb5_hdr + 24;
+       /* XXXJBF: */ BUG_ON(buf->head[0].iov_base + offset + headlen != msg_start + blocksize);
+
+       *(u16 *)(krb5_hdr + 2) = htons(kctx->signalg);
+       memset(krb5_hdr + 4, 0xff, 4);
+       *(u16 *)(krb5_hdr + 4) = htons(kctx->sealalg);
+
+       make_confounder(msg_start, blocksize);
+
+       /* XXXJBF: UGH!: */
+       tmp_pages = buf->pages;
+       buf->pages = pages;
+       if (make_checksum(checksum_type, krb5_hdr, 8, buf,
+                               offset + headlen - blocksize, &md5cksum))
+               goto out_err;
+       buf->pages = tmp_pages;
+
+       switch (kctx->signalg) {
+       case SGN_ALG_DES_MAC_MD5:
+               if (krb5_encrypt(kctx->seq, NULL, md5cksum.data,
+                                 md5cksum.data, md5cksum.len))
+                       goto out_err;
+               memcpy(krb5_hdr + 16,
+                      md5cksum.data + md5cksum.len - KRB5_CKSUM_LENGTH,
+                      KRB5_CKSUM_LENGTH);
+
+               dprintk("RPC:      make_seal_token: cksum data: \n");
+               print_hexl((u32 *) (krb5_hdr + 16), KRB5_CKSUM_LENGTH, 0);
+               break;
+       default:
+               BUG();
+       }
+
+       kfree(md5cksum.data);
+
+       /* XXX would probably be more efficient to compute checksum
+        * and encrypt at the same time: */
+       if ((krb5_make_seq_num(kctx->seq, kctx->initiate ? 0 : 0xff,
+                              kctx->seq_send, krb5_hdr + 16, krb5_hdr + 8)))
+               goto out_err;
+
+       if (gss_encrypt_xdr_buf(kctx->enc, buf, offset + headlen - blocksize,
+                                                                       pages))
+               goto out_err;
+
+       kctx->seq_send++;
+
+       return ((kctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE);
+out_err:
+       if (md5cksum.data) kfree(md5cksum.data);
+       return GSS_S_FAILURE;
+}
+
+u32
+gss_unwrap_kerberos(struct gss_ctx *ctx, int offset, struct xdr_buf *buf)
+{
+       struct krb5_ctx         *kctx = ctx->internal_ctx_id;
+       int                     signalg;
+       int                     sealalg;
+       s32                     checksum_type;
+       struct xdr_netobj       md5cksum = {.len = 0, .data = NULL};
+       s32                     now;
+       int                     direction;
+       s32                     seqnum;
+       unsigned char           *ptr;
+       int                     bodysize;
+       u32                     ret = GSS_S_DEFECTIVE_TOKEN;
+       void                    *data_start, *orig_start;
+       int                     data_len;
+       int                     blocksize;
+
+       dprintk("RPC:      gss_unwrap_kerberos\n");
+
+       ptr = (u8 *)buf->head[0].iov_base + offset;
+       if (g_verify_token_header(&kctx->mech_used, &bodysize, &ptr,
+                                       buf->len - offset))
+               goto out;
+
+       if ((*ptr++ != ((KG_TOK_WRAP_MSG>>8)&0xff)) ||
+           (*ptr++ !=  (KG_TOK_WRAP_MSG    &0xff))   )
+               goto out;
+
+       /* XXX sanity-check bodysize?? */
+
+       /* get the sign and seal algorithms */
+
+       signalg = ptr[0] + (ptr[1] << 8);
+       sealalg = ptr[2] + (ptr[3] << 8);
+
+       /* Sanity checks */
+
+       if ((ptr[4] != 0xff) || (ptr[5] != 0xff))
+               goto out;
+
+       if (sealalg == 0xffff)
+               goto out;
+
+       /* in the current spec, there is only one valid seal algorithm per
+          key type, so a simple comparison is ok */
+
+       if (sealalg != kctx->sealalg)
+               goto out;
+
+       /* there are several mappings of seal algorithms to sign algorithms,
+          but few enough that we can try them all. */
+
+       if ((kctx->sealalg == SEAL_ALG_NONE && signalg > 1) ||
+           (kctx->sealalg == SEAL_ALG_1 && signalg != SGN_ALG_3) ||
+           (kctx->sealalg == SEAL_ALG_DES3KD &&
+            signalg != SGN_ALG_HMAC_SHA1_DES3_KD))
+               goto out;
+
+       if (gss_decrypt_xdr_buf(kctx->enc, buf,
+                       ptr + 22 - (unsigned char *)buf->head[0].iov_base))
+               goto out;
+
+       /* compute the checksum of the message */
+
+       /* initialize the the cksum */
+       switch (signalg) {
+       case SGN_ALG_DES_MAC_MD5:
+               checksum_type = CKSUMTYPE_RSA_MD5;
+               break;
+       default:
+               ret = GSS_S_DEFECTIVE_TOKEN;
+               goto out;
+       }
+
+       switch (signalg) {
+       case SGN_ALG_DES_MAC_MD5:
+               ret = make_checksum(checksum_type, ptr - 2, 8, buf,
+                        ptr + 22 - (unsigned char *)buf->head[0].iov_base, &md5cksum);
+               if (ret)
+                       goto out;
+
+               ret = krb5_encrypt(kctx->seq, NULL, md5cksum.data,
+                                  md5cksum.data, md5cksum.len);
+               if (ret)
+                       goto out;
+
+               if (memcmp(md5cksum.data + 8, ptr + 14, 8)) {
+                       ret = GSS_S_BAD_SIG;
+                       goto out;
+               }
+               break;
+       default:
+               ret = GSS_S_DEFECTIVE_TOKEN;
+               goto out;
+       }
+
+       /* it got through unscathed.  Make sure the context is unexpired */
+
+       now = get_seconds();
+
+       ret = GSS_S_CONTEXT_EXPIRED;
+       if (now > kctx->endtime)
+               goto out;
+
+       /* do sequencing checks */
+
+       ret = GSS_S_BAD_SIG;
+       if ((ret = krb5_get_seq_num(kctx->seq, ptr + 14, ptr + 6, &direction,
+                                   &seqnum)))
+               goto out;
+
+       if ((kctx->initiate && direction != 0xff) ||
+           (!kctx->initiate && direction != 0))
+               goto out;
+
+       /* Copy the data back to the right position.  XXX: Would probably be
+        * better to copy and encrypt at the same time. */
+
+       blocksize = crypto_tfm_alg_blocksize(kctx->enc);
+       data_start = ptr + 22 + blocksize;
+       orig_start = buf->head[0].iov_base + offset;
+       data_len = (buf->head[0].iov_base + buf->head[0].iov_len) - data_start;
+       memmove(orig_start, data_start, data_len);
+       buf->head[0].iov_len -= (data_start - orig_start);
+       buf->len -= (data_start - orig_start);
+
+       ret = GSS_S_DEFECTIVE_TOKEN;
+       if (gss_krb5_remove_padding(buf, blocksize))
+               goto out;
+
+       ret = GSS_S_COMPLETE;
+out:
+       if (md5cksum.data) kfree(md5cksum.data);
+       return ret;
+}
index 9dfb68377d694818beabf3983d3e19a891bf020e..b048bf672da2bbffbe35953b3e47a57b7e2383d3 100644 (file)
@@ -35,7 +35,6 @@
 
 #include <linux/types.h>
 #include <linux/slab.h>
-#include <linux/socket.h>
 #include <linux/module.h>
 #include <linux/sunrpc/msg_prot.h>
 #include <linux/sunrpc/gss_asn1.h>
@@ -251,13 +250,11 @@ gss_import_sec_context(const void *input_token, size_t bufsize,
 
 u32
 gss_get_mic(struct gss_ctx     *context_handle,
-           u32                 qop,
            struct xdr_buf      *message,
            struct xdr_netobj   *mic_token)
 {
         return context_handle->mech_type->gm_ops
                ->gss_get_mic(context_handle,
-                             qop,
                              message,
                              mic_token);
 }
@@ -267,16 +264,34 @@ gss_get_mic(struct gss_ctx        *context_handle,
 u32
 gss_verify_mic(struct gss_ctx          *context_handle,
               struct xdr_buf           *message,
-              struct xdr_netobj        *mic_token,
-              u32                      *qstate)
+              struct xdr_netobj        *mic_token)
 {
        return context_handle->mech_type->gm_ops
                ->gss_verify_mic(context_handle,
                                 message,
-                                mic_token,
-                                qstate);
+                                mic_token);
 }
 
+u32
+gss_wrap(struct gss_ctx        *ctx_id,
+        int            offset,
+        struct xdr_buf *buf,
+        struct page    **inpages)
+{
+       return ctx_id->mech_type->gm_ops
+               ->gss_wrap(ctx_id, offset, buf, inpages);
+}
+
+u32
+gss_unwrap(struct gss_ctx      *ctx_id,
+          int                  offset,
+          struct xdr_buf       *buf)
+{
+       return ctx_id->mech_type->gm_ops
+               ->gss_unwrap(ctx_id, offset, buf);
+}
+
+
 /* gss_delete_sec_context: free all resources associated with context_handle.
  * Note this differs from the RFC 2744-specified prototype in that we don't
  * bother returning an output token, since it would never be used anyway. */
index 6c97d61baa9bfa3a819fa079a132eb745babd081..39b3edc146947a9c9918b3a6cbf8c0da9308dec8 100644 (file)
@@ -224,18 +224,13 @@ gss_delete_sec_context_spkm3(void *internal_ctx) {
 static u32
 gss_verify_mic_spkm3(struct gss_ctx            *ctx,
                        struct xdr_buf          *signbuf,
-                       struct xdr_netobj       *checksum,
-                       u32             *qstate) {
+                       struct xdr_netobj       *checksum)
+{
        u32 maj_stat = 0;
-       int qop_state = 0;
        struct spkm3_ctx *sctx = ctx->internal_ctx_id;
 
        dprintk("RPC: gss_verify_mic_spkm3 calling spkm3_read_token\n");
-       maj_stat = spkm3_read_token(sctx, checksum, signbuf, &qop_state,
-                                  SPKM_MIC_TOK);
-
-       if (!maj_stat && qop_state)
-           *qstate = qop_state;
+       maj_stat = spkm3_read_token(sctx, checksum, signbuf, SPKM_MIC_TOK);
 
        dprintk("RPC: gss_verify_mic_spkm3 returning %d\n", maj_stat);
        return maj_stat;
@@ -243,15 +238,15 @@ gss_verify_mic_spkm3(struct gss_ctx               *ctx,
 
 static u32
 gss_get_mic_spkm3(struct gss_ctx       *ctx,
-                    u32                qop,
                     struct xdr_buf     *message_buffer,
-                    struct xdr_netobj  *message_token) {
+                    struct xdr_netobj  *message_token)
+{
        u32 err = 0;
        struct spkm3_ctx *sctx = ctx->internal_ctx_id;
 
        dprintk("RPC: gss_get_mic_spkm3\n");
 
-       err = spkm3_make_token(sctx, qop, message_buffer,
+       err = spkm3_make_token(sctx, message_buffer,
                              message_token, SPKM_MIC_TOK);
        return err;
 }
@@ -264,8 +259,8 @@ static struct gss_api_ops gss_spkm3_ops = {
 };
 
 static struct pf_desc gss_spkm3_pfs[] = {
-       {RPC_AUTH_GSS_SPKM, 0, RPC_GSS_SVC_NONE, "spkm3"},
-       {RPC_AUTH_GSS_SPKMI, 0, RPC_GSS_SVC_INTEGRITY, "spkm3i"},
+       {RPC_AUTH_GSS_SPKM, RPC_GSS_SVC_NONE, "spkm3"},
+       {RPC_AUTH_GSS_SPKMI, RPC_GSS_SVC_INTEGRITY, "spkm3i"},
 };
 
 static struct gss_api_mech gss_spkm3_mech = {
index 25339868d4621bbccdaedc95a3647b3d9843b08d..148201e929d08de77ca44f6b6dfbe8da20ab7e04 100644 (file)
@@ -51,7 +51,7 @@
  */
 
 u32
-spkm3_make_token(struct spkm3_ctx *ctx, int qop_req,
+spkm3_make_token(struct spkm3_ctx *ctx,
                   struct xdr_buf * text, struct xdr_netobj * token,
                   int toktype)
 {
@@ -68,8 +68,6 @@ spkm3_make_token(struct spkm3_ctx *ctx, int qop_req,
        dprintk("RPC: spkm3_make_token\n");
 
        now = jiffies;
-       if (qop_req != 0)
-               goto out_err;
 
        if (ctx->ctx_id.len != 16) {
                dprintk("RPC: spkm3_make_token BAD ctx_id.len %d\n",
index 65ce81bf0bc45789d1bbda9d2d944c41ca6a95c8..c3c0d95861039958305e89f437174b8c3bc13272 100644 (file)
@@ -52,7 +52,7 @@ u32
 spkm3_read_token(struct spkm3_ctx *ctx,
                struct xdr_netobj *read_token,    /* checksum */
                struct xdr_buf *message_buffer, /* signbuf */
-               int *qop_state, int toktype)
+               int toktype)
 {
        s32                     code;
        struct xdr_netobj       wire_cksum = {.len =0, .data = NULL};
index e3308195374e635b2ea617d64fc48684c24d1241..e4ada15ed856feba1f8c26683969c56cac1958b7 100644 (file)
@@ -566,8 +566,7 @@ gss_verify_header(struct svc_rqst *rqstp, struct rsc *rsci,
 
        if (rqstp->rq_deferred) /* skip verification of revisited request */
                return SVC_OK;
-       if (gss_verify_mic(ctx_id, &rpchdr, &checksum, NULL)
-                                                       != GSS_S_COMPLETE) {
+       if (gss_verify_mic(ctx_id, &rpchdr, &checksum) != GSS_S_COMPLETE) {
                *authp = rpcsec_gsserr_credproblem;
                return SVC_DENIED;
        }
@@ -604,7 +603,7 @@ gss_write_verf(struct svc_rqst *rqstp, struct gss_ctx *ctx_id, u32 seq)
        xdr_buf_from_iov(&iov, &verf_data);
        p = rqstp->rq_res.head->iov_base + rqstp->rq_res.head->iov_len;
        mic.data = (u8 *)(p + 1);
-       maj_stat = gss_get_mic(ctx_id, 0, &verf_data, &mic);
+       maj_stat = gss_get_mic(ctx_id, &verf_data, &mic);
        if (maj_stat != GSS_S_COMPLETE)
                return -1;
        *p++ = htonl(mic.len);
@@ -710,7 +709,7 @@ unwrap_integ_data(struct xdr_buf *buf, u32 seq, struct gss_ctx *ctx)
                goto out;
        if (read_bytes_from_xdr_buf(buf, integ_len + 4, mic.data, mic.len))
                goto out;
-       maj_stat = gss_verify_mic(ctx, &integ_buf, &mic, NULL);
+       maj_stat = gss_verify_mic(ctx, &integ_buf, &mic);
        if (maj_stat != GSS_S_COMPLETE)
                goto out;
        if (ntohl(svc_getu32(&buf->head[0])) != seq)
@@ -1012,7 +1011,7 @@ svcauth_gss_release(struct svc_rqst *rqstp)
                        resv = &resbuf->tail[0];
                }
                mic.data = (u8 *)resv->iov_base + resv->iov_len + 4;
-               if (gss_get_mic(gsd->rsci->mechctx, 0, &integ_buf, &mic))
+               if (gss_get_mic(gsd->rsci->mechctx, &integ_buf, &mic))
                        goto out_err;
                svc_putu32(resv, htonl(mic.len));
                memset(mic.data + mic.len, 0,
index 9b72d3abf823bfd0fa0da0654bfd2b323c549169..f56767aaa9273678ca702758316acdd1587d9eef 100644 (file)
@@ -7,9 +7,7 @@
  */
 
 #include <linux/types.h>
-#include <linux/socket.h>
 #include <linux/module.h>
-#include <linux/in.h>
 #include <linux/utsname.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sched.h>
index 4ff297a9b15bbced0257d07071d65763e3a1ff0b..890fb5ea0dcbf29fcc9af5e56e7c8c356b09d4b4 100644 (file)
@@ -9,8 +9,6 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/module.h>
-#include <linux/socket.h>
-#include <linux/in.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/auth.h>
 
index f17e6153b688d34ae22b0df226ee74a63445c524..702ede309b067260130321a32f8e8c1779b529bf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/net/sunrpc/rpcclnt.c
+ *  linux/net/sunrpc/clnt.c
  *
  *  This file contains the high-level RPC interface.
  *  It is modeled as a finite state machine to support both synchronous
@@ -27,7 +27,6 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
-#include <linux/in.h>
 #include <linux/utsname.h>
 
 #include <linux/sunrpc/clnt.h>
@@ -53,6 +52,7 @@ static void   call_allocate(struct rpc_task *task);
 static void    call_encode(struct rpc_task *task);
 static void    call_decode(struct rpc_task *task);
 static void    call_bind(struct rpc_task *task);
+static void    call_bind_status(struct rpc_task *task);
 static void    call_transmit(struct rpc_task *task);
 static void    call_status(struct rpc_task *task);
 static void    call_refresh(struct rpc_task *task);
@@ -517,15 +517,8 @@ void
 rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize)
 {
        struct rpc_xprt *xprt = clnt->cl_xprt;
-
-       xprt->sndsize = 0;
-       if (sndsize)
-               xprt->sndsize = sndsize + RPC_SLACK_SPACE;
-       xprt->rcvsize = 0;
-       if (rcvsize)
-               xprt->rcvsize = rcvsize + RPC_SLACK_SPACE;
-       if (xprt_connected(xprt))
-               xprt_sock_setbufsize(xprt);
+       if (xprt->ops->set_buffer_size)
+               xprt->ops->set_buffer_size(xprt, sndsize, rcvsize);
 }
 
 /*
@@ -685,13 +678,11 @@ call_allocate(struct rpc_task *task)
 static void
 call_encode(struct rpc_task *task)
 {
-       struct rpc_clnt *clnt = task->tk_client;
        struct rpc_rqst *req = task->tk_rqstp;
        struct xdr_buf *sndbuf = &req->rq_snd_buf;
        struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
        unsigned int    bufsiz;
        kxdrproc_t      encode;
-       int             status;
        u32             *p;
 
        dprintk("RPC: %4d call_encode (status %d)\n", 
@@ -719,11 +710,15 @@ call_encode(struct rpc_task *task)
                rpc_exit(task, -EIO);
                return;
        }
-       if (encode && (status = rpcauth_wrap_req(task, encode, req, p,
-                                                task->tk_msg.rpc_argp)) < 0) {
-               printk(KERN_WARNING "%s: can't encode arguments: %d\n",
-                               clnt->cl_protname, -status);
-               rpc_exit(task, status);
+       if (encode == NULL)
+               return;
+
+       task->tk_status = rpcauth_wrap_req(task, encode, req, p,
+                       task->tk_msg.rpc_argp);
+       if (task->tk_status == -ENOMEM) {
+               /* XXX: Is this sane? */
+               rpc_delay(task, 3*HZ);
+               task->tk_status = -EAGAIN;
        }
 }
 
@@ -734,43 +729,95 @@ static void
 call_bind(struct rpc_task *task)
 {
        struct rpc_clnt *clnt = task->tk_client;
-       struct rpc_xprt *xprt = clnt->cl_xprt;
-
-       dprintk("RPC: %4d call_bind xprt %p %s connected\n", task->tk_pid,
-                       xprt, (xprt_connected(xprt) ? "is" : "is not"));
 
-       task->tk_action = (xprt_connected(xprt)) ? call_transmit : call_connect;
+       dprintk("RPC: %4d call_bind (status %d)\n",
+                               task->tk_pid, task->tk_status);
 
+       task->tk_action = call_connect;
        if (!clnt->cl_port) {
-               task->tk_action = call_connect;
-               task->tk_timeout = RPC_CONNECT_TIMEOUT;
+               task->tk_action = call_bind_status;
+               task->tk_timeout = task->tk_xprt->bind_timeout;
                rpc_getport(task, clnt);
        }
 }
 
 /*
- * 4a. Connect to the RPC server (TCP case)
+ * 4a. Sort out bind result
+ */
+static void
+call_bind_status(struct rpc_task *task)
+{
+       int status = -EACCES;
+
+       if (task->tk_status >= 0) {
+               dprintk("RPC: %4d call_bind_status (status %d)\n",
+                                       task->tk_pid, task->tk_status);
+               task->tk_status = 0;
+               task->tk_action = call_connect;
+               return;
+       }
+
+       switch (task->tk_status) {
+       case -EACCES:
+               dprintk("RPC: %4d remote rpcbind: RPC program/version unavailable\n",
+                               task->tk_pid);
+               rpc_delay(task, 3*HZ);
+               goto retry_bind;
+       case -ETIMEDOUT:
+               dprintk("RPC: %4d rpcbind request timed out\n",
+                               task->tk_pid);
+               if (RPC_IS_SOFT(task)) {
+                       status = -EIO;
+                       break;
+               }
+               goto retry_bind;
+       case -EPFNOSUPPORT:
+               dprintk("RPC: %4d remote rpcbind service unavailable\n",
+                               task->tk_pid);
+               break;
+       case -EPROTONOSUPPORT:
+               dprintk("RPC: %4d remote rpcbind version 2 unavailable\n",
+                               task->tk_pid);
+               break;
+       default:
+               dprintk("RPC: %4d unrecognized rpcbind error (%d)\n",
+                               task->tk_pid, -task->tk_status);
+               status = -EIO;
+               break;
+       }
+
+       rpc_exit(task, status);
+       return;
+
+retry_bind:
+       task->tk_status = 0;
+       task->tk_action = call_bind;
+       return;
+}
+
+/*
+ * 4b. Connect to the RPC server
  */
 static void
 call_connect(struct rpc_task *task)
 {
-       struct rpc_clnt *clnt = task->tk_client;
+       struct rpc_xprt *xprt = task->tk_xprt;
 
-       dprintk("RPC: %4d call_connect status %d\n",
-                               task->tk_pid, task->tk_status);
+       dprintk("RPC: %4d call_connect xprt %p %s connected\n",
+                       task->tk_pid, xprt,
+                       (xprt_connected(xprt) ? "is" : "is not"));
 
-       if (xprt_connected(clnt->cl_xprt)) {
-               task->tk_action = call_transmit;
-               return;
+       task->tk_action = call_transmit;
+       if (!xprt_connected(xprt)) {
+               task->tk_action = call_connect_status;
+               if (task->tk_status < 0)
+                       return;
+               xprt_connect(task);
        }
-       task->tk_action = call_connect_status;
-       if (task->tk_status < 0)
-               return;
-       xprt_connect(task);
 }
 
 /*
- * 4b. Sort out connect result
+ * 4c. Sort out connect result
  */
 static void
 call_connect_status(struct rpc_task *task)
@@ -778,6 +825,9 @@ call_connect_status(struct rpc_task *task)
        struct rpc_clnt *clnt = task->tk_client;
        int status = task->tk_status;
 
+       dprintk("RPC: %5u call_connect_status (status %d)\n", 
+                               task->tk_pid, task->tk_status);
+
        task->tk_status = 0;
        if (status >= 0) {
                clnt->cl_stats->netreconn++;
@@ -785,17 +835,19 @@ call_connect_status(struct rpc_task *task)
                return;
        }
 
-       /* Something failed: we may have to rebind */
+       /* Something failed: remote service port may have changed */
        if (clnt->cl_autobind)
                clnt->cl_port = 0;
+
        switch (status) {
        case -ENOTCONN:
        case -ETIMEDOUT:
        case -EAGAIN:
-               task->tk_action = (clnt->cl_port == 0) ? call_bind : call_connect;
+               task->tk_action = call_bind;
                break;
        default:
                rpc_exit(task, -EIO);
+               break;
        }
 }
 
@@ -815,10 +867,12 @@ call_transmit(struct rpc_task *task)
        if (task->tk_status != 0)
                return;
        /* Encode here so that rpcsec_gss can use correct sequence number. */
-       if (!task->tk_rqstp->rq_bytes_sent)
+       if (task->tk_rqstp->rq_bytes_sent == 0) {
                call_encode(task);
-       if (task->tk_status < 0)
-               return;
+               /* Did the encode result in an error condition? */
+               if (task->tk_status != 0)
+                       goto out_nosend;
+       }
        xprt_transmit(task);
        if (task->tk_status < 0)
                return;
@@ -826,6 +880,10 @@ call_transmit(struct rpc_task *task)
                task->tk_action = NULL;
                rpc_wake_up_task(task);
        }
+       return;
+out_nosend:
+       /* release socket write lock before attempting to handle error */
+       xprt_abort_transmit(task);
 }
 
 /*
@@ -1020,13 +1078,12 @@ static u32 *
 call_header(struct rpc_task *task)
 {
        struct rpc_clnt *clnt = task->tk_client;
-       struct rpc_xprt *xprt = clnt->cl_xprt;
        struct rpc_rqst *req = task->tk_rqstp;
        u32             *p = req->rq_svec[0].iov_base;
 
        /* FIXME: check buffer size? */
-       if (xprt->stream)
-               *p++ = 0;               /* fill in later */
+
+       p = xprt_skip_transport_header(task->tk_xprt, p);
        *p++ = req->rq_xid;             /* XID */
        *p++ = htonl(RPC_CALL);         /* CALL */
        *p++ = htonl(RPC_VERSION);      /* RPC version */
index 4e81f27669239cbf9a4ca83d7d7af2040d30317a..a398575f94b8a1dd1a9da067c597ccdd7bb24ce3 100644 (file)
@@ -26,7 +26,7 @@
 #define PMAP_GETPORT           3
 
 static struct rpc_procinfo     pmap_procedures[];
-static struct rpc_clnt *       pmap_create(char *, struct sockaddr_in *, int);
+static struct rpc_clnt *       pmap_create(char *, struct sockaddr_in *, int, int);
 static void                    pmap_getport_done(struct rpc_task *);
 static struct rpc_program      pmap_program;
 static DEFINE_SPINLOCK(pmap_lock);
@@ -65,7 +65,7 @@ rpc_getport(struct rpc_task *task, struct rpc_clnt *clnt)
        map->pm_binding = 1;
        spin_unlock(&pmap_lock);
 
-       pmap_clnt = pmap_create(clnt->cl_server, sap, map->pm_prot);
+       pmap_clnt = pmap_create(clnt->cl_server, sap, map->pm_prot, 0);
        if (IS_ERR(pmap_clnt)) {
                task->tk_status = PTR_ERR(pmap_clnt);
                goto bailout;
@@ -112,7 +112,7 @@ rpc_getport_external(struct sockaddr_in *sin, __u32 prog, __u32 vers, int prot)
                        NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
 
        sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr));
-       pmap_clnt = pmap_create(hostname, sin, prot);
+       pmap_clnt = pmap_create(hostname, sin, prot, 0);
        if (IS_ERR(pmap_clnt))
                return PTR_ERR(pmap_clnt);
 
@@ -171,7 +171,7 @@ rpc_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
 
        sin.sin_family = AF_INET;
        sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-       pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP);
+       pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP, 1);
        if (IS_ERR(pmap_clnt)) {
                error = PTR_ERR(pmap_clnt);
                dprintk("RPC: couldn't create pmap client. Error = %d\n", error);
@@ -198,7 +198,7 @@ rpc_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
 }
 
 static struct rpc_clnt *
-pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto)
+pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto, int privileged)
 {
        struct rpc_xprt *xprt;
        struct rpc_clnt *clnt;
@@ -208,6 +208,8 @@ pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto)
        if (IS_ERR(xprt))
                return (struct rpc_clnt *)xprt;
        xprt->addr.sin_port = htons(RPC_PMAP_PORT);
+       if (!privileged)
+               xprt->resvport = 0;
 
        /* printk("pmap: create clnt\n"); */
        clnt = rpc_new_client(xprt, hostname,
index ded6c63f11ec968263890ebded1f65ea31f1f674..4f188d0a5d11c2d51dd3c6b7b65a7ccd2e21d2c2 100644 (file)
@@ -76,25 +76,35 @@ int
 rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg)
 {
        struct rpc_inode *rpci = RPC_I(inode);
-       int res = 0;
+       int res = -EPIPE;
 
        down(&inode->i_sem);
+       if (rpci->ops == NULL)
+               goto out;
        if (rpci->nreaders) {
                list_add_tail(&msg->list, &rpci->pipe);
                rpci->pipelen += msg->len;
+               res = 0;
        } else if (rpci->flags & RPC_PIPE_WAIT_FOR_OPEN) {
                if (list_empty(&rpci->pipe))
                        schedule_delayed_work(&rpci->queue_timeout,
                                        RPC_UPCALL_TIMEOUT);
                list_add_tail(&msg->list, &rpci->pipe);
                rpci->pipelen += msg->len;
-       } else
-               res = -EPIPE;
+               res = 0;
+       }
+out:
        up(&inode->i_sem);
        wake_up(&rpci->waitq);
        return res;
 }
 
+static inline void
+rpc_inode_setowner(struct inode *inode, void *private)
+{
+       RPC_I(inode)->private = private;
+}
+
 static void
 rpc_close_pipes(struct inode *inode)
 {
@@ -111,15 +121,10 @@ rpc_close_pipes(struct inode *inode)
                        rpci->ops->release_pipe(inode);
                rpci->ops = NULL;
        }
+       rpc_inode_setowner(inode, NULL);
        up(&inode->i_sem);
 }
 
-static inline void
-rpc_inode_setowner(struct inode *inode, void *private)
-{
-       RPC_I(inode)->private = private;
-}
-
 static struct inode *
 rpc_alloc_inode(struct super_block *sb)
 {
@@ -501,7 +506,6 @@ repeat:
                        dentry = dvec[--n];
                        if (dentry->d_inode) {
                                rpc_close_pipes(dentry->d_inode);
-                               rpc_inode_setowner(dentry->d_inode, NULL);
                                simple_unlink(dir, dentry);
                        }
                        dput(dentry);
@@ -576,10 +580,8 @@ __rpc_rmdir(struct inode *dir, struct dentry *dentry)
        int error;
 
        shrink_dcache_parent(dentry);
-       if (dentry->d_inode) {
+       if (dentry->d_inode)
                rpc_close_pipes(dentry->d_inode);
-               rpc_inode_setowner(dentry->d_inode, NULL);
-       }
        if ((error = simple_rmdir(dir, dentry)) != 0)
                return error;
        if (!error) {
@@ -732,7 +734,6 @@ rpc_unlink(char *path)
        d_drop(dentry);
        if (dentry->d_inode) {
                rpc_close_pipes(dentry->d_inode);
-               rpc_inode_setowner(dentry->d_inode, NULL);
                error = simple_unlink(dir, dentry);
        }
        dput(dentry);
diff --git a/net/sunrpc/socklib.c b/net/sunrpc/socklib.c
new file mode 100644 (file)
index 0000000..8f97e90
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * linux/net/sunrpc/socklib.c
+ *
+ * Common socket helper routines for RPC client and server
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include <linux/types.h>
+#include <linux/pagemap.h>
+#include <linux/udp.h>
+#include <linux/sunrpc/xdr.h>
+
+
+/**
+ * skb_read_bits - copy some data bits from skb to internal buffer
+ * @desc: sk_buff copy helper
+ * @to: copy destination
+ * @len: number of bytes to copy
+ *
+ * Possibly called several times to iterate over an sk_buff and copy
+ * data out of it.
+ */
+static size_t skb_read_bits(skb_reader_t *desc, void *to, size_t len)
+{
+       if (len > desc->count)
+               len = desc->count;
+       if (skb_copy_bits(desc->skb, desc->offset, to, len))
+               return 0;
+       desc->count -= len;
+       desc->offset += len;
+       return len;
+}
+
+/**
+ * skb_read_and_csum_bits - copy and checksum from skb to buffer
+ * @desc: sk_buff copy helper
+ * @to: copy destination
+ * @len: number of bytes to copy
+ *
+ * Same as skb_read_bits, but calculate a checksum at the same time.
+ */
+static size_t skb_read_and_csum_bits(skb_reader_t *desc, void *to, size_t len)
+{
+       unsigned int    csum2, pos;
+
+       if (len > desc->count)
+               len = desc->count;
+       pos = desc->offset;
+       csum2 = skb_copy_and_csum_bits(desc->skb, pos, to, len, 0);
+       desc->csum = csum_block_add(desc->csum, csum2, pos);
+       desc->count -= len;
+       desc->offset += len;
+       return len;
+}
+
+/**
+ * xdr_partial_copy_from_skb - copy data out of an skb
+ * @xdr: target XDR buffer
+ * @base: starting offset
+ * @desc: sk_buff copy helper
+ * @copy_actor: virtual method for copying data
+ *
+ */
+ssize_t 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;
+               base = 0;
+       } else
+               base -= len;
+
+       if (unlikely(pglen == 0))
+               goto copy_tail;
+       if (unlikely(base >= pglen)) {
+               base -= pglen;
+               goto copy_tail;
+       }
+       if (base || xdr->page_base) {
+               pglen -= base;
+               base += xdr->page_base;
+               ppage += base >> PAGE_CACHE_SHIFT;
+               base &= ~PAGE_CACHE_MASK;
+       }
+       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) {
+                       len -= base;
+                       if (pglen < len)
+                               len = pglen;
+                       ret = copy_actor(desc, kaddr + base, len);
+                       base = 0;
+               } else {
+                       if (pglen < len)
+                               len = pglen;
+                       ret = copy_actor(desc, kaddr, len);
+               }
+               flush_dcache_page(*ppage);
+               kunmap_atomic(kaddr, KM_SKB_SUNRPC_DATA);
+               copied += ret;
+               if (ret != len || !desc->count)
+                       goto out;
+               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;
+}
+
+/**
+ * csum_partial_copy_to_xdr - checksum and copy data
+ * @xdr: target XDR buffer
+ * @skb: source skb
+ *
+ * We have set things up such that we perform the checksum of the UDP
+ * packet in parallel with the copies into the RPC client iovec.  -DaveM
+ */
+int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
+{
+       skb_reader_t    desc;
+
+       desc.skb = skb;
+       desc.offset = sizeof(struct udphdr);
+       desc.count = skb->len - desc.offset;
+
+       if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+               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;
+       if (desc.offset != skb->len) {
+               unsigned int csum2;
+               csum2 = skb_checksum(skb, desc.offset, skb->len - desc.offset, 0);
+               desc.csum = csum_block_add(desc.csum, csum2, desc.offset);
+       }
+       if (desc.count)
+               return -1;
+       if ((unsigned short)csum_fold(desc.csum))
+               return -1;
+       return 0;
+no_checksum:
+       if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits) < 0)
+               return -1;
+       if (desc.count)
+               return -1;
+       return 0;
+}
index ed48ff022d3529055c4a508ca86db9379052107d..2387e7b823ff8b49da0c1ddeb14db6c780e775d0 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/module.h>
 
 #include <linux/types.h>
-#include <linux/socket.h>
 #include <linux/sched.h>
 #include <linux/uio.h>
 #include <linux/unistd.h>
index 691dea4a58e757ed60e7ff739b0acac3b6bb79e7..f16e7cdd6150a811f9523ca311de6b46c47f63ef 100644 (file)
@@ -548,9 +548,6 @@ svc_write_space(struct sock *sk)
 /*
  * Receive a datagram from a UDP socket.
  */
-extern int
-csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb);
-
 static int
 svc_udp_recvfrom(struct svc_rqst *rqstp)
 {
index 1b9616a12e245405427606c494941327664e52c6..d0c9f460e411e04c2b4400c6e9e0fb33ff46f051 100644 (file)
@@ -119,8 +119,18 @@ done:
        return 0;
 }
 
+unsigned int xprt_udp_slot_table_entries = RPC_DEF_SLOT_TABLE;
+unsigned int xprt_tcp_slot_table_entries = RPC_DEF_SLOT_TABLE;
+unsigned int xprt_min_resvport = RPC_DEF_MIN_RESVPORT;
+EXPORT_SYMBOL(xprt_min_resvport);
+unsigned int xprt_max_resvport = RPC_DEF_MAX_RESVPORT;
+EXPORT_SYMBOL(xprt_max_resvport);
+
+
 static unsigned int min_slot_table_size = RPC_MIN_SLOT_TABLE;
 static unsigned int max_slot_table_size = RPC_MAX_SLOT_TABLE;
+static unsigned int xprt_min_resvport_limit = RPC_MIN_RESVPORT;
+static unsigned int xprt_max_resvport_limit = RPC_MAX_RESVPORT;
 
 static ctl_table debug_table[] = {
        {
@@ -177,6 +187,28 @@ static ctl_table debug_table[] = {
                .extra1         = &min_slot_table_size,
                .extra2         = &max_slot_table_size
        },
+       {
+               .ctl_name       = CTL_MIN_RESVPORT,
+               .procname       = "min_resvport",
+               .data           = &xprt_min_resvport,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_minmax,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &xprt_min_resvport_limit,
+               .extra2         = &xprt_max_resvport_limit
+       },
+       {
+               .ctl_name       = CTL_MAX_RESVPORT,
+               .procname       = "max_resvport",
+               .data           = &xprt_max_resvport,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_minmax,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &xprt_min_resvport_limit,
+               .extra2         = &xprt_max_resvport_limit
+       },
        { .ctl_name = 0 }
 };
 
index fde16f40a581dfb64e725e694afb4df5090693ed..32df43372ee97cc277ed54d058f77667c8985160 100644 (file)
@@ -6,15 +6,12 @@
  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
  */
 
+#include <linux/module.h>
 #include <linux/types.h>
-#include <linux/socket.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/pagemap.h>
 #include <linux/errno.h>
-#include <linux/in.h>
-#include <linux/net.h>
-#include <net/sock.h>
 #include <linux/sunrpc/xdr.h>
 #include <linux/sunrpc/msg_prot.h>
 
@@ -176,178 +173,6 @@ xdr_inline_pages(struct xdr_buf *xdr, unsigned int offset,
        xdr->buflen += len;
 }
 
-ssize_t
-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;
-               base = 0;
-       } else
-               base -= len;
-
-       if (pglen == 0)
-               goto copy_tail;
-       if (base >= pglen) {
-               base -= pglen;
-               goto copy_tail;
-       }
-       if (base || xdr->page_base) {
-               pglen -= base;
-               base  += xdr->page_base;
-               ppage += base >> PAGE_CACHE_SHIFT;
-               base &= ~PAGE_CACHE_MASK;
-       }
-       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) {
-                       len -= base;
-                       if (pglen < len)
-                               len = pglen;
-                       ret = copy_actor(desc, kaddr + base, len);
-                       base = 0;
-               } else {
-                       if (pglen < len)
-                               len = pglen;
-                       ret = copy_actor(desc, kaddr, len);
-               }
-               flush_dcache_page(*ppage);
-               kunmap_atomic(kaddr, KM_SKB_SUNRPC_DATA);
-               copied += ret;
-               if (ret != len || !desc->count)
-                       goto out;
-               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;
-}
-
-
-int
-xdr_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
-               struct xdr_buf *xdr, unsigned int base, int msgflags)
-{
-       struct page **ppage = xdr->pages;
-       unsigned int len, pglen = xdr->page_len;
-       int err, ret = 0;
-       ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
-
-       len = xdr->head[0].iov_len;
-       if (base < len || (addr != NULL && base == 0)) {
-               struct kvec iov = {
-                       .iov_base = xdr->head[0].iov_base + base,
-                       .iov_len  = len - base,
-               };
-               struct msghdr msg = {
-                       .msg_name    = addr,
-                       .msg_namelen = addrlen,
-                       .msg_flags   = msgflags,
-               };
-               if (xdr->len > len)
-                       msg.msg_flags |= MSG_MORE;
-
-               if (iov.iov_len != 0)
-                       err = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
-               else
-                       err = kernel_sendmsg(sock, &msg, NULL, 0, 0);
-               if (ret == 0)
-                       ret = err;
-               else if (err > 0)
-                       ret += err;
-               if (err != iov.iov_len)
-                       goto out;
-               base = 0;
-       } else
-               base -= len;
-
-       if (pglen == 0)
-               goto copy_tail;
-       if (base >= pglen) {
-               base -= pglen;
-               goto copy_tail;
-       }
-       if (base || xdr->page_base) {
-               pglen -= base;
-               base  += xdr->page_base;
-               ppage += base >> PAGE_CACHE_SHIFT;
-               base &= ~PAGE_CACHE_MASK;
-       }
-
-       sendpage = sock->ops->sendpage ? : sock_no_sendpage;
-       do {
-               int flags = msgflags;
-
-               len = PAGE_CACHE_SIZE;
-               if (base)
-                       len -= base;
-               if (pglen < len)
-                       len = pglen;
-
-               if (pglen != len || xdr->tail[0].iov_len != 0)
-                       flags |= MSG_MORE;
-
-               /* Hmm... We might be dealing with highmem pages */
-               if (PageHighMem(*ppage))
-                       sendpage = sock_no_sendpage;
-               err = sendpage(sock, *ppage, base, len, flags);
-               if (ret == 0)
-                       ret = err;
-               else if (err > 0)
-                       ret += err;
-               if (err != len)
-                       goto out;
-               base = 0;
-               ppage++;
-       } while ((pglen -= len) != 0);
-copy_tail:
-       len = xdr->tail[0].iov_len;
-       if (base < len) {
-               struct kvec iov = {
-                       .iov_base = xdr->tail[0].iov_base + base,
-                       .iov_len  = len - base,
-               };
-               struct msghdr msg = {
-                       .msg_flags   = msgflags,
-               };
-               err = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
-               if (ret == 0)
-                       ret = err;
-               else if (err > 0)
-                       ret += err;
-       }
-out:
-       return ret;
-}
-
 
 /*
  * Helper routines for doing 'memmove' like operations on a struct xdr_buf
index 3c654e06b08455477185df8b20f48f8bc4928f12..6dda3860351fb1502f5ee12d0cc7e00e7aebb060 100644 (file)
  *     one is available. Otherwise, it sleeps on the backlog queue
  *     (xprt_reserve).
  *  -  Next, the caller puts together the RPC message, stuffs it into
- *     the request struct, and calls xprt_call().
- *  -  xprt_call transmits the message and installs the caller on the
- *     socket's wait list. At the same time, it installs a timer that
+ *     the request struct, and calls xprt_transmit().
+ *  -  xprt_transmit sends the message and installs the caller on the
+ *     transport's wait list. At the same time, it installs a timer that
  *     is run after the packet's timeout has expired.
  *  -  When a packet arrives, the data_ready handler walks the list of
- *     pending requests for that socket. If a matching XID is found, the
+ *     pending requests for that transport. If a matching XID is found, the
  *     caller is woken up, and the timer removed.
  *  -  When no reply arrives within the timeout interval, the timer is
  *     fired by the kernel and runs xprt_timer(). It either adjusts the
  *
  *  Copyright (C) 1995-1997, Olaf Kirch <okir@monad.swb.de>
  *
- *  TCP callback races fixes (C) 1998 Red Hat Software <alan@redhat.com>
- *  TCP send fixes (C) 1998 Red Hat Software <alan@redhat.com>
- *  TCP NFS related read + write fixes
- *   (C) 1999 Dave Airlie, University of Limerick, Ireland <airlied@linux.ie>
- *
- *  Rewrite of larges part of the code in order to stabilize TCP stuff.
- *  Fix behaviour when socket buffer is full.
- *   (C) 1999 Trond Myklebust <trond.myklebust@fys.uio.no>
+ *  Transport switch API copyright (C) 2005, Chuck Lever <cel@netapp.com>
  */
 
+#include <linux/module.h>
+
 #include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/capability.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/net.h>
-#include <linux/mm.h>
-#include <linux/udp.h>
-#include <linux/tcp.h>
-#include <linux/sunrpc/clnt.h>
-#include <linux/file.h>
+#include <linux/interrupt.h>
 #include <linux/workqueue.h>
 #include <linux/random.h>
 
-#include <net/sock.h>
-#include <net/checksum.h>
-#include <net/udp.h>
-#include <net/tcp.h>
+#include <linux/sunrpc/clnt.h>
 
 /*
  * Local variables
 # define RPCDBG_FACILITY       RPCDBG_XPRT
 #endif
 
-#define XPRT_MAX_BACKOFF       (8)
-#define XPRT_IDLE_TIMEOUT      (5*60*HZ)
-#define XPRT_MAX_RESVPORT      (800)
-
 /*
  * Local functions
  */
 static void    xprt_request_init(struct rpc_task *, struct rpc_xprt *);
 static inline void     do_xprt_reserve(struct rpc_task *);
-static void    xprt_disconnect(struct rpc_xprt *);
 static void    xprt_connect_status(struct rpc_task *task);
-static struct rpc_xprt * xprt_setup(int proto, struct sockaddr_in *ap,
-                                               struct rpc_timeout *to);
-static struct socket *xprt_create_socket(struct rpc_xprt *, int, int);
-static void    xprt_bind_socket(struct rpc_xprt *, struct socket *);
 static int      __xprt_get_cong(struct rpc_xprt *, struct rpc_task *);
 
-static int     xprt_clear_backlog(struct rpc_xprt *xprt);
-
-#ifdef RPC_DEBUG_DATA
 /*
- * Print the buffer contents (first 128 bytes only--just enough for
- * diropres return).
+ * The transport code maintains an estimate on the maximum number of out-
+ * standing RPC requests, using a smoothed version of the congestion
+ * avoidance implemented in 44BSD. This is basically the Van Jacobson
+ * congestion algorithm: If a retransmit occurs, the congestion window is
+ * halved; otherwise, it is incremented by 1/cwnd when
+ *
+ *     -       a reply is received and
+ *     -       a full number of requests are outstanding and
+ *     -       the congestion window hasn't been updated recently.
  */
-static void
-xprt_pktdump(char *msg, u32 *packet, unsigned int count)
-{
-       u8      *buf = (u8 *) packet;
-       int     j;
-
-       dprintk("RPC:      %s\n", msg);
-       for (j = 0; j < count && j < 128; j += 4) {
-               if (!(j & 31)) {
-                       if (j)
-                               dprintk("\n");
-                       dprintk("0x%04x ", j);
-               }
-               dprintk("%02x%02x%02x%02x ",
-                       buf[j], buf[j+1], buf[j+2], buf[j+3]);
-       }
-       dprintk("\n");
-}
-#else
-static inline void
-xprt_pktdump(char *msg, u32 *packet, unsigned int count)
-{
-       /* NOP */
-}
-#endif
+#define RPC_CWNDSHIFT          (8U)
+#define RPC_CWNDSCALE          (1U << RPC_CWNDSHIFT)
+#define RPC_INITCWND           RPC_CWNDSCALE
+#define RPC_MAXCWND(xprt)      ((xprt)->max_reqs << RPC_CWNDSHIFT)
 
-/*
- * Look up RPC transport given an INET socket
+#define RPCXPRT_CONGESTED(xprt) ((xprt)->cong >= (xprt)->cwnd)
+
+/**
+ * xprt_reserve_xprt - serialize write access to transports
+ * @task: task that is requesting access to the transport
+ *
+ * This prevents mixing the payload of separate requests, and prevents
+ * transport connects from colliding with writes.  No congestion control
+ * is provided.
  */
-static inline struct rpc_xprt *
-xprt_from_sock(struct sock *sk)
+int xprt_reserve_xprt(struct rpc_task *task)
 {
-       return (struct rpc_xprt *) sk->sk_user_data;
+       struct rpc_xprt *xprt = task->tk_xprt;
+       struct rpc_rqst *req = task->tk_rqstp;
+
+       if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) {
+               if (task == xprt->snd_task)
+                       return 1;
+               if (task == NULL)
+                       return 0;
+               goto out_sleep;
+       }
+       xprt->snd_task = task;
+       if (req) {
+               req->rq_bytes_sent = 0;
+               req->rq_ntrans++;
+       }
+       return 1;
+
+out_sleep:
+       dprintk("RPC: %4d failed to lock transport %p\n",
+                       task->tk_pid, xprt);
+       task->tk_timeout = 0;
+       task->tk_status = -EAGAIN;
+       if (req && req->rq_ntrans)
+               rpc_sleep_on(&xprt->resend, task, NULL, NULL);
+       else
+               rpc_sleep_on(&xprt->sending, task, NULL, NULL);
+       return 0;
 }
 
 /*
- * Serialize write access to sockets, in order to prevent different
- * requests from interfering with each other.
- * Also prevents TCP socket connects from colliding with writes.
+ * xprt_reserve_xprt_cong - serialize write access to transports
+ * @task: task that is requesting access to the transport
+ *
+ * Same as xprt_reserve_xprt, but Van Jacobson congestion control is
+ * integrated into the decision of whether a request is allowed to be
+ * woken up and given access to the transport.
  */
-static int
-__xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
+int xprt_reserve_xprt_cong(struct rpc_task *task)
 {
+       struct rpc_xprt *xprt = task->tk_xprt;
        struct rpc_rqst *req = task->tk_rqstp;
 
-       if (test_and_set_bit(XPRT_LOCKED, &xprt->sockstate)) {
+       if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) {
                if (task == xprt->snd_task)
                        return 1;
                goto out_sleep;
        }
-       if (xprt->nocong || __xprt_get_cong(xprt, task)) {
+       if (__xprt_get_cong(xprt, task)) {
                xprt->snd_task = task;
                if (req) {
                        req->rq_bytes_sent = 0;
@@ -156,10 +146,10 @@ __xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
                return 1;
        }
        smp_mb__before_clear_bit();
-       clear_bit(XPRT_LOCKED, &xprt->sockstate);
+       clear_bit(XPRT_LOCKED, &xprt->state);
        smp_mb__after_clear_bit();
 out_sleep:
-       dprintk("RPC: %4d failed to lock socket %p\n", task->tk_pid, xprt);
+       dprintk("RPC: %4d failed to lock transport %p\n", task->tk_pid, xprt);
        task->tk_timeout = 0;
        task->tk_status = -EAGAIN;
        if (req && req->rq_ntrans)
@@ -169,26 +159,52 @@ out_sleep:
        return 0;
 }
 
-static inline int
-xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
+static inline int xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
 {
        int retval;
 
-       spin_lock_bh(&xprt->sock_lock);
-       retval = __xprt_lock_write(xprt, task);
-       spin_unlock_bh(&xprt->sock_lock);
+       spin_lock_bh(&xprt->transport_lock);
+       retval = xprt->ops->reserve_xprt(task);
+       spin_unlock_bh(&xprt->transport_lock);
        return retval;
 }
 
+static void __xprt_lock_write_next(struct rpc_xprt *xprt)
+{
+       struct rpc_task *task;
+       struct rpc_rqst *req;
 
-static void
-__xprt_lock_write_next(struct rpc_xprt *xprt)
+       if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
+               return;
+
+       task = rpc_wake_up_next(&xprt->resend);
+       if (!task) {
+               task = rpc_wake_up_next(&xprt->sending);
+               if (!task)
+                       goto out_unlock;
+       }
+
+       req = task->tk_rqstp;
+       xprt->snd_task = task;
+       if (req) {
+               req->rq_bytes_sent = 0;
+               req->rq_ntrans++;
+       }
+       return;
+
+out_unlock:
+       smp_mb__before_clear_bit();
+       clear_bit(XPRT_LOCKED, &xprt->state);
+       smp_mb__after_clear_bit();
+}
+
+static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt)
 {
        struct rpc_task *task;
 
-       if (test_and_set_bit(XPRT_LOCKED, &xprt->sockstate))
+       if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
                return;
-       if (!xprt->nocong && RPCXPRT_CONGESTED(xprt))
+       if (RPCXPRT_CONGESTED(xprt))
                goto out_unlock;
        task = rpc_wake_up_next(&xprt->resend);
        if (!task) {
@@ -196,7 +212,7 @@ __xprt_lock_write_next(struct rpc_xprt *xprt)
                if (!task)
                        goto out_unlock;
        }
-       if (xprt->nocong || __xprt_get_cong(xprt, task)) {
+       if (__xprt_get_cong(xprt, task)) {
                struct rpc_rqst *req = task->tk_rqstp;
                xprt->snd_task = task;
                if (req) {
@@ -207,87 +223,52 @@ __xprt_lock_write_next(struct rpc_xprt *xprt)
        }
 out_unlock:
        smp_mb__before_clear_bit();
-       clear_bit(XPRT_LOCKED, &xprt->sockstate);
+       clear_bit(XPRT_LOCKED, &xprt->state);
        smp_mb__after_clear_bit();
 }
 
-/*
- * Releases the socket for use by other requests.
+/**
+ * xprt_release_xprt - allow other requests to use a transport
+ * @xprt: transport with other tasks potentially waiting
+ * @task: task that is releasing access to the transport
+ *
+ * Note that "task" can be NULL.  No congestion control is provided.
  */
-static void
-__xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task)
+void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task)
 {
        if (xprt->snd_task == task) {
                xprt->snd_task = NULL;
                smp_mb__before_clear_bit();
-               clear_bit(XPRT_LOCKED, &xprt->sockstate);
+               clear_bit(XPRT_LOCKED, &xprt->state);
                smp_mb__after_clear_bit();
                __xprt_lock_write_next(xprt);
        }
 }
 
-static inline void
-xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task)
-{
-       spin_lock_bh(&xprt->sock_lock);
-       __xprt_release_write(xprt, task);
-       spin_unlock_bh(&xprt->sock_lock);
-}
-
-/*
- * Write data to socket.
+/**
+ * xprt_release_xprt_cong - allow other requests to use a transport
+ * @xprt: transport with other tasks potentially waiting
+ * @task: task that is releasing access to the transport
+ *
+ * Note that "task" can be NULL.  Another task is awoken to use the
+ * transport if the transport's congestion window allows it.
  */
-static inline int
-xprt_sendmsg(struct rpc_xprt *xprt, struct rpc_rqst *req)
+void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task)
 {
-       struct socket   *sock = xprt->sock;
-       struct xdr_buf  *xdr = &req->rq_snd_buf;
-       struct sockaddr *addr = NULL;
-       int addrlen = 0;
-       unsigned int    skip;
-       int             result;
-
-       if (!sock)
-               return -ENOTCONN;
-
-       xprt_pktdump("packet data:",
-                               req->rq_svec->iov_base,
-                               req->rq_svec->iov_len);
-
-       /* For UDP, we need to provide an address */
-       if (!xprt->stream) {
-               addr = (struct sockaddr *) &xprt->addr;
-               addrlen = sizeof(xprt->addr);
+       if (xprt->snd_task == task) {
+               xprt->snd_task = NULL;
+               smp_mb__before_clear_bit();
+               clear_bit(XPRT_LOCKED, &xprt->state);
+               smp_mb__after_clear_bit();
+               __xprt_lock_write_next_cong(xprt);
        }
-       /* Dont repeat bytes */
-       skip = req->rq_bytes_sent;
-
-       clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
-       result = xdr_sendpages(sock, addr, addrlen, xdr, skip, MSG_DONTWAIT);
-
-       dprintk("RPC:      xprt_sendmsg(%d) = %d\n", xdr->len - skip, result);
-
-       if (result >= 0)
-               return result;
+}
 
-       switch (result) {
-       case -ECONNREFUSED:
-               /* When the server has died, an ICMP port unreachable message
-                * prompts ECONNREFUSED.
-                */
-       case -EAGAIN:
-               break;
-       case -ECONNRESET:
-       case -ENOTCONN:
-       case -EPIPE:
-               /* connection broken */
-               if (xprt->stream)
-                       result = -ENOTCONN;
-               break;
-       default:
-               printk(KERN_NOTICE "RPC: sendmsg returned error %d\n", -result);
-       }
-       return result;
+static inline void xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task)
+{
+       spin_lock_bh(&xprt->transport_lock);
+       xprt->ops->release_xprt(xprt, task);
+       spin_unlock_bh(&xprt->transport_lock);
 }
 
 /*
@@ -321,26 +302,40 @@ __xprt_put_cong(struct rpc_xprt *xprt, struct rpc_rqst *req)
                return;
        req->rq_cong = 0;
        xprt->cong -= RPC_CWNDSCALE;
-       __xprt_lock_write_next(xprt);
+       __xprt_lock_write_next_cong(xprt);
 }
 
-/*
- * Adjust RPC congestion window
+/**
+ * xprt_release_rqst_cong - housekeeping when request is complete
+ * @task: RPC request that recently completed
+ *
+ * Useful for transports that require congestion control.
+ */
+void xprt_release_rqst_cong(struct rpc_task *task)
+{
+       __xprt_put_cong(task->tk_xprt, task->tk_rqstp);
+}
+
+/**
+ * xprt_adjust_cwnd - adjust transport congestion window
+ * @task: recently completed RPC request used to adjust window
+ * @result: result code of completed RPC request
+ *
  * We use a time-smoothed congestion estimator to avoid heavy oscillation.
  */
-static void
-xprt_adjust_cwnd(struct rpc_xprt *xprt, int result)
+void xprt_adjust_cwnd(struct rpc_task *task, int result)
 {
-       unsigned long   cwnd;
+       struct rpc_rqst *req = task->tk_rqstp;
+       struct rpc_xprt *xprt = task->tk_xprt;
+       unsigned long cwnd = xprt->cwnd;
 
-       cwnd = xprt->cwnd;
        if (result >= 0 && cwnd <= xprt->cong) {
                /* The (cwnd >> 1) term makes sure
                 * the result gets rounded properly. */
                cwnd += (RPC_CWNDSCALE * RPC_CWNDSCALE + (cwnd >> 1)) / cwnd;
                if (cwnd > RPC_MAXCWND(xprt))
                        cwnd = RPC_MAXCWND(xprt);
-               __xprt_lock_write_next(xprt);
+               __xprt_lock_write_next_cong(xprt);
        } else if (result == -ETIMEDOUT) {
                cwnd >>= 1;
                if (cwnd < RPC_CWNDSCALE)
@@ -349,11 +344,89 @@ xprt_adjust_cwnd(struct rpc_xprt *xprt, int result)
        dprintk("RPC:      cong %ld, cwnd was %ld, now %ld\n",
                        xprt->cong, xprt->cwnd, cwnd);
        xprt->cwnd = cwnd;
+       __xprt_put_cong(xprt, req);
+}
+
+/**
+ * xprt_wake_pending_tasks - wake all tasks on a transport's pending queue
+ * @xprt: transport with waiting tasks
+ * @status: result code to plant in each task before waking it
+ *
+ */
+void xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status)
+{
+       if (status < 0)
+               rpc_wake_up_status(&xprt->pending, status);
+       else
+               rpc_wake_up(&xprt->pending);
+}
+
+/**
+ * xprt_wait_for_buffer_space - wait for transport output buffer to clear
+ * @task: task to be put to sleep
+ *
+ */
+void xprt_wait_for_buffer_space(struct rpc_task *task)
+{
+       struct rpc_rqst *req = task->tk_rqstp;
+       struct rpc_xprt *xprt = req->rq_xprt;
+
+       task->tk_timeout = req->rq_timeout;
+       rpc_sleep_on(&xprt->pending, task, NULL, NULL);
+}
+
+/**
+ * xprt_write_space - wake the task waiting for transport output buffer space
+ * @xprt: transport with waiting tasks
+ *
+ * Can be called in a soft IRQ context, so xprt_write_space never sleeps.
+ */
+void xprt_write_space(struct rpc_xprt *xprt)
+{
+       if (unlikely(xprt->shutdown))
+               return;
+
+       spin_lock_bh(&xprt->transport_lock);
+       if (xprt->snd_task) {
+               dprintk("RPC:      write space: waking waiting task on xprt %p\n",
+                               xprt);
+               rpc_wake_up_task(xprt->snd_task);
+       }
+       spin_unlock_bh(&xprt->transport_lock);
+}
+
+/**
+ * xprt_set_retrans_timeout_def - set a request's retransmit timeout
+ * @task: task whose timeout is to be set
+ *
+ * Set a request's retransmit timeout based on the transport's
+ * default timeout parameters.  Used by transports that don't adjust
+ * the retransmit timeout based on round-trip time estimation.
+ */
+void xprt_set_retrans_timeout_def(struct rpc_task *task)
+{
+       task->tk_timeout = task->tk_rqstp->rq_timeout;
 }
 
 /*
- * Reset the major timeout value
+ * xprt_set_retrans_timeout_rtt - set a request's retransmit timeout
+ * @task: task whose timeout is to be set
+ * 
+ * Set a request's retransmit timeout using the RTT estimator.
  */
+void xprt_set_retrans_timeout_rtt(struct rpc_task *task)
+{
+       int timer = task->tk_msg.rpc_proc->p_timer;
+       struct rpc_rtt *rtt = task->tk_client->cl_rtt;
+       struct rpc_rqst *req = task->tk_rqstp;
+       unsigned long max_timeout = req->rq_xprt->timeout.to_maxval;
+
+       task->tk_timeout = rpc_calc_rto(rtt, timer);
+       task->tk_timeout <<= rpc_ntimeo(rtt, timer) + req->rq_retries;
+       if (task->tk_timeout > max_timeout || task->tk_timeout == 0)
+               task->tk_timeout = max_timeout;
+}
+
 static void xprt_reset_majortimeo(struct rpc_rqst *req)
 {
        struct rpc_timeout *to = &req->rq_xprt->timeout;
@@ -368,8 +441,10 @@ static void xprt_reset_majortimeo(struct rpc_rqst *req)
        req->rq_majortimeo += jiffies;
 }
 
-/*
- * Adjust timeout values etc for next retransmit
+/**
+ * xprt_adjust_timeout - adjust timeout values for next retransmit
+ * @req: RPC request containing parameters to use for the adjustment
+ *
  */
 int xprt_adjust_timeout(struct rpc_rqst *req)
 {
@@ -391,9 +466,9 @@ int xprt_adjust_timeout(struct rpc_rqst *req)
                req->rq_retries = 0;
                xprt_reset_majortimeo(req);
                /* Reset the RTT counters == "slow start" */
-               spin_lock_bh(&xprt->sock_lock);
+               spin_lock_bh(&xprt->transport_lock);
                rpc_init_rtt(req->rq_task->tk_client->cl_rtt, to->to_initval);
-               spin_unlock_bh(&xprt->sock_lock);
+               spin_unlock_bh(&xprt->transport_lock);
                pprintk("RPC: %lu timeout\n", jiffies);
                status = -ETIMEDOUT;
        }
@@ -405,133 +480,52 @@ int xprt_adjust_timeout(struct rpc_rqst *req)
        return status;
 }
 
-/*
- * Close down a transport socket
- */
-static void
-xprt_close(struct rpc_xprt *xprt)
-{
-       struct socket   *sock = xprt->sock;
-       struct sock     *sk = xprt->inet;
-
-       if (!sk)
-               return;
-
-       write_lock_bh(&sk->sk_callback_lock);
-       xprt->inet = NULL;
-       xprt->sock = NULL;
-
-       sk->sk_user_data    = NULL;
-       sk->sk_data_ready   = xprt->old_data_ready;
-       sk->sk_state_change = xprt->old_state_change;
-       sk->sk_write_space  = xprt->old_write_space;
-       write_unlock_bh(&sk->sk_callback_lock);
-
-       sk->sk_no_check  = 0;
-
-       sock_release(sock);
-}
-
-static void
-xprt_socket_autoclose(void *args)
+static void xprt_autoclose(void *args)
 {
        struct rpc_xprt *xprt = (struct rpc_xprt *)args;
 
        xprt_disconnect(xprt);
-       xprt_close(xprt);
+       xprt->ops->close(xprt);
        xprt_release_write(xprt, NULL);
 }
 
-/*
- * Mark a transport as disconnected
+/**
+ * xprt_disconnect - mark a transport as disconnected
+ * @xprt: transport to flag for disconnect
+ *
  */
-static void
-xprt_disconnect(struct rpc_xprt *xprt)
+void xprt_disconnect(struct rpc_xprt *xprt)
 {
        dprintk("RPC:      disconnected transport %p\n", xprt);
-       spin_lock_bh(&xprt->sock_lock);
+       spin_lock_bh(&xprt->transport_lock);
        xprt_clear_connected(xprt);
-       rpc_wake_up_status(&xprt->pending, -ENOTCONN);
-       spin_unlock_bh(&xprt->sock_lock);
+       xprt_wake_pending_tasks(xprt, -ENOTCONN);
+       spin_unlock_bh(&xprt->transport_lock);
 }
 
-/*
- * Used to allow disconnection when we've been idle
- */
 static void
 xprt_init_autodisconnect(unsigned long data)
 {
        struct rpc_xprt *xprt = (struct rpc_xprt *)data;
 
-       spin_lock(&xprt->sock_lock);
+       spin_lock(&xprt->transport_lock);
        if (!list_empty(&xprt->recv) || xprt->shutdown)
                goto out_abort;
-       if (test_and_set_bit(XPRT_LOCKED, &xprt->sockstate))
+       if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
                goto out_abort;
-       spin_unlock(&xprt->sock_lock);
-       /* Let keventd close the socket */
-       if (test_bit(XPRT_CONNECTING, &xprt->sockstate) != 0)
+       spin_unlock(&xprt->transport_lock);
+       if (xprt_connecting(xprt))
                xprt_release_write(xprt, NULL);
        else
                schedule_work(&xprt->task_cleanup);
        return;
 out_abort:
-       spin_unlock(&xprt->sock_lock);
-}
-
-static void xprt_socket_connect(void *args)
-{
-       struct rpc_xprt *xprt = (struct rpc_xprt *)args;
-       struct socket *sock = xprt->sock;
-       int status = -EIO;
-
-       if (xprt->shutdown || xprt->addr.sin_port == 0)
-               goto out;
-
-       /*
-        * Start by resetting any existing state
-        */
-       xprt_close(xprt);
-       sock = xprt_create_socket(xprt, xprt->prot, xprt->resvport);
-       if (sock == NULL) {
-               /* couldn't create socket or bind to reserved port;
-                * this is likely a permanent error, so cause an abort */
-               goto out;
-       }
-       xprt_bind_socket(xprt, sock);
-       xprt_sock_setbufsize(xprt);
-
-       status = 0;
-       if (!xprt->stream)
-               goto out;
-
-       /*
-        * Tell the socket layer to start connecting...
-        */
-       status = sock->ops->connect(sock, (struct sockaddr *) &xprt->addr,
-                       sizeof(xprt->addr), O_NONBLOCK);
-       dprintk("RPC: %p  connect status %d connected %d sock state %d\n",
-                       xprt, -status, xprt_connected(xprt), sock->sk->sk_state);
-       if (status < 0) {
-               switch (status) {
-                       case -EINPROGRESS:
-                       case -EALREADY:
-                               goto out_clear;
-               }
-       }
-out:
-       if (status < 0)
-               rpc_wake_up_status(&xprt->pending, status);
-       else
-               rpc_wake_up(&xprt->pending);
-out_clear:
-       smp_mb__before_clear_bit();
-       clear_bit(XPRT_CONNECTING, &xprt->sockstate);
-       smp_mb__after_clear_bit();
+       spin_unlock(&xprt->transport_lock);
 }
 
-/*
- * Attempt to connect a TCP socket.
+/**
+ * xprt_connect - schedule a transport connect operation
+ * @task: RPC task that is requesting the connect
  *
  */
 void xprt_connect(struct rpc_task *task)
@@ -552,37 +546,19 @@ void xprt_connect(struct rpc_task *task)
        if (!xprt_lock_write(xprt, task))
                return;
        if (xprt_connected(xprt))
-               goto out_write;
+               xprt_release_write(xprt, task);
+       else {
+               if (task->tk_rqstp)
+                       task->tk_rqstp->rq_bytes_sent = 0;
 
-       if (task->tk_rqstp)
-               task->tk_rqstp->rq_bytes_sent = 0;
-
-       task->tk_timeout = RPC_CONNECT_TIMEOUT;
-       rpc_sleep_on(&xprt->pending, task, xprt_connect_status, NULL);
-       if (!test_and_set_bit(XPRT_CONNECTING, &xprt->sockstate)) {
-               /* Note: if we are here due to a dropped connection
-                *       we delay reconnecting by RPC_REESTABLISH_TIMEOUT/HZ
-                *       seconds
-                */
-               if (xprt->sock != NULL)
-                       schedule_delayed_work(&xprt->sock_connect,
-                                       RPC_REESTABLISH_TIMEOUT);
-               else {
-                       schedule_work(&xprt->sock_connect);
-                       if (!RPC_IS_ASYNC(task))
-                               flush_scheduled_work();
-               }
+               task->tk_timeout = xprt->connect_timeout;
+               rpc_sleep_on(&xprt->pending, task, xprt_connect_status, NULL);
+               xprt->ops->connect(task);
        }
        return;
- out_write:
-       xprt_release_write(xprt, task);
 }
 
-/*
- * We arrive here when awoken from waiting on connection establishment.
- */
-static void
-xprt_connect_status(struct rpc_task *task)
+static void xprt_connect_status(struct rpc_task *task)
 {
        struct rpc_xprt *xprt = task->tk_xprt;
 
@@ -592,31 +568,42 @@ xprt_connect_status(struct rpc_task *task)
                return;
        }
 
-       /* if soft mounted, just cause this RPC to fail */
-       if (RPC_IS_SOFT(task))
-               task->tk_status = -EIO;
-
        switch (task->tk_status) {
        case -ECONNREFUSED:
        case -ECONNRESET:
+               dprintk("RPC: %4d xprt_connect_status: server %s refused connection\n",
+                               task->tk_pid, task->tk_client->cl_server);
+               break;
        case -ENOTCONN:
-               return;
+               dprintk("RPC: %4d xprt_connect_status: connection broken\n",
+                               task->tk_pid);
+               break;
        case -ETIMEDOUT:
-               dprintk("RPC: %4d xprt_connect_status: timed out\n",
+               dprintk("RPC: %4d xprt_connect_status: connect attempt timed out\n",
                                task->tk_pid);
                break;
        default:
-               printk(KERN_ERR "RPC: error %d connecting to server %s\n",
-                               -task->tk_status, task->tk_client->cl_server);
+               dprintk("RPC: %4d xprt_connect_status: error %d connecting to server %s\n",
+                               task->tk_pid, -task->tk_status, task->tk_client->cl_server);
+               xprt_release_write(xprt, task);
+               task->tk_status = -EIO;
+               return;
+       }
+
+       /* if soft mounted, just cause this RPC to fail */
+       if (RPC_IS_SOFT(task)) {
+               xprt_release_write(xprt, task);
+               task->tk_status = -EIO;
        }
-       xprt_release_write(xprt, task);
 }
 
-/*
- * Look up the RPC request corresponding to a reply, and then lock it.
+/**
+ * xprt_lookup_rqst - find an RPC request corresponding to an XID
+ * @xprt: transport on which the original request was transmitted
+ * @xid: RPC XID of incoming reply
+ *
  */
-static inline struct rpc_rqst *
-xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid)
+struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid)
 {
        struct list_head *pos;
        struct rpc_rqst *req = NULL;
@@ -631,556 +618,68 @@ xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid)
        return req;
 }
 
-/*
- * Complete reply received.
- * The TCP code relies on us to remove the request from xprt->pending.
- */
-static void
-xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied)
-{
-       struct rpc_task *task = req->rq_task;
-       struct rpc_clnt *clnt = task->tk_client;
-
-       /* Adjust congestion window */
-       if (!xprt->nocong) {
-               unsigned timer = task->tk_msg.rpc_proc->p_timer;
-               xprt_adjust_cwnd(xprt, copied);
-               __xprt_put_cong(xprt, req);
-               if (timer) {
-                       if (req->rq_ntrans == 1)
-                               rpc_update_rtt(clnt->cl_rtt, timer,
-                                               (long)jiffies - req->rq_xtime);
-                       rpc_set_timeo(clnt->cl_rtt, timer, req->rq_ntrans - 1);
-               }
-       }
-
-#ifdef RPC_PROFILE
-       /* Profile only reads for now */
-       if (copied > 1024) {
-               static unsigned long    nextstat;
-               static unsigned long    pkt_rtt, pkt_len, pkt_cnt;
-
-               pkt_cnt++;
-               pkt_len += req->rq_slen + copied;
-               pkt_rtt += jiffies - req->rq_xtime;
-               if (time_before(nextstat, jiffies)) {
-                       printk("RPC: %lu %ld cwnd\n", jiffies, xprt->cwnd);
-                       printk("RPC: %ld %ld %ld %ld stat\n",
-                                       jiffies, pkt_cnt, pkt_len, pkt_rtt);
-                       pkt_rtt = pkt_len = pkt_cnt = 0;
-                       nextstat = jiffies + 5 * HZ;
-               }
-       }
-#endif
-
-       dprintk("RPC: %4d has input (%d bytes)\n", task->tk_pid, copied);
-       list_del_init(&req->rq_list);
-       req->rq_received = req->rq_private_buf.len = copied;
-
-       /* ... and wake up the process. */
-       rpc_wake_up_task(task);
-       return;
-}
-
-static size_t
-skb_read_bits(skb_reader_t *desc, void *to, size_t len)
-{
-       if (len > desc->count)
-               len = desc->count;
-       if (skb_copy_bits(desc->skb, desc->offset, to, len))
-               return 0;
-       desc->count -= len;
-       desc->offset += len;
-       return len;
-}
-
-static size_t
-skb_read_and_csum_bits(skb_reader_t *desc, void *to, size_t len)
-{
-       unsigned int csum2, pos;
-
-       if (len > desc->count)
-               len = desc->count;
-       pos = desc->offset;
-       csum2 = skb_copy_and_csum_bits(desc->skb, pos, to, len, 0);
-       desc->csum = csum_block_add(desc->csum, csum2, pos);
-       desc->count -= len;
-       desc->offset += len;
-       return len;
-}
-
-/*
- * We have set things up such that we perform the checksum of the UDP
- * packet in parallel with the copies into the RPC client iovec.  -DaveM
- */
-int
-csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
-{
-       skb_reader_t desc;
-
-       desc.skb = skb;
-       desc.offset = sizeof(struct udphdr);
-       desc.count = skb->len - desc.offset;
-
-       if (skb->ip_summed == CHECKSUM_UNNECESSARY)
-               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;
-       if (desc.offset != skb->len) {
-               unsigned int csum2;
-               csum2 = skb_checksum(skb, desc.offset, skb->len - desc.offset, 0);
-               desc.csum = csum_block_add(desc.csum, csum2, desc.offset);
-       }
-       if (desc.count)
-               return -1;
-       if ((unsigned short)csum_fold(desc.csum))
-               return -1;
-       return 0;
-no_checksum:
-       if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits) < 0)
-               return -1;
-       if (desc.count)
-               return -1;
-       return 0;
-}
-
-/*
- * Input handler for RPC replies. Called from a bottom half and hence
- * atomic.
- */
-static void
-udp_data_ready(struct sock *sk, int len)
-{
-       struct rpc_task *task;
-       struct rpc_xprt *xprt;
-       struct rpc_rqst *rovr;
-       struct sk_buff  *skb;
-       int err, repsize, copied;
-       u32 _xid, *xp;
-
-       read_lock(&sk->sk_callback_lock);
-       dprintk("RPC:      udp_data_ready...\n");
-       if (!(xprt = xprt_from_sock(sk))) {
-               printk("RPC:      udp_data_ready request not found!\n");
-               goto out;
-       }
-
-       dprintk("RPC:      udp_data_ready client %p\n", xprt);
-
-       if ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL)
-               goto out;
-
-       if (xprt->shutdown)
-               goto dropit;
-
-       repsize = skb->len - sizeof(struct udphdr);
-       if (repsize < 4) {
-               printk("RPC: impossible RPC reply size %d!\n", repsize);
-               goto dropit;
-       }
-
-       /* Copy the XID from the skb... */
-       xp = skb_header_pointer(skb, sizeof(struct udphdr),
-                               sizeof(_xid), &_xid);
-       if (xp == NULL)
-               goto dropit;
-
-       /* Look up and lock the request corresponding to the given XID */
-       spin_lock(&xprt->sock_lock);
-       rovr = xprt_lookup_rqst(xprt, *xp);
-       if (!rovr)
-               goto out_unlock;
-       task = rovr->rq_task;
-
-       dprintk("RPC: %4d received reply\n", task->tk_pid);
-
-       if ((copied = rovr->rq_private_buf.buflen) > repsize)
-               copied = repsize;
-
-       /* Suck it into the iovec, verify checksum if not done by hw. */
-       if (csum_partial_copy_to_xdr(&rovr->rq_private_buf, skb))
-               goto out_unlock;
-
-       /* Something worked... */
-       dst_confirm(skb->dst);
-
-       xprt_complete_rqst(xprt, rovr, copied);
-
- out_unlock:
-       spin_unlock(&xprt->sock_lock);
- dropit:
-       skb_free_datagram(sk, skb);
- out:
-       read_unlock(&sk->sk_callback_lock);
-}
-
-/*
- * Copy from an skb into memory and shrink the skb.
- */
-static inline size_t
-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);
-               return 0;
-       }
-       desc->offset += len;
-       desc->count -= len;
-       dprintk("RPC:      copied %zu bytes from skb. %zu bytes remain\n",
-                       len, desc->count);
-       return len;
-}
-
-/*
- * TCP read fragment marker
- */
-static inline void
-tcp_read_fraghdr(struct rpc_xprt *xprt, skb_reader_t *desc)
-{
-       size_t len, used;
-       char *p;
-
-       p = ((char *) &xprt->tcp_recm) + xprt->tcp_offset;
-       len = sizeof(xprt->tcp_recm) - xprt->tcp_offset;
-       used = tcp_copy_data(desc, p, len);
-       xprt->tcp_offset += used;
-       if (used != len)
-               return;
-       xprt->tcp_reclen = ntohl(xprt->tcp_recm);
-       if (xprt->tcp_reclen & 0x80000000)
-               xprt->tcp_flags |= XPRT_LAST_FRAG;
-       else
-               xprt->tcp_flags &= ~XPRT_LAST_FRAG;
-       xprt->tcp_reclen &= 0x7fffffff;
-       xprt->tcp_flags &= ~XPRT_COPY_RECM;
-       xprt->tcp_offset = 0;
-       /* Sanity check of the record length */
-       if (xprt->tcp_reclen < 4) {
-               printk(KERN_ERR "RPC: Invalid TCP record fragment length\n");
-               xprt_disconnect(xprt);
-       }
-       dprintk("RPC:      reading TCP record fragment of length %d\n",
-                       xprt->tcp_reclen);
-}
-
-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;
-               if (xprt->tcp_flags & XPRT_LAST_FRAG) {
-                       xprt->tcp_flags &= ~XPRT_COPY_DATA;
-                       xprt->tcp_flags |= XPRT_COPY_XID;
-                       xprt->tcp_copied = 0;
-               }
-       }
-}
-
-/*
- * TCP read xid
- */
-static inline void
-tcp_read_xid(struct rpc_xprt *xprt, skb_reader_t *desc)
-{
-       size_t len, used;
-       char *p;
-
-       len = sizeof(xprt->tcp_xid) - xprt->tcp_offset;
-       dprintk("RPC:      reading XID (%Zu bytes)\n", len);
-       p = ((char *) &xprt->tcp_xid) + xprt->tcp_offset;
-       used = tcp_copy_data(desc, p, len);
-       xprt->tcp_offset += used;
-       if (used != len)
-               return;
-       xprt->tcp_flags &= ~XPRT_COPY_XID;
-       xprt->tcp_flags |= XPRT_COPY_DATA;
-       xprt->tcp_copied = 4;
-       dprintk("RPC:      reading reply for XID %08x\n",
-                                               ntohl(xprt->tcp_xid));
-       tcp_check_recm(xprt);
-}
-
-/*
- * TCP read and complete request
- */
-static inline void
-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);
-       req = xprt_lookup_rqst(xprt, xprt->tcp_xid);
-       if (!req) {
-               xprt->tcp_flags &= ~XPRT_COPY_DATA;
-               dprintk("RPC:      XID %08x request not found!\n",
-                               ntohl(xprt->tcp_xid));
-               spin_unlock(&xprt->sock_lock);
-               return;
-       }
-
-       rcvbuf = &req->rq_private_buf;
-       len = desc->count;
-       if (len > xprt->tcp_reclen - xprt->tcp_offset) {
-               skb_reader_t my_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,
-                                         &my_desc, tcp_copy_data);
-               desc->count -= r;
-               desc->offset += r;
-       } else
-               r = 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 %Zd 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);
-
-       if (xprt->tcp_copied == req->rq_private_buf.buflen)
-               xprt->tcp_flags &= ~XPRT_COPY_DATA;
-       else if (xprt->tcp_offset == xprt->tcp_reclen) {
-               if (xprt->tcp_flags & XPRT_LAST_FRAG)
-                       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);
-               xprt_complete_rqst(xprt, req, xprt->tcp_copied);
-       }
-       spin_unlock(&xprt->sock_lock);
-       tcp_check_recm(xprt);
-}
-
-/*
- * TCP discard extra bytes from a short read
- */
-static inline void
-tcp_read_discard(struct rpc_xprt *xprt, skb_reader_t *desc)
-{
-       size_t len;
-
-       len = xprt->tcp_reclen - xprt->tcp_offset;
-       if (len > desc->count)
-               len = desc->count;
-       desc->count -= len;
-       desc->offset += len;
-       xprt->tcp_offset += len;
-       dprintk("RPC:      discarded %Zu bytes\n", len);
-       tcp_check_recm(xprt);
-}
-
-/*
- * TCP record receive routine
- * We first have to grab the record marker, then the XID, then the data.
+/**
+ * xprt_update_rtt - update an RPC client's RTT state after receiving a reply
+ * @task: RPC request that recently completed
+ *
  */
-static int
-tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
-               unsigned int offset, size_t len)
-{
-       struct rpc_xprt *xprt = rd_desc->arg.data;
-       skb_reader_t desc = {
-               .skb    = skb,
-               .offset = offset,
-               .count  = len,
-               .csum   = 0
-               };
-
-       dprintk("RPC:      tcp_data_recv\n");
-       do {
-               /* Read in a new fragment marker if necessary */
-               /* Can we ever really expect to get completely empty fragments? */
-               if (xprt->tcp_flags & XPRT_COPY_RECM) {
-                       tcp_read_fraghdr(xprt, &desc);
-                       continue;
-               }
-               /* Read in the xid if necessary */
-               if (xprt->tcp_flags & XPRT_COPY_XID) {
-                       tcp_read_xid(xprt, &desc);
-                       continue;
-               }
-               /* Read in the request data */
-               if (xprt->tcp_flags & XPRT_COPY_DATA) {
-                       tcp_read_request(xprt, &desc);
-                       continue;
-               }
-               /* Skip over any trailing bytes on short reads */
-               tcp_read_discard(xprt, &desc);
-       } while (desc.count);
-       dprintk("RPC:      tcp_data_recv done\n");
-       return len - desc.count;
-}
-
-static void tcp_data_ready(struct sock *sk, int bytes)
+void xprt_update_rtt(struct rpc_task *task)
 {
-       struct rpc_xprt *xprt;
-       read_descriptor_t rd_desc;
-
-       read_lock(&sk->sk_callback_lock);
-       dprintk("RPC:      tcp_data_ready...\n");
-       if (!(xprt = xprt_from_sock(sk))) {
-               printk("RPC:      tcp_data_ready socket info not found!\n");
-               goto out;
-       }
-       if (xprt->shutdown)
-               goto out;
-
-       /* We use rd_desc to pass struct xprt to tcp_data_recv */
-       rd_desc.arg.data = xprt;
-       rd_desc.count = 65536;
-       tcp_read_sock(sk, &rd_desc, tcp_data_recv);
-out:
-       read_unlock(&sk->sk_callback_lock);
-}
-
-static void
-tcp_state_change(struct sock *sk)
-{
-       struct rpc_xprt *xprt;
+       struct rpc_rqst *req = task->tk_rqstp;
+       struct rpc_rtt *rtt = task->tk_client->cl_rtt;
+       unsigned timer = task->tk_msg.rpc_proc->p_timer;
 
-       read_lock(&sk->sk_callback_lock);
-       if (!(xprt = xprt_from_sock(sk)))
-               goto out;
-       dprintk("RPC:      tcp_state_change client %p...\n", xprt);
-       dprintk("RPC:      state %x conn %d dead %d zapped %d\n",
-                               sk->sk_state, xprt_connected(xprt),
-                               sock_flag(sk, SOCK_DEAD),
-                               sock_flag(sk, SOCK_ZAPPED));
-
-       switch (sk->sk_state) {
-       case TCP_ESTABLISHED:
-               spin_lock_bh(&xprt->sock_lock);
-               if (!xprt_test_and_set_connected(xprt)) {
-                       /* Reset TCP record info */
-                       xprt->tcp_offset = 0;
-                       xprt->tcp_reclen = 0;
-                       xprt->tcp_copied = 0;
-                       xprt->tcp_flags = XPRT_COPY_RECM | XPRT_COPY_XID;
-                       rpc_wake_up(&xprt->pending);
-               }
-               spin_unlock_bh(&xprt->sock_lock);
-               break;
-       case TCP_SYN_SENT:
-       case TCP_SYN_RECV:
-               break;
-       default:
-               xprt_disconnect(xprt);
-               break;
+       if (timer) {
+               if (req->rq_ntrans == 1)
+                       rpc_update_rtt(rtt, timer,
+                                       (long)jiffies - req->rq_xtime);
+               rpc_set_timeo(rtt, timer, req->rq_ntrans - 1);
        }
- out:
-       read_unlock(&sk->sk_callback_lock);
 }
 
-/*
- * Called when more output buffer space is available for this socket.
- * We try not to wake our writers until they can make "significant"
- * progress, otherwise we'll waste resources thrashing sock_sendmsg
- * with a bunch of small requests.
+/**
+ * xprt_complete_rqst - called when reply processing is complete
+ * @task: RPC request that recently completed
+ * @copied: actual number of bytes received from the transport
+ *
+ * Caller holds transport lock.
  */
-static void
-xprt_write_space(struct sock *sk)
+void xprt_complete_rqst(struct rpc_task *task, int copied)
 {
-       struct rpc_xprt *xprt;
-       struct socket   *sock;
-
-       read_lock(&sk->sk_callback_lock);
-       if (!(xprt = xprt_from_sock(sk)) || !(sock = sk->sk_socket))
-               goto out;
-       if (xprt->shutdown)
-               goto out;
-
-       /* Wait until we have enough socket memory */
-       if (xprt->stream) {
-               /* from net/core/stream.c:sk_stream_write_space */
-               if (sk_stream_wspace(sk) < sk_stream_min_wspace(sk))
-                       goto out;
-       } else {
-               /* from net/core/sock.c:sock_def_write_space */
-               if (!sock_writeable(sk))
-                       goto out;
-       }
+       struct rpc_rqst *req = task->tk_rqstp;
 
-       if (!test_and_clear_bit(SOCK_NOSPACE, &sock->flags))
-               goto out;
+       dprintk("RPC: %5u xid %08x complete (%d bytes received)\n",
+                       task->tk_pid, ntohl(req->rq_xid), copied);
 
-       spin_lock_bh(&xprt->sock_lock);
-       if (xprt->snd_task)
-               rpc_wake_up_task(xprt->snd_task);
-       spin_unlock_bh(&xprt->sock_lock);
-out:
-       read_unlock(&sk->sk_callback_lock);
+       list_del_init(&req->rq_list);
+       req->rq_received = req->rq_private_buf.len = copied;
+       rpc_wake_up_task(task);
 }
 
-/*
- * RPC receive timeout handler.
- */
-static void
-xprt_timer(struct rpc_task *task)
+static void xprt_timer(struct rpc_task *task)
 {
-       struct rpc_rqst *req = task->tk_rqstp;
+       struct rpc_rqst *req = task->tk_rqstp;
        struct rpc_xprt *xprt = req->rq_xprt;
 
-       spin_lock(&xprt->sock_lock);
-       if (req->rq_received)
-               goto out;
-
-       xprt_adjust_cwnd(req->rq_xprt, -ETIMEDOUT);
-       __xprt_put_cong(xprt, req);
+       dprintk("RPC: %4d xprt_timer\n", task->tk_pid);
 
-       dprintk("RPC: %4d xprt_timer (%s request)\n",
-               task->tk_pid, req ? "pending" : "backlogged");
-
-       task->tk_status  = -ETIMEDOUT;
-out:
+       spin_lock(&xprt->transport_lock);
+       if (!req->rq_received) {
+               if (xprt->ops->timer)
+                       xprt->ops->timer(task);
+               task->tk_status = -ETIMEDOUT;
+       }
        task->tk_timeout = 0;
        rpc_wake_up_task(task);
-       spin_unlock(&xprt->sock_lock);
+       spin_unlock(&xprt->transport_lock);
 }
 
-/*
- * Place the actual RPC call.
- * We have to copy the iovec because sendmsg fiddles with its contents.
+/**
+ * xprt_prepare_transmit - reserve the transport before sending a request
+ * @task: RPC task about to send a request
+ *
  */
-int
-xprt_prepare_transmit(struct rpc_task *task)
+int xprt_prepare_transmit(struct rpc_task *task)
 {
        struct rpc_rqst *req = task->tk_rqstp;
        struct rpc_xprt *xprt = req->rq_xprt;
@@ -1191,12 +690,12 @@ xprt_prepare_transmit(struct rpc_task *task)
        if (xprt->shutdown)
                return -EIO;
 
-       spin_lock_bh(&xprt->sock_lock);
+       spin_lock_bh(&xprt->transport_lock);
        if (req->rq_received && !req->rq_bytes_sent) {
                err = req->rq_received;
                goto out_unlock;
        }
-       if (!__xprt_lock_write(xprt, task)) {
+       if (!xprt->ops->reserve_xprt(task)) {
                err = -EAGAIN;
                goto out_unlock;
        }
@@ -1206,39 +705,42 @@ xprt_prepare_transmit(struct rpc_task *task)
                goto out_unlock;
        }
 out_unlock:
-       spin_unlock_bh(&xprt->sock_lock);
+       spin_unlock_bh(&xprt->transport_lock);
        return err;
 }
 
 void
-xprt_transmit(struct rpc_task *task)
+xprt_abort_transmit(struct rpc_task *task)
+{
+       struct rpc_xprt *xprt = task->tk_xprt;
+
+       xprt_release_write(xprt, task);
+}
+
+/**
+ * xprt_transmit - send an RPC request on a transport
+ * @task: controlling RPC task
+ *
+ * We have to copy the iovec because sendmsg fiddles with its contents.
+ */
+void xprt_transmit(struct rpc_task *task)
 {
-       struct rpc_clnt *clnt = task->tk_client;
        struct rpc_rqst *req = task->tk_rqstp;
        struct rpc_xprt *xprt = req->rq_xprt;
-       int status, retry = 0;
-
+       int status;
 
        dprintk("RPC: %4d xprt_transmit(%u)\n", task->tk_pid, req->rq_slen);
 
-       /* set up everything as needed. */
-       /* Write the record marker */
-       if (xprt->stream) {
-               u32     *marker = req->rq_svec[0].iov_base;
-
-               *marker = htonl(0x80000000|(req->rq_slen-sizeof(*marker)));
-       }
-
        smp_rmb();
        if (!req->rq_received) {
                if (list_empty(&req->rq_list)) {
-                       spin_lock_bh(&xprt->sock_lock);
+                       spin_lock_bh(&xprt->transport_lock);
                        /* Update the softirq receive buffer */
                        memcpy(&req->rq_private_buf, &req->rq_rcv_buf,
                                        sizeof(req->rq_private_buf));
                        /* Add request to the receive list */
                        list_add_tail(&req->rq_list, &xprt->recv);
-                       spin_unlock_bh(&xprt->sock_lock);
+                       spin_unlock_bh(&xprt->transport_lock);
                        xprt_reset_majortimeo(req);
                        /* Turn off autodisconnect */
                        del_singleshot_timer_sync(&xprt->timer);
@@ -1246,40 +748,19 @@ xprt_transmit(struct rpc_task *task)
        } else if (!req->rq_bytes_sent)
                return;
 
-       /* Continue transmitting the packet/record. We must be careful
-        * to cope with writespace callbacks arriving _after_ we have
-        * called xprt_sendmsg().
-        */
-       while (1) {
-               req->rq_xtime = jiffies;
-               status = xprt_sendmsg(xprt, req);
-
-               if (status < 0)
-                       break;
-
-               if (xprt->stream) {
-                       req->rq_bytes_sent += status;
-
-                       /* If we've sent the entire packet, immediately
-                        * reset the count of bytes sent. */
-                       if (req->rq_bytes_sent >= req->rq_slen) {
-                               req->rq_bytes_sent = 0;
-                               goto out_receive;
-                       }
-               } else {
-                       if (status >= req->rq_slen)
-                               goto out_receive;
-                       status = -EAGAIN;
-                       break;
-               }
-
-               dprintk("RPC: %4d xmit incomplete (%d left of %d)\n",
-                               task->tk_pid, req->rq_slen - req->rq_bytes_sent,
-                               req->rq_slen);
-
-               status = -EAGAIN;
-               if (retry++ > 50)
-                       break;
+       status = xprt->ops->send_request(task);
+       if (status == 0) {
+               dprintk("RPC: %4d xmit complete\n", task->tk_pid);
+               spin_lock_bh(&xprt->transport_lock);
+               xprt->ops->set_retrans_timeout(task);
+               /* Don't race with disconnect */
+               if (!xprt_connected(xprt))
+                       task->tk_status = -ENOTCONN;
+               else if (!req->rq_received)
+                       rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);
+               xprt->ops->release_xprt(xprt, task);
+               spin_unlock_bh(&xprt->transport_lock);
+               return;
        }
 
        /* Note: at this point, task->tk_sleeping has not yet been set,
@@ -1289,60 +770,19 @@ xprt_transmit(struct rpc_task *task)
        task->tk_status = status;
 
        switch (status) {
-       case -EAGAIN:
-               if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) {
-                       /* Protect against races with xprt_write_space */
-                       spin_lock_bh(&xprt->sock_lock);
-                       /* Don't race with disconnect */
-                       if (!xprt_connected(xprt))
-                               task->tk_status = -ENOTCONN;
-                       else if (test_bit(SOCK_NOSPACE, &xprt->sock->flags)) {
-                               task->tk_timeout = req->rq_timeout;
-                               rpc_sleep_on(&xprt->pending, task, NULL, NULL);
-                       }
-                       spin_unlock_bh(&xprt->sock_lock);
-                       return;
-               }
-               /* Keep holding the socket if it is blocked */
-               rpc_delay(task, HZ>>4);
-               return;
        case -ECONNREFUSED:
-               task->tk_timeout = RPC_REESTABLISH_TIMEOUT;
                rpc_sleep_on(&xprt->sending, task, NULL, NULL);
+       case -EAGAIN:
        case -ENOTCONN:
                return;
        default:
-               if (xprt->stream)
-                       xprt_disconnect(xprt);
+               break;
        }
        xprt_release_write(xprt, task);
        return;
- out_receive:
-       dprintk("RPC: %4d xmit complete\n", task->tk_pid);
-       /* Set the task's receive timeout value */
-       spin_lock_bh(&xprt->sock_lock);
-       if (!xprt->nocong) {
-               int timer = task->tk_msg.rpc_proc->p_timer;
-               task->tk_timeout = rpc_calc_rto(clnt->cl_rtt, timer);
-               task->tk_timeout <<= rpc_ntimeo(clnt->cl_rtt, timer) + req->rq_retries;
-               if (task->tk_timeout > xprt->timeout.to_maxval || task->tk_timeout == 0)
-                       task->tk_timeout = xprt->timeout.to_maxval;
-       } else
-               task->tk_timeout = req->rq_timeout;
-       /* Don't race with disconnect */
-       if (!xprt_connected(xprt))
-               task->tk_status = -ENOTCONN;
-       else if (!req->rq_received)
-               rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);
-       __xprt_release_write(xprt, task);
-       spin_unlock_bh(&xprt->sock_lock);
 }
 
-/*
- * Reserve an RPC call slot.
- */
-static inline void
-do_xprt_reserve(struct rpc_task *task)
+static inline void do_xprt_reserve(struct rpc_task *task)
 {
        struct rpc_xprt *xprt = task->tk_xprt;
 
@@ -1362,22 +802,25 @@ do_xprt_reserve(struct rpc_task *task)
        rpc_sleep_on(&xprt->backlog, task, NULL, NULL);
 }
 
-void
-xprt_reserve(struct rpc_task *task)
+/**
+ * xprt_reserve - allocate an RPC request slot
+ * @task: RPC task requesting a slot allocation
+ *
+ * If no more slots are available, place the task on the transport's
+ * backlog queue.
+ */
+void xprt_reserve(struct rpc_task *task)
 {
        struct rpc_xprt *xprt = task->tk_xprt;
 
        task->tk_status = -EIO;
        if (!xprt->shutdown) {
-               spin_lock(&xprt->xprt_lock);
+               spin_lock(&xprt->reserve_lock);
                do_xprt_reserve(task);
-               spin_unlock(&xprt->xprt_lock);
+               spin_unlock(&xprt->reserve_lock);
        }
 }
 
-/*
- * Allocate a 'unique' XID
- */
 static inline u32 xprt_alloc_xid(struct rpc_xprt *xprt)
 {
        return xprt->xid++;
@@ -1388,11 +831,7 @@ static inline void xprt_init_xid(struct rpc_xprt *xprt)
        get_random_bytes(&xprt->xid, sizeof(xprt->xid));
 }
 
-/*
- * Initialize RPC request
- */
-static void
-xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
+static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
 {
        struct rpc_rqst *req = task->tk_rqstp;
 
@@ -1400,128 +839,104 @@ xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
        req->rq_task    = task;
        req->rq_xprt    = xprt;
        req->rq_xid     = xprt_alloc_xid(xprt);
+       req->rq_release_snd_buf = NULL;
        dprintk("RPC: %4d reserved req %p xid %08x\n", task->tk_pid,
                        req, ntohl(req->rq_xid));
 }
 
-/*
- * Release an RPC call slot
+/**
+ * xprt_release - release an RPC request slot
+ * @task: task which is finished with the slot
+ *
  */
-void
-xprt_release(struct rpc_task *task)
+void xprt_release(struct rpc_task *task)
 {
        struct rpc_xprt *xprt = task->tk_xprt;
        struct rpc_rqst *req;
 
        if (!(req = task->tk_rqstp))
                return;
-       spin_lock_bh(&xprt->sock_lock);
-       __xprt_release_write(xprt, task);
-       __xprt_put_cong(xprt, req);
+       spin_lock_bh(&xprt->transport_lock);
+       xprt->ops->release_xprt(xprt, task);
+       if (xprt->ops->release_request)
+               xprt->ops->release_request(task);
        if (!list_empty(&req->rq_list))
                list_del(&req->rq_list);
        xprt->last_used = jiffies;
        if (list_empty(&xprt->recv) && !xprt->shutdown)
-               mod_timer(&xprt->timer, xprt->last_used + XPRT_IDLE_TIMEOUT);
-       spin_unlock_bh(&xprt->sock_lock);
+               mod_timer(&xprt->timer,
+                               xprt->last_used + xprt->idle_timeout);
+       spin_unlock_bh(&xprt->transport_lock);
        task->tk_rqstp = NULL;
+       if (req->rq_release_snd_buf)
+               req->rq_release_snd_buf(req);
        memset(req, 0, sizeof(*req));   /* mark unused */
 
        dprintk("RPC: %4d release request %p\n", task->tk_pid, req);
 
-       spin_lock(&xprt->xprt_lock);
+       spin_lock(&xprt->reserve_lock);
        list_add(&req->rq_list, &xprt->free);
-       xprt_clear_backlog(xprt);
-       spin_unlock(&xprt->xprt_lock);
-}
-
-/*
- * Set default timeout parameters
- */
-static void
-xprt_default_timeout(struct rpc_timeout *to, int proto)
-{
-       if (proto == IPPROTO_UDP)
-               xprt_set_timeout(to, 5,  5 * HZ);
-       else
-               xprt_set_timeout(to, 5, 60 * HZ);
+       rpc_wake_up_next(&xprt->backlog);
+       spin_unlock(&xprt->reserve_lock);
 }
 
-/*
- * Set constant timeout
+/**
+ * xprt_set_timeout - set constant RPC timeout
+ * @to: RPC timeout parameters to set up
+ * @retr: number of retries
+ * @incr: amount of increase after each retry
+ *
  */
-void
-xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr)
+void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr)
 {
        to->to_initval   = 
        to->to_increment = incr;
-       to->to_maxval    = incr * retr;
+       to->to_maxval    = to->to_initval + (incr * retr);
        to->to_retries   = retr;
        to->to_exponential = 0;
 }
 
-unsigned int xprt_udp_slot_table_entries = RPC_DEF_SLOT_TABLE;
-unsigned int xprt_tcp_slot_table_entries = RPC_DEF_SLOT_TABLE;
-
-/*
- * Initialize an RPC client
- */
-static struct rpc_xprt *
-xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to)
+static struct rpc_xprt *xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to)
 {
+       int result;
        struct rpc_xprt *xprt;
-       unsigned int entries;
-       size_t slot_table_size;
        struct rpc_rqst *req;
 
-       dprintk("RPC:      setting up %s transport...\n",
-                               proto == IPPROTO_UDP? "UDP" : "TCP");
-
-       entries = (proto == IPPROTO_TCP)?
-               xprt_tcp_slot_table_entries : xprt_udp_slot_table_entries;
-
        if ((xprt = kmalloc(sizeof(struct rpc_xprt), GFP_KERNEL)) == NULL)
                return ERR_PTR(-ENOMEM);
        memset(xprt, 0, sizeof(*xprt)); /* Nnnngh! */
-       xprt->max_reqs = entries;
-       slot_table_size = entries * sizeof(xprt->slot[0]);
-       xprt->slot = kmalloc(slot_table_size, GFP_KERNEL);
-       if (xprt->slot == NULL) {
-               kfree(xprt);
-               return ERR_PTR(-ENOMEM);
-       }
-       memset(xprt->slot, 0, slot_table_size);
 
        xprt->addr = *ap;
-       xprt->prot = proto;
-       xprt->stream = (proto == IPPROTO_TCP)? 1 : 0;
-       if (xprt->stream) {
-               xprt->cwnd = RPC_MAXCWND(xprt);
-               xprt->nocong = 1;
-               xprt->max_payload = (1U << 31) - 1;
-       } else {
-               xprt->cwnd = RPC_INITCWND;
-               xprt->max_payload = (1U << 16) - (MAX_HEADER << 3);
+
+       switch (proto) {
+       case IPPROTO_UDP:
+               result = xs_setup_udp(xprt, to);
+               break;
+       case IPPROTO_TCP:
+               result = xs_setup_tcp(xprt, to);
+               break;
+       default:
+               printk(KERN_ERR "RPC: unrecognized transport protocol: %d\n",
+                               proto);
+               result = -EIO;
+               break;
+       }
+       if (result) {
+               kfree(xprt);
+               return ERR_PTR(result);
        }
-       spin_lock_init(&xprt->sock_lock);
-       spin_lock_init(&xprt->xprt_lock);
-       init_waitqueue_head(&xprt->cong_wait);
+
+       spin_lock_init(&xprt->transport_lock);
+       spin_lock_init(&xprt->reserve_lock);
 
        INIT_LIST_HEAD(&xprt->free);
        INIT_LIST_HEAD(&xprt->recv);
-       INIT_WORK(&xprt->sock_connect, xprt_socket_connect, xprt);
-       INIT_WORK(&xprt->task_cleanup, xprt_socket_autoclose, xprt);
+       INIT_WORK(&xprt->task_cleanup, xprt_autoclose, xprt);
        init_timer(&xprt->timer);
        xprt->timer.function = xprt_init_autodisconnect;
        xprt->timer.data = (unsigned long) xprt;
        xprt->last_used = jiffies;
-       xprt->port = XPRT_MAX_RESVPORT;
-
-       /* Set timeout parameters */
-       if (to) {
-               xprt->timeout = *to;
-       } else
-               xprt_default_timeout(&xprt->timeout, xprt->prot);
+       xprt->cwnd = RPC_INITCWND;
 
        rpc_init_wait_queue(&xprt->pending, "xprt_pending");
        rpc_init_wait_queue(&xprt->sending, "xprt_sending");
@@ -1529,139 +944,25 @@ xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to)
        rpc_init_priority_wait_queue(&xprt->backlog, "xprt_backlog");
 
        /* initialize free list */
-       for (req = &xprt->slot[entries-1]; req >= &xprt->slot[0]; req--)
+       for (req = &xprt->slot[xprt->max_reqs-1]; req >= &xprt->slot[0]; req--)
                list_add(&req->rq_list, &xprt->free);
 
        xprt_init_xid(xprt);
 
-       /* Check whether we want to use a reserved port */
-       xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
-
        dprintk("RPC:      created transport %p with %u slots\n", xprt,
                        xprt->max_reqs);
        
        return xprt;
 }
 
-/*
- * Bind to a reserved port
- */
-static inline int xprt_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
-{
-       struct sockaddr_in myaddr = {
-               .sin_family = AF_INET,
-       };
-       int             err, port;
-
-       /* Were we already bound to a given port? Try to reuse it */
-       port = xprt->port;
-       do {
-               myaddr.sin_port = htons(port);
-               err = sock->ops->bind(sock, (struct sockaddr *) &myaddr,
-                                               sizeof(myaddr));
-               if (err == 0) {
-                       xprt->port = port;
-                       return 0;
-               }
-               if (--port == 0)
-                       port = XPRT_MAX_RESVPORT;
-       } while (err == -EADDRINUSE && port != xprt->port);
-
-       printk("RPC: Can't bind to reserved port (%d).\n", -err);
-       return err;
-}
-
-static void
-xprt_bind_socket(struct rpc_xprt *xprt, struct socket *sock)
-{
-       struct sock     *sk = sock->sk;
-
-       if (xprt->inet)
-               return;
-
-       write_lock_bh(&sk->sk_callback_lock);
-       sk->sk_user_data = xprt;
-       xprt->old_data_ready = sk->sk_data_ready;
-       xprt->old_state_change = sk->sk_state_change;
-       xprt->old_write_space = sk->sk_write_space;
-       if (xprt->prot == IPPROTO_UDP) {
-               sk->sk_data_ready = udp_data_ready;
-               sk->sk_no_check = UDP_CSUM_NORCV;
-               xprt_set_connected(xprt);
-       } else {
-               tcp_sk(sk)->nonagle = 1;        /* disable Nagle's algorithm */
-               sk->sk_data_ready = tcp_data_ready;
-               sk->sk_state_change = tcp_state_change;
-               xprt_clear_connected(xprt);
-       }
-       sk->sk_write_space = xprt_write_space;
-
-       /* Reset to new socket */
-       xprt->sock = sock;
-       xprt->inet = sk;
-       write_unlock_bh(&sk->sk_callback_lock);
-
-       return;
-}
-
-/*
- * Set socket buffer length
- */
-void
-xprt_sock_setbufsize(struct rpc_xprt *xprt)
-{
-       struct sock *sk = xprt->inet;
-
-       if (xprt->stream)
-               return;
-       if (xprt->rcvsize) {
-               sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
-               sk->sk_rcvbuf = xprt->rcvsize * xprt->max_reqs *  2;
-       }
-       if (xprt->sndsize) {
-               sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
-               sk->sk_sndbuf = xprt->sndsize * xprt->max_reqs * 2;
-               sk->sk_write_space(sk);
-       }
-}
-
-/*
- * Datastream sockets are created here, but xprt_connect will create
- * and connect stream sockets.
- */
-static struct socket * xprt_create_socket(struct rpc_xprt *xprt, int proto, int resvport)
-{
-       struct socket   *sock;
-       int             type, err;
-
-       dprintk("RPC:      xprt_create_socket(%s %d)\n",
-                          (proto == IPPROTO_UDP)? "udp" : "tcp", proto);
-
-       type = (proto == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
-
-       if ((err = sock_create_kern(PF_INET, type, proto, &sock)) < 0) {
-               printk("RPC: can't create socket (%d).\n", -err);
-               return NULL;
-       }
-
-       /* If the caller has the capability, bind to a reserved port */
-       if (resvport && xprt_bindresvport(xprt, sock) < 0) {
-               printk("RPC: can't bind to reserved port.\n");
-               goto failed;
-       }
-
-       return sock;
-
-failed:
-       sock_release(sock);
-       return NULL;
-}
-
-/*
- * Create an RPC client transport given the protocol and peer address.
+/**
+ * xprt_create_proto - create an RPC client transport
+ * @proto: requested transport protocol
+ * @sap: remote peer's address
+ * @to: timeout parameters for new transport
+ *
  */
-struct rpc_xprt *
-xprt_create_proto(int proto, struct sockaddr_in *sap, struct rpc_timeout *to)
+struct rpc_xprt *xprt_create_proto(int proto, struct sockaddr_in *sap, struct rpc_timeout *to)
 {
        struct rpc_xprt *xprt;
 
@@ -1673,46 +974,26 @@ xprt_create_proto(int proto, struct sockaddr_in *sap, struct rpc_timeout *to)
        return xprt;
 }
 
-/*
- * Prepare for transport shutdown.
- */
-static void
-xprt_shutdown(struct rpc_xprt *xprt)
+static void xprt_shutdown(struct rpc_xprt *xprt)
 {
        xprt->shutdown = 1;
        rpc_wake_up(&xprt->sending);
        rpc_wake_up(&xprt->resend);
-       rpc_wake_up(&xprt->pending);
+       xprt_wake_pending_tasks(xprt, -EIO);
        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();
 }
 
-/*
- * Clear the xprt backlog queue
- */
-static int
-xprt_clear_backlog(struct rpc_xprt *xprt) {
-       rpc_wake_up_next(&xprt->backlog);
-       wake_up(&xprt->cong_wait);
-       return 1;
-}
-
-/*
- * Destroy an RPC transport, killing off all requests.
+/**
+ * xprt_destroy - destroy an RPC transport, killing off all requests.
+ * @xprt: transport to destroy
+ *
  */
-int
-xprt_destroy(struct rpc_xprt *xprt)
+int xprt_destroy(struct rpc_xprt *xprt)
 {
        dprintk("RPC:      destroying transport %p\n", xprt);
        xprt_shutdown(xprt);
-       xprt_disconnect(xprt);
-       xprt_close(xprt);
-       kfree(xprt->slot);
+       xprt->ops->destroy(xprt);
        kfree(xprt);
 
        return 0;
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
new file mode 100644 (file)
index 0000000..2e15292
--- /dev/null
@@ -0,0 +1,1252 @@
+/*
+ * linux/net/sunrpc/xprtsock.c
+ *
+ * Client-side transport implementation for sockets.
+ *
+ * TCP callback races fixes (C) 1998 Red Hat Software <alan@redhat.com>
+ * TCP send fixes (C) 1998 Red Hat Software <alan@redhat.com>
+ * TCP NFS related read + write fixes
+ *  (C) 1999 Dave Airlie, University of Limerick, Ireland <airlied@linux.ie>
+ *
+ * Rewrite of larges part of the code in order to stabilize TCP stuff.
+ * Fix behaviour when socket buffer is full.
+ *  (C) 1999 Trond Myklebust <trond.myklebust@fys.uio.no>
+ *
+ * IP socket transport implementation, (C) 2005 Chuck Lever <cel@netapp.com>
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/capability.h>
+#include <linux/sched.h>
+#include <linux/pagemap.h>
+#include <linux/errno.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/net.h>
+#include <linux/mm.h>
+#include <linux/udp.h>
+#include <linux/tcp.h>
+#include <linux/sunrpc/clnt.h>
+#include <linux/file.h>
+
+#include <net/sock.h>
+#include <net/checksum.h>
+#include <net/udp.h>
+#include <net/tcp.h>
+
+/*
+ * How many times to try sending a request on a socket before waiting
+ * for the socket buffer to clear.
+ */
+#define XS_SENDMSG_RETRY       (10U)
+
+/*
+ * Time out for an RPC UDP socket connect.  UDP socket connects are
+ * synchronous, but we set a timeout anyway in case of resource
+ * exhaustion on the local host.
+ */
+#define XS_UDP_CONN_TO         (5U * HZ)
+
+/*
+ * Wait duration for an RPC TCP connection to be established.  Solaris
+ * NFS over TCP uses 60 seconds, for example, which is in line with how
+ * long a server takes to reboot.
+ */
+#define XS_TCP_CONN_TO         (60U * HZ)
+
+/*
+ * Wait duration for a reply from the RPC portmapper.
+ */
+#define XS_BIND_TO             (60U * HZ)
+
+/*
+ * Delay if a UDP socket connect error occurs.  This is most likely some
+ * kind of resource problem on the local host.
+ */
+#define XS_UDP_REEST_TO                (2U * HZ)
+
+/*
+ * The reestablish timeout allows clients to delay for a bit before attempting
+ * to reconnect to a server that just dropped our connection.
+ *
+ * We implement an exponential backoff when trying to reestablish a TCP
+ * transport connection with the server.  Some servers like to drop a TCP
+ * connection when they are overworked, so we start with a short timeout and
+ * increase over time if the server is down or not responding.
+ */
+#define XS_TCP_INIT_REEST_TO   (3U * HZ)
+#define XS_TCP_MAX_REEST_TO    (5U * 60 * HZ)
+
+/*
+ * TCP idle timeout; client drops the transport socket if it is idle
+ * for this long.  Note that we also timeout UDP sockets to prevent
+ * holding port numbers when there is no RPC traffic.
+ */
+#define XS_IDLE_DISC_TO                (5U * 60 * HZ)
+
+#ifdef RPC_DEBUG
+# undef  RPC_DEBUG_DATA
+# define RPCDBG_FACILITY       RPCDBG_TRANS
+#endif
+
+#ifdef RPC_DEBUG_DATA
+static void xs_pktdump(char *msg, u32 *packet, unsigned int count)
+{
+       u8 *buf = (u8 *) packet;
+       int j;
+
+       dprintk("RPC:      %s\n", msg);
+       for (j = 0; j < count && j < 128; j += 4) {
+               if (!(j & 31)) {
+                       if (j)
+                               dprintk("\n");
+                       dprintk("0x%04x ", j);
+               }
+               dprintk("%02x%02x%02x%02x ",
+                       buf[j], buf[j+1], buf[j+2], buf[j+3]);
+       }
+       dprintk("\n");
+}
+#else
+static inline void xs_pktdump(char *msg, u32 *packet, unsigned int count)
+{
+       /* NOP */
+}
+#endif
+
+#define XS_SENDMSG_FLAGS       (MSG_DONTWAIT | MSG_NOSIGNAL)
+
+static inline int xs_send_head(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, unsigned int len)
+{
+       struct kvec iov = {
+               .iov_base       = xdr->head[0].iov_base + base,
+               .iov_len        = len - base,
+       };
+       struct msghdr msg = {
+               .msg_name       = addr,
+               .msg_namelen    = addrlen,
+               .msg_flags      = XS_SENDMSG_FLAGS,
+       };
+
+       if (xdr->len > len)
+               msg.msg_flags |= MSG_MORE;
+
+       if (likely(iov.iov_len))
+               return kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
+       return kernel_sendmsg(sock, &msg, NULL, 0, 0);
+}
+
+static int xs_send_tail(struct socket *sock, struct xdr_buf *xdr, unsigned int base, unsigned int len)
+{
+       struct kvec iov = {
+               .iov_base       = xdr->tail[0].iov_base + base,
+               .iov_len        = len - base,
+       };
+       struct msghdr msg = {
+               .msg_flags      = XS_SENDMSG_FLAGS,
+       };
+
+       return kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
+}
+
+/**
+ * xs_sendpages - write pages directly to a socket
+ * @sock: socket to send on
+ * @addr: UDP only -- address of destination
+ * @addrlen: UDP only -- length of destination address
+ * @xdr: buffer containing this request
+ * @base: starting position in the buffer
+ *
+ */
+static inline int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base)
+{
+       struct page **ppage = xdr->pages;
+       unsigned int len, pglen = xdr->page_len;
+       int err, ret = 0;
+       ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
+
+       if (unlikely(!sock))
+               return -ENOTCONN;
+
+       clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
+
+       len = xdr->head[0].iov_len;
+       if (base < len || (addr != NULL && base == 0)) {
+               err = xs_send_head(sock, addr, addrlen, xdr, base, len);
+               if (ret == 0)
+                       ret = err;
+               else if (err > 0)
+                       ret += err;
+               if (err != (len - base))
+                       goto out;
+               base = 0;
+       } else
+               base -= len;
+
+       if (unlikely(pglen == 0))
+               goto copy_tail;
+       if (unlikely(base >= pglen)) {
+               base -= pglen;
+               goto copy_tail;
+       }
+       if (base || xdr->page_base) {
+               pglen -= base;
+               base += xdr->page_base;
+               ppage += base >> PAGE_CACHE_SHIFT;
+               base &= ~PAGE_CACHE_MASK;
+       }
+
+       sendpage = sock->ops->sendpage ? : sock_no_sendpage;
+       do {
+               int flags = XS_SENDMSG_FLAGS;
+
+               len = PAGE_CACHE_SIZE;
+               if (base)
+                       len -= base;
+               if (pglen < len)
+                       len = pglen;
+
+               if (pglen != len || xdr->tail[0].iov_len != 0)
+                       flags |= MSG_MORE;
+
+               /* Hmm... We might be dealing with highmem pages */
+               if (PageHighMem(*ppage))
+                       sendpage = sock_no_sendpage;
+               err = sendpage(sock, *ppage, base, len, flags);
+               if (ret == 0)
+                       ret = err;
+               else if (err > 0)
+                       ret += err;
+               if (err != len)
+                       goto out;
+               base = 0;
+               ppage++;
+       } while ((pglen -= len) != 0);
+copy_tail:
+       len = xdr->tail[0].iov_len;
+       if (base < len) {
+               err = xs_send_tail(sock, xdr, base, len);
+               if (ret == 0)
+                       ret = err;
+               else if (err > 0)
+                       ret += err;
+       }
+out:
+       return ret;
+}
+
+/**
+ * xs_nospace - place task on wait queue if transmit was incomplete
+ * @task: task to put to sleep
+ *
+ */
+static void xs_nospace(struct rpc_task *task)
+{
+       struct rpc_rqst *req = task->tk_rqstp;
+       struct rpc_xprt *xprt = req->rq_xprt;
+
+       dprintk("RPC: %4d xmit incomplete (%u left of %u)\n",
+                       task->tk_pid, req->rq_slen - req->rq_bytes_sent,
+                       req->rq_slen);
+
+       if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) {
+               /* Protect against races with write_space */
+               spin_lock_bh(&xprt->transport_lock);
+
+               /* Don't race with disconnect */
+               if (!xprt_connected(xprt))
+                       task->tk_status = -ENOTCONN;
+               else if (test_bit(SOCK_NOSPACE, &xprt->sock->flags))
+                       xprt_wait_for_buffer_space(task);
+
+               spin_unlock_bh(&xprt->transport_lock);
+       } else
+               /* Keep holding the socket if it is blocked */
+               rpc_delay(task, HZ>>4);
+}
+
+/**
+ * xs_udp_send_request - write an RPC request to a UDP socket
+ * @task: address of RPC task that manages the state of an RPC request
+ *
+ * Return values:
+ *        0:   The request has been sent
+ *   EAGAIN:   The socket was blocked, please call again later to
+ *             complete the request
+ * ENOTCONN:   Caller needs to invoke connect logic then call again
+ *    other:   Some other error occured, the request was not sent
+ */
+static int xs_udp_send_request(struct rpc_task *task)
+{
+       struct rpc_rqst *req = task->tk_rqstp;
+       struct rpc_xprt *xprt = req->rq_xprt;
+       struct xdr_buf *xdr = &req->rq_snd_buf;
+       int status;
+
+       xs_pktdump("packet data:",
+                               req->rq_svec->iov_base,
+                               req->rq_svec->iov_len);
+
+       req->rq_xtime = jiffies;
+       status = xs_sendpages(xprt->sock, (struct sockaddr *) &xprt->addr,
+                               sizeof(xprt->addr), xdr, req->rq_bytes_sent);
+
+       dprintk("RPC:      xs_udp_send_request(%u) = %d\n",
+                       xdr->len - req->rq_bytes_sent, status);
+
+       if (likely(status >= (int) req->rq_slen))
+               return 0;
+
+       /* Still some bytes left; set up for a retry later. */
+       if (status > 0)
+               status = -EAGAIN;
+
+       switch (status) {
+       case -ENETUNREACH:
+       case -EPIPE:
+       case -ECONNREFUSED:
+               /* When the server has died, an ICMP port unreachable message
+                * prompts ECONNREFUSED. */
+               break;
+       case -EAGAIN:
+               xs_nospace(task);
+               break;
+       default:
+               dprintk("RPC:      sendmsg returned unrecognized error %d\n",
+                       -status);
+               break;
+       }
+
+       return status;
+}
+
+static inline void xs_encode_tcp_record_marker(struct xdr_buf *buf)
+{
+       u32 reclen = buf->len - sizeof(rpc_fraghdr);
+       rpc_fraghdr *base = buf->head[0].iov_base;
+       *base = htonl(RPC_LAST_STREAM_FRAGMENT | reclen);
+}
+
+/**
+ * xs_tcp_send_request - write an RPC request to a TCP socket
+ * @task: address of RPC task that manages the state of an RPC request
+ *
+ * Return values:
+ *        0:   The request has been sent
+ *   EAGAIN:   The socket was blocked, please call again later to
+ *             complete the request
+ * ENOTCONN:   Caller needs to invoke connect logic then call again
+ *    other:   Some other error occured, the request was not sent
+ *
+ * XXX: In the case of soft timeouts, should we eventually give up
+ *     if sendmsg is not able to make progress?
+ */
+static int xs_tcp_send_request(struct rpc_task *task)
+{
+       struct rpc_rqst *req = task->tk_rqstp;
+       struct rpc_xprt *xprt = req->rq_xprt;
+       struct xdr_buf *xdr = &req->rq_snd_buf;
+       int status, retry = 0;
+
+       xs_encode_tcp_record_marker(&req->rq_snd_buf);
+
+       xs_pktdump("packet data:",
+                               req->rq_svec->iov_base,
+                               req->rq_svec->iov_len);
+
+       /* Continue transmitting the packet/record. We must be careful
+        * to cope with writespace callbacks arriving _after_ we have
+        * called sendmsg(). */
+       while (1) {
+               req->rq_xtime = jiffies;
+               status = xs_sendpages(xprt->sock, NULL, 0, xdr,
+                                               req->rq_bytes_sent);
+
+               dprintk("RPC:      xs_tcp_send_request(%u) = %d\n",
+                               xdr->len - req->rq_bytes_sent, status);
+
+               if (unlikely(status < 0))
+                       break;
+
+               /* If we've sent the entire packet, immediately
+                * reset the count of bytes sent. */
+               req->rq_bytes_sent += status;
+               if (likely(req->rq_bytes_sent >= req->rq_slen)) {
+                       req->rq_bytes_sent = 0;
+                       return 0;
+               }
+
+               status = -EAGAIN;
+               if (retry++ > XS_SENDMSG_RETRY)
+                       break;
+       }
+
+       switch (status) {
+       case -EAGAIN:
+               xs_nospace(task);
+               break;
+       case -ECONNREFUSED:
+       case -ECONNRESET:
+       case -ENOTCONN:
+       case -EPIPE:
+               status = -ENOTCONN;
+               break;
+       default:
+               dprintk("RPC:      sendmsg returned unrecognized error %d\n",
+                       -status);
+               xprt_disconnect(xprt);
+               break;
+       }
+
+       return status;
+}
+
+/**
+ * xs_close - close a socket
+ * @xprt: transport
+ *
+ * This is used when all requests are complete; ie, no DRC state remains
+ * on the server we want to save.
+ */
+static void xs_close(struct rpc_xprt *xprt)
+{
+       struct socket *sock = xprt->sock;
+       struct sock *sk = xprt->inet;
+
+       if (!sk)
+               return;
+
+       dprintk("RPC:      xs_close xprt %p\n", xprt);
+
+       write_lock_bh(&sk->sk_callback_lock);
+       xprt->inet = NULL;
+       xprt->sock = NULL;
+
+       sk->sk_user_data = NULL;
+       sk->sk_data_ready = xprt->old_data_ready;
+       sk->sk_state_change = xprt->old_state_change;
+       sk->sk_write_space = xprt->old_write_space;
+       write_unlock_bh(&sk->sk_callback_lock);
+
+       sk->sk_no_check = 0;
+
+       sock_release(sock);
+}
+
+/**
+ * xs_destroy - prepare to shutdown a transport
+ * @xprt: doomed transport
+ *
+ */
+static void xs_destroy(struct rpc_xprt *xprt)
+{
+       dprintk("RPC:      xs_destroy xprt %p\n", xprt);
+
+       cancel_delayed_work(&xprt->connect_worker);
+       flush_scheduled_work();
+
+       xprt_disconnect(xprt);
+       xs_close(xprt);
+       kfree(xprt->slot);
+}
+
+static inline struct rpc_xprt *xprt_from_sock(struct sock *sk)
+{
+       return (struct rpc_xprt *) sk->sk_user_data;
+}
+
+/**
+ * xs_udp_data_ready - "data ready" callback for UDP sockets
+ * @sk: socket with data to read
+ * @len: how much data to read
+ *
+ */
+static void xs_udp_data_ready(struct sock *sk, int len)
+{
+       struct rpc_task *task;
+       struct rpc_xprt *xprt;
+       struct rpc_rqst *rovr;
+       struct sk_buff *skb;
+       int err, repsize, copied;
+       u32 _xid, *xp;
+
+       read_lock(&sk->sk_callback_lock);
+       dprintk("RPC:      xs_udp_data_ready...\n");
+       if (!(xprt = xprt_from_sock(sk)))
+               goto out;
+
+       if ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL)
+               goto out;
+
+       if (xprt->shutdown)
+               goto dropit;
+
+       repsize = skb->len - sizeof(struct udphdr);
+       if (repsize < 4) {
+               dprintk("RPC:      impossible RPC reply size %d!\n", repsize);
+               goto dropit;
+       }
+
+       /* Copy the XID from the skb... */
+       xp = skb_header_pointer(skb, sizeof(struct udphdr),
+                               sizeof(_xid), &_xid);
+       if (xp == NULL)
+               goto dropit;
+
+       /* Look up and lock the request corresponding to the given XID */
+       spin_lock(&xprt->transport_lock);
+       rovr = xprt_lookup_rqst(xprt, *xp);
+       if (!rovr)
+               goto out_unlock;
+       task = rovr->rq_task;
+
+       if ((copied = rovr->rq_private_buf.buflen) > repsize)
+               copied = repsize;
+
+       /* Suck it into the iovec, verify checksum if not done by hw. */
+       if (csum_partial_copy_to_xdr(&rovr->rq_private_buf, skb))
+               goto out_unlock;
+
+       /* Something worked... */
+       dst_confirm(skb->dst);
+
+       xprt_adjust_cwnd(task, copied);
+       xprt_update_rtt(task);
+       xprt_complete_rqst(task, copied);
+
+ out_unlock:
+       spin_unlock(&xprt->transport_lock);
+ dropit:
+       skb_free_datagram(sk, skb);
+ out:
+       read_unlock(&sk->sk_callback_lock);
+}
+
+static inline size_t xs_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);
+               return 0;
+       }
+       desc->offset += len;
+       desc->count -= len;
+       dprintk("RPC:      copied %zu bytes from skb. %zu bytes remain\n",
+                       len, desc->count);
+       return len;
+}
+
+static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, skb_reader_t *desc)
+{
+       size_t len, used;
+       char *p;
+
+       p = ((char *) &xprt->tcp_recm) + xprt->tcp_offset;
+       len = sizeof(xprt->tcp_recm) - xprt->tcp_offset;
+       used = xs_tcp_copy_data(desc, p, len);
+       xprt->tcp_offset += used;
+       if (used != len)
+               return;
+
+       xprt->tcp_reclen = ntohl(xprt->tcp_recm);
+       if (xprt->tcp_reclen & RPC_LAST_STREAM_FRAGMENT)
+               xprt->tcp_flags |= XPRT_LAST_FRAG;
+       else
+               xprt->tcp_flags &= ~XPRT_LAST_FRAG;
+       xprt->tcp_reclen &= RPC_FRAGMENT_SIZE_MASK;
+
+       xprt->tcp_flags &= ~XPRT_COPY_RECM;
+       xprt->tcp_offset = 0;
+
+       /* Sanity check of the record length */
+       if (unlikely(xprt->tcp_reclen < 4)) {
+               dprintk("RPC:      invalid TCP record fragment length\n");
+               xprt_disconnect(xprt);
+               return;
+       }
+       dprintk("RPC:      reading TCP record fragment of length %d\n",
+                       xprt->tcp_reclen);
+}
+
+static void xs_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;
+               if (xprt->tcp_flags & XPRT_LAST_FRAG) {
+                       xprt->tcp_flags &= ~XPRT_COPY_DATA;
+                       xprt->tcp_flags |= XPRT_COPY_XID;
+                       xprt->tcp_copied = 0;
+               }
+       }
+}
+
+static inline void xs_tcp_read_xid(struct rpc_xprt *xprt, skb_reader_t *desc)
+{
+       size_t len, used;
+       char *p;
+
+       len = sizeof(xprt->tcp_xid) - xprt->tcp_offset;
+       dprintk("RPC:      reading XID (%Zu bytes)\n", len);
+       p = ((char *) &xprt->tcp_xid) + xprt->tcp_offset;
+       used = xs_tcp_copy_data(desc, p, len);
+       xprt->tcp_offset += used;
+       if (used != len)
+               return;
+       xprt->tcp_flags &= ~XPRT_COPY_XID;
+       xprt->tcp_flags |= XPRT_COPY_DATA;
+       xprt->tcp_copied = 4;
+       dprintk("RPC:      reading reply for XID %08x\n",
+                                               ntohl(xprt->tcp_xid));
+       xs_tcp_check_recm(xprt);
+}
+
+static inline void xs_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->transport_lock);
+       req = xprt_lookup_rqst(xprt, xprt->tcp_xid);
+       if (!req) {
+               xprt->tcp_flags &= ~XPRT_COPY_DATA;
+               dprintk("RPC:      XID %08x request not found!\n",
+                               ntohl(xprt->tcp_xid));
+               spin_unlock(&xprt->transport_lock);
+               return;
+       }
+
+       rcvbuf = &req->rq_private_buf;
+       len = desc->count;
+       if (len > xprt->tcp_reclen - xprt->tcp_offset) {
+               skb_reader_t my_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,
+                                         &my_desc, xs_tcp_copy_data);
+               desc->count -= r;
+               desc->offset += r;
+       } else
+               r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
+                                         desc, xs_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 %Zd 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);
+
+       if (xprt->tcp_copied == req->rq_private_buf.buflen)
+               xprt->tcp_flags &= ~XPRT_COPY_DATA;
+       else if (xprt->tcp_offset == xprt->tcp_reclen) {
+               if (xprt->tcp_flags & XPRT_LAST_FRAG)
+                       xprt->tcp_flags &= ~XPRT_COPY_DATA;
+       }
+
+out:
+       if (!(xprt->tcp_flags & XPRT_COPY_DATA))
+               xprt_complete_rqst(req->rq_task, xprt->tcp_copied);
+       spin_unlock(&xprt->transport_lock);
+       xs_tcp_check_recm(xprt);
+}
+
+static inline void xs_tcp_read_discard(struct rpc_xprt *xprt, skb_reader_t *desc)
+{
+       size_t len;
+
+       len = xprt->tcp_reclen - xprt->tcp_offset;
+       if (len > desc->count)
+               len = desc->count;
+       desc->count -= len;
+       desc->offset += len;
+       xprt->tcp_offset += len;
+       dprintk("RPC:      discarded %Zu bytes\n", len);
+       xs_tcp_check_recm(xprt);
+}
+
+static int xs_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, unsigned int offset, size_t len)
+{
+       struct rpc_xprt *xprt = rd_desc->arg.data;
+       skb_reader_t desc = {
+               .skb    = skb,
+               .offset = offset,
+               .count  = len,
+               .csum   = 0
+       };
+
+       dprintk("RPC:      xs_tcp_data_recv started\n");
+       do {
+               /* Read in a new fragment marker if necessary */
+               /* Can we ever really expect to get completely empty fragments? */
+               if (xprt->tcp_flags & XPRT_COPY_RECM) {
+                       xs_tcp_read_fraghdr(xprt, &desc);
+                       continue;
+               }
+               /* Read in the xid if necessary */
+               if (xprt->tcp_flags & XPRT_COPY_XID) {
+                       xs_tcp_read_xid(xprt, &desc);
+                       continue;
+               }
+               /* Read in the request data */
+               if (xprt->tcp_flags & XPRT_COPY_DATA) {
+                       xs_tcp_read_request(xprt, &desc);
+                       continue;
+               }
+               /* Skip over any trailing bytes on short reads */
+               xs_tcp_read_discard(xprt, &desc);
+       } while (desc.count);
+       dprintk("RPC:      xs_tcp_data_recv done\n");
+       return len - desc.count;
+}
+
+/**
+ * xs_tcp_data_ready - "data ready" callback for TCP sockets
+ * @sk: socket with data to read
+ * @bytes: how much data to read
+ *
+ */
+static void xs_tcp_data_ready(struct sock *sk, int bytes)
+{
+       struct rpc_xprt *xprt;
+       read_descriptor_t rd_desc;
+
+       read_lock(&sk->sk_callback_lock);
+       dprintk("RPC:      xs_tcp_data_ready...\n");
+       if (!(xprt = xprt_from_sock(sk)))
+               goto out;
+       if (xprt->shutdown)
+               goto out;
+
+       /* We use rd_desc to pass struct xprt to xs_tcp_data_recv */
+       rd_desc.arg.data = xprt;
+       rd_desc.count = 65536;
+       tcp_read_sock(sk, &rd_desc, xs_tcp_data_recv);
+out:
+       read_unlock(&sk->sk_callback_lock);
+}
+
+/**
+ * xs_tcp_state_change - callback to handle TCP socket state changes
+ * @sk: socket whose state has changed
+ *
+ */
+static void xs_tcp_state_change(struct sock *sk)
+{
+       struct rpc_xprt *xprt;
+
+       read_lock(&sk->sk_callback_lock);
+       if (!(xprt = xprt_from_sock(sk)))
+               goto out;
+       dprintk("RPC:      xs_tcp_state_change client %p...\n", xprt);
+       dprintk("RPC:      state %x conn %d dead %d zapped %d\n",
+                               sk->sk_state, xprt_connected(xprt),
+                               sock_flag(sk, SOCK_DEAD),
+                               sock_flag(sk, SOCK_ZAPPED));
+
+       switch (sk->sk_state) {
+       case TCP_ESTABLISHED:
+               spin_lock_bh(&xprt->transport_lock);
+               if (!xprt_test_and_set_connected(xprt)) {
+                       /* Reset TCP record info */
+                       xprt->tcp_offset = 0;
+                       xprt->tcp_reclen = 0;
+                       xprt->tcp_copied = 0;
+                       xprt->tcp_flags = XPRT_COPY_RECM | XPRT_COPY_XID;
+                       xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
+                       xprt_wake_pending_tasks(xprt, 0);
+               }
+               spin_unlock_bh(&xprt->transport_lock);
+               break;
+       case TCP_SYN_SENT:
+       case TCP_SYN_RECV:
+               break;
+       default:
+               xprt_disconnect(xprt);
+               break;
+       }
+ out:
+       read_unlock(&sk->sk_callback_lock);
+}
+
+/**
+ * xs_udp_write_space - callback invoked when socket buffer space
+ *                             becomes available
+ * @sk: socket whose state has changed
+ *
+ * Called when more output buffer space is available for this socket.
+ * We try not to wake our writers until they can make "significant"
+ * progress, otherwise we'll waste resources thrashing kernel_sendmsg
+ * with a bunch of small requests.
+ */
+static void xs_udp_write_space(struct sock *sk)
+{
+       read_lock(&sk->sk_callback_lock);
+
+       /* from net/core/sock.c:sock_def_write_space */
+       if (sock_writeable(sk)) {
+               struct socket *sock;
+               struct rpc_xprt *xprt;
+
+               if (unlikely(!(sock = sk->sk_socket)))
+                       goto out;
+               if (unlikely(!(xprt = xprt_from_sock(sk))))
+                       goto out;
+               if (unlikely(!test_and_clear_bit(SOCK_NOSPACE, &sock->flags)))
+                       goto out;
+
+               xprt_write_space(xprt);
+       }
+
+ out:
+       read_unlock(&sk->sk_callback_lock);
+}
+
+/**
+ * xs_tcp_write_space - callback invoked when socket buffer space
+ *                             becomes available
+ * @sk: socket whose state has changed
+ *
+ * Called when more output buffer space is available for this socket.
+ * We try not to wake our writers until they can make "significant"
+ * progress, otherwise we'll waste resources thrashing kernel_sendmsg
+ * with a bunch of small requests.
+ */
+static void xs_tcp_write_space(struct sock *sk)
+{
+       read_lock(&sk->sk_callback_lock);
+
+       /* from net/core/stream.c:sk_stream_write_space */
+       if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) {
+               struct socket *sock;
+               struct rpc_xprt *xprt;
+
+               if (unlikely(!(sock = sk->sk_socket)))
+                       goto out;
+               if (unlikely(!(xprt = xprt_from_sock(sk))))
+                       goto out;
+               if (unlikely(!test_and_clear_bit(SOCK_NOSPACE, &sock->flags)))
+                       goto out;
+
+               xprt_write_space(xprt);
+       }
+
+ out:
+       read_unlock(&sk->sk_callback_lock);
+}
+
+static void xs_udp_do_set_buffer_size(struct rpc_xprt *xprt)
+{
+       struct sock *sk = xprt->inet;
+
+       if (xprt->rcvsize) {
+               sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
+               sk->sk_rcvbuf = xprt->rcvsize * xprt->max_reqs *  2;
+       }
+       if (xprt->sndsize) {
+               sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
+               sk->sk_sndbuf = xprt->sndsize * xprt->max_reqs * 2;
+               sk->sk_write_space(sk);
+       }
+}
+
+/**
+ * xs_udp_set_buffer_size - set send and receive limits
+ * @xprt: generic transport
+ * @sndsize: requested size of send buffer, in bytes
+ * @rcvsize: requested size of receive buffer, in bytes
+ *
+ * Set socket send and receive buffer size limits.
+ */
+static void xs_udp_set_buffer_size(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize)
+{
+       xprt->sndsize = 0;
+       if (sndsize)
+               xprt->sndsize = sndsize + 1024;
+       xprt->rcvsize = 0;
+       if (rcvsize)
+               xprt->rcvsize = rcvsize + 1024;
+
+       xs_udp_do_set_buffer_size(xprt);
+}
+
+/**
+ * xs_udp_timer - called when a retransmit timeout occurs on a UDP transport
+ * @task: task that timed out
+ *
+ * Adjust the congestion window after a retransmit timeout has occurred.
+ */
+static void xs_udp_timer(struct rpc_task *task)
+{
+       xprt_adjust_cwnd(task, -ETIMEDOUT);
+}
+
+static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
+{
+       struct sockaddr_in myaddr = {
+               .sin_family = AF_INET,
+       };
+       int err;
+       unsigned short port = xprt->port;
+
+       do {
+               myaddr.sin_port = htons(port);
+               err = sock->ops->bind(sock, (struct sockaddr *) &myaddr,
+                                               sizeof(myaddr));
+               if (err == 0) {
+                       xprt->port = port;
+                       dprintk("RPC:      xs_bindresvport bound to port %u\n",
+                                       port);
+                       return 0;
+               }
+               if (port <= xprt_min_resvport)
+                       port = xprt_max_resvport;
+               else
+                       port--;
+       } while (err == -EADDRINUSE && port != xprt->port);
+
+       dprintk("RPC:      can't bind to reserved port (%d).\n", -err);
+       return err;
+}
+
+/**
+ * xs_udp_connect_worker - set up a UDP socket
+ * @args: RPC transport to connect
+ *
+ * Invoked by a work queue tasklet.
+ */
+static void xs_udp_connect_worker(void *args)
+{
+       struct rpc_xprt *xprt = (struct rpc_xprt *) args;
+       struct socket *sock = xprt->sock;
+       int err, status = -EIO;
+
+       if (xprt->shutdown || xprt->addr.sin_port == 0)
+               goto out;
+
+       dprintk("RPC:      xs_udp_connect_worker for xprt %p\n", xprt);
+
+       /* Start by resetting any existing state */
+       xs_close(xprt);
+
+       if ((err = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock)) < 0) {
+               dprintk("RPC:      can't create UDP transport socket (%d).\n", -err);
+               goto out;
+       }
+
+       if (xprt->resvport && xs_bindresvport(xprt, sock) < 0) {
+               sock_release(sock);
+               goto out;
+       }
+
+       if (!xprt->inet) {
+               struct sock *sk = sock->sk;
+
+               write_lock_bh(&sk->sk_callback_lock);
+
+               sk->sk_user_data = xprt;
+               xprt->old_data_ready = sk->sk_data_ready;
+               xprt->old_state_change = sk->sk_state_change;
+               xprt->old_write_space = sk->sk_write_space;
+               sk->sk_data_ready = xs_udp_data_ready;
+               sk->sk_write_space = xs_udp_write_space;
+               sk->sk_no_check = UDP_CSUM_NORCV;
+
+               xprt_set_connected(xprt);
+
+               /* Reset to new socket */
+               xprt->sock = sock;
+               xprt->inet = sk;
+
+               write_unlock_bh(&sk->sk_callback_lock);
+       }
+       xs_udp_do_set_buffer_size(xprt);
+       status = 0;
+out:
+       xprt_wake_pending_tasks(xprt, status);
+       xprt_clear_connecting(xprt);
+}
+
+/*
+ * We need to preserve the port number so the reply cache on the server can
+ * find our cached RPC replies when we get around to reconnecting.
+ */
+static void xs_tcp_reuse_connection(struct rpc_xprt *xprt)
+{
+       int result;
+       struct socket *sock = xprt->sock;
+       struct sockaddr any;
+
+       dprintk("RPC:      disconnecting xprt %p to reuse port\n", xprt);
+
+       /*
+        * Disconnect the transport socket by doing a connect operation
+        * with AF_UNSPEC.  This should return immediately...
+        */
+       memset(&any, 0, sizeof(any));
+       any.sa_family = AF_UNSPEC;
+       result = sock->ops->connect(sock, &any, sizeof(any), 0);
+       if (result)
+               dprintk("RPC:      AF_UNSPEC connect return code %d\n",
+                               result);
+}
+
+/**
+ * xs_tcp_connect_worker - connect a TCP socket to a remote endpoint
+ * @args: RPC transport to connect
+ *
+ * Invoked by a work queue tasklet.
+ */
+static void xs_tcp_connect_worker(void *args)
+{
+       struct rpc_xprt *xprt = (struct rpc_xprt *)args;
+       struct socket *sock = xprt->sock;
+       int err, status = -EIO;
+
+       if (xprt->shutdown || xprt->addr.sin_port == 0)
+               goto out;
+
+       dprintk("RPC:      xs_tcp_connect_worker for xprt %p\n", xprt);
+
+       if (!xprt->sock) {
+               /* start from scratch */
+               if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) {
+                       dprintk("RPC:      can't create TCP transport socket (%d).\n", -err);
+                       goto out;
+               }
+
+               if (xprt->resvport && xs_bindresvport(xprt, sock) < 0) {
+                       sock_release(sock);
+                       goto out;
+               }
+       } else
+               /* "close" the socket, preserving the local port */
+               xs_tcp_reuse_connection(xprt);
+
+       if (!xprt->inet) {
+               struct sock *sk = sock->sk;
+
+               write_lock_bh(&sk->sk_callback_lock);
+
+               sk->sk_user_data = xprt;
+               xprt->old_data_ready = sk->sk_data_ready;
+               xprt->old_state_change = sk->sk_state_change;
+               xprt->old_write_space = sk->sk_write_space;
+               sk->sk_data_ready = xs_tcp_data_ready;
+               sk->sk_state_change = xs_tcp_state_change;
+               sk->sk_write_space = xs_tcp_write_space;
+
+               /* socket options */
+               sk->sk_userlocks |= SOCK_BINDPORT_LOCK;
+               sock_reset_flag(sk, SOCK_LINGER);
+               tcp_sk(sk)->linger2 = 0;
+               tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF;
+
+               xprt_clear_connected(xprt);
+
+               /* Reset to new socket */
+               xprt->sock = sock;
+               xprt->inet = sk;
+
+               write_unlock_bh(&sk->sk_callback_lock);
+       }
+
+       /* Tell the socket layer to start connecting... */
+       status = sock->ops->connect(sock, (struct sockaddr *) &xprt->addr,
+                       sizeof(xprt->addr), O_NONBLOCK);
+       dprintk("RPC: %p  connect status %d connected %d sock state %d\n",
+                       xprt, -status, xprt_connected(xprt), sock->sk->sk_state);
+       if (status < 0) {
+               switch (status) {
+                       case -EINPROGRESS:
+                       case -EALREADY:
+                               goto out_clear;
+                       case -ECONNREFUSED:
+                       case -ECONNRESET:
+                               /* retry with existing socket, after a delay */
+                               break;
+                       default:
+                               /* get rid of existing socket, and retry */
+                               xs_close(xprt);
+                               break;
+               }
+       }
+out:
+       xprt_wake_pending_tasks(xprt, status);
+out_clear:
+       xprt_clear_connecting(xprt);
+}
+
+/**
+ * xs_connect - connect a socket to a remote endpoint
+ * @task: address of RPC task that manages state of connect request
+ *
+ * TCP: If the remote end dropped the connection, delay reconnecting.
+ *
+ * UDP socket connects are synchronous, but we use a work queue anyway
+ * to guarantee that even unprivileged user processes can set up a
+ * socket on a privileged port.
+ *
+ * If a UDP socket connect fails, the delay behavior here prevents
+ * retry floods (hard mounts).
+ */
+static void xs_connect(struct rpc_task *task)
+{
+       struct rpc_xprt *xprt = task->tk_xprt;
+
+       if (xprt_test_and_set_connecting(xprt))
+               return;
+
+       if (xprt->sock != NULL) {
+               dprintk("RPC:      xs_connect delayed xprt %p for %lu seconds\n",
+                               xprt, xprt->reestablish_timeout / HZ);
+               schedule_delayed_work(&xprt->connect_worker,
+                                       xprt->reestablish_timeout);
+               xprt->reestablish_timeout <<= 1;
+               if (xprt->reestablish_timeout > XS_TCP_MAX_REEST_TO)
+                       xprt->reestablish_timeout = XS_TCP_MAX_REEST_TO;
+       } else {
+               dprintk("RPC:      xs_connect scheduled xprt %p\n", xprt);
+               schedule_work(&xprt->connect_worker);
+
+               /* flush_scheduled_work can sleep... */
+               if (!RPC_IS_ASYNC(task))
+                       flush_scheduled_work();
+       }
+}
+
+static struct rpc_xprt_ops xs_udp_ops = {
+       .set_buffer_size        = xs_udp_set_buffer_size,
+       .reserve_xprt           = xprt_reserve_xprt_cong,
+       .release_xprt           = xprt_release_xprt_cong,
+       .connect                = xs_connect,
+       .send_request           = xs_udp_send_request,
+       .set_retrans_timeout    = xprt_set_retrans_timeout_rtt,
+       .timer                  = xs_udp_timer,
+       .release_request        = xprt_release_rqst_cong,
+       .close                  = xs_close,
+       .destroy                = xs_destroy,
+};
+
+static struct rpc_xprt_ops xs_tcp_ops = {
+       .reserve_xprt           = xprt_reserve_xprt,
+       .release_xprt           = xprt_release_xprt,
+       .connect                = xs_connect,
+       .send_request           = xs_tcp_send_request,
+       .set_retrans_timeout    = xprt_set_retrans_timeout_def,
+       .close                  = xs_close,
+       .destroy                = xs_destroy,
+};
+
+/**
+ * xs_setup_udp - Set up transport to use a UDP socket
+ * @xprt: transport to set up
+ * @to:   timeout parameters
+ *
+ */
+int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to)
+{
+       size_t slot_table_size;
+
+       dprintk("RPC:      setting up udp-ipv4 transport...\n");
+
+       xprt->max_reqs = xprt_udp_slot_table_entries;
+       slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]);
+       xprt->slot = kmalloc(slot_table_size, GFP_KERNEL);
+       if (xprt->slot == NULL)
+               return -ENOMEM;
+       memset(xprt->slot, 0, slot_table_size);
+
+       xprt->prot = IPPROTO_UDP;
+       xprt->port = xprt_max_resvport;
+       xprt->tsh_size = 0;
+       xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
+       /* XXX: header size can vary due to auth type, IPv6, etc. */
+       xprt->max_payload = (1U << 16) - (MAX_HEADER << 3);
+
+       INIT_WORK(&xprt->connect_worker, xs_udp_connect_worker, xprt);
+       xprt->bind_timeout = XS_BIND_TO;
+       xprt->connect_timeout = XS_UDP_CONN_TO;
+       xprt->reestablish_timeout = XS_UDP_REEST_TO;
+       xprt->idle_timeout = XS_IDLE_DISC_TO;
+
+       xprt->ops = &xs_udp_ops;
+
+       if (to)
+               xprt->timeout = *to;
+       else
+               xprt_set_timeout(&xprt->timeout, 5, 5 * HZ);
+
+       return 0;
+}
+
+/**
+ * xs_setup_tcp - Set up transport to use a TCP socket
+ * @xprt: transport to set up
+ * @to: timeout parameters
+ *
+ */
+int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to)
+{
+       size_t slot_table_size;
+
+       dprintk("RPC:      setting up tcp-ipv4 transport...\n");
+
+       xprt->max_reqs = xprt_tcp_slot_table_entries;
+       slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]);
+       xprt->slot = kmalloc(slot_table_size, GFP_KERNEL);
+       if (xprt->slot == NULL)
+               return -ENOMEM;
+       memset(xprt->slot, 0, slot_table_size);
+
+       xprt->prot = IPPROTO_TCP;
+       xprt->port = xprt_max_resvport;
+       xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32);
+       xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
+       xprt->max_payload = RPC_MAX_FRAGMENT_SIZE;
+
+       INIT_WORK(&xprt->connect_worker, xs_tcp_connect_worker, xprt);
+       xprt->bind_timeout = XS_BIND_TO;
+       xprt->connect_timeout = XS_TCP_CONN_TO;
+       xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
+       xprt->idle_timeout = XS_IDLE_DISC_TO;
+
+       xprt->ops = &xs_tcp_ops;
+
+       if (to)
+               xprt->timeout = *to;
+       else
+               xprt_set_timeout(&xprt->timeout, 2, 60 * HZ);
+
+       return 0;
+}
index cbb0ba34a60092a90f717440f110c06b30e63289..0db9e57013fdfaf738b608d688ea44b1d5e7cfe6 100644 (file)
@@ -1192,46 +1192,6 @@ int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family)
 
 EXPORT_SYMBOL(xfrm_bundle_ok);
 
-/* Well... that's _TASK_. We need to scan through transformation
- * list and figure out what mss tcp should generate in order to
- * final datagram fit to mtu. Mama mia... :-)
- *
- * Apparently, some easy way exists, but we used to choose the most
- * bizarre ones. :-) So, raising Kalashnikov... tra-ta-ta.
- *
- * Consider this function as something like dark humour. :-)
- */
-static int xfrm_get_mss(struct dst_entry *dst, u32 mtu)
-{
-       int res = mtu - dst->header_len;
-
-       for (;;) {
-               struct dst_entry *d = dst;
-               int m = res;
-
-               do {
-                       struct xfrm_state *x = d->xfrm;
-                       if (x) {
-                               spin_lock_bh(&x->lock);
-                               if (x->km.state == XFRM_STATE_VALID &&
-                                   x->type && x->type->get_max_size)
-                                       m = x->type->get_max_size(d->xfrm, m);
-                               else
-                                       m += x->props.header_len;
-                               spin_unlock_bh(&x->lock);
-                       }
-               } while ((d = d->child) != NULL);
-
-               if (m <= mtu)
-                       break;
-               res -= (m - mtu);
-               if (res < 88)
-                       return mtu;
-       }
-
-       return res + dst->header_len;
-}
-
 int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
 {
        int err = 0;
@@ -1252,8 +1212,6 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
                        dst_ops->negative_advice = xfrm_negative_advice;
                if (likely(dst_ops->link_failure == NULL))
                        dst_ops->link_failure = xfrm_link_failure;
-               if (likely(dst_ops->get_mss == NULL))
-                       dst_ops->get_mss = xfrm_get_mss;
                if (likely(afinfo->garbage_collect == NULL))
                        afinfo->garbage_collect = __xfrm_garbage_collect;
                xfrm_policy_afinfo[afinfo->family] = afinfo;
@@ -1281,7 +1239,6 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo)
                        dst_ops->check = NULL;
                        dst_ops->negative_advice = NULL;
                        dst_ops->link_failure = NULL;
-                       dst_ops->get_mss = NULL;
                        afinfo->garbage_collect = NULL;
                }
        }
index 9d206c282cf193a9867ff3b2c0078a683588a066..8b9a4747417d00bbf4c6b9050f59f7ca4eb24951 100644 (file)
@@ -1026,6 +1026,12 @@ void xfrm_state_delete_tunnel(struct xfrm_state *x)
 }
 EXPORT_SYMBOL(xfrm_state_delete_tunnel);
 
+/*
+ * This function is NOT optimal.  For example, with ESP it will give an
+ * MTU that's usually two bytes short of being optimal.  However, it will
+ * usually give an answer that's a multiple of 4 provided the input is
+ * also a multiple of 4.
+ */
 int xfrm_state_mtu(struct xfrm_state *x, int mtu)
 {
        int res = mtu;
index 9623a61dfc763df8511c6d515aac2705454ce64c..3d34f3de7e82d06e646b1e79f1f1b18f377ec1d8 100644 (file)
@@ -768,7 +768,7 @@ static int dummy_socket_getpeersec(struct socket *sock, char __user *optval,
        return -ENOPROTOOPT;
 }
 
-static inline int dummy_sk_alloc_security (struct sock *sk, int family, int priority)
+static inline int dummy_sk_alloc_security (struct sock *sk, int family, gfp_t priority)
 {
        return 0;
 }
index b13be15165f57d527ea6e334bf1ca8fe9606b6b8..447a1e0f48cb1c9bdfa520f874a76b3877b054bb 100644 (file)
@@ -262,7 +262,7 @@ static void superblock_free_security(struct super_block *sb)
 }
 
 #ifdef CONFIG_SECURITY_NETWORK
-static int sk_alloc_security(struct sock *sk, int family, int priority)
+static int sk_alloc_security(struct sock *sk, int family, gfp_t priority)
 {
        struct sk_security_struct *ssec;
 
@@ -3380,7 +3380,7 @@ out:
        return err;
 }
 
-static int selinux_sk_alloc_security(struct sock *sk, int family, int priority)
+static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
 {
        return sk_alloc_security(sk, family, priority);
 }
index e72cec77f0db8ebc7bf911afd5e8e48eac8bd979..129abab5ce98a42fcd3a96fc587abe0da6e31ec9 100644 (file)
@@ -190,7 +190,7 @@ static void unmark_pages(struct page *page, int order)
  *
  * Returns the pointer of the buffer, or NULL if no enoguh memory.
  */
-void *snd_malloc_pages(size_t size, unsigned int gfp_flags)
+void *snd_malloc_pages(size_t size, gfp_t gfp_flags)
 {
        int pg;
        void *res;
@@ -235,7 +235,7 @@ static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *d
 {
        int pg;
        void *res;
-       unsigned int gfp_flags;
+       gfp_t gfp_flags;
 
        snd_assert(size > 0, return NULL);
        snd_assert(dma != NULL, return NULL);
index 207c2c54bf1de91cbc5e69648098289e89f62f47..0e4df8826eedf6128a3f0591ad72559205e83261 100644 (file)
@@ -51,7 +51,7 @@ static int snd_seq_gf1_copy_wave_from_stream(snd_gf1_ops_t *ops,
        gf1_wave_t *wp, *prev;
        gf1_xwave_t xp;
        int err;
-       unsigned int gfp_mask;
+       gfp_t gfp_mask;
        unsigned int real_size;
        
        gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
@@ -144,7 +144,8 @@ static int snd_seq_gf1_put(void *private_data, snd_seq_kinstr_t *instr,
        snd_gf1_ops_t *ops = (snd_gf1_ops_t *)private_data;
        gf1_instrument_t *ip;
        gf1_xinstrument_t ix;
-       int err, gfp_mask;
+       int err;
+       gfp_t gfp_mask;
 
        if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
                return -EINVAL;
index 67c24c8e8e7be4eb3d3a7848d5fef3963f88e741..7c19fbbc5d0ffeaa34b28c2d918196b4be738bcb 100644 (file)
@@ -129,7 +129,7 @@ static int snd_seq_iwffff_copy_wave_from_stream(snd_iwffff_ops_t *ops,
        iwffff_wave_t *wp, *prev;
        iwffff_xwave_t xp;
        int err;
-       unsigned int gfp_mask;
+       gfp_t gfp_mask;
        unsigned int real_size;
        
        gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
@@ -236,7 +236,7 @@ static int snd_seq_iwffff_put(void *private_data, snd_seq_kinstr_t *instr,
        iwffff_layer_t *lp, *prev_lp;
        iwffff_xlayer_t lx;
        int err;
-       unsigned int gfp_mask;
+       gfp_t gfp_mask;
 
        if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
                return -EINVAL;
index 6183d21510345c9cb9f1c427235ffcf6724d0c2c..17ab94e760737242187450416dab8b6225ca5a32 100644 (file)
@@ -57,7 +57,8 @@ static int snd_seq_simple_put(void *private_data, snd_seq_kinstr_t *instr,
        snd_simple_ops_t *ops = (snd_simple_ops_t *)private_data;
        simple_instrument_t *ip;
        simple_xinstrument_t ix;
-       int err, gfp_mask;
+       int err;
+       gfp_t gfp_mask;
        unsigned int real_size;
 
        if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
index 9a2f50f0b184e58c03239e30928075a97d9c34ca..222014cafc1a9050c5670b28e55a2ebc5a1c91c9 100644 (file)
@@ -116,7 +116,7 @@ typedef struct {
     const char *name;
     const char *name2;
     struct module *owner;
-    void *(*dma_alloc)(unsigned int, int);
+    void *(*dma_alloc)(unsigned int, gfp_t);
     void (*dma_free)(void *, unsigned int);
     int (*irqinit)(void);
 #ifdef MODULE
index 8daaf87664ba1b10ee542aa3af768daebb3ab433..59eb53f893184a22a26a2fa52b2bca055179c758 100644 (file)
@@ -114,7 +114,7 @@ static ssize_t ata_ctx_u16le(const u_char *userPtr, size_t userCount,
 /*** Low level stuff *********************************************************/
 
 
-static void *AtaAlloc(unsigned int size, int flags);
+static void *AtaAlloc(unsigned int size, gfp_t flags);
 static void AtaFree(void *, unsigned int size);
 static int AtaIrqInit(void);
 #ifdef MODULE
@@ -810,7 +810,7 @@ static TRANS transFalconExpanding = {
  * Atari (TT/Falcon)
  */
 
-static void *AtaAlloc(unsigned int size, int flags)
+static void *AtaAlloc(unsigned int size, gfp_t flags)
 {
        return atari_stram_alloc(size, "dmasound");
 }
index 2ceb46f1d40f9dfd14c99eb04ab2de157e0885c3..b2bf8bac842d1a1384d32845536b20160b2a9ce0 100644 (file)
@@ -271,7 +271,7 @@ int expand_read_bal;        /* Balance factor for expanding reads (not volume!) */
 
 /*** Low level stuff *********************************************************/
 
-static void *PMacAlloc(unsigned int size, int flags);
+static void *PMacAlloc(unsigned int size, gfp_t flags);
 static void PMacFree(void *ptr, unsigned int size);
 static int PMacIrqInit(void);
 #ifdef MODULE
@@ -614,7 +614,7 @@ tas_init_frame_rates(unsigned int *prop, unsigned int l)
 /*
  * PCI PowerMac, with AWACS, Screamer, Burgundy, DACA or Tumbler and DBDMA.
  */
-static void *PMacAlloc(unsigned int size, int flags)
+static void *PMacAlloc(unsigned int size, gfp_t flags)
 {
        return kmalloc(size, flags);
 }
index 558db5311e0625b8d437a8d18d01cb444fe662d7..d59f60b2641096119a898f67319812aac988b6e4 100644 (file)
@@ -69,7 +69,7 @@ static int write_sq_block_size_half, write_sq_block_size_quarter;
 /*** Low level stuff *********************************************************/
 
 
-static void *AmiAlloc(unsigned int size, int flags);
+static void *AmiAlloc(unsigned int size, gfp_t flags);
 static void AmiFree(void *obj, unsigned int size);
 static int AmiIrqInit(void);
 #ifdef MODULE
@@ -317,7 +317,7 @@ static inline void StopDMA(void)
        enable_heartbeat();
 }
 
-static void *AmiAlloc(unsigned int size, int flags)
+static void *AmiAlloc(unsigned int size, gfp_t flags)
 {
        return amiga_chip_alloc((long)size, "dmasound [Paula]");
 }
index 92c25a0174db4d5b439ab186faf03473ef58d679..1ddaa6284b08f745d800fffaf428bd41450d486a 100644 (file)
@@ -36,7 +36,7 @@ static int expand_data;       /* Data for expanding */
 /*** Low level stuff *********************************************************/
 
 
-static void *Q40Alloc(unsigned int size, int flags);
+static void *Q40Alloc(unsigned int size, gfp_t flags);
 static void Q40Free(void *, unsigned int);
 static int Q40IrqInit(void);
 #ifdef MODULE
@@ -358,7 +358,7 @@ static TRANS transQ40Compressing = {
 
 /*** Low level stuff *********************************************************/
 
-static void *Q40Alloc(unsigned int size, int flags)
+static void *Q40Alloc(unsigned int size, gfp_t flags)
 {
          return kmalloc(size, flags); /* change to vmalloc */
 }
index e0d0365453b346bb13117df9d7a6356d643f64a3..f1a2e2c2e02fa8c1b679695fb20d4d5e892c936b 100644 (file)
@@ -163,7 +163,7 @@ static const uint8_t snd_usbmidi_cin_length[] = {
 /*
  * Submits the URB, with error handling.
  */
-static int snd_usbmidi_submit_urb(struct urb* urb, int flags)
+static int snd_usbmidi_submit_urb(struct urb* urb, gfp_t flags)
 {
        int err = usb_submit_urb(urb, flags);
        if (err < 0 && err != -ENODEV)