Merge branch 'linus' of master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa
authorLinus Torvalds <torvalds@g5.osdl.org>
Sun, 24 Sep 2006 00:21:12 +0000 (17:21 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Sun, 24 Sep 2006 00:21:12 +0000 (17:21 -0700)
* 'linus' of master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa: (148 commits)
  [ALSA] intel8x0m - Free irq in suspend
  [ALSA] Move CONFIG_SND_AC97_POWER_SAVE to pci/Kconfig
  [ALSA] usb-audio: add mixer control names for the Aureon 5.1 MkII
  [ALSA] ES1938: remove duplicate field initialization
  [ALSA] usb-audio: increase number of packets per URB
  [ALSA] hda-codec - Fix headphone auto-toggle on sigmatel codec
  [ALSA] hda-intel - A slight cleanup of timeout check in azx_get_response()
  [ALSA] hda-codec - Fix mic input with STAC92xx codecs
  [ALSA] mixart: Use SEEK_{SET,CUR,END} instead of hardcoded values
  [ALSA] gus: Use SEEK_{SET,CUR,END} instead of hardcoded values
  [ALSA] opl4: Use SEEK_{SET,CUR,END} instead of hardcoded values
  [ALSA] sound core: Use SEEK_{SET,CUR,END} instead of hardcoded values
  [ALSA] hda-codec - Support multiple headphone pins
  [ALSA] hda_intel prefer 24bit instead of 20bit
  [ALSA] hda-codec - Add vendor ids for Motorola and Conexant
  [ALSA] hda-codec - Add device id for Motorola si3054-compatible codec
  [ALSA] Add missing compat ioctls for ALSA control API
  [ALSA] powermac - Fix Oops when conflicting with aoa driver
  [ALSA] aoa: add locking to tas codec
  [ALSA] hda-intel - Fix suspend/resume with MSI
  ...

515 files changed:
CREDITS
Documentation/00-INDEX
Documentation/netlabel/00-INDEX [new file with mode: 0644]
Documentation/netlabel/cipso_ipv4.txt [new file with mode: 0644]
Documentation/netlabel/draft-ietf-cipso-ipsecurity-01.txt [new file with mode: 0644]
Documentation/netlabel/introduction.txt [new file with mode: 0644]
Documentation/netlabel/lsm_interface.txt [new file with mode: 0644]
Documentation/networking/ip-sysctl.txt
Documentation/networking/secid.txt [new file with mode: 0644]
arch/powerpc/platforms/powermac/feature.c
arch/powerpc/platforms/powermac/smp.c
block/ll_rw_blk.c
crypto/hmac.c
drivers/atm/he.c
drivers/char/briq_panel.c
drivers/infiniband/core/mad_priv.h
drivers/infiniband/hw/amso1100/c2_provider.c
drivers/infiniband/hw/amso1100/c2_rnic.c
drivers/infiniband/hw/ipath/ipath_diag.c
drivers/net/3c59x.c
drivers/net/8139cp.c
drivers/net/acenic.c
drivers/net/arcnet/com20020-pci.c
drivers/net/bnx2.c
drivers/net/cassini.c
drivers/net/chelsio/sge.c
drivers/net/dl2k.c
drivers/net/e1000/e1000_main.c
drivers/net/forcedeth.c
drivers/net/gianfar.c
drivers/net/hamachi.c
drivers/net/ibm_emac/ibm_emac_core.c
drivers/net/ioc3-eth.c
drivers/net/irda/ali-ircc.c
drivers/net/irda/irport.c
drivers/net/irda/via-ircc.c
drivers/net/irda/w83977af_ir.c
drivers/net/ixgb/ixgb_main.c
drivers/net/mv643xx_eth.c
drivers/net/myri10ge/myri10ge.c
drivers/net/ns83820.c
drivers/net/r8169.c
drivers/net/s2io.c
drivers/net/sk98lin/skge.c
drivers/net/skge.c
drivers/net/sky2.c
drivers/net/starfire.c
drivers/net/sungem.c
drivers/net/sunhme.c
drivers/net/tg3.c
drivers/net/typhoon.c
drivers/net/via-rhine.c
drivers/net/via-velocity.c
drivers/video/riva/fbdev.c
fs/Kconfig
fs/dcache.c
fs/lockd/clntproc.c
fs/lockd/host.c
fs/lockd/mon.c
fs/nfs/Makefile
fs/nfs/callback.c
fs/nfs/callback.h
fs/nfs/callback_proc.c
fs/nfs/client.c [new file with mode: 0644]
fs/nfs/delegation.c
fs/nfs/delegation.h
fs/nfs/dir.c
fs/nfs/file.c
fs/nfs/getroot.c [new file with mode: 0644]
fs/nfs/idmap.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/mount_clnt.c
fs/nfs/namespace.c
fs/nfs/nfs2xdr.c
fs/nfs/nfs3proc.c
fs/nfs/nfs3xdr.c
fs/nfs/nfs4_fs.h
fs/nfs/nfs4namespace.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4renewd.c
fs/nfs/nfs4state.c
fs/nfs/nfs4xdr.c
fs/nfs/proc.c
fs/nfs/read.c
fs/nfs/super.c
fs/nfs/write.c
fs/nfsd/nfs4callback.c
include/asm-ppc/ibm4xx.h
include/linux/blkdev.h
include/linux/bootmem.h
include/linux/dcache.h
include/linux/dccp.h
include/linux/fib_rules.h [new file with mode: 0644]
include/linux/filter.h
include/linux/genetlink.h
include/linux/if.h
include/linux/if_addr.h [new file with mode: 0644]
include/linux/in.h
include/linux/in6.h
include/linux/inet.h
include/linux/ip.h
include/linux/ipv6.h
include/linux/kernel.h
include/linux/neighbour.h [new file with mode: 0644]
include/linux/net.h
include/linux/netdevice.h
include/linux/netfilter.h
include/linux/netfilter/nf_conntrack_common.h
include/linux/netfilter/nf_conntrack_tcp.h
include/linux/netfilter/nfnetlink.h
include/linux/netfilter/nfnetlink_log.h
include/linux/netfilter/nfnetlink_queue.h
include/linux/netfilter/x_tables.h
include/linux/netfilter/xt_DSCP.h [new file with mode: 0644]
include/linux/netfilter/xt_dscp.h [new file with mode: 0644]
include/linux/netfilter_arp/arp_tables.h
include/linux/netfilter_bridge.h
include/linux/netfilter_ipv4/ip_conntrack_helper.h
include/linux/netfilter_ipv4/ip_conntrack_pptp.h
include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h
include/linux/netfilter_ipv4/ip_nat.h
include/linux/netfilter_ipv4/ip_nat_core.h
include/linux/netfilter_ipv4/ip_nat_pptp.h
include/linux/netfilter_ipv4/ip_tables.h
include/linux/netfilter_ipv4/ipt_DSCP.h
include/linux/netfilter_ipv4/ipt_dscp.h
include/linux/netfilter_ipv4/listhelp.h [deleted file]
include/linux/netfilter_ipv6.h
include/linux/netfilter_ipv6/ip6_tables.h
include/linux/netfilter_logging.h [deleted file]
include/linux/nfs_fs.h
include/linux/nfs_fs_sb.h
include/linux/nfs_idmap.h
include/linux/nfs_xdr.h
include/linux/pkt_cls.h
include/linux/rtnetlink.h
include/linux/security.h
include/linux/skbuff.h
include/linux/snmp.h
include/linux/sunrpc/clnt.h
include/linux/sunrpc/rpc_pipe_fs.h
include/linux/sunrpc/sched.h
include/linux/sunrpc/xprt.h
include/linux/sysctl.h
include/linux/writeback.h
include/linux/xfrm.h
include/net/act_api.h
include/net/act_generic.h [deleted file]
include/net/addrconf.h
include/net/cipso_ipv4.h [new file with mode: 0644]
include/net/dn_fib.h
include/net/dst.h
include/net/esp.h
include/net/fib_rules.h [new file with mode: 0644]
include/net/flow.h
include/net/genetlink.h
include/net/if_inet6.h
include/net/inet_connection_sock.h
include/net/inet_hashtables.h
include/net/inet_sock.h
include/net/ip6_fib.h
include/net/ip6_route.h
include/net/ip_fib.h
include/net/ipv6.h
include/net/mip6.h [new file with mode: 0644]
include/net/neighbour.h
include/net/netlabel.h [new file with mode: 0644]
include/net/netlink.h
include/net/nexthop.h [new file with mode: 0644]
include/net/pkt_act.h [deleted file]
include/net/request_sock.h
include/net/route.h
include/net/sctp/constants.h
include/net/sctp/sctp.h
include/net/sctp/structs.h
include/net/snmp.h
include/net/sock.h
include/net/tc_act/tc_defact.h
include/net/tc_act/tc_gact.h
include/net/tc_act/tc_ipt.h
include/net/tc_act/tc_mirred.h
include/net/tc_act/tc_pedit.h
include/net/udp.h
include/net/xfrm.h
kernel/taskstats.c
mm/page-writeback.c
mm/page_alloc.c
net/Kconfig
net/Makefile
net/atm/atm_sysfs.c
net/atm/mpc.c
net/atm/mpc.h
net/bridge/br_forward.c
net/bridge/br_netfilter.c
net/bridge/br_netlink.c
net/bridge/netfilter/ebtables.c
net/core/Makefile
net/core/datagram.c
net/core/dev.c
net/core/dev_mcast.c
net/core/fib_rules.c [new file with mode: 0644]
net/core/filter.c
net/core/flow.c
net/core/neighbour.c
net/core/netpoll.c
net/core/pktgen.c
net/core/rtnetlink.c
net/core/skbuff.c
net/core/sock.c
net/core/utils.c
net/core/wireless.c
net/dccp/ackvec.c
net/dccp/ackvec.h
net/dccp/ccids/Kconfig
net/dccp/ccids/ccid2.c
net/dccp/ccids/ccid2.h
net/dccp/ccids/ccid3.c
net/dccp/dccp.h
net/dccp/feat.h
net/dccp/ipv4.c
net/dccp/ipv6.c
net/dccp/output.c
net/dccp/proto.c
net/dccp/sysctl.c
net/decnet/Kconfig
net/decnet/af_decnet.c
net/decnet/dn_dev.c
net/decnet/dn_fib.c
net/decnet/dn_nsp_in.c
net/decnet/dn_route.c
net/decnet/dn_rules.c
net/decnet/dn_table.c
net/ethernet/eth.c
net/ipv4/Kconfig
net/ipv4/Makefile
net/ipv4/af_inet.c
net/ipv4/ah4.c
net/ipv4/cipso_ipv4.c [new file with mode: 0644]
net/ipv4/devinet.c
net/ipv4/esp4.c
net/ipv4/fib_frontend.c
net/ipv4/fib_hash.c
net/ipv4/fib_lookup.h
net/ipv4/fib_rules.c
net/ipv4/fib_semantics.c
net/ipv4/fib_trie.c
net/ipv4/icmp.c
net/ipv4/igmp.c
net/ipv4/inet_connection_sock.c
net/ipv4/inet_hashtables.c
net/ipv4/inetpeer.c
net/ipv4/ip_fragment.c
net/ipv4/ip_gre.c
net/ipv4/ip_options.c
net/ipv4/ip_output.c
net/ipv4/ipcomp.c
net/ipv4/ipconfig.c
net/ipv4/ipip.c
net/ipv4/ipmr.c
net/ipv4/ipvs/ip_vs_proto_tcp.c
net/ipv4/ipvs/ip_vs_proto_udp.c
net/ipv4/netfilter.c
net/ipv4/netfilter/Kconfig
net/ipv4/netfilter/Makefile
net/ipv4/netfilter/arp_tables.c
net/ipv4/netfilter/arpt_mangle.c
net/ipv4/netfilter/arptable_filter.c
net/ipv4/netfilter/ip_conntrack_core.c
net/ipv4/netfilter/ip_conntrack_helper_pptp.c
net/ipv4/netfilter/ip_conntrack_netbios_ns.c
net/ipv4/netfilter/ip_conntrack_netlink.c
net/ipv4/netfilter/ip_conntrack_proto_generic.c
net/ipv4/netfilter/ip_conntrack_proto_gre.c
net/ipv4/netfilter/ip_conntrack_proto_icmp.c
net/ipv4/netfilter/ip_conntrack_proto_sctp.c
net/ipv4/netfilter/ip_conntrack_proto_tcp.c
net/ipv4/netfilter/ip_conntrack_proto_udp.c
net/ipv4/netfilter/ip_conntrack_sip.c
net/ipv4/netfilter/ip_conntrack_standalone.c
net/ipv4/netfilter/ip_nat_core.c
net/ipv4/netfilter/ip_nat_helper.c
net/ipv4/netfilter/ip_nat_helper_pptp.c
net/ipv4/netfilter/ip_nat_proto_gre.c
net/ipv4/netfilter/ip_nat_proto_icmp.c
net/ipv4/netfilter/ip_nat_proto_tcp.c
net/ipv4/netfilter/ip_nat_proto_udp.c
net/ipv4/netfilter/ip_nat_rule.c
net/ipv4/netfilter/ip_nat_standalone.c
net/ipv4/netfilter/ip_queue.c
net/ipv4/netfilter/ip_tables.c
net/ipv4/netfilter/ipt_CLUSTERIP.c
net/ipv4/netfilter/ipt_DSCP.c [deleted file]
net/ipv4/netfilter/ipt_ECN.c
net/ipv4/netfilter/ipt_LOG.c
net/ipv4/netfilter/ipt_MASQUERADE.c
net/ipv4/netfilter/ipt_NETMAP.c
net/ipv4/netfilter/ipt_REDIRECT.c
net/ipv4/netfilter/ipt_REJECT.c
net/ipv4/netfilter/ipt_SAME.c
net/ipv4/netfilter/ipt_TCPMSS.c
net/ipv4/netfilter/ipt_TOS.c
net/ipv4/netfilter/ipt_TTL.c
net/ipv4/netfilter/ipt_ULOG.c
net/ipv4/netfilter/ipt_ah.c
net/ipv4/netfilter/ipt_dscp.c [deleted file]
net/ipv4/netfilter/ipt_ecn.c
net/ipv4/netfilter/ipt_hashlimit.c
net/ipv4/netfilter/ipt_owner.c
net/ipv4/netfilter/ipt_recent.c
net/ipv4/netfilter/iptable_filter.c
net/ipv4/netfilter/iptable_mangle.c
net/ipv4/netfilter/iptable_raw.c
net/ipv4/netfilter/nf_conntrack_proto_icmp.c
net/ipv4/proc.c
net/ipv4/raw.c
net/ipv4/route.c
net/ipv4/syncookies.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp.c
net/ipv4/tcp_bic.c
net/ipv4/tcp_cubic.c
net/ipv4/tcp_highspeed.c
net/ipv4/tcp_htcp.c
net/ipv4/tcp_hybla.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_lp.c
net/ipv4/tcp_minisocks.c
net/ipv4/tcp_output.c
net/ipv4/tcp_timer.c
net/ipv4/tcp_vegas.c
net/ipv4/tcp_veno.c
net/ipv4/tcp_westwood.c
net/ipv4/udp.c
net/ipv4/xfrm4_input.c
net/ipv4/xfrm4_mode_transport.c
net/ipv4/xfrm4_mode_tunnel.c
net/ipv4/xfrm4_output.c
net/ipv4/xfrm4_policy.c
net/ipv4/xfrm4_state.c
net/ipv4/xfrm4_tunnel.c
net/ipv6/Kconfig
net/ipv6/Makefile
net/ipv6/addrconf.c
net/ipv6/af_inet6.c
net/ipv6/ah6.c
net/ipv6/anycast.c
net/ipv6/datagram.c
net/ipv6/esp6.c
net/ipv6/exthdrs.c
net/ipv6/fib6_rules.c [new file with mode: 0644]
net/ipv6/icmp.c
net/ipv6/inet6_connection_sock.c
net/ipv6/ip6_fib.c
net/ipv6/ip6_input.c
net/ipv6/ip6_output.c
net/ipv6/ipcomp6.c
net/ipv6/ipv6_sockglue.c
net/ipv6/ipv6_syms.c
net/ipv6/mcast.c
net/ipv6/mip6.c [new file with mode: 0644]
net/ipv6/ndisc.c
net/ipv6/netfilter.c
net/ipv6/netfilter/Makefile
net/ipv6/netfilter/ip6_queue.c
net/ipv6/netfilter/ip6_tables.c
net/ipv6/netfilter/ip6t_HL.c
net/ipv6/netfilter/ip6t_LOG.c
net/ipv6/netfilter/ip6t_REJECT.c
net/ipv6/netfilter/ip6t_ah.c
net/ipv6/netfilter/ip6t_dst.c [deleted file]
net/ipv6/netfilter/ip6t_frag.c
net/ipv6/netfilter/ip6t_hbh.c
net/ipv6/netfilter/ip6t_ipv6header.c
net/ipv6/netfilter/ip6t_owner.c
net/ipv6/netfilter/ip6t_rt.c
net/ipv6/netfilter/ip6table_filter.c
net/ipv6/netfilter/ip6table_mangle.c
net/ipv6/netfilter/ip6table_raw.c
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
net/ipv6/netfilter/nf_conntrack_reasm.c
net/ipv6/raw.c
net/ipv6/reassembly.c
net/ipv6/route.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/ipv6/xfrm6_input.c
net/ipv6/xfrm6_mode_ro.c [new file with mode: 0644]
net/ipv6/xfrm6_mode_transport.c
net/ipv6/xfrm6_mode_tunnel.c
net/ipv6/xfrm6_output.c
net/ipv6/xfrm6_policy.c
net/ipv6/xfrm6_state.c
net/ipv6/xfrm6_tunnel.c
net/key/af_key.c
net/netfilter/Kconfig
net/netfilter/Makefile
net/netfilter/core.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_ftp.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_conntrack_proto_generic.c
net/netfilter/nf_conntrack_proto_sctp.c
net/netfilter/nf_conntrack_proto_tcp.c
net/netfilter/nf_conntrack_proto_udp.c
net/netfilter/nf_conntrack_standalone.c
net/netfilter/nf_internals.h
net/netfilter/nf_queue.c
net/netfilter/nfnetlink_queue.c
net/netfilter/x_tables.c
net/netfilter/xt_CLASSIFY.c
net/netfilter/xt_CONNMARK.c
net/netfilter/xt_CONNSECMARK.c
net/netfilter/xt_DSCP.c [new file with mode: 0644]
net/netfilter/xt_MARK.c
net/netfilter/xt_NFQUEUE.c
net/netfilter/xt_NOTRACK.c
net/netfilter/xt_SECMARK.c
net/netfilter/xt_comment.c
net/netfilter/xt_connbytes.c
net/netfilter/xt_connmark.c
net/netfilter/xt_conntrack.c
net/netfilter/xt_dccp.c
net/netfilter/xt_dscp.c [new file with mode: 0644]
net/netfilter/xt_esp.c
net/netfilter/xt_helper.c
net/netfilter/xt_length.c
net/netfilter/xt_limit.c
net/netfilter/xt_mac.c
net/netfilter/xt_mark.c
net/netfilter/xt_multiport.c
net/netfilter/xt_physdev.c
net/netfilter/xt_pkttype.c
net/netfilter/xt_policy.c
net/netfilter/xt_quota.c
net/netfilter/xt_sctp.c
net/netfilter/xt_state.c
net/netfilter/xt_statistic.c
net/netfilter/xt_string.c
net/netfilter/xt_tcpmss.c
net/netfilter/xt_tcpudp.c
net/netlabel/Kconfig [new file with mode: 0644]
net/netlabel/Makefile [new file with mode: 0644]
net/netlabel/netlabel_cipso_v4.c [new file with mode: 0644]
net/netlabel/netlabel_cipso_v4.h [new file with mode: 0644]
net/netlabel/netlabel_domainhash.c [new file with mode: 0644]
net/netlabel/netlabel_domainhash.h [new file with mode: 0644]
net/netlabel/netlabel_kapi.c [new file with mode: 0644]
net/netlabel/netlabel_mgmt.c [new file with mode: 0644]
net/netlabel/netlabel_mgmt.h [new file with mode: 0644]
net/netlabel/netlabel_unlabeled.c [new file with mode: 0644]
net/netlabel/netlabel_unlabeled.h [new file with mode: 0644]
net/netlabel/netlabel_user.c [new file with mode: 0644]
net/netlabel/netlabel_user.h [new file with mode: 0644]
net/netlink/af_netlink.c
net/netlink/attr.c
net/netlink/genetlink.c
net/packet/af_packet.c
net/sched/act_api.c
net/sched/act_gact.c
net/sched/act_ipt.c
net/sched/act_mirred.c
net/sched/act_pedit.c
net/sched/act_police.c
net/sched/act_simple.c
net/sched/cls_fw.c
net/sched/sch_htb.c
net/sched/sch_netem.c
net/sctp/input.c
net/sctp/inqueue.c
net/sctp/ipv6.c
net/sctp/outqueue.c
net/sctp/proc.c
net/sctp/protocol.c
net/sctp/sm_statefuns.c
net/sctp/socket.c
net/sctp/sysctl.c
net/sctp/transport.c
net/socket.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/clnt.c
net/sunrpc/pmap_clnt.c
net/sunrpc/rpc_pipe.c
net/sunrpc/sched.c
net/sunrpc/socklib.c
net/sunrpc/sunrpc_syms.c
net/sunrpc/svcsock.c
net/sunrpc/timer.c
net/sunrpc/xprt.c
net/sunrpc/xprtsock.c
net/unix/af_unix.c
net/xfrm/Kconfig
net/xfrm/Makefile
net/xfrm/xfrm_hash.c [new file with mode: 0644]
net/xfrm/xfrm_hash.h [new file with mode: 0644]
net/xfrm/xfrm_input.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c
net/xfrm/xfrm_user.c
security/dummy.c
security/selinux/hooks.c
security/selinux/include/av_perm_to_string.h
security/selinux/include/av_permissions.h
security/selinux/include/objsec.h
security/selinux/include/security.h
security/selinux/include/selinux_netlabel.h [new file with mode: 0644]
security/selinux/include/xfrm.h
security/selinux/ss/ebitmap.c
security/selinux/ss/ebitmap.h
security/selinux/ss/mls.c
security/selinux/ss/mls.h
security/selinux/ss/services.c
security/selinux/xfrm.c

diff --git a/CREDITS b/CREDITS
index 0fe904ebb7c7d9cc19022a8b685ca748dacb8e02..cc3453a55fb948f5173ff82715c304d18dc1212d 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -2384,6 +2384,13 @@ N: Thomas Molina
 E: tmolina@cablespeed.com
 D: bug fixes, documentation, minor hackery
 
+N: Paul Moore
+E: paul.moore@hp.com
+D: NetLabel author
+S: Hewlett-Packard
+S: 110 Spit Brook Road
+S: Nashua, NH 03062
+
 N: James Morris
 E: jmorris@namei.org
 W: http://namei.org/
index 5f7f7d7f77d25ebbfdd2f31359257991d92dc69a..02457ec9c94fe27ec74dc943186283137774e232 100644 (file)
@@ -184,6 +184,8 @@ mtrr.txt
        - how to use PPro Memory Type Range Registers to increase performance.
 nbd.txt
        - info on a TCP implementation of a network block device.
+netlabel/
+       - directory with information on the NetLabel subsystem.
 networking/
        - directory with info on various aspects of networking with Linux.
 nfsroot.txt
diff --git a/Documentation/netlabel/00-INDEX b/Documentation/netlabel/00-INDEX
new file mode 100644 (file)
index 0000000..837bf35
--- /dev/null
@@ -0,0 +1,10 @@
+00-INDEX
+       - this file.
+cipso_ipv4.txt
+       - documentation on the IPv4 CIPSO protocol engine.
+draft-ietf-cipso-ipsecurity-01.txt
+       - IETF draft of the CIPSO protocol, dated 16 July 1992.
+introduction.txt
+       - NetLabel introduction, READ THIS FIRST.
+lsm_interface.txt
+       - documentation on the NetLabel kernel security module API.
diff --git a/Documentation/netlabel/cipso_ipv4.txt b/Documentation/netlabel/cipso_ipv4.txt
new file mode 100644 (file)
index 0000000..93dacb1
--- /dev/null
@@ -0,0 +1,48 @@
+NetLabel CIPSO/IPv4 Protocol Engine
+==============================================================================
+Paul Moore, paul.moore@hp.com
+
+May 17, 2006
+
+ * Overview
+
+The NetLabel CIPSO/IPv4 protocol engine is based on the IETF Commercial IP
+Security Option (CIPSO) draft from July 16, 1992.  A copy of this draft can be
+found in this directory, consult '00-INDEX' for the filename.  While the IETF
+draft never made it to an RFC standard it has become a de-facto standard for
+labeled networking and is used in many trusted operating systems.
+
+ * Outbound Packet Processing
+
+The CIPSO/IPv4 protocol engine applies the CIPSO IP option to packets by
+adding the CIPSO label to the socket.  This causes all packets leaving the
+system through the socket to have the CIPSO IP option applied.  The socket's
+CIPSO label can be changed at any point in time, however, it is recommended
+that it is set upon the socket's creation.  The LSM can set the socket's CIPSO
+label by using the NetLabel security module API; if the NetLabel "domain" is
+configured to use CIPSO for packet labeling then a CIPSO IP option will be
+generated and attached to the socket.
+
+ * Inbound Packet Processing
+
+The CIPSO/IPv4 protocol engine validates every CIPSO IP option it finds at the
+IP layer without any special handling required by the LSM.  However, in order
+to decode and translate the CIPSO label on the packet the LSM must use the
+NetLabel security module API to extract the security attributes of the packet.
+This is typically done at the socket layer using the 'socket_sock_rcv_skb()'
+LSM hook.
+
+ * Label Translation
+
+The CIPSO/IPv4 protocol engine contains a mechanism to translate CIPSO security
+attributes such as sensitivity level and category to values which are
+appropriate for the host.  These mappings are defined as part of a CIPSO
+Domain Of Interpretation (DOI) definition and are configured through the
+NetLabel user space communication layer.  Each DOI definition can have a
+different security attribute mapping table.
+
+ * Label Translation Cache
+
+The NetLabel system provides a framework for caching security attribute
+mappings from the network labels to the corresponding LSM identifiers.  The
+CIPSO/IPv4 protocol engine supports this caching mechanism.
diff --git a/Documentation/netlabel/draft-ietf-cipso-ipsecurity-01.txt b/Documentation/netlabel/draft-ietf-cipso-ipsecurity-01.txt
new file mode 100644 (file)
index 0000000..256c2c9
--- /dev/null
@@ -0,0 +1,791 @@
+IETF CIPSO Working Group
+16 July, 1992
+
+
+
+                 COMMERCIAL IP SECURITY OPTION (CIPSO 2.2)
+
+
+
+1.    Status
+
+This Internet Draft provides the high level specification for a Commercial
+IP Security Option (CIPSO).  This draft reflects the version as approved by
+the CIPSO IETF Working Group.  Distribution of this memo is unlimited.
+
+This document is an Internet Draft.  Internet Drafts are working documents
+of the Internet Engineering Task Force (IETF), its Areas, and its Working
+Groups. Note that other groups may also distribute working documents as
+Internet Drafts.
+
+Internet Drafts are draft documents valid for a maximum of six months.
+Internet Drafts may be updated, replaced, or obsoleted by other documents
+at any time.  It is not appropriate to use Internet Drafts as reference
+material or to cite them other than as a "working draft" or "work in
+progress."
+
+Please check the I-D abstract listing contained in each Internet Draft
+directory to learn the current status of this or any other Internet Draft.
+
+
+
+
+2.    Background
+
+Currently the Internet Protocol includes two security options.  One of
+these options is the DoD Basic Security Option (BSO) (Type 130) which allows
+IP datagrams to be labeled with security classifications.  This option
+provides sixteen security classifications and a variable number of handling
+restrictions.  To handle additional security information, such as security
+categories or compartments, another security option (Type 133) exists and
+is referred to as the DoD Extended Security Option (ESO).  The values for
+the fixed fields within these two options are administered by the Defense
+Information Systems Agency (DISA).
+
+Computer vendors are now building commercial operating systems with
+mandatory access controls and multi-level security.  These systems are
+no longer built specifically for a particular group in the defense or
+intelligence communities.  They are generally available commercial systems
+for use in a variety of government and civil sector environments.
+
+The small number of ESO format codes can not support all the possible
+applications of a commercial security option.  The BSO and ESO were
+designed to only support the United States DoD.  CIPSO has been designed
+to support multiple security policies.  This Internet Draft provides the
+format and procedures required to support a Mandatory Access Control
+security policy.  Support for additional security policies shall be
+defined in future RFCs.
+
+
+
+
+Internet Draft, Expires 15 Jan 93                                 [PAGE 1]
+
+
+
+CIPSO INTERNET DRAFT                                         16 July, 1992
+
+
+
+
+3.    CIPSO Format
+
+Option type: 134 (Class 0, Number 6, Copy on Fragmentation)
+Option length: Variable
+
+This option permits security related information to be passed between
+systems within a single Domain of Interpretation (DOI).  A DOI is a
+collection of systems which agree on the meaning of particular values
+in the security option.  An authority that has been assigned a DOI
+identifier will define a mapping between appropriate CIPSO field values
+and their human readable equivalent.  This authority will distribute that
+mapping to hosts within the authority's domain.  These mappings may be
+sensitive, therefore a DOI authority is not required to make these
+mappings available to anyone other than the systems that are included in
+the DOI.
+
+This option MUST be copied on fragmentation.  This option appears at most
+once in a datagram.  All multi-octet fields in the option are defined to be
+transmitted in network byte order.  The format of this option is as follows:
+
++----------+----------+------//------+-----------//---------+
+| 10000110 | LLLLLLLL | DDDDDDDDDDDD | TTTTTTTTTTTTTTTTTTTT |
++----------+----------+------//------+-----------//---------+
+
+  TYPE=134    OPTION    DOMAIN OF               TAGS
+              LENGTH    INTERPRETATION
+
+
+                Figure 1. CIPSO Format
+
+
+3.1    Type
+
+This field is 1 octet in length.  Its value is 134.
+
+
+3.2    Length
+
+This field is 1 octet in length.  It is the total length of the option
+including the type and length fields.  With the current IP header length
+restriction of 40 octets the value of this field MUST not exceed 40.
+
+
+3.3    Domain of Interpretation Identifier
+
+This field is an unsigned 32 bit integer.  The value 0 is reserved and MUST
+not appear as the DOI identifier in any CIPSO option.  Implementations
+should assume that the DOI identifier field is not aligned on any particular
+byte boundary.
+
+To conserve space in the protocol, security levels and categories are
+represented by numbers rather than their ASCII equivalent.  This requires
+a mapping table within CIPSO hosts to map these numbers to their
+corresponding ASCII representations.  Non-related groups of systems may
+
+
+
+Internet Draft, Expires 15 Jan 93                                 [PAGE 2]
+
+
+
+CIPSO INTERNET DRAFT                                         16 July, 1992
+
+
+
+have their own unique mappings.  For example, one group of systems may
+use the number 5 to represent Unclassified while another group may use the
+number 1 to represent that same security level.  The DOI identifier is used
+to identify which mapping was used for the values within the option.
+
+
+3.4    Tag Types
+
+A common format for passing security related information is necessary
+for interoperability.  CIPSO uses sets of "tags" to contain the security
+information relevant to the data in the IP packet.  Each tag begins with
+a tag type identifier followed by the length of the tag and ends with the
+actual security information to be passed.  All multi-octet fields in a tag
+are defined to be transmitted in network byte order.  Like the DOI
+identifier field in the CIPSO header, implementations should assume that
+all tags, as well as fields within a tag, are not aligned on any particular
+octet boundary.   The tag types defined in this document contain alignment
+bytes to assist alignment of some information, however alignment can not
+be guaranteed if CIPSO is not the first IP option.
+
+CIPSO tag types 0 through 127 are reserved for defining standard tag
+formats.  Their definitions will be published in RFCs.  Tag types whose
+identifiers are greater than 127 are defined by the DOI authority and may
+only be meaningful in certain Domains of Interpretation.  For these tag
+types, implementations will require the DOI identifier as well as the tag
+number to determine the security policy and the format associated with the
+tag.  Use of tag types above 127 are restricted to closed networks where
+interoperability with other networks will not be an issue.  Implementations
+that support a tag type greater than 127 MUST support at least one DOI that
+requires only tag types 1 to 127.
+
+Tag type 0 is reserved. Tag types 1, 2, and 5 are defined in this
+Internet Draft.  Types 3 and 4 are reserved for work in progress.
+The standard format for all current and future CIPSO tags is shown below:
+
++----------+----------+--------//--------+
+| TTTTTTTT | LLLLLLLL | IIIIIIIIIIIIIIII |
++----------+----------+--------//--------+
+    TAG       TAG         TAG
+    TYPE      LENGTH      INFORMATION
+
+    Figure 2:  Standard Tag Format
+
+In the three tag types described in this document, the length and count
+restrictions are based on the current IP limitation of 40 octets for all
+IP options.  If the IP header is later expanded, then the length and count
+restrictions specified in this document may increase to use the full area
+provided for IP options.
+
+
+3.4.1    Tag Type Classes
+
+Tag classes consist of tag types that have common processing requirements
+and support the same security policy.  The three tags defined in this
+Internet Draft belong to the Mandatory Access Control (MAC) Sensitivity
+
+
+
+Internet Draft, Expires 15 Jan 93                                 [PAGE 3]
+
+
+
+CIPSO INTERNET DRAFT                                         16 July, 1992
+
+
+
+class and support the MAC Sensitivity security policy.
+
+
+3.4.2    Tag Type 1
+
+This is referred to as the "bit-mapped" tag type.  Tag type 1 is included
+in the MAC Sensitivity tag type class.  The format of this tag type is as
+follows:
+
++----------+----------+----------+----------+--------//---------+
+| 00000001 | LLLLLLLL | 00000000 | LLLLLLLL | CCCCCCCCCCCCCCCCC |
++----------+----------+----------+----------+--------//---------+
+
+    TAG       TAG      ALIGNMENT  SENSITIVITY    BIT MAP OF
+    TYPE      LENGTH   OCTET      LEVEL          CATEGORIES
+
+            Figure 3. Tag Type 1 Format
+
+
+3.4.2.1    Tag Type
+
+This field is 1 octet in length and has a value of 1.
+
+
+3.4.2.2    Tag Length
+
+This field is 1 octet in length.  It is the total length of the tag type
+including the type and length fields.  With the current IP header length
+restriction of 40 bytes the value within this field is between 4 and 34.
+
+
+3.4.2.3    Alignment Octet
+
+This field is 1 octet in length and always has the value of 0.  Its purpose
+is to align the category bitmap field on an even octet boundary.  This will
+speed many implementations including router implementations.
+
+
+3.4.2.4    Sensitivity Level
+
+This field is 1 octet in length.  Its value is from 0 to 255.  The values
+are ordered with 0 being the minimum value and 255 representing the maximum
+value.
+
+
+3.4.2.5    Bit Map of Categories
+
+The length of this field is variable and ranges from 0 to 30 octets.  This
+provides representation of categories 0 to 239.  The ordering of the bits
+is left to right or MSB to LSB.  For example category 0 is represented by
+the most significant bit of the first byte and category 15 is represented
+by the least significant bit of the second byte.  Figure 4 graphically
+shows this ordering.  Bit N is binary 1 if category N is part of the label
+for the datagram, and bit N is binary 0 if category N is not part of the
+label.  Except for the optimized tag 1 format described in the next section,
+
+
+
+Internet Draft, Expires 15 Jan 93                                 [PAGE 4]
+
+
+
+CIPSO INTERNET DRAFT                                         16 July, 1992
+
+
+
+minimal encoding SHOULD be used resulting in no trailing zero octets in the
+category bitmap.
+
+        octet 0  octet 1  octet 2  octet 3  octet 4  octet 5
+        XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX . . .
+bit     01234567 89111111 11112222 22222233 33333333 44444444
+number             012345 67890123 45678901 23456789 01234567
+
+            Figure 4. Ordering of Bits in Tag 1 Bit Map
+
+
+3.4.2.6    Optimized Tag 1 Format
+
+Routers work most efficiently when processing fixed length fields.  To
+support these routers there is an optimized form of tag type 1.  The format
+does not change.  The only change is to the category bitmap which is set to
+a constant length of 10 octets.  Trailing octets required to fill out the 10
+octets are zero filled.  Ten octets, allowing for 80 categories, was chosen
+because it makes the total length of the CIPSO option 20 octets.  If CIPSO
+is the only option then the option will be full word aligned and additional
+filler octets will not be required.
+
+
+3.4.3    Tag Type 2
+
+This is referred to as the "enumerated" tag type.  It is used to describe
+large but sparsely populated sets of categories.  Tag type 2 is in the MAC
+Sensitivity tag type class.  The format of this tag type is as follows:
+
++----------+----------+----------+----------+-------------//-------------+
+| 00000010 | LLLLLLLL | 00000000 | LLLLLLLL | CCCCCCCCCCCCCCCCCCCCCCCCCC |
++----------+----------+----------+----------+-------------//-------------+
+
+    TAG       TAG      ALIGNMENT  SENSITIVITY         ENUMERATED
+    TYPE      LENGTH   OCTET      LEVEL               CATEGORIES
+
+                Figure 5. Tag Type 2 Format
+
+
+3.4.3.1     Tag Type
+
+This field is one octet in length and has a value of 2.
+
+
+3.4.3.2    Tag Length
+
+This field is 1 octet in length. It is the total length of the tag type
+including the type and length fields.  With the current IP header length
+restriction of 40 bytes the value within this field is between 4 and 34.
+
+
+3.4.3.3    Alignment Octet
+
+This field is 1 octet in length and always has the value of 0.  Its purpose
+is to align the category field on an even octet boundary.  This will
+
+
+
+Internet Draft, Expires 15 Jan 93                                 [PAGE 5]
+
+
+
+CIPSO INTERNET DRAFT                                         16 July, 1992
+
+
+
+speed many implementations including router implementations.
+
+
+3.4.3.4    Sensitivity Level
+
+This field is 1 octet in length. Its value is from 0 to 255.  The values
+are ordered with 0 being the minimum value and 255 representing the
+maximum value.
+
+
+3.4.3.5    Enumerated Categories
+
+In this tag, categories are represented by their actual value rather than
+by their position within a bit field.  The length of each category is 2
+octets.  Up to 15 categories may be represented by this tag.  Valid values
+for categories are 0 to 65534.  Category 65535 is not a valid category
+value.  The categories MUST be listed in ascending order within the tag.
+
+
+3.4.4    Tag Type 5
+
+This is referred to as the "range" tag type.  It is used to represent
+labels where all categories in a range, or set of ranges, are included
+in the sensitivity label.  Tag type 5 is in the MAC Sensitivity tag type
+class.  The format of this tag type is as follows:
+
++----------+----------+----------+----------+------------//-------------+
+| 00000101 | LLLLLLLL | 00000000 | LLLLLLLL |  Top/Bottom | Top/Bottom  |
++----------+----------+----------+----------+------------//-------------+
+
+    TAG       TAG      ALIGNMENT  SENSITIVITY        CATEGORY RANGES
+    TYPE      LENGTH   OCTET      LEVEL
+
+                     Figure 6. Tag Type 5 Format
+
+
+3.4.4.1     Tag Type
+
+This field is one octet in length and has a value of 5.
+
+
+3.4.4.2    Tag Length
+
+This field is 1 octet in length. It is the total length of the tag type
+including the type and length fields.  With the current IP header length
+restriction of 40 bytes the value within this field is between 4 and 34.
+
+
+3.4.4.3    Alignment Octet
+
+This field is 1 octet in length and always has the value of 0.  Its purpose
+is to align the category range field on an even octet boundary.  This will
+speed many implementations including router implementations.
+
+
+
+
+
+Internet Draft, Expires 15 Jan 93                                 [PAGE 6]
+
+
+
+CIPSO INTERNET DRAFT                                         16 July, 1992
+
+
+
+3.4.4.4    Sensitivity Level
+
+This field is 1 octet in length. Its value is from 0 to 255.  The values
+are ordered with 0 being the minimum value and 255 representing the maximum
+value.
+
+
+3.4.4.5    Category Ranges
+
+A category range is a 4 octet field comprised of the 2 octet index of the
+highest numbered category followed by the 2 octet index of the lowest
+numbered category.  These range endpoints are inclusive within the range of
+categories.  All categories within a range are included in the sensitivity
+label.  This tag may contain a maximum of 7 category pairs.  The bottom
+category endpoint for the last pair in the tag MAY be omitted and SHOULD be
+assumed to be 0.  The ranges MUST be non-overlapping and be listed in
+descending order.  Valid values for categories are 0 to 65534.  Category
+65535 is not a valid category value.
+
+
+3.4.5     Minimum Requirements
+
+A CIPSO implementation MUST be capable of generating at least tag type 1 in
+the non-optimized form.  In addition, a CIPSO implementation MUST be able
+to receive any valid tag type 1 even those using the optimized tag type 1
+format.
+
+
+4.    Configuration Parameters
+
+The configuration parameters defined below are required for all CIPSO hosts,
+gateways, and routers that support multiple sensitivity labels.  A CIPSO
+host is defined to be the origination or destination system for an IP
+datagram.  A CIPSO gateway provides IP routing services between two or more
+IP networks and may be required to perform label translations between
+networks.  A CIPSO gateway may be an enhanced CIPSO host or it may just
+provide gateway services with no end system CIPSO capabilities.  A CIPSO
+router is a dedicated IP router that routes IP datagrams between two or more
+IP networks.
+
+An implementation of CIPSO on a host MUST have the capability to reject a
+datagram for reasons that the information contained can not be adequately
+protected by the receiving host or if acceptance may result in violation of
+the host or network security policy.  In addition, a CIPSO gateway or router
+MUST be able to reject datagrams going to networks that can not provide
+adequate protection or may violate the network's security policy.  To
+provide this capability the following minimal set of configuration
+parameters are required for CIPSO implementations:
+
+HOST_LABEL_MAX - This parameter contains the maximum sensitivity label that
+a CIPSO host is authorized to handle.  All datagrams that have a label
+greater than this maximum MUST be rejected by the CIPSO host.  This
+parameter does not apply to CIPSO gateways or routers.  This parameter need
+not be defined explicitly as it can be implicitly derived from the
+PORT_LABEL_MAX parameters for the associated interfaces.
+
+
+
+Internet Draft, Expires 15 Jan 93                                 [PAGE 7]
+
+
+
+CIPSO INTERNET DRAFT                                         16 July, 1992
+
+
+
+
+HOST_LABEL_MIN - This parameter contains the minimum sensitivity label that
+a CIPSO host is authorized to handle.  All datagrams that have a label less
+than this minimum MUST be rejected by the CIPSO host.  This parameter does
+not apply to CIPSO gateways or routers.  This parameter need not be defined
+explicitly as it can be implicitly derived from the PORT_LABEL_MIN
+parameters for the associated interfaces.
+
+PORT_LABEL_MAX - This parameter contains the maximum sensitivity label for
+all datagrams that may exit a particular network interface port.  All
+outgoing datagrams that have a label greater than this maximum MUST be
+rejected by the CIPSO system.  The label within this parameter MUST be
+less than or equal to the label within the HOST_LABEL_MAX parameter.  This
+parameter does not apply to CIPSO hosts that support only one network port.
+
+PORT_LABEL_MIN - This parameter contains the minimum sensitivity label for
+all datagrams that may exit a particular network interface port.  All
+outgoing datagrams that have a label less than this minimum MUST be
+rejected by the CIPSO system.  The label within this parameter MUST be
+greater than or equal to the label within the HOST_LABEL_MIN parameter.
+This parameter does not apply to CIPSO hosts that support only one network
+port.
+
+PORT_DOI - This parameter is used to assign a DOI identifier value to a
+particular network interface port.  All CIPSO labels within datagrams
+going out this port MUST use the specified DOI identifier.  All CIPSO
+hosts and gateways MUST support either this parameter, the NET_DOI
+parameter, or the HOST_DOI parameter.
+
+NET_DOI - This parameter is used to assign a DOI identifier value to a
+particular IP network address.  All CIPSO labels within datagrams destined
+for the particular IP network MUST use the specified DOI identifier.  All
+CIPSO hosts and gateways MUST support either this parameter, the PORT_DOI
+parameter, or the HOST_DOI parameter.
+
+HOST_DOI - This parameter is used to assign a DOI identifier value to a
+particular IP host address.  All CIPSO labels within datagrams destined for
+the particular IP host will use the specified DOI identifier.  All CIPSO
+hosts and gateways MUST support either this parameter, the PORT_DOI
+parameter, or the NET_DOI parameter.
+
+This list represents the minimal set of configuration parameters required
+to be compliant.  Implementors are encouraged to add to this list to
+provide enhanced functionality and control.  For example, many security
+policies may require both incoming and outgoing datagrams be checked against
+the port and host label ranges.
+
+
+4.1    Port Range Parameters
+
+The labels represented by the PORT_LABEL_MAX and PORT_LABEL_MIN parameters
+MAY be in CIPSO or local format.  Some CIPSO systems, such as routers, may
+want to have the range parameters expressed in CIPSO format so that incoming
+labels do not have to be converted to a local format before being compared
+against the range.  If multiple DOIs are supported by one of these CIPSO
+
+
+
+Internet Draft, Expires 15 Jan 93                                 [PAGE 8]
+
+
+
+CIPSO INTERNET DRAFT                                         16 July, 1992
+
+
+
+systems then multiple port range parameters would be needed, one set for
+each DOI supported on a particular port.
+
+The port range will usually represent the total set of labels that may
+exist on the logical network accessed through the corresponding network
+interface.  It may, however, represent a subset of these labels that are
+allowed to enter the CIPSO system.
+
+
+4.2    Single Label CIPSO Hosts
+
+CIPSO implementations that support only one label are not required to
+support the parameters described above.  These limited implementations are
+only required to support a NET_LABEL parameter.  This parameter contains
+the CIPSO label that may be inserted in datagrams that exit the host.  In
+addition, the host MUST reject any incoming datagram that has a label which
+is not equivalent to the NET_LABEL parameter.
+
+
+5.    Handling Procedures
+
+This section describes the processing requirements for incoming and
+outgoing IP datagrams.  Just providing the correct CIPSO label format
+is not enough.  Assumptions will be made by one system on how a
+receiving system will handle the CIPSO label.  Wrong assumptions may
+lead to non-interoperability or even a security incident.  The
+requirements described below represent the minimal set needed for
+interoperability and that provide users some level of confidence.
+Many other requirements could be added to increase user confidence,
+however at the risk of restricting creativity and limiting vendor
+participation.
+
+
+5.1    Input Procedures
+
+All datagrams received through a network port MUST have a security label
+associated with them, either contained in the datagram or assigned to the
+receiving port.  Without this label the host, gateway, or router will not
+have the information it needs to make security decisions.  This security
+label will be obtained from the CIPSO if the option is present in the
+datagram.  See section 4.1.2 for handling procedures for unlabeled
+datagrams.  This label will be compared against the PORT (if appropriate)
+and HOST configuration parameters defined in section 3.
+
+If any field within the CIPSO option, such as the DOI identifier, is not
+recognized the IP datagram is discarded and an ICMP "parameter problem"
+(type 12) is generated and returned.  The ICMP code field is set to "bad
+parameter" (code 0) and the pointer is set to the start of the CIPSO field
+that is unrecognized.
+
+If the contents of the CIPSO are valid but the security label is
+outside of the configured host or port label range, the datagram is
+discarded and an ICMP "destination unreachable" (type 3) is generated
+and returned.  The code field of the ICMP is set to "communication with
+destination network administratively prohibited" (code 9) or to
+
+
+
+Internet Draft, Expires 15 Jan 93                                 [PAGE 9]
+
+
+
+CIPSO INTERNET DRAFT                                         16 July, 1992
+
+
+
+"communication with destination host administratively prohibited"
+(code 10).  The value of the code field used is dependent upon whether
+the originator of the ICMP message is acting as a CIPSO host or a CIPSO
+gateway.  The recipient of the ICMP message MUST be able to handle either
+value.  The same procedure is performed if a CIPSO can not be added to an
+IP packet because it is too large to fit in the IP options area.
+
+If the error is triggered by receipt of an ICMP message, the message
+is discarded and no response is permitted (consistent with general ICMP
+processing rules).
+
+
+5.1.1    Unrecognized tag types
+
+The default condition for any CIPSO implementation is that an
+unrecognized tag type MUST be treated as a "parameter problem" and
+handled as described in section 4.1.  A CIPSO implementation MAY allow
+the system administrator to identify tag types that may safely be
+ignored.  This capability is an allowable enhancement, not a
+requirement.
+
+
+5.1.2    Unlabeled Packets
+
+A network port may be configured to not require a CIPSO label for all
+incoming  datagrams.  For this configuration a CIPSO label must be
+assigned to that network port and associated with all unlabeled IP
+datagrams.  This capability might be used for single level networks or
+networks that have CIPSO and non-CIPSO hosts and the non-CIPSO hosts
+all operate at the same label.
+
+If a CIPSO option is required and none is found, the datagram is
+discarded and an ICMP "parameter problem" (type 12) is generated and
+returned to the originator of the datagram.  The code field of the ICMP
+is set to "option missing" (code 1) and the ICMP pointer is set to 134
+(the value of the option type for the missing CIPSO option).
+
+
+5.2    Output Procedures
+
+A CIPSO option MUST appear only once in a datagram.  Only one tag type
+from the MAC Sensitivity class MAY be included in a CIPSO option.  Given
+the current set of defined tag types, this means that CIPSO labels at
+first will contain only one tag.
+
+All datagrams leaving a CIPSO system MUST meet the following condition:
+
+        PORT_LABEL_MIN <= CIPSO label <= PORT_LABEL_MAX
+
+If this condition is not satisfied the datagram MUST be discarded.
+If the CIPSO system only supports one port, the HOST_LABEL_MIN and the
+HOST_LABEL_MAX parameters MAY be substituted for the PORT parameters in
+the above condition.
+
+The DOI identifier to be used for all outgoing datagrams is configured by
+
+
+
+Internet Draft, Expires 15 Jan 93                                 [PAGE 10]
+
+
+
+CIPSO INTERNET DRAFT                                         16 July, 1992
+
+
+
+the administrator.  If port level DOI identifier assignment is used, then
+the PORT_DOI configuration parameter MUST contain the DOI identifier to
+use.  If network level DOI assignment is used, then the NET_DOI parameter
+MUST contain the DOI identifier to use.  And if host level DOI assignment
+is employed, then the HOST_DOI parameter MUST contain the DOI identifier
+to use.  A CIPSO implementation need only support one level of DOI
+assignment.
+
+
+5.3    DOI Processing Requirements
+
+A CIPSO implementation MUST support at least one DOI and SHOULD support
+multiple DOIs.  System and network administrators are cautioned to
+ensure that at least one DOI is common within an IP network to allow for
+broadcasting of IP datagrams.
+
+CIPSO gateways MUST be capable of translating a CIPSO option from one
+DOI to another when forwarding datagrams between networks.  For
+efficiency purposes this capability is only a desired feature for CIPSO
+routers.
+
+
+5.4    Label of ICMP Messages
+
+The CIPSO label to be used on all outgoing ICMP messages MUST be equivalent
+to the label of the datagram that caused the ICMP message.  If the ICMP was
+generated due to a problem associated with the original CIPSO label then the
+following responses are allowed:
+
+  a.  Use the CIPSO label of the original IP datagram
+  b.  Drop the original datagram with no return message generated
+
+In most cases these options will have the same effect.  If you can not
+interpret the label or if it is outside the label range of your host or
+interface then an ICMP message with the same label will probably not be
+able to exit the system.
+
+
+6.    Assignment of DOI Identifier Numbers                                   =
+
+Requests for assignment of a DOI identifier number should be addressed to
+the Internet Assigned Numbers Authority (IANA).
+
+
+7.    Acknowledgements
+
+Much of the material in this RFC is based on (and copied from) work
+done by Gary Winiger of Sun Microsystems and published as Commercial
+IP Security Option at the INTEROP 89, Commercial IPSO Workshop.
+
+
+8.    Author's Address
+
+To submit mail for distribution to members of the IETF CIPSO Working
+Group, send mail to: cipso@wdl1.wdl.loral.com.
+
+
+
+Internet Draft, Expires 15 Jan 93                                 [PAGE 11]
+
+
+
+CIPSO INTERNET DRAFT                                         16 July, 1992
+
+
+
+
+To be added to or deleted from this distribution, send mail to:
+cipso-request@wdl1.wdl.loral.com.
+
+
+9.    References
+
+RFC 1038, "Draft Revised IP Security Option", M. St. Johns, IETF, January
+1988.
+
+RFC 1108, "U.S. Department of Defense Security Options
+for the Internet Protocol", Stephen Kent, IAB, 1 March, 1991.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Internet Draft, Expires 15 Jan 93                                 [PAGE 12]
+
+
+
diff --git a/Documentation/netlabel/introduction.txt b/Documentation/netlabel/introduction.txt
new file mode 100644 (file)
index 0000000..a4ffba1
--- /dev/null
@@ -0,0 +1,46 @@
+NetLabel Introduction
+==============================================================================
+Paul Moore, paul.moore@hp.com
+
+August 2, 2006
+
+ * Overview
+
+NetLabel is a mechanism which can be used by kernel security modules to attach
+security attributes to outgoing network packets generated from user space
+applications and read security attributes from incoming network packets.  It
+is composed of three main components, the protocol engines, the communication
+layer, and the kernel security module API.
+
+ * Protocol Engines
+
+The protocol engines are responsible for both applying and retrieving the
+network packet's security attributes.  If any translation between the network
+security attributes and those on the host are required then the protocol
+engine will handle those tasks as well.  Other kernel subsystems should
+refrain from calling the protocol engines directly, instead they should use
+the NetLabel kernel security module API described below.
+
+Detailed information about each NetLabel protocol engine can be found in this
+directory, consult '00-INDEX' for filenames.
+
+ * Communication Layer
+
+The communication layer exists to allow NetLabel configuration and monitoring
+from user space.  The NetLabel communication layer uses a message based
+protocol built on top of the Generic NETLINK transport mechanism.  The exact
+formatting of these NetLabel messages as well as the Generic NETLINK family
+names can be found in the the 'net/netlabel/' directory as comments in the
+header files as well as in 'include/net/netlabel.h'.
+
+ * Security Module API
+
+The purpose of the NetLabel security module API is to provide a protocol
+independent interface to the underlying NetLabel protocol engines.  In addition
+to protocol independence, the security module API is designed to be completely
+LSM independent which should allow multiple LSMs to leverage the same code
+base.
+
+Detailed information about the NetLabel security module API can be found in the
+'include/net/netlabel.h' header file as well as the 'lsm_interface.txt' file
+found in this directory.
diff --git a/Documentation/netlabel/lsm_interface.txt b/Documentation/netlabel/lsm_interface.txt
new file mode 100644 (file)
index 0000000..98dd9f7
--- /dev/null
@@ -0,0 +1,47 @@
+NetLabel Linux Security Module Interface
+==============================================================================
+Paul Moore, paul.moore@hp.com
+
+May 17, 2006
+
+ * Overview
+
+NetLabel is a mechanism which can set and retrieve security attributes from
+network packets.  It is intended to be used by LSM developers who want to make
+use of a common code base for several different packet labeling protocols.
+The NetLabel security module API is defined in 'include/net/netlabel.h' but a
+brief overview is given below.
+
+ * NetLabel Security Attributes
+
+Since NetLabel supports multiple different packet labeling protocols and LSMs
+it uses the concept of security attributes to refer to the packet's security
+labels.  The NetLabel security attributes are defined by the
+'netlbl_lsm_secattr' structure in the NetLabel header file.  Internally the
+NetLabel subsystem converts the security attributes to and from the correct
+low-level packet label depending on the NetLabel build time and run time
+configuration.  It is up to the LSM developer to translate the NetLabel
+security attributes into whatever security identifiers are in use for their
+particular LSM.
+
+ * NetLabel LSM Protocol Operations
+
+These are the functions which allow the LSM developer to manipulate the labels
+on outgoing packets as well as read the labels on incoming packets.  Functions
+exist to operate both on sockets as well as the sk_buffs directly.  These high
+level functions are translated into low level protocol operations based on how
+the administrator has configured the NetLabel subsystem.
+
+ * NetLabel Label Mapping Cache Operations
+
+Depending on the exact configuration, translation between the network packet
+label and the internal LSM security identifier can be time consuming.  The
+NetLabel label mapping cache is a caching mechanism which can be used to
+sidestep much of this overhead once a mapping has been established.  Once the
+LSM has received a packet, used NetLabel to decode it's security attributes,
+and translated the security attributes into a LSM internal identifier the LSM
+can use the NetLabel caching functions to associate the LSM internal
+identifier with the network packet's label.  This means that in the future
+when a incoming packet matches a cached value not only are the internal
+NetLabel translation mechanisms bypassed but the LSM translation mechanisms are
+bypassed as well which should result in a significant reduction in overhead.
index 90ed78110fd49fde8b3a8ad237730e76afb55ab2..935e298f674adf846d4b4038939e5e17128c7b95 100644 (file)
@@ -375,6 +375,41 @@ tcp_slow_start_after_idle - BOOLEAN
        be timed out after an idle period.
        Default: 1
 
+CIPSOv4 Variables:
+
+cipso_cache_enable - BOOLEAN
+       If set, enable additions to and lookups from the CIPSO label mapping
+       cache.  If unset, additions are ignored and lookups always result in a
+       miss.  However, regardless of the setting the cache is still
+       invalidated when required when means you can safely toggle this on and
+       off and the cache will always be "safe".
+       Default: 1
+
+cipso_cache_bucket_size - INTEGER
+       The CIPSO label cache consists of a fixed size hash table with each
+       hash bucket containing a number of cache entries.  This variable limits
+       the number of entries in each hash bucket; the larger the value the
+       more CIPSO label mappings that can be cached.  When the number of
+       entries in a given hash bucket reaches this limit adding new entries
+       causes the oldest entry in the bucket to be removed to make room.
+       Default: 10
+
+cipso_rbm_optfmt - BOOLEAN
+       Enable the "Optimized Tag 1 Format" as defined in section 3.4.2.6 of
+       the CIPSO draft specification (see Documentation/netlabel for details).
+       This means that when set the CIPSO tag will be padded with empty
+       categories in order to make the packet data 32-bit aligned.
+       Default: 0
+
+cipso_rbm_structvalid - BOOLEAN
+       If set, do a very strict check of the CIPSO option when
+       ip_options_compile() is called.  If unset, relax the checks done during
+       ip_options_compile().  Either way is "safe" as errors are caught else
+       where in the CIPSO processing code but setting this to 0 (False) should
+       result in less work (i.e. it should be faster) but could cause problems
+       with other implementations that require strict checking.
+       Default: 0
+
 IP Variables:
 
 ip_local_port_range - 2 INTEGERS
@@ -730,6 +765,9 @@ conf/all/forwarding - BOOLEAN
 
        This referred to as global forwarding.
 
+proxy_ndp - BOOLEAN
+       Do proxy ndp.
+
 conf/interface/*:
        Change special settings per interface.
 
diff --git a/Documentation/networking/secid.txt b/Documentation/networking/secid.txt
new file mode 100644 (file)
index 0000000..95ea067
--- /dev/null
@@ -0,0 +1,14 @@
+flowi structure:
+
+The secid member in the flow structure is used in LSMs (e.g. SELinux) to indicate
+the label of the flow. This label of the flow is currently used in selecting
+matching labeled xfrm(s).
+
+If this is an outbound flow, the label is derived from the socket, if any, or
+the incoming packet this flow is being generated as a response to (e.g. tcp
+resets, timewait ack, etc.). It is also conceivable that the label could be
+derived from other sources such as process context, device, etc., in special
+cases, as may be appropriate.
+
+If this is an inbound flow, the label is derived from the IPSec security
+associations, if any, used by the packet.
index 13fcaf5b17960edbec0b8740550fa325006888bd..e49621be66400103b0e69c0f22d1e0d380c4e72f 100644 (file)
@@ -1058,8 +1058,8 @@ core99_reset_cpu(struct device_node *node, long param, long value)
        if (np == NULL)
                return -ENODEV;
        for (np = np->child; np != NULL; np = np->sibling) {
-               u32 *num = get_property(np, "reg", NULL);
-               u32 *rst = get_property(np, "soft-reset", NULL);
+               const u32 *num = get_property(np, "reg", NULL);
+               const u32 *rst = get_property(np, "soft-reset", NULL);
                if (num == NULL || rst == NULL)
                        continue;
                if (param == *num) {
index 653eeb64d1e28e448ef67191b7f38de13edbfa89..1949b657b0926158cf10fc2f226fc43b4600b695 100644 (file)
@@ -702,7 +702,7 @@ static void __init smp_core99_setup(int ncpus)
        /* GPIO based HW sync on ppc32 Core99 */
        if (pmac_tb_freeze == NULL && !machine_is_compatible("MacRISC4")) {
                struct device_node *cpu;
-               u32 *tbprop = NULL;
+               const u32 *tbprop = NULL;
 
                core99_tb_gpio = KL_GPIO_TB_ENABLE;     /* default value */
                cpu = of_find_node_by_type(NULL, "cpu");
index ddd9253f9d55f267120ddf04a014eaecd12d283c..dcbd6ff1fa333224bcf34ae664a3ea256beb9c3f 100644 (file)
@@ -2734,6 +2734,18 @@ long blk_congestion_wait(int rw, long timeout)
 
 EXPORT_SYMBOL(blk_congestion_wait);
 
+/**
+ * blk_congestion_end - wake up sleepers on a congestion queue
+ * @rw: READ or WRITE
+ */
+void blk_congestion_end(int rw)
+{
+       wait_queue_head_t *wqh = &congestion_wqh[rw];
+
+       if (waitqueue_active(wqh))
+               wake_up(wqh);
+}
+
 /*
  * Has to be called with the request spinlock acquired
  */
index f403b6946047161db8ea6a11e023f51d9598c0cb..b521bcd2b2c6036f155bc23641d41df877baca18 100644 (file)
@@ -92,13 +92,17 @@ static int hmac_init(struct hash_desc *pdesc)
        struct hmac_ctx *ctx = align_ptr(ipad + bs * 2 + ds, sizeof(void *));
        struct hash_desc desc;
        struct scatterlist tmp;
+       int err;
 
        desc.tfm = ctx->child;
        desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
        sg_set_buf(&tmp, ipad, bs);
 
-       return unlikely(crypto_hash_init(&desc)) ?:
-              crypto_hash_update(&desc, &tmp, 1);
+       err = crypto_hash_init(&desc);
+       if (unlikely(err))
+               return err;
+
+       return crypto_hash_update(&desc, &tmp, bs);
 }
 
 static int hmac_update(struct hash_desc *pdesc,
@@ -123,13 +127,17 @@ static int hmac_final(struct hash_desc *pdesc, u8 *out)
        struct hmac_ctx *ctx = align_ptr(digest + ds, sizeof(void *));
        struct hash_desc desc;
        struct scatterlist tmp;
+       int err;
 
        desc.tfm = ctx->child;
        desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
        sg_set_buf(&tmp, opad, bs + ds);
 
-       return unlikely(crypto_hash_final(&desc, digest)) ?:
-              crypto_hash_digest(&desc, &tmp, bs + ds, out);
+       err = crypto_hash_final(&desc, digest);
+       if (unlikely(err))
+               return err;
+
+       return crypto_hash_digest(&desc, &tmp, bs + ds, out);
 }
 
 static int hmac_digest(struct hash_desc *pdesc, struct scatterlist *sg,
@@ -145,6 +153,7 @@ static int hmac_digest(struct hash_desc *pdesc, struct scatterlist *sg,
        struct hash_desc desc;
        struct scatterlist sg1[2];
        struct scatterlist sg2[1];
+       int err;
 
        desc.tfm = ctx->child;
        desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
@@ -154,8 +163,11 @@ static int hmac_digest(struct hash_desc *pdesc, struct scatterlist *sg,
        sg1[1].length = 0;
        sg_set_buf(sg2, opad, bs + ds);
 
-       return unlikely(crypto_hash_digest(&desc, sg1, nbytes + bs, digest)) ?:
-              crypto_hash_digest(&desc, sg2, bs + ds, out);
+       err = crypto_hash_digest(&desc, sg1, nbytes + bs, digest);
+       if (unlikely(err))
+               return err;
+
+       return crypto_hash_digest(&desc, sg2, bs + ds, out);
 }
 
 static int hmac_init_tfm(struct crypto_tfm *tfm)
index ffcb9fd31c38fbdd7a1efbb2b52eb6f7e5d2c116..41e052fecd7fdfe60f4f571ee2e13ae439c3ad39 100644 (file)
@@ -1912,7 +1912,7 @@ he_service_rbrq(struct he_dev *he_dev, int group)
                                skb->tail = skb->data + skb->len;
 #ifdef USE_CHECKSUM_HW
                                if (vcc->vpi == 0 && vcc->vci >= ATM_NOT_RSV_VCI) {
-                                       skb->ip_summed = CHECKSUM_HW;
+                                       skb->ip_summed = CHECKSUM_COMPLETE;
                                        skb->csum = TCP_CKSUM(skb->data,
                                                        he_vcc->pdu_len);
                                }
index a0e5eac5f33aa73821c0fe4f87e339034178009d..b8c22255f6ada92615b2e70d8ad717927e04c9ae 100644 (file)
@@ -87,7 +87,7 @@ static int briq_panel_release(struct inode *ino, struct file *filep)
        return 0;
 }
 
-static ssize_t briq_panel_read(struct file *file, char *buf, size_t count,
+static ssize_t briq_panel_read(struct file *file, char __user *buf, size_t count,
                         loff_t *ppos)
 {
        unsigned short c;
@@ -135,7 +135,7 @@ static void scroll_vfd( void )
        vfd_cursor = 20;
 }
 
-static ssize_t briq_panel_write(struct file *file, const char *buf, size_t len,
+static ssize_t briq_panel_write(struct file *file, const char __user *buf, size_t len,
                          loff_t *ppos)
 {
        size_t indx = len;
@@ -150,19 +150,22 @@ static ssize_t briq_panel_write(struct file *file, const char *buf, size_t len,
                return -EBUSY;
 
        for (;;) {
+               char c;
                if (!indx)
                        break;
+               if (get_user(c, buf))
+                       return -EFAULT;
                if (esc) {
-                       set_led(*buf);
+                       set_led(c);
                        esc = 0;
-               } else if (*buf == 27) {
+               } else if (c == 27) {
                        esc = 1;
-               } else if (*buf == 12) {
+               } else if (c == 12) {
                        /* do a form feed */
                        for (i=0; i<40; i++)
                                vfd[i] = ' ';
                        vfd_cursor = 0;
-               } else if (*buf == 10) {
+               } else if (c == 10) {
                        if (vfd_cursor < 20)
                                vfd_cursor = 20;
                        else if (vfd_cursor < 40)
@@ -175,7 +178,7 @@ static ssize_t briq_panel_write(struct file *file, const char *buf, size_t len,
                        /* just a character */
                        if (vfd_cursor > 39)
                                scroll_vfd();
-                       vfd[vfd_cursor++] = *buf;
+                       vfd[vfd_cursor++] = c;
                }
                indx--;
                buf++;
@@ -202,7 +205,7 @@ static struct miscdevice briq_panel_miscdev = {
 static int __init briq_panel_init(void)
 {
        struct device_node *root = find_path_device("/");
-       char *machine;
+       const char *machine;
        int i;
 
        machine = get_property(root, "model", NULL);
index 1da9adbccaecdbe90ba95dd028fe07cb361a3da6..d06b59083f6ea91f59a2e0698b61b2a322471a39 100644 (file)
@@ -38,6 +38,7 @@
 #define __IB_MAD_PRIV_H__
 
 #include <linux/completion.h>
+#include <linux/err.h>
 #include <linux/pci.h>
 #include <linux/workqueue.h>
 #include <rdma/ib_mad.h>
index 8fddc8cccdf3d744c964b4d2c4876ceaecaeff22..dd6af551108bc111a87c4bb0cbd8ebd449007a6e 100644 (file)
@@ -49,6 +49,7 @@
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
 #include <linux/if_arp.h>
+#include <linux/vmalloc.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
index 1c3c9d65ecea6b1b07e1a76b1989b4f48a44f91d..f49a32b7a8f6472545a2594f5c888232142f6d63 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/mm.h>
 #include <linux/inet.h>
+#include <linux/vmalloc.h>
 
 #include <linux/route.h>
 
index 28b6b46c106aebf3245640a8f04de5421416bcbe..29958b6e0214a672905bab6dc61a50e7f8a021d0 100644 (file)
@@ -43,6 +43,7 @@
 
 #include <linux/io.h>
 #include <linux/pci.h>
+#include <linux/vmalloc.h>
 #include <asm/uaccess.h>
 
 #include "ipath_kernel.h"
index 80e8ca013e448a96e54af66220810e80b3c794fb..29dede2eaa850d3d1f7fca430697b8a65c844498 100644 (file)
@@ -2077,7 +2077,7 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        vp->tx_ring[entry].next = 0;
 #if DO_ZEROCOPY
-       if (skb->ip_summed != CHECKSUM_HW)
+       if (skb->ip_summed != CHECKSUM_PARTIAL)
                        vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded);
        else
                        vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded | AddTCPChksum | AddUDPChksum);
index 1428bb7715afd16a04fb6132cd560b420636d111..a48b211c489dfe947b1683af9d0cde36e2bb0846 100644 (file)
@@ -813,7 +813,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
 
                if (mss)
                        flags |= LargeSend | ((mss & MSSMask) << MSSShift);
-               else if (skb->ip_summed == CHECKSUM_HW) {
+               else if (skb->ip_summed == CHECKSUM_PARTIAL) {
                        const struct iphdr *ip = skb->nh.iph;
                        if (ip->protocol == IPPROTO_TCP)
                                flags |= IPCS | TCPCS;
@@ -867,7 +867,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
                        if (mss)
                                ctrl |= LargeSend |
                                        ((mss & MSSMask) << MSSShift);
-                       else if (skb->ip_summed == CHECKSUM_HW) {
+                       else if (skb->ip_summed == CHECKSUM_PARTIAL) {
                                if (ip->protocol == IPPROTO_TCP)
                                        ctrl |= IPCS | TCPCS;
                                else if (ip->protocol == IPPROTO_UDP)
@@ -898,7 +898,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
                txd->addr = cpu_to_le64(first_mapping);
                wmb();
 
-               if (skb->ip_summed == CHECKSUM_HW) {
+               if (skb->ip_summed == CHECKSUM_PARTIAL) {
                        if (ip->protocol == IPPROTO_TCP)
                                txd->opts1 = cpu_to_le32(first_eor | first_len |
                                                         FirstFrag | DescOwn |
index 1c01e9b3d07c88cd2856232d268736ac77d87adc..826548644d7b13779dda4a67a9809e13d972d843 100644 (file)
@@ -2040,7 +2040,7 @@ static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm)
                 */
                if (bd_flags & BD_FLG_TCP_UDP_SUM) {
                        skb->csum = htons(csum);
-                       skb->ip_summed = CHECKSUM_HW;
+                       skb->ip_summed = CHECKSUM_COMPLETE;
                } else {
                        skb->ip_summed = CHECKSUM_NONE;
                }
@@ -2511,7 +2511,7 @@ restart:
 
                mapping = ace_map_tx_skb(ap, skb, skb, idx);
                flagsize = (skb->len << 16) | (BD_FLG_END);
-               if (skb->ip_summed == CHECKSUM_HW)
+               if (skb->ip_summed == CHECKSUM_PARTIAL)
                        flagsize |= BD_FLG_TCP_UDP_SUM;
 #if ACENIC_DO_VLAN
                if (vlan_tx_tag_present(skb)) {
@@ -2534,7 +2534,7 @@ restart:
 
                mapping = ace_map_tx_skb(ap, skb, NULL, idx);
                flagsize = (skb_headlen(skb) << 16);
-               if (skb->ip_summed == CHECKSUM_HW)
+               if (skb->ip_summed == CHECKSUM_PARTIAL)
                        flagsize |= BD_FLG_TCP_UDP_SUM;
 #if ACENIC_DO_VLAN
                if (vlan_tx_tag_present(skb)) {
@@ -2560,7 +2560,7 @@ restart:
                                               PCI_DMA_TODEVICE);
 
                        flagsize = (frag->size << 16);
-                       if (skb->ip_summed == CHECKSUM_HW)
+                       if (skb->ip_summed == CHECKSUM_PARTIAL)
                                flagsize |= BD_FLG_TCP_UDP_SUM;
                        idx = (idx + 1) % ACE_TX_RING_ENTRIES(ap);
 
index 979a33df0a8c3d84dc4871188c465871b822b50f..96d8a694d433c43c405c16dd425edec2c012823d 100644 (file)
@@ -161,6 +161,7 @@ static struct pci_device_id com20020pci_id_table[] = {
        { 0x1571, 0xa204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
        { 0x1571, 0xa205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
        { 0x1571, 0xa206, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
+       { 0x10B5, 0x9030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
        { 0x10B5, 0x9050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
        {0,}
 };
index 652eb05a6c2df6c7e406eef8ecbfa82cfcb03564..7857b463012447c404eb256206921427cc20d56c 100644 (file)
@@ -4423,7 +4423,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
        ring_prod = TX_RING_IDX(prod);
 
        vlan_tag_flags = 0;
-       if (skb->ip_summed == CHECKSUM_HW) {
+       if (skb->ip_summed == CHECKSUM_PARTIAL) {
                vlan_tag_flags |= TX_BD_FLAGS_TCP_UDP_CKSUM;
        }
 
index a31544ccb3c494aed1e63cd01335aca8d2926583..558fdb8ad2dc248a2250d4f61cd8ccf879989920 100644 (file)
@@ -2167,7 +2167,7 @@ end_copy_pkt:
                        cas_page_unmap(addr);
        }
        skb->csum = ntohs(i ^ 0xffff);
-       skb->ip_summed = CHECKSUM_HW;
+       skb->ip_summed = CHECKSUM_COMPLETE;
        skb->protocol = eth_type_trans(skb, cp->dev);
        return len;
 }
@@ -2821,7 +2821,7 @@ static inline int cas_xmit_tx_ringN(struct cas *cp, int ring,
        }
 
        ctrl = 0;
-       if (skb->ip_summed == CHECKSUM_HW) {
+       if (skb->ip_summed == CHECKSUM_PARTIAL) {
                u64 csum_start_off, csum_stuff_off;
 
                csum_start_off = (u64) (skb->h.raw - skb->data);
index 61b3754f50ff6645a16b7f8352dcb57b699b1dcc..ddd0bdb498f4f4f7dcf1bbd62c614dd21756f6e7 100644 (file)
@@ -1470,9 +1470,9 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
                }
 
                if (!(adapter->flags & UDP_CSUM_CAPABLE) &&
-                   skb->ip_summed == CHECKSUM_HW &&
+                   skb->ip_summed == CHECKSUM_PARTIAL &&
                    skb->nh.iph->protocol == IPPROTO_UDP)
-                       if (unlikely(skb_checksum_help(skb, 0))) {
+                       if (unlikely(skb_checksum_help(skb))) {
                                dev_kfree_skb_any(skb);
                                return NETDEV_TX_OK;
                        }
@@ -1495,11 +1495,11 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
                cpl = (struct cpl_tx_pkt *)__skb_push(skb, sizeof(*cpl));
                cpl->opcode = CPL_TX_PKT;
                cpl->ip_csum_dis = 1;    /* SW calculates IP csum */
-               cpl->l4_csum_dis = skb->ip_summed == CHECKSUM_HW ? 0 : 1;
+               cpl->l4_csum_dis = skb->ip_summed == CHECKSUM_PARTIAL ? 0 : 1;
                /* the length field isn't used so don't bother setting it */
 
-               st->tx_cso += (skb->ip_summed == CHECKSUM_HW);
-               sge->stats.tx_do_cksum += (skb->ip_summed == CHECKSUM_HW);
+               st->tx_cso += (skb->ip_summed == CHECKSUM_PARTIAL);
+               sge->stats.tx_do_cksum += (skb->ip_summed == CHECKSUM_PARTIAL);
                sge->stats.tx_reg_pkts++;
        }
        cpl->iff = dev->if_port;
index 402961e68c89fca4223fc07503274367668c9117..b74e67654764f22d374c802ca51838ab6e749e1b 100644 (file)
@@ -611,7 +611,7 @@ start_xmit (struct sk_buff *skb, struct net_device *dev)
        txdesc = &np->tx_ring[entry];
 
 #if 0
-       if (skb->ip_summed == CHECKSUM_HW) {
+       if (skb->ip_summed == CHECKSUM_PARTIAL) {
                txdesc->status |=
                    cpu_to_le64 (TCPChecksumEnable | UDPChecksumEnable |
                                 IPChecksumEnable);
index 98ef9f85482f0b15578e0ee08c9ced8b5b90ccfa..2ab9f96f5dab899274a1bfb024f5094a7f5c9879 100644 (file)
@@ -2600,7 +2600,7 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
        unsigned int i;
        uint8_t css;
 
-       if (likely(skb->ip_summed == CHECKSUM_HW)) {
+       if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
                css = skb->h.raw - skb->data;
 
                i = tx_ring->next_to_use;
@@ -2927,11 +2927,11 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        }
 
        /* reserve a descriptor for the offload context */
-       if ((mss) || (skb->ip_summed == CHECKSUM_HW))
+       if ((mss) || (skb->ip_summed == CHECKSUM_PARTIAL))
                count++;
        count++;
 #else
-       if (skb->ip_summed == CHECKSUM_HW)
+       if (skb->ip_summed == CHECKSUM_PARTIAL)
                count++;
 #endif
 
@@ -3608,7 +3608,7 @@ e1000_rx_checksum(struct e1000_adapter *adapter,
                 */
                csum = ntohl(csum ^ 0xFFFF);
                skb->csum = csum;
-               skb->ip_summed = CHECKSUM_HW;
+               skb->ip_summed = CHECKSUM_COMPLETE;
        }
        adapter->hw_csum_good++;
 }
index 11b8f1b43dd5994a255c1b6613d0cfa868a4bdeb..32cacf115f754f0c500432363d930c01ceb39ebd 100644 (file)
@@ -1503,7 +1503,8 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
                tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->gso_size << NV_TX2_TSO_SHIFT);
        else
 #endif
-       tx_flags_extra = (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0);
+       tx_flags_extra = skb->ip_summed == CHECKSUM_PARTIAL ?
+                        NV_TX2_CHECKSUM_L3 | NV_TX2_CHECKSUM_L4 : 0;
 
        /* vlan tag */
        if (np->vlangrp && vlan_tx_tag_present(skb)) {
index ebbbd6ca6204e28ba605cd980d8b6d5e1a408047..ba960913c034f08d8485235b1de3ccb1b04bf187 100644 (file)
@@ -947,7 +947,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        /* Set up checksumming */
        if (likely((dev->features & NETIF_F_IP_CSUM)
-                       && (CHECKSUM_HW == skb->ip_summed))) {
+                       && (CHECKSUM_PARTIAL == skb->ip_summed))) {
                fcb = gfar_add_fcb(skb, txbdp);
                status |= TXBD_TOE;
                gfar_tx_checksum(skb, fcb);
index 409c6aab0411c510431ce16d562eeb02943d62bb..763373ae966601c3dbaacb4d74f4e9deb5922de9 100644 (file)
@@ -1648,7 +1648,7 @@ static int hamachi_rx(struct net_device *dev)
                                                * could do the pseudo myself and return
                                                * CHECKSUM_UNNECESSARY
                                                */
-                                               skb->ip_summed = CHECKSUM_HW;
+                                               skb->ip_summed = CHECKSUM_COMPLETE;
                                        }
                                }       
                        }
index 82468e2dc7991dfc386ccae6d96ccfba8aa36f65..57e214d85e9ac4cd5601fd686888ce489da91c98 100644 (file)
@@ -1036,7 +1036,7 @@ static inline u16 emac_tx_csum(struct ocp_enet_private *dev,
                               struct sk_buff *skb)
 {
 #if defined(CONFIG_IBM_EMAC_TAH)
-       if (skb->ip_summed == CHECKSUM_HW) {
+       if (skb->ip_summed == CHECKSUM_PARTIAL) {
                ++dev->stats.tx_packets_csum;
                return EMAC_TX_CTRL_TAH_CSUM;
        }
index 68d8af7df08e31fe6e1bee61f7c495782ceba1ec..65f897ddb9205ce83ec443a2f56b1b0344dff2e3 100644 (file)
@@ -1387,7 +1387,7 @@ static int ioc3_start_xmit(struct sk_buff *skb, struct net_device *dev)
         * MAC header which should not be summed and the TCP/UDP pseudo headers
         * manually.
         */
-       if (skb->ip_summed == CHECKSUM_HW) {
+       if (skb->ip_summed == CHECKSUM_PARTIAL) {
                int proto = ntohs(skb->nh.iph->protocol);
                unsigned int csoff;
                struct iphdr *ih = skb->nh.iph;
index e3c8cd5eca676c8b126b5624607ea8577c12c702..68d4c418cb98481924c5f7403d764b67b81053ef 100644 (file)
@@ -249,7 +249,7 @@ static void __exit ali_ircc_cleanup(void)
 
        IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__); 
 
-       for (i=0; i < 4; i++) {
+       for (i=0; i < ARRAY_SIZE(dev_self); i++) {
                if (dev_self[i])
                        ali_ircc_close(dev_self[i]);
        }
@@ -273,6 +273,12 @@ static int ali_ircc_open(int i, chipio_t *info)
        int err;
                        
        IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__); 
+
+       if (i >= ARRAY_SIZE(dev_self)) {
+               IRDA_ERROR("%s(), maximum number of supported chips reached!\n",
+                          __FUNCTION__);
+               return -ENOMEM;
+       }
        
        /* Set FIR FIFO and DMA Threshold */
        if ((ali_ircc_setup(info)) == -1)
index 44efd49bf4a9fd8f13e38b1aea9e073d31d065b6..ba4f3eb988b3999dfac84f8936e0b1e716e535a3 100644 (file)
@@ -1090,7 +1090,7 @@ static int __init irport_init(void)
 {
        int i;
 
-       for (i=0; (io[i] < 2000) && (i < 4); i++) {
+       for (i=0; (io[i] < 2000) && (i < ARRAY_SIZE(dev_self)); i++) {
                if (irport_open(i, io[i], irq[i]) != NULL)
                        return 0;
        }
@@ -1112,7 +1112,7 @@ static void __exit irport_cleanup(void)
 
         IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
 
-       for (i=0; i < 4; i++) {
+       for (i=0; i < ARRAY_SIZE(dev_self); i++) {
                if (dev_self[i])
                        irport_close(dev_self[i]);
        }
index 8bafb455c102d0f95ade96f86da89621be2f1ed9..79b85f327500c4e553bccf2c69007d2e22e89468 100644 (file)
@@ -279,7 +279,7 @@ static void via_ircc_clean(void)
 
        IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
 
-       for (i=0; i < 4; i++) {
+       for (i=0; i < ARRAY_SIZE(dev_self); i++) {
                if (dev_self[i])
                        via_ircc_close(dev_self[i]);
        }
@@ -327,6 +327,9 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id)
 
        IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
 
+       if (i >= ARRAY_SIZE(dev_self))
+               return -ENOMEM;
+
        /* Allocate new instance of the driver */
        dev = alloc_irdadev(sizeof(struct via_ircc_cb));
        if (dev == NULL) 
index 0ea65c4c6f8543b9972bd7b8d398f4aacd856563..8421597072a741caf66c6537ed676eb701adbaa3 100644 (file)
@@ -117,7 +117,7 @@ static int __init w83977af_init(void)
 
        IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
 
-       for (i=0; (io[i] < 2000) && (i < 4); i++) { 
+       for (i=0; (io[i] < 2000) && (i < ARRAY_SIZE(dev_self)); i++) {
                if (w83977af_open(i, io[i], irq[i], dma[i]) == 0)
                        return 0;
        }
@@ -136,7 +136,7 @@ static void __exit w83977af_cleanup(void)
 
         IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
 
-       for (i=0; i < 4; i++) {
+       for (i=0; i < ARRAY_SIZE(dev_self); i++) {
                if (dev_self[i])
                        w83977af_close(dev_self[i]);
        }
index 7bbd447289b58df7906c396d6948701770ff2c6e..9405b44f321485913df35f118b26a31b15f6e154 100644 (file)
@@ -1232,7 +1232,7 @@ ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
        unsigned int i;
        uint8_t css, cso;
 
-       if(likely(skb->ip_summed == CHECKSUM_HW)) {
+       if(likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
                css = skb->h.raw - skb->data;
                cso = (skb->h.raw + skb->csum) - skb->data;
 
index 59de3e74d2d7662de775790ac43bb1542ae041e8..d4dcc856b3cd2322c30d8a4881c8b51ec491d26c 100644 (file)
@@ -1147,7 +1147,7 @@ static void eth_tx_submit_descs_for_skb(struct mv643xx_private *mp,
        desc->byte_cnt = length;
        desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE);
 
-       if (skb->ip_summed == CHECKSUM_HW) {
+       if (skb->ip_summed == CHECKSUM_PARTIAL) {
                BUG_ON(skb->protocol != ETH_P_IP);
 
                cmd_sts |= ETH_GEN_TCP_UDP_CHECKSUM |
index 9bdd43ab3573afb5981b456d9a50b0a7a7c6ce73..9f16681d0e7ee7c3b2a00bde3e4fb14542c8554b 100644 (file)
@@ -930,7 +930,7 @@ static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, u16 hw_csum)
            (vh->h_vlan_encapsulated_proto == htons(ETH_P_IP) ||
             vh->h_vlan_encapsulated_proto == htons(ETH_P_IPV6))) {
                skb->csum = hw_csum;
-               skb->ip_summed = CHECKSUM_HW;
+               skb->ip_summed = CHECKSUM_COMPLETE;
        }
 }
 
@@ -973,7 +973,7 @@ myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
                if ((skb->protocol == ntohs(ETH_P_IP)) ||
                    (skb->protocol == ntohs(ETH_P_IPV6))) {
                        skb->csum = ntohs((u16) csum);
-                       skb->ip_summed = CHECKSUM_HW;
+                       skb->ip_summed = CHECKSUM_COMPLETE;
                } else
                        myri10ge_vlan_ip_csum(skb, ntohs((u16) csum));
        }
@@ -1897,13 +1897,13 @@ again:
        pseudo_hdr_offset = 0;
        odd_flag = 0;
        flags = (MXGEFW_FLAGS_NO_TSO | MXGEFW_FLAGS_FIRST);
-       if (likely(skb->ip_summed == CHECKSUM_HW)) {
+       if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
                cksum_offset = (skb->h.raw - skb->data);
                pseudo_hdr_offset = (skb->h.raw + skb->csum) - skb->data;
                /* If the headers are excessively large, then we must
                 * fall back to a software checksum */
                if (unlikely(cksum_offset > 255 || pseudo_hdr_offset > 127)) {
-                       if (skb_checksum_help(skb, 0))
+                       if (skb_checksum_help(skb))
                                goto drop;
                        cksum_offset = 0;
                        pseudo_hdr_offset = 0;
index 0e76859c90a2af03b3c967b4bf1bd1061b34d236..5143f5dbb2e53e34f52a83a0a08d9bad57dbb566 100644 (file)
@@ -1153,7 +1153,7 @@ again:
        if (!nr_frags)
                frag = NULL;
        extsts = 0;
-       if (skb->ip_summed == CHECKSUM_HW) {
+       if (skb->ip_summed == CHECKSUM_PARTIAL) {
                extsts |= EXTSTS_IPPKT;
                if (IPPROTO_TCP == skb->nh.iph->protocol)
                        extsts |= EXTSTS_TCPPKT;
index 4c2f575faad709db506ce5c250ab81eefacd2e79..d9b960aa9b0dbfaa44298288335d6e73b8ab2c32 100644 (file)
@@ -2169,7 +2169,7 @@ static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev)
                if (mss)
                        return LargeSend | ((mss & MSSMask) << MSSShift);
        }
-       if (skb->ip_summed == CHECKSUM_HW) {
+       if (skb->ip_summed == CHECKSUM_PARTIAL) {
                const struct iphdr *ip = skb->nh.iph;
 
                if (ip->protocol == IPPROTO_TCP)
index e72e0e099060f6386f22e3800dfdef76aa326e1e..5b3713f622d7229915ba5425e254232bebb9be25 100644 (file)
@@ -3893,7 +3893,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
                txdp->Control_1 |= TXD_TCP_LSO_MSS(s2io_tcp_mss(skb));
        }
 #endif
-       if (skb->ip_summed == CHECKSUM_HW) {
+       if (skb->ip_summed == CHECKSUM_PARTIAL) {
                txdp->Control_2 |=
                    (TXD_TX_CKO_IPV4_EN | TXD_TX_CKO_TCP_EN |
                     TXD_TX_CKO_UDP_EN);
index ee62845d3ac9d9140eea0e2a8c0e801ce75a9682..eb3b35180c2fabbc669c614dd9ad2d4751758c6f 100644 (file)
@@ -1559,7 +1559,7 @@ struct sk_buff    *pMessage)      /* pointer to send-message              */
        pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
        pTxd->pMBuf     = pMessage;
 
-       if (pMessage->ip_summed == CHECKSUM_HW) {
+       if (pMessage->ip_summed == CHECKSUM_PARTIAL) {
                u16 hdrlen = pMessage->h.raw - pMessage->data;
                u16 offset = hdrlen + pMessage->csum;
 
@@ -1678,7 +1678,7 @@ struct sk_buff    *pMessage)      /* pointer to send-message              */
        /* 
        ** Does the HW need to evaluate checksum for TCP or UDP packets? 
        */
-       if (pMessage->ip_summed == CHECKSUM_HW) {
+       if (pMessage->ip_summed == CHECKSUM_PARTIAL) {
                u16 hdrlen = pMessage->h.raw - pMessage->data;
                u16 offset = hdrlen + pMessage->csum;
 
@@ -2158,7 +2158,7 @@ rx_start:
 
 #ifdef USE_SK_RX_CHECKSUM
                pMsg->csum = pRxd->TcpSums & 0xffff;
-               pMsg->ip_summed = CHECKSUM_HW;
+               pMsg->ip_summed = CHECKSUM_COMPLETE;
 #else
                pMsg->ip_summed = CHECKSUM_NONE;
 #endif
index ad878dfddef461395ce80c00bad17df9a34a1733..b3d6fa3d6df4b54d0b85fa3c33759600aa347921 100644 (file)
@@ -2338,7 +2338,7 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev)
        td->dma_lo = map;
        td->dma_hi = map >> 32;
 
-       if (skb->ip_summed == CHECKSUM_HW) {
+       if (skb->ip_summed == CHECKSUM_PARTIAL) {
                int offset = skb->h.raw - skb->data;
 
                /* This seems backwards, but it is what the sk98lin
@@ -2642,7 +2642,7 @@ static inline struct sk_buff *skge_rx_get(struct skge_port *skge,
        skb->dev = skge->netdev;
        if (skge->rx_csum) {
                skb->csum = csum;
-               skb->ip_summed = CHECKSUM_HW;
+               skb->ip_summed = CHECKSUM_COMPLETE;
        }
 
        skb->protocol = eth_type_trans(skb, skge->netdev);
index 933e87f1cc687dc6c8c300af83f6725dde79c7d9..8e92566b587eeb26549362fa0eb849c16f2e9a5e 100644 (file)
@@ -1163,7 +1163,7 @@ static unsigned tx_le_req(const struct sk_buff *skb)
        if (skb_is_gso(skb))
                ++count;
 
-       if (skb->ip_summed == CHECKSUM_HW)
+       if (skb->ip_summed == CHECKSUM_PARTIAL)
                ++count;
 
        return count;
@@ -1272,7 +1272,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
 #endif
 
        /* Handle TCP checksum offload */
-       if (skb->ip_summed == CHECKSUM_HW) {
+       if (skb->ip_summed == CHECKSUM_PARTIAL) {
                u16 hdr = skb->h.raw - skb->data;
                u16 offset = hdr + skb->csum;
 
@@ -2000,7 +2000,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
 #endif
                case OP_RXCHKS:
                        skb = sky2->rx_ring[sky2->rx_next].skb;
-                       skb->ip_summed = CHECKSUM_HW;
+                       skb->ip_summed = CHECKSUM_COMPLETE;
                        skb->csum = le16_to_cpu(status);
                        break;
 
index c0a62b00ffc896879be84b96fbca0572692d46e3..2607aa51d8e034267d5883d116bd11f8a128455c 100644 (file)
@@ -1230,7 +1230,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
        }
 
 #if defined(ZEROCOPY) && defined(HAS_BROKEN_FIRMWARE)
-       if (skb->ip_summed == CHECKSUM_HW) {
+       if (skb->ip_summed == CHECKSUM_PARTIAL) {
                if (skb_padto(skb, (skb->len + PADDING_MASK) & ~PADDING_MASK))
                        return NETDEV_TX_OK;
        }
@@ -1252,7 +1252,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
                                status |= TxDescIntr;
                                np->reap_tx = 0;
                        }
-                       if (skb->ip_summed == CHECKSUM_HW) {
+                       if (skb->ip_summed == CHECKSUM_PARTIAL) {
                                status |= TxCalTCP;
                                np->stats.tx_compressed++;
                        }
@@ -1499,7 +1499,7 @@ static int __netdev_rx(struct net_device *dev, int *quota)
                 * Until then, the printk stays. :-) -Ion
                 */
                else if (le16_to_cpu(desc->status2) & 0x0040) {
-                       skb->ip_summed = CHECKSUM_HW;
+                       skb->ip_summed = CHECKSUM_COMPLETE;
                        skb->csum = le16_to_cpu(desc->csum);
                        printk(KERN_DEBUG "%s: checksum_hw, status2 = %#x\n", dev->name, le16_to_cpu(desc->status2));
                }
index d7b1d1882cab5fb773dc9ce58c6c12e9e9a233c2..b388651b78361182a510b51a93f1921fc03ac427 100644 (file)
@@ -855,7 +855,7 @@ static int gem_rx(struct gem *gp, int work_to_do)
                }
 
                skb->csum = ntohs((status & RXDCTRL_TCPCSUM) ^ 0xffff);
-               skb->ip_summed = CHECKSUM_HW;
+               skb->ip_summed = CHECKSUM_COMPLETE;
                skb->protocol = eth_type_trans(skb, gp->dev);
 
                netif_receive_skb(skb);
@@ -1026,7 +1026,7 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev)
        unsigned long flags;
 
        ctrl = 0;
-       if (skb->ip_summed == CHECKSUM_HW) {
+       if (skb->ip_summed == CHECKSUM_PARTIAL) {
                u64 csum_start_off, csum_stuff_off;
 
                csum_start_off = (u64) (skb->h.raw - skb->data);
index c6f5bc3c042ffde958ba2841f1730d92ae325f82..17981da22730e270cf952198574a3c29e1517abe 100644 (file)
@@ -1207,7 +1207,7 @@ static void happy_meal_transceiver_check(struct happy_meal *hp, void __iomem *tr
  * flags, thus:
  *
  *     skb->csum = rxd->rx_flags & 0xffff;
- *     skb->ip_summed = CHECKSUM_HW;
+ *     skb->ip_summed = CHECKSUM_COMPLETE;
  *
  * before sending off the skb to the protocols, and we are good as gold.
  */
@@ -2074,7 +2074,7 @@ static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev)
 
                /* This card is _fucking_ hot... */
                skb->csum = ntohs(csum ^ 0xffff);
-               skb->ip_summed = CHECKSUM_HW;
+               skb->ip_summed = CHECKSUM_COMPLETE;
 
                RXD(("len=%d csum=%4x]", len, csum));
                skb->protocol = eth_type_trans(skb, dev);
@@ -2268,7 +2268,7 @@ static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev)
        u32 tx_flags;
 
        tx_flags = TXFLAG_OWN;
-       if (skb->ip_summed == CHECKSUM_HW) {
+       if (skb->ip_summed == CHECKSUM_PARTIAL) {
                u32 csum_start_off, csum_stuff_off;
 
                csum_start_off = (u32) (skb->h.raw - skb->data);
index eafabb253f08d244585e8be5e74164586c111f91..fb702615386188e10f13380f24066eb4b02547f0 100644 (file)
@@ -149,122 +149,67 @@ module_param(tg3_debug, int, 0);
 MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value");
 
 static struct pci_device_id tg3_pci_tbl[] = {
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702FE,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705_2,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M_2,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702X,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703X,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702A3,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703A3,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5782,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5788,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5789,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S_2,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5720,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5721,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750M,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751M,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752M,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755M,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715S,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5781,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1001,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1003,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC9100,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_TIGON3,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { 0, }
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702FE)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705_2)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M_2)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702X)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703X)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702A3)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703A3)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5782)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5788)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5789)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S_2)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5720)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5721)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750M)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751M)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752M)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755M)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715S)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5781)},
+       {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)},
+       {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)},
+       {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)},
+       {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1001)},
+       {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1003)},
+       {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC9100)},
+       {PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_TIGON3)},
+       {}
 };
 
 MODULE_DEVICE_TABLE(pci, tg3_pci_tbl);
 
-static struct {
+static const struct {
        const char string[ETH_GSTRING_LEN];
 } ethtool_stats_keys[TG3_NUM_STATS] = {
        { "rx_octets" },
@@ -345,7 +290,7 @@ static struct {
        { "nic_tx_threshold_hit" }
 };
 
-static struct {
+static const struct {
        const char string[ETH_GSTRING_LEN];
 } ethtool_test_keys[TG3_NUM_TEST] = {
        { "nvram test     (online) " },
@@ -3851,11 +3796,11 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
                skb->h.th->check = 0;
 
        }
-       else if (skb->ip_summed == CHECKSUM_HW)
+       else if (skb->ip_summed == CHECKSUM_PARTIAL)
                base_flags |= TXD_FLAG_TCPUDP_CSUM;
 #else
        mss = 0;
-       if (skb->ip_summed == CHECKSUM_HW)
+       if (skb->ip_summed == CHECKSUM_PARTIAL)
                base_flags |= TXD_FLAG_TCPUDP_CSUM;
 #endif
 #if TG3_VLAN_TAG_USED
@@ -3981,7 +3926,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
 
        entry = tp->tx_prod;
        base_flags = 0;
-       if (skb->ip_summed == CHECKSUM_HW)
+       if (skb->ip_summed == CHECKSUM_PARTIAL)
                base_flags |= TXD_FLAG_TCPUDP_CSUM;
 #if TG3_TSO_SUPPORT != 0
        mss = 0;
@@ -4969,7 +4914,7 @@ static int tg3_halt(struct tg3 *tp, int kind, int silent)
 #define TG3_FW_BSS_ADDR                0x08000a70
 #define TG3_FW_BSS_LEN         0x10
 
-static u32 tg3FwText[(TG3_FW_TEXT_LEN / sizeof(u32)) + 1] = {
+static const u32 tg3FwText[(TG3_FW_TEXT_LEN / sizeof(u32)) + 1] = {
        0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c1d0800,
        0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100000, 0x0e000018, 0x00000000,
        0x0000000d, 0x3c1d0800, 0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100034,
@@ -5063,7 +5008,7 @@ static u32 tg3FwText[(TG3_FW_TEXT_LEN / sizeof(u32)) + 1] = {
        0x27bd0008, 0x03e00008, 0x00000000, 0x00000000, 0x00000000
 };
 
-static u32 tg3FwRodata[(TG3_FW_RODATA_LEN / sizeof(u32)) + 1] = {
+static const u32 tg3FwRodata[(TG3_FW_RODATA_LEN / sizeof(u32)) + 1] = {
        0x35373031, 0x726c7341, 0x00000000, 0x00000000, 0x53774576, 0x656e7430,
        0x00000000, 0x726c7045, 0x76656e74, 0x31000000, 0x556e6b6e, 0x45766e74,
        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x66617461, 0x6c457272,
@@ -5128,13 +5073,13 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset)
 struct fw_info {
        unsigned int text_base;
        unsigned int text_len;
-       u32 *text_data;
+       const u32 *text_data;
        unsigned int rodata_base;
        unsigned int rodata_len;
-       u32 *rodata_data;
+       const u32 *rodata_data;
        unsigned int data_base;
        unsigned int data_len;
-       u32 *data_data;
+       const u32 *data_data;
 };
 
 /* tp->lock is held. */
@@ -5266,7 +5211,7 @@ static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp)
 #define TG3_TSO_FW_BSS_ADDR            0x08001b80
 #define TG3_TSO_FW_BSS_LEN             0x894
 
-static u32 tg3TsoFwText[(TG3_TSO_FW_TEXT_LEN / 4) + 1] = {
+static const u32 tg3TsoFwText[(TG3_TSO_FW_TEXT_LEN / 4) + 1] = {
        0x0e000003, 0x00000000, 0x08001b24, 0x00000000, 0x10000003, 0x00000000,
        0x0000000d, 0x0000000d, 0x3c1d0800, 0x37bd4000, 0x03a0f021, 0x3c100800,
        0x26100000, 0x0e000010, 0x00000000, 0x0000000d, 0x27bdffe0, 0x3c04fefe,
@@ -5553,7 +5498,7 @@ static u32 tg3TsoFwText[(TG3_TSO_FW_TEXT_LEN / 4) + 1] = {
        0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c, 0x00000000, 0x00000000,
 };
 
-static u32 tg3TsoFwRodata[] = {
+static const u32 tg3TsoFwRodata[] = {
        0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000,
        0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x496e0000, 0x73746b6f,
        0x66662a2a, 0x00000000, 0x53774576, 0x656e7430, 0x00000000, 0x00000000,
@@ -5561,7 +5506,7 @@ static u32 tg3TsoFwRodata[] = {
        0x00000000,
 };
 
-static u32 tg3TsoFwData[] = {
+static const u32 tg3TsoFwData[] = {
        0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x362e3000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000,
@@ -5583,7 +5528,7 @@ static u32 tg3TsoFwData[] = {
 #define TG3_TSO5_FW_BSS_ADDR           0x00010f50
 #define TG3_TSO5_FW_BSS_LEN            0x88
 
-static u32 tg3Tso5FwText[(TG3_TSO5_FW_TEXT_LEN / 4) + 1] = {
+static const u32 tg3Tso5FwText[(TG3_TSO5_FW_TEXT_LEN / 4) + 1] = {
        0x0c004003, 0x00000000, 0x00010f04, 0x00000000, 0x10000003, 0x00000000,
        0x0000000d, 0x0000000d, 0x3c1d0001, 0x37bde000, 0x03a0f021, 0x3c100001,
        0x26100000, 0x0c004010, 0x00000000, 0x0000000d, 0x27bdffe0, 0x3c04fefe,
@@ -5742,14 +5687,14 @@ static u32 tg3Tso5FwText[(TG3_TSO5_FW_TEXT_LEN / 4) + 1] = {
        0x00000000, 0x00000000, 0x00000000,
 };
 
-static u32 tg3Tso5FwRodata[(TG3_TSO5_FW_RODATA_LEN / 4) + 1] = {
+static const u32 tg3Tso5FwRodata[(TG3_TSO5_FW_RODATA_LEN / 4) + 1] = {
        0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000,
        0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000,
        0x73746b6f, 0x66666c64, 0x00000000, 0x00000000, 0x66617461, 0x6c457272,
        0x00000000, 0x00000000, 0x00000000,
 };
 
-static u32 tg3Tso5FwData[(TG3_TSO5_FW_DATA_LEN / 4) + 1] = {
+static const u32 tg3Tso5FwData[(TG3_TSO5_FW_DATA_LEN / 4) + 1] = {
        0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x322e3000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000,
 };
index 4103c37172f9b154804f882ebf87be6ae3e26e29..c6e601dc6bbcfe16d9615832798dcaff5b88a18d 100644 (file)
@@ -830,7 +830,7 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev)
        first_txd->addrHi = (u64)((unsigned long) skb) >> 32;
        first_txd->processFlags = 0;
 
-       if(skb->ip_summed == CHECKSUM_HW) {
+       if(skb->ip_summed == CHECKSUM_PARTIAL) {
                /* The 3XP will figure out if this is UDP/TCP */
                first_txd->processFlags |= TYPHOON_TX_PF_TCP_CHKSUM;
                first_txd->processFlags |= TYPHOON_TX_PF_UDP_CHKSUM;
index ae971080e2e4389fb681f191c05b785d2984556e..66547159bfd9b8ec4cf367ca7d41182b9abdfd85 100644 (file)
@@ -1230,7 +1230,7 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev)
        rp->tx_skbuff[entry] = skb;
 
        if ((rp->quirks & rqRhineI) &&
-           (((unsigned long)skb->data & 3) || skb_shinfo(skb)->nr_frags != 0 || skb->ip_summed == CHECKSUM_HW)) {
+           (((unsigned long)skb->data & 3) || skb_shinfo(skb)->nr_frags != 0 || skb->ip_summed == CHECKSUM_PARTIAL)) {
                /* Must use alignment buffer. */
                if (skb->len > PKT_BUF_SZ) {
                        /* packet too long, drop it */
index aa9cd92f46b2dbbb51716416acd4f26d503aca1c..f1e0c746a388e87110d623505c7655fa9a08eb19 100644 (file)
@@ -2002,7 +2002,7 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev)
         *      Handle hardware checksum
         */
        if ((vptr->flags & VELOCITY_FLAGS_TX_CSUM)
-                                && (skb->ip_summed == CHECKSUM_HW)) {
+                                && (skb->ip_summed == CHECKSUM_PARTIAL)) {
                struct iphdr *ip = skb->nh.iph;
                if (ip->protocol == IPPROTO_TCP)
                        td_ptr->tdesc1.TCR |= TCR0_TCPCK;
index 67d1e1c8813d3ac55f4504400c1e2a99be403218..4acde4f7dbf8925a159fce3a9594be4bd4727e4a 100644 (file)
@@ -1826,8 +1826,8 @@ static int __devinit riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd)
 {
        struct riva_par *par = info->par;
        struct device_node *dp;
-       unsigned char *pedid = NULL;
-       unsigned char *disptype = NULL;
+       const unsigned char *pedid = NULL;
+       const unsigned char *disptype = NULL;
        static char *propnames[] = {
                "DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID,B", "EDID,A", NULL };
        int i;
index 5305816283113ed95815c34ede91a040cfe8cfda..a27002668bd36a7abb3074bfa41036ae16580b73 100644 (file)
@@ -1471,8 +1471,8 @@ config NFS_V4
          If unsure, say N.
 
 config NFS_DIRECTIO
-       bool "Allow direct I/O on NFS files (EXPERIMENTAL)"
-       depends on NFS_FS && EXPERIMENTAL
+       bool "Allow direct I/O on NFS files"
+       depends on NFS_FS
        help
          This option enables applications to perform uncached I/O on files
          in NFS file systems using the O_DIRECT open() flag.  When O_DIRECT
index 1b4a3a34ec57f20d605386c129c9ebf315dd1765..17b392a2049ebfb9b39103ecedbd9fe6ec884828 100644 (file)
@@ -828,17 +828,19 @@ void d_instantiate(struct dentry *entry, struct inode * inode)
  * (or otherwise set) by the caller to indicate that it is now
  * in use by the dcache.
  */
-struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode)
+static struct dentry *__d_instantiate_unique(struct dentry *entry,
+                                            struct inode *inode)
 {
        struct dentry *alias;
        int len = entry->d_name.len;
        const char *name = entry->d_name.name;
        unsigned int hash = entry->d_name.hash;
 
-       BUG_ON(!list_empty(&entry->d_alias));
-       spin_lock(&dcache_lock);
-       if (!inode)
-               goto do_negative;
+       if (!inode) {
+               entry->d_inode = NULL;
+               return NULL;
+       }
+
        list_for_each_entry(alias, &inode->i_dentry, d_alias) {
                struct qstr *qstr = &alias->d_name;
 
@@ -851,19 +853,35 @@ struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode)
                if (memcmp(qstr->name, name, len))
                        continue;
                dget_locked(alias);
-               spin_unlock(&dcache_lock);
-               BUG_ON(!d_unhashed(alias));
-               iput(inode);
                return alias;
        }
+
        list_add(&entry->d_alias, &inode->i_dentry);
-do_negative:
        entry->d_inode = inode;
        fsnotify_d_instantiate(entry, inode);
-       spin_unlock(&dcache_lock);
-       security_d_instantiate(entry, inode);
        return NULL;
 }
+
+struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode)
+{
+       struct dentry *result;
+
+       BUG_ON(!list_empty(&entry->d_alias));
+
+       spin_lock(&dcache_lock);
+       result = __d_instantiate_unique(entry, inode);
+       spin_unlock(&dcache_lock);
+
+       if (!result) {
+               security_d_instantiate(entry, inode);
+               return NULL;
+       }
+
+       BUG_ON(!d_unhashed(result));
+       iput(inode);
+       return result;
+}
+
 EXPORT_SYMBOL(d_instantiate_unique);
 
 /**
@@ -1235,6 +1253,11 @@ static void __d_rehash(struct dentry * entry, struct hlist_head *list)
        hlist_add_head_rcu(&entry->d_hash, list);
 }
 
+static void _d_rehash(struct dentry * entry)
+{
+       __d_rehash(entry, d_hash(entry->d_parent, entry->d_name.hash));
+}
+
 /**
  * d_rehash    - add an entry back to the hash
  * @entry: dentry to add to the hash
@@ -1244,11 +1267,9 @@ static void __d_rehash(struct dentry * entry, struct hlist_head *list)
  
 void d_rehash(struct dentry * entry)
 {
-       struct hlist_head *list = d_hash(entry->d_parent, entry->d_name.hash);
-
        spin_lock(&dcache_lock);
        spin_lock(&entry->d_lock);
-       __d_rehash(entry, list);
+       _d_rehash(entry);
        spin_unlock(&entry->d_lock);
        spin_unlock(&dcache_lock);
 }
@@ -1386,6 +1407,120 @@ already_unhashed:
        spin_unlock(&dcache_lock);
 }
 
+/*
+ * Prepare an anonymous dentry for life in the superblock's dentry tree as a
+ * named dentry in place of the dentry to be replaced.
+ */
+static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon)
+{
+       struct dentry *dparent, *aparent;
+
+       switch_names(dentry, anon);
+       do_switch(dentry->d_name.len, anon->d_name.len);
+       do_switch(dentry->d_name.hash, anon->d_name.hash);
+
+       dparent = dentry->d_parent;
+       aparent = anon->d_parent;
+
+       dentry->d_parent = (aparent == anon) ? dentry : aparent;
+       list_del(&dentry->d_u.d_child);
+       if (!IS_ROOT(dentry))
+               list_add(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs);
+       else
+               INIT_LIST_HEAD(&dentry->d_u.d_child);
+
+       anon->d_parent = (dparent == dentry) ? anon : dparent;
+       list_del(&anon->d_u.d_child);
+       if (!IS_ROOT(anon))
+               list_add(&anon->d_u.d_child, &anon->d_parent->d_subdirs);
+       else
+               INIT_LIST_HEAD(&anon->d_u.d_child);
+
+       anon->d_flags &= ~DCACHE_DISCONNECTED;
+}
+
+/**
+ * d_materialise_unique - introduce an inode into the tree
+ * @dentry: candidate dentry
+ * @inode: inode to bind to the dentry, to which aliases may be attached
+ *
+ * Introduces an dentry into the tree, substituting an extant disconnected
+ * root directory alias in its place if there is one
+ */
+struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
+{
+       struct dentry *alias, *actual;
+
+       BUG_ON(!d_unhashed(dentry));
+
+       spin_lock(&dcache_lock);
+
+       if (!inode) {
+               actual = dentry;
+               dentry->d_inode = NULL;
+               goto found_lock;
+       }
+
+       /* See if a disconnected directory already exists as an anonymous root
+        * that we should splice into the tree instead */
+       if (S_ISDIR(inode->i_mode) && (alias = __d_find_alias(inode, 1))) {
+               spin_lock(&alias->d_lock);
+
+               /* Is this a mountpoint that we could splice into our tree? */
+               if (IS_ROOT(alias))
+                       goto connect_mountpoint;
+
+               if (alias->d_name.len == dentry->d_name.len &&
+                   alias->d_parent == dentry->d_parent &&
+                   memcmp(alias->d_name.name,
+                          dentry->d_name.name,
+                          dentry->d_name.len) == 0)
+                       goto replace_with_alias;
+
+               spin_unlock(&alias->d_lock);
+
+               /* Doh! Seem to be aliasing directories for some reason... */
+               dput(alias);
+       }
+
+       /* Add a unique reference */
+       actual = __d_instantiate_unique(dentry, inode);
+       if (!actual)
+               actual = dentry;
+       else if (unlikely(!d_unhashed(actual)))
+               goto shouldnt_be_hashed;
+
+found_lock:
+       spin_lock(&actual->d_lock);
+found:
+       _d_rehash(actual);
+       spin_unlock(&actual->d_lock);
+       spin_unlock(&dcache_lock);
+
+       if (actual == dentry) {
+               security_d_instantiate(dentry, inode);
+               return NULL;
+       }
+
+       iput(inode);
+       return actual;
+
+       /* Convert the anonymous/root alias into an ordinary dentry */
+connect_mountpoint:
+       __d_materialise_dentry(dentry, alias);
+
+       /* Replace the candidate dentry with the alias in the tree */
+replace_with_alias:
+       __d_drop(alias);
+       actual = alias;
+       goto found;
+
+shouldnt_be_hashed:
+       spin_unlock(&dcache_lock);
+       BUG();
+       goto shouldnt_be_hashed;
+}
+
 /**
  * d_path - return the path of a dentry
  * @dentry: dentry to report
@@ -1784,6 +1919,7 @@ EXPORT_SYMBOL(d_instantiate);
 EXPORT_SYMBOL(d_invalidate);
 EXPORT_SYMBOL(d_lookup);
 EXPORT_SYMBOL(d_move);
+EXPORT_SYMBOL_GPL(d_materialise_unique);
 EXPORT_SYMBOL(d_path);
 EXPORT_SYMBOL(d_prune_aliases);
 EXPORT_SYMBOL(d_rehash);
index 89ba0df14c220f4af771c216a4be34d42b63e1ad..50dbb67ae0c4bb271d60784135dfc0bf7cd8e6e2 100644 (file)
@@ -151,11 +151,13 @@ static void nlmclnt_release_lockargs(struct nlm_rqst *req)
 int
 nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl)
 {
+       struct rpc_clnt         *client = NFS_CLIENT(inode);
+       struct sockaddr_in      addr;
        struct nlm_host         *host;
        struct nlm_rqst         *call;
        sigset_t                oldset;
        unsigned long           flags;
-       int                     status, proto, vers;
+       int                     status, vers;
 
        vers = (NFS_PROTO(inode)->version == 3) ? 4 : 1;
        if (NFS_PROTO(inode)->version > 3) {
@@ -163,10 +165,8 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl)
                return -ENOLCK;
        }
 
-       /* Retrieve transport protocol from NFS client */
-       proto = NFS_CLIENT(inode)->cl_xprt->prot;
-
-       host = nlmclnt_lookup_host(NFS_ADDR(inode), proto, vers);
+       rpc_peeraddr(client, (struct sockaddr *) &addr, sizeof(addr));
+       host = nlmclnt_lookup_host(&addr, client->cl_xprt->prot, vers);
        if (host == NULL)
                return -ENOLCK;
 
index 38b0e8a1aec0903d61b8bd78a10e05d5f77d29b4..703fb038c813c352430295c3537b6a7cc32debf8 100644 (file)
@@ -26,7 +26,6 @@
 #define NLM_HOST_REBIND                (60 * HZ)
 #define NLM_HOST_EXPIRE                ((nrhosts > NLM_HOST_MAX)? 300 * HZ : 120 * HZ)
 #define NLM_HOST_COLLECT       ((nrhosts > NLM_HOST_MAX)? 120 * HZ :  60 * HZ)
-#define NLM_HOST_ADDR(sv)      (&(sv)->s_nlmclnt->cl_xprt->addr)
 
 static struct nlm_host *       nlm_hosts[NLM_HOST_NRHASH];
 static unsigned long           next_gc;
@@ -167,7 +166,6 @@ struct rpc_clnt *
 nlm_bind_host(struct nlm_host *host)
 {
        struct rpc_clnt *clnt;
-       struct rpc_xprt *xprt;
 
        dprintk("lockd: nlm_bind_host(%08x)\n",
                        (unsigned)ntohl(host->h_addr.sin_addr.s_addr));
@@ -179,7 +177,6 @@ nlm_bind_host(struct nlm_host *host)
         * RPC rebind is required
         */
        if ((clnt = host->h_rpcclnt) != NULL) {
-               xprt = clnt->cl_xprt;
                if (time_after_eq(jiffies, host->h_nextrebind)) {
                        rpc_force_rebind(clnt);
                        host->h_nextrebind = jiffies + NLM_HOST_REBIND;
@@ -187,31 +184,37 @@ nlm_bind_host(struct nlm_host *host)
                                        host->h_nextrebind - jiffies);
                }
        } else {
-               xprt = xprt_create_proto(host->h_proto, &host->h_addr, NULL);
-               if (IS_ERR(xprt))
-                       goto forgetit;
-
-               xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout);
-               xprt->resvport = 1;     /* NLM requires a reserved port */
-
-               /* Existing NLM servers accept AUTH_UNIX only */
-               clnt = rpc_new_client(xprt, host->h_name, &nlm_program,
-                                       host->h_version, RPC_AUTH_UNIX);
-               if (IS_ERR(clnt))
-                       goto forgetit;
-               clnt->cl_autobind = 1;  /* turn on pmap queries */
-               clnt->cl_softrtry = 1; /* All queries are soft */
-
-               host->h_rpcclnt = clnt;
+               unsigned long increment = nlmsvc_timeout * HZ;
+               struct rpc_timeout timeparms = {
+                       .to_initval     = increment,
+                       .to_increment   = increment,
+                       .to_maxval      = increment * 6UL,
+                       .to_retries     = 5U,
+               };
+               struct rpc_create_args args = {
+                       .protocol       = host->h_proto,
+                       .address        = (struct sockaddr *)&host->h_addr,
+                       .addrsize       = sizeof(host->h_addr),
+                       .timeout        = &timeparms,
+                       .servername     = host->h_name,
+                       .program        = &nlm_program,
+                       .version        = host->h_version,
+                       .authflavor     = RPC_AUTH_UNIX,
+                       .flags          = (RPC_CLNT_CREATE_HARDRTRY |
+                                          RPC_CLNT_CREATE_AUTOBIND),
+               };
+
+               clnt = rpc_create(&args);
+               if (!IS_ERR(clnt))
+                       host->h_rpcclnt = clnt;
+               else {
+                       printk("lockd: couldn't create RPC handle for %s\n", host->h_name);
+                       clnt = NULL;
+               }
        }
 
        mutex_unlock(&host->h_mutex);
        return clnt;
-
-forgetit:
-       printk("lockd: couldn't create RPC handle for %s\n", host->h_name);
-       mutex_unlock(&host->h_mutex);
-       return NULL;
 }
 
 /*
index 3fc683f46b3e1cd38df9e0da718fa1f4d46f3c8c..5954dcb497e4e43b241ba48d6cab7f6b1453e307 100644 (file)
@@ -109,30 +109,23 @@ nsm_unmonitor(struct nlm_host *host)
 static struct rpc_clnt *
 nsm_create(void)
 {
-       struct rpc_xprt         *xprt;
-       struct rpc_clnt         *clnt;
-       struct sockaddr_in      sin;
-
-       sin.sin_family = AF_INET;
-       sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-       sin.sin_port = 0;
-
-       xprt = xprt_create_proto(IPPROTO_UDP, &sin, NULL);
-       if (IS_ERR(xprt))
-               return (struct rpc_clnt *)xprt;
-       xprt->resvport = 1;     /* NSM requires a reserved port */
-
-       clnt = rpc_create_client(xprt, "localhost",
-                               &nsm_program, SM_VERSION,
-                               RPC_AUTH_NULL);
-       if (IS_ERR(clnt))
-               goto out_err;
-       clnt->cl_softrtry = 1;
-       clnt->cl_oneshot  = 1;
-       return clnt;
-
-out_err:
-       return clnt;
+       struct sockaddr_in      sin = {
+               .sin_family     = AF_INET,
+               .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
+               .sin_port       = 0,
+       };
+       struct rpc_create_args args = {
+               .protocol       = IPPROTO_UDP,
+               .address        = (struct sockaddr *)&sin,
+               .addrsize       = sizeof(sin),
+               .servername     = "localhost",
+               .program        = &nsm_program,
+               .version        = SM_VERSION,
+               .authflavor     = RPC_AUTH_NULL,
+               .flags          = (RPC_CLNT_CREATE_ONESHOT),
+       };
+
+       return rpc_create(&args);
 }
 
 /*
index 0b572a0c19678a0faf85daaea7e56814da5c77a4..f4580b44eef4b02ee0045c5732cf29d0d6efa347 100644 (file)
@@ -4,9 +4,9 @@
 
 obj-$(CONFIG_NFS_FS) += nfs.o
 
-nfs-y                  := dir.o file.o inode.o super.o nfs2xdr.o pagelist.o \
-                          proc.o read.o symlink.o unlink.o write.o \
-                          namespace.o
+nfs-y                  := client.o dir.o file.o getroot.o inode.o super.o nfs2xdr.o \
+                          pagelist.o proc.o read.o symlink.o unlink.o \
+                          write.o namespace.o
 nfs-$(CONFIG_ROOT_NFS) += nfsroot.o mount_clnt.o      
 nfs-$(CONFIG_NFS_V3)   += nfs3proc.o nfs3xdr.o
 nfs-$(CONFIG_NFS_V3_ACL)       += nfs3acl.o
index fe0a6b8ac149cbb5cfb5808343948f44990fb752..a3ee11364db02044e07cd6dce7a5546aa4016650 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "nfs4_fs.h"
 #include "callback.h"
+#include "internal.h"
 
 #define NFSDBG_FACILITY NFSDBG_CALLBACK
 
@@ -36,6 +37,21 @@ static struct svc_program nfs4_callback_program;
 
 unsigned int nfs_callback_set_tcpport;
 unsigned short nfs_callback_tcpport;
+static const int nfs_set_port_min = 0;
+static const int nfs_set_port_max = 65535;
+
+static int param_set_port(const char *val, struct kernel_param *kp)
+{
+       char *endp;
+       int num = simple_strtol(val, &endp, 0);
+       if (endp == val || *endp || num < nfs_set_port_min || num > nfs_set_port_max)
+               return -EINVAL;
+       *((int *)kp->arg) = num;
+       return 0;
+}
+
+module_param_call(callback_tcpport, param_set_port, param_get_int,
+                &nfs_callback_set_tcpport, 0644);
 
 /*
  * This is the callback kernel thread.
@@ -134,10 +150,8 @@ out_err:
 /*
  * Kill the server process if it is not already up.
  */
-int nfs_callback_down(void)
+void nfs_callback_down(void)
 {
-       int ret = 0;
-
        lock_kernel();
        mutex_lock(&nfs_callback_mutex);
        nfs_callback_info.users--;
@@ -149,20 +163,19 @@ int nfs_callback_down(void)
        } while (wait_for_completion_timeout(&nfs_callback_info.stopped, 5*HZ) == 0);
        mutex_unlock(&nfs_callback_mutex);
        unlock_kernel();
-       return ret;
 }
 
 static int nfs_callback_authenticate(struct svc_rqst *rqstp)
 {
-       struct in_addr *addr = &rqstp->rq_addr.sin_addr;
-       struct nfs4_client *clp;
+       struct sockaddr_in *addr = &rqstp->rq_addr;
+       struct nfs_client *clp;
 
        /* Don't talk to strangers */
-       clp = nfs4_find_client(addr);
+       clp = nfs_find_client(addr, 4);
        if (clp == NULL)
                return SVC_DROP;
-       dprintk("%s: %u.%u.%u.%u NFSv4 callback!\n", __FUNCTION__, NIPQUAD(addr));
-       nfs4_put_client(clp);
+       dprintk("%s: %u.%u.%u.%u NFSv4 callback!\n", __FUNCTION__, NIPQUAD(addr->sin_addr));
+       nfs_put_client(clp);
        switch (rqstp->rq_authop->flavour) {
                case RPC_AUTH_NULL:
                        if (rqstp->rq_proc != CB_NULL)
index b252e7fe53a5c2ffb52e053a609368f280cad2a4..5676163d26e819c45e13617337916186e4335290 100644 (file)
@@ -62,8 +62,13 @@ struct cb_recallargs {
 extern unsigned nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res);
 extern unsigned nfs4_callback_recall(struct cb_recallargs *args, void *dummy);
 
+#ifdef CONFIG_NFS_V4
 extern int nfs_callback_up(void);
-extern int nfs_callback_down(void);
+extern void nfs_callback_down(void);
+#else
+#define nfs_callback_up()      (0)
+#define nfs_callback_down()    do {} while(0)
+#endif
 
 extern unsigned int nfs_callback_set_tcpport;
 extern unsigned short nfs_callback_tcpport;
index 7719483ecdfc0827171f1a8a8fd5b8a4aef42ba2..97cf8f71451ffbbd02e85d2d4c4061ee73dfb75a 100644 (file)
 #include "nfs4_fs.h"
 #include "callback.h"
 #include "delegation.h"
+#include "internal.h"
 
 #define NFSDBG_FACILITY NFSDBG_CALLBACK
  
 unsigned nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res)
 {
-       struct nfs4_client *clp;
+       struct nfs_client *clp;
        struct nfs_delegation *delegation;
        struct nfs_inode *nfsi;
        struct inode *inode;
        
        res->bitmap[0] = res->bitmap[1] = 0;
        res->status = htonl(NFS4ERR_BADHANDLE);
-       clp = nfs4_find_client(&args->addr->sin_addr);
+       clp = nfs_find_client(args->addr, 4);
        if (clp == NULL)
                goto out;
        inode = nfs_delegation_find_inode(clp, &args->fh);
@@ -48,7 +49,7 @@ out_iput:
        up_read(&nfsi->rwsem);
        iput(inode);
 out_putclient:
-       nfs4_put_client(clp);
+       nfs_put_client(clp);
 out:
        dprintk("%s: exit with status = %d\n", __FUNCTION__, ntohl(res->status));
        return res->status;
@@ -56,12 +57,12 @@ out:
 
 unsigned nfs4_callback_recall(struct cb_recallargs *args, void *dummy)
 {
-       struct nfs4_client *clp;
+       struct nfs_client *clp;
        struct inode *inode;
        unsigned res;
        
        res = htonl(NFS4ERR_BADHANDLE);
-       clp = nfs4_find_client(&args->addr->sin_addr);
+       clp = nfs_find_client(args->addr, 4);
        if (clp == NULL)
                goto out;
        inode = nfs_delegation_find_inode(clp, &args->fh);
@@ -80,7 +81,7 @@ unsigned nfs4_callback_recall(struct cb_recallargs *args, void *dummy)
        }
        iput(inode);
 out_putclient:
-       nfs4_put_client(clp);
+       nfs_put_client(clp);
 out:
        dprintk("%s: exit with status = %d\n", __FUNCTION__, ntohl(res));
        return res;
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
new file mode 100644 (file)
index 0000000..ec1938d
--- /dev/null
@@ -0,0 +1,1448 @@
+/* client.c: NFS client sharing and management code
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/time.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/stat.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/stats.h>
+#include <linux/sunrpc/metrics.h>
+#include <linux/nfs_fs.h>
+#include <linux/nfs_mount.h>
+#include <linux/nfs4_mount.h>
+#include <linux/lockd/bind.h>
+#include <linux/smp_lock.h>
+#include <linux/seq_file.h>
+#include <linux/mount.h>
+#include <linux/nfs_idmap.h>
+#include <linux/vfs.h>
+#include <linux/inet.h>
+#include <linux/nfs_xdr.h>
+
+#include <asm/system.h>
+
+#include "nfs4_fs.h"
+#include "callback.h"
+#include "delegation.h"
+#include "iostat.h"
+#include "internal.h"
+
+#define NFSDBG_FACILITY                NFSDBG_CLIENT
+
+static DEFINE_SPINLOCK(nfs_client_lock);
+static LIST_HEAD(nfs_client_list);
+static LIST_HEAD(nfs_volume_list);
+static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);
+
+/*
+ * RPC cruft for NFS
+ */
+static struct rpc_version *nfs_version[5] = {
+       [2]                     = &nfs_version2,
+#ifdef CONFIG_NFS_V3
+       [3]                     = &nfs_version3,
+#endif
+#ifdef CONFIG_NFS_V4
+       [4]                     = &nfs_version4,
+#endif
+};
+
+struct rpc_program nfs_program = {
+       .name                   = "nfs",
+       .number                 = NFS_PROGRAM,
+       .nrvers                 = ARRAY_SIZE(nfs_version),
+       .version                = nfs_version,
+       .stats                  = &nfs_rpcstat,
+       .pipe_dir_name          = "/nfs",
+};
+
+struct rpc_stat nfs_rpcstat = {
+       .program                = &nfs_program
+};
+
+
+#ifdef CONFIG_NFS_V3_ACL
+static struct rpc_stat         nfsacl_rpcstat = { &nfsacl_program };
+static struct rpc_version *    nfsacl_version[] = {
+       [3]                     = &nfsacl_version3,
+};
+
+struct rpc_program             nfsacl_program = {
+       .name                   = "nfsacl",
+       .number                 = NFS_ACL_PROGRAM,
+       .nrvers                 = ARRAY_SIZE(nfsacl_version),
+       .version                = nfsacl_version,
+       .stats                  = &nfsacl_rpcstat,
+};
+#endif  /* CONFIG_NFS_V3_ACL */
+
+/*
+ * Allocate a shared client record
+ *
+ * Since these are allocated/deallocated very rarely, we don't
+ * bother putting them in a slab cache...
+ */
+static struct nfs_client *nfs_alloc_client(const char *hostname,
+                                          const struct sockaddr_in *addr,
+                                          int nfsversion)
+{
+       struct nfs_client *clp;
+       int error;
+
+       if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL)
+               goto error_0;
+
+       error = rpciod_up();
+       if (error < 0) {
+               dprintk("%s: couldn't start rpciod! Error = %d\n",
+                               __FUNCTION__, error);
+               goto error_1;
+       }
+       __set_bit(NFS_CS_RPCIOD, &clp->cl_res_state);
+
+       if (nfsversion == 4) {
+               if (nfs_callback_up() < 0)
+                       goto error_2;
+               __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
+       }
+
+       atomic_set(&clp->cl_count, 1);
+       clp->cl_cons_state = NFS_CS_INITING;
+
+       clp->cl_nfsversion = nfsversion;
+       memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr));
+
+       if (hostname) {
+               clp->cl_hostname = kstrdup(hostname, GFP_KERNEL);
+               if (!clp->cl_hostname)
+                       goto error_3;
+       }
+
+       INIT_LIST_HEAD(&clp->cl_superblocks);
+       clp->cl_rpcclient = ERR_PTR(-EINVAL);
+
+#ifdef CONFIG_NFS_V4
+       init_rwsem(&clp->cl_sem);
+       INIT_LIST_HEAD(&clp->cl_delegations);
+       INIT_LIST_HEAD(&clp->cl_state_owners);
+       INIT_LIST_HEAD(&clp->cl_unused);
+       spin_lock_init(&clp->cl_lock);
+       INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp);
+       rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
+       clp->cl_boot_time = CURRENT_TIME;
+       clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
+#endif
+
+       return clp;
+
+error_3:
+       if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
+               nfs_callback_down();
+error_2:
+       rpciod_down();
+       __clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state);
+error_1:
+       kfree(clp);
+error_0:
+       return NULL;
+}
+
+static void nfs4_shutdown_client(struct nfs_client *clp)
+{
+#ifdef CONFIG_NFS_V4
+       if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
+               nfs4_kill_renewd(clp);
+       while (!list_empty(&clp->cl_unused)) {
+               struct nfs4_state_owner *sp;
+
+               sp = list_entry(clp->cl_unused.next,
+                               struct nfs4_state_owner,
+                               so_list);
+               list_del(&sp->so_list);
+               kfree(sp);
+       }
+       BUG_ON(!list_empty(&clp->cl_state_owners));
+       if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
+               nfs_idmap_delete(clp);
+#endif
+}
+
+/*
+ * Destroy a shared client record
+ */
+static void nfs_free_client(struct nfs_client *clp)
+{
+       dprintk("--> nfs_free_client(%d)\n", clp->cl_nfsversion);
+
+       nfs4_shutdown_client(clp);
+
+       /* -EIO all pending I/O */
+       if (!IS_ERR(clp->cl_rpcclient))
+               rpc_shutdown_client(clp->cl_rpcclient);
+
+       if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
+               nfs_callback_down();
+
+       if (__test_and_clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state))
+               rpciod_down();
+
+       kfree(clp->cl_hostname);
+       kfree(clp);
+
+       dprintk("<-- nfs_free_client()\n");
+}
+
+/*
+ * Release a reference to a shared client record
+ */
+void nfs_put_client(struct nfs_client *clp)
+{
+       if (!clp)
+               return;
+
+       dprintk("--> nfs_put_client({%d})\n", atomic_read(&clp->cl_count));
+
+       if (atomic_dec_and_lock(&clp->cl_count, &nfs_client_lock)) {
+               list_del(&clp->cl_share_link);
+               spin_unlock(&nfs_client_lock);
+
+               BUG_ON(!list_empty(&clp->cl_superblocks));
+
+               nfs_free_client(clp);
+       }
+}
+
+/*
+ * Find a client by address
+ * - caller must hold nfs_client_lock
+ */
+static struct nfs_client *__nfs_find_client(const struct sockaddr_in *addr, int nfsversion)
+{
+       struct nfs_client *clp;
+
+       list_for_each_entry(clp, &nfs_client_list, cl_share_link) {
+               /* Different NFS versions cannot share the same nfs_client */
+               if (clp->cl_nfsversion != nfsversion)
+                       continue;
+
+               if (memcmp(&clp->cl_addr.sin_addr, &addr->sin_addr,
+                          sizeof(clp->cl_addr.sin_addr)) != 0)
+                       continue;
+
+               if (clp->cl_addr.sin_port == addr->sin_port)
+                       goto found;
+       }
+
+       return NULL;
+
+found:
+       atomic_inc(&clp->cl_count);
+       return clp;
+}
+
+/*
+ * Find a client by IP address and protocol version
+ * - returns NULL if no such client
+ */
+struct nfs_client *nfs_find_client(const struct sockaddr_in *addr, int nfsversion)
+{
+       struct nfs_client *clp;
+
+       spin_lock(&nfs_client_lock);
+       clp = __nfs_find_client(addr, nfsversion);
+       spin_unlock(&nfs_client_lock);
+
+       BUG_ON(clp && clp->cl_cons_state == 0);
+
+       return clp;
+}
+
+/*
+ * Look up a client by IP address and protocol version
+ * - creates a new record if one doesn't yet exist
+ */
+static struct nfs_client *nfs_get_client(const char *hostname,
+                                        const struct sockaddr_in *addr,
+                                        int nfsversion)
+{
+       struct nfs_client *clp, *new = NULL;
+       int error;
+
+       dprintk("--> nfs_get_client(%s,"NIPQUAD_FMT":%d,%d)\n",
+               hostname ?: "", NIPQUAD(addr->sin_addr),
+               addr->sin_port, nfsversion);
+
+       /* see if the client already exists */
+       do {
+               spin_lock(&nfs_client_lock);
+
+               clp = __nfs_find_client(addr, nfsversion);
+               if (clp)
+                       goto found_client;
+               if (new)
+                       goto install_client;
+
+               spin_unlock(&nfs_client_lock);
+
+               new = nfs_alloc_client(hostname, addr, nfsversion);
+       } while (new);
+
+       return ERR_PTR(-ENOMEM);
+
+       /* install a new client and return with it unready */
+install_client:
+       clp = new;
+       list_add(&clp->cl_share_link, &nfs_client_list);
+       spin_unlock(&nfs_client_lock);
+       dprintk("--> nfs_get_client() = %p [new]\n", clp);
+       return clp;
+
+       /* found an existing client
+        * - make sure it's ready before returning
+        */
+found_client:
+       spin_unlock(&nfs_client_lock);
+
+       if (new)
+               nfs_free_client(new);
+
+       if (clp->cl_cons_state == NFS_CS_INITING) {
+               DECLARE_WAITQUEUE(myself, current);
+
+               add_wait_queue(&nfs_client_active_wq, &myself);
+
+               for (;;) {
+                       set_current_state(TASK_INTERRUPTIBLE);
+                       if (signal_pending(current) ||
+                           clp->cl_cons_state > NFS_CS_READY)
+                               break;
+                       schedule();
+               }
+
+               remove_wait_queue(&nfs_client_active_wq, &myself);
+
+               if (signal_pending(current)) {
+                       nfs_put_client(clp);
+                       return ERR_PTR(-ERESTARTSYS);
+               }
+       }
+
+       if (clp->cl_cons_state < NFS_CS_READY) {
+               error = clp->cl_cons_state;
+               nfs_put_client(clp);
+               return ERR_PTR(error);
+       }
+
+       BUG_ON(clp->cl_cons_state != NFS_CS_READY);
+
+       dprintk("--> nfs_get_client() = %p [share]\n", clp);
+       return clp;
+}
+
+/*
+ * Mark a server as ready or failed
+ */
+static void nfs_mark_client_ready(struct nfs_client *clp, int state)
+{
+       clp->cl_cons_state = state;
+       wake_up_all(&nfs_client_active_wq);
+}
+
+/*
+ * Initialise the timeout values for a connection
+ */
+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
+ */
+static int nfs_create_rpc_client(struct nfs_client *clp, int proto,
+                                               unsigned int timeo,
+                                               unsigned int retrans,
+                                               rpc_authflavor_t flavor)
+{
+       struct rpc_timeout      timeparms;
+       struct rpc_clnt         *clnt = NULL;
+       struct rpc_create_args args = {
+               .protocol       = proto,
+               .address        = (struct sockaddr *)&clp->cl_addr,
+               .addrsize       = sizeof(clp->cl_addr),
+               .timeout        = &timeparms,
+               .servername     = clp->cl_hostname,
+               .program        = &nfs_program,
+               .version        = clp->rpc_ops->version,
+               .authflavor     = flavor,
+       };
+
+       if (!IS_ERR(clp->cl_rpcclient))
+               return 0;
+
+       nfs_init_timeout_values(&timeparms, proto, timeo, retrans);
+       clp->retrans_timeo = timeparms.to_initval;
+       clp->retrans_count = timeparms.to_retries;
+
+       clnt = rpc_create(&args);
+       if (IS_ERR(clnt)) {
+               dprintk("%s: cannot create RPC client. Error = %ld\n",
+                               __FUNCTION__, PTR_ERR(clnt));
+               return PTR_ERR(clnt);
+       }
+
+       clp->cl_rpcclient = clnt;
+       return 0;
+}
+
+/*
+ * Version 2 or 3 client destruction
+ */
+static void nfs_destroy_server(struct nfs_server *server)
+{
+       if (!IS_ERR(server->client_acl))
+               rpc_shutdown_client(server->client_acl);
+
+       if (!(server->flags & NFS_MOUNT_NONLM))
+               lockd_down();   /* release rpc.lockd */
+}
+
+/*
+ * Version 2 or 3 lockd setup
+ */
+static int nfs_start_lockd(struct nfs_server *server)
+{
+       int error = 0;
+
+       if (server->nfs_client->cl_nfsversion > 3)
+               goto out;
+       if (server->flags & NFS_MOUNT_NONLM)
+               goto out;
+       error = lockd_up();
+       if (error < 0)
+               server->flags |= NFS_MOUNT_NONLM;
+       else
+               server->destroy = nfs_destroy_server;
+out:
+       return error;
+}
+
+/*
+ * Initialise an NFSv3 ACL client connection
+ */
+#ifdef CONFIG_NFS_V3_ACL
+static void nfs_init_server_aclclient(struct nfs_server *server)
+{
+       if (server->nfs_client->cl_nfsversion != 3)
+               goto out_noacl;
+       if (server->flags & NFS_MOUNT_NOACL)
+               goto out_noacl;
+
+       server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3);
+       if (IS_ERR(server->client_acl))
+               goto out_noacl;
+
+       /* No errors! Assume that Sun nfsacls are supported */
+       server->caps |= NFS_CAP_ACLS;
+       return;
+
+out_noacl:
+       server->caps &= ~NFS_CAP_ACLS;
+}
+#else
+static inline void nfs_init_server_aclclient(struct nfs_server *server)
+{
+       server->flags &= ~NFS_MOUNT_NOACL;
+       server->caps &= ~NFS_CAP_ACLS;
+}
+#endif
+
+/*
+ * Create a general RPC client
+ */
+static int nfs_init_server_rpcclient(struct nfs_server *server, rpc_authflavor_t pseudoflavour)
+{
+       struct nfs_client *clp = server->nfs_client;
+
+       server->client = rpc_clone_client(clp->cl_rpcclient);
+       if (IS_ERR(server->client)) {
+               dprintk("%s: couldn't create rpc_client!\n", __FUNCTION__);
+               return PTR_ERR(server->client);
+       }
+
+       if (pseudoflavour != clp->cl_rpcclient->cl_auth->au_flavor) {
+               struct rpc_auth *auth;
+
+               auth = rpcauth_create(pseudoflavour, server->client);
+               if (IS_ERR(auth)) {
+                       dprintk("%s: couldn't create credcache!\n", __FUNCTION__);
+                       return PTR_ERR(auth);
+               }
+       }
+       server->client->cl_softrtry = 0;
+       if (server->flags & NFS_MOUNT_SOFT)
+               server->client->cl_softrtry = 1;
+
+       server->client->cl_intr = 0;
+       if (server->flags & NFS4_MOUNT_INTR)
+               server->client->cl_intr = 1;
+
+       return 0;
+}
+
+/*
+ * Initialise an NFS2 or NFS3 client
+ */
+static int nfs_init_client(struct nfs_client *clp, const struct nfs_mount_data *data)
+{
+       int proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
+       int error;
+
+       if (clp->cl_cons_state == NFS_CS_READY) {
+               /* the client is already initialised */
+               dprintk("<-- nfs_init_client() = 0 [already %p]\n", clp);
+               return 0;
+       }
+
+       /* Check NFS protocol revision and initialize RPC op vector */
+       clp->rpc_ops = &nfs_v2_clientops;
+#ifdef CONFIG_NFS_V3
+       if (clp->cl_nfsversion == 3)
+               clp->rpc_ops = &nfs_v3_clientops;
+#endif
+       /*
+        * Create a client RPC handle for doing FSSTAT with UNIX auth only
+        * - RFC 2623, sec 2.3.2
+        */
+       error = nfs_create_rpc_client(clp, proto, data->timeo, data->retrans,
+                       RPC_AUTH_UNIX);
+       if (error < 0)
+               goto error;
+       nfs_mark_client_ready(clp, NFS_CS_READY);
+       return 0;
+
+error:
+       nfs_mark_client_ready(clp, error);
+       dprintk("<-- nfs_init_client() = xerror %d\n", error);
+       return error;
+}
+
+/*
+ * Create a version 2 or 3 client
+ */
+static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_data *data)
+{
+       struct nfs_client *clp;
+       int error, nfsvers = 2;
+
+       dprintk("--> nfs_init_server()\n");
+
+#ifdef CONFIG_NFS_V3
+       if (data->flags & NFS_MOUNT_VER3)
+               nfsvers = 3;
+#endif
+
+       /* Allocate or find a client reference we can use */
+       clp = nfs_get_client(data->hostname, &data->addr, nfsvers);
+       if (IS_ERR(clp)) {
+               dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp));
+               return PTR_ERR(clp);
+       }
+
+       error = nfs_init_client(clp, data);
+       if (error < 0)
+               goto error;
+
+       server->nfs_client = clp;
+
+       /* Initialise the client representation from the mount data */
+       server->flags = data->flags & NFS_MOUNT_FLAGMASK;
+
+       if (data->rsize)
+               server->rsize = nfs_block_size(data->rsize, NULL);
+       if (data->wsize)
+               server->wsize = nfs_block_size(data->wsize, NULL);
+
+       server->acregmin = data->acregmin * HZ;
+       server->acregmax = data->acregmax * HZ;
+       server->acdirmin = data->acdirmin * HZ;
+       server->acdirmax = data->acdirmax * HZ;
+
+       /* Start lockd here, before we might error out */
+       error = nfs_start_lockd(server);
+       if (error < 0)
+               goto error;
+
+       error = nfs_init_server_rpcclient(server, data->pseudoflavor);
+       if (error < 0)
+               goto error;
+
+       server->namelen  = data->namlen;
+       /* Create a client RPC handle for the NFSv3 ACL management interface */
+       nfs_init_server_aclclient(server);
+       if (clp->cl_nfsversion == 3) {
+               if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN)
+                       server->namelen = NFS3_MAXNAMLEN;
+               server->caps |= NFS_CAP_READDIRPLUS;
+       } else {
+               if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN)
+                       server->namelen = NFS2_MAXNAMLEN;
+       }
+
+       dprintk("<-- nfs_init_server() = 0 [new %p]\n", clp);
+       return 0;
+
+error:
+       server->nfs_client = NULL;
+       nfs_put_client(clp);
+       dprintk("<-- nfs_init_server() = xerror %d\n", error);
+       return error;
+}
+
+/*
+ * Load up the server record from information gained in an fsinfo record
+ */
+static void nfs_server_set_fsinfo(struct nfs_server *server, struct nfs_fsinfo *fsinfo)
+{
+       unsigned long max_rpc_payload;
+
+       /* Work out a lot of parameters */
+       if (server->rsize == 0)
+               server->rsize = nfs_block_size(fsinfo->rtpref, NULL);
+       if (server->wsize == 0)
+               server->wsize = nfs_block_size(fsinfo->wtpref, NULL);
+
+       if (fsinfo->rtmax >= 512 && server->rsize > fsinfo->rtmax)
+               server->rsize = nfs_block_size(fsinfo->rtmax, NULL);
+       if (fsinfo->wtmax >= 512 && server->wsize > fsinfo->wtmax)
+               server->wsize = nfs_block_size(fsinfo->wtmax, NULL);
+
+       max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL);
+       if (server->rsize > max_rpc_payload)
+               server->rsize = max_rpc_payload;
+       if (server->rsize > NFS_MAX_FILE_IO_SIZE)
+               server->rsize = NFS_MAX_FILE_IO_SIZE;
+       server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+       server->backing_dev_info.ra_pages = server->rpages * NFS_MAX_READAHEAD;
+
+       if (server->wsize > max_rpc_payload)
+               server->wsize = max_rpc_payload;
+       if (server->wsize > NFS_MAX_FILE_IO_SIZE)
+               server->wsize = NFS_MAX_FILE_IO_SIZE;
+       server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+       server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL);
+
+       server->dtsize = nfs_block_size(fsinfo->dtpref, NULL);
+       if (server->dtsize > PAGE_CACHE_SIZE)
+               server->dtsize = PAGE_CACHE_SIZE;
+       if (server->dtsize > server->rsize)
+               server->dtsize = server->rsize;
+
+       if (server->flags & NFS_MOUNT_NOAC) {
+               server->acregmin = server->acregmax = 0;
+               server->acdirmin = server->acdirmax = 0;
+       }
+
+       server->maxfilesize = fsinfo->maxfilesize;
+
+       /* We're airborne Set socket buffersize */
+       rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);
+}
+
+/*
+ * Probe filesystem information, including the FSID on v2/v3
+ */
+static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, struct nfs_fattr *fattr)
+{
+       struct nfs_fsinfo fsinfo;
+       struct nfs_client *clp = server->nfs_client;
+       int error;
+
+       dprintk("--> nfs_probe_fsinfo()\n");
+
+       if (clp->rpc_ops->set_capabilities != NULL) {
+               error = clp->rpc_ops->set_capabilities(server, mntfh);
+               if (error < 0)
+                       goto out_error;
+       }
+
+       fsinfo.fattr = fattr;
+       nfs_fattr_init(fattr);
+       error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo);
+       if (error < 0)
+               goto out_error;
+
+       nfs_server_set_fsinfo(server, &fsinfo);
+
+       /* Get some general file system info */
+       if (server->namelen == 0) {
+               struct nfs_pathconf pathinfo;
+
+               pathinfo.fattr = fattr;
+               nfs_fattr_init(fattr);
+
+               if (clp->rpc_ops->pathconf(server, mntfh, &pathinfo) >= 0)
+                       server->namelen = pathinfo.max_namelen;
+       }
+
+       dprintk("<-- nfs_probe_fsinfo() = 0\n");
+       return 0;
+
+out_error:
+       dprintk("nfs_probe_fsinfo: error = %d\n", -error);
+       return error;
+}
+
+/*
+ * Copy useful information when duplicating a server record
+ */
+static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source)
+{
+       target->flags = source->flags;
+       target->acregmin = source->acregmin;
+       target->acregmax = source->acregmax;
+       target->acdirmin = source->acdirmin;
+       target->acdirmax = source->acdirmax;
+       target->caps = source->caps;
+}
+
+/*
+ * Allocate and initialise a server record
+ */
+static struct nfs_server *nfs_alloc_server(void)
+{
+       struct nfs_server *server;
+
+       server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
+       if (!server)
+               return NULL;
+
+       server->client = server->client_acl = ERR_PTR(-EINVAL);
+
+       /* Zero out the NFS state stuff */
+       INIT_LIST_HEAD(&server->client_link);
+       INIT_LIST_HEAD(&server->master_link);
+
+       server->io_stats = nfs_alloc_iostats();
+       if (!server->io_stats) {
+               kfree(server);
+               return NULL;
+       }
+
+       return server;
+}
+
+/*
+ * Free up a server record
+ */
+void nfs_free_server(struct nfs_server *server)
+{
+       dprintk("--> nfs_free_server()\n");
+
+       spin_lock(&nfs_client_lock);
+       list_del(&server->client_link);
+       list_del(&server->master_link);
+       spin_unlock(&nfs_client_lock);
+
+       if (server->destroy != NULL)
+               server->destroy(server);
+       if (!IS_ERR(server->client))
+               rpc_shutdown_client(server->client);
+
+       nfs_put_client(server->nfs_client);
+
+       nfs_free_iostats(server->io_stats);
+       kfree(server);
+       nfs_release_automount_timer();
+       dprintk("<-- nfs_free_server()\n");
+}
+
+/*
+ * Create a version 2 or 3 volume record
+ * - keyed on server and FSID
+ */
+struct nfs_server *nfs_create_server(const struct nfs_mount_data *data,
+                                    struct nfs_fh *mntfh)
+{
+       struct nfs_server *server;
+       struct nfs_fattr fattr;
+       int error;
+
+       server = nfs_alloc_server();
+       if (!server)
+               return ERR_PTR(-ENOMEM);
+
+       /* Get a client representation */
+       error = nfs_init_server(server, data);
+       if (error < 0)
+               goto error;
+
+       BUG_ON(!server->nfs_client);
+       BUG_ON(!server->nfs_client->rpc_ops);
+       BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
+
+       /* Probe the root fh to retrieve its FSID */
+       error = nfs_probe_fsinfo(server, mntfh, &fattr);
+       if (error < 0)
+               goto error;
+       if (!(fattr.valid & NFS_ATTR_FATTR)) {
+               error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr);
+               if (error < 0) {
+                       dprintk("nfs_create_server: getattr error = %d\n", -error);
+                       goto error;
+               }
+       }
+       memcpy(&server->fsid, &fattr.fsid, sizeof(server->fsid));
+
+       dprintk("Server FSID: %llx:%llx\n",
+               (unsigned long long) server->fsid.major,
+               (unsigned long long) server->fsid.minor);
+
+       BUG_ON(!server->nfs_client);
+       BUG_ON(!server->nfs_client->rpc_ops);
+       BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
+
+       spin_lock(&nfs_client_lock);
+       list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
+       list_add_tail(&server->master_link, &nfs_volume_list);
+       spin_unlock(&nfs_client_lock);
+
+       server->mount_time = jiffies;
+       return server;
+
+error:
+       nfs_free_server(server);
+       return ERR_PTR(error);
+}
+
+#ifdef CONFIG_NFS_V4
+/*
+ * Initialise an NFS4 client record
+ */
+static int nfs4_init_client(struct nfs_client *clp,
+               int proto, int timeo, int retrans,
+               rpc_authflavor_t authflavour)
+{
+       int error;
+
+       if (clp->cl_cons_state == NFS_CS_READY) {
+               /* the client is initialised already */
+               dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp);
+               return 0;
+       }
+
+       /* Check NFS protocol revision and initialize RPC op vector */
+       clp->rpc_ops = &nfs_v4_clientops;
+
+       error = nfs_create_rpc_client(clp, proto, timeo, retrans, authflavour);
+       if (error < 0)
+               goto error;
+
+       error = nfs_idmap_new(clp);
+       if (error < 0) {
+               dprintk("%s: failed to create idmapper. Error = %d\n",
+                       __FUNCTION__, error);
+               goto error;
+       }
+       __set_bit(NFS_CS_IDMAP, &clp->cl_res_state);
+
+       nfs_mark_client_ready(clp, NFS_CS_READY);
+       return 0;
+
+error:
+       nfs_mark_client_ready(clp, error);
+       dprintk("<-- nfs4_init_client() = xerror %d\n", error);
+       return error;
+}
+
+/*
+ * Set up an NFS4 client
+ */
+static int nfs4_set_client(struct nfs_server *server,
+               const char *hostname, const struct sockaddr_in *addr,
+               rpc_authflavor_t authflavour,
+               int proto, int timeo, int retrans)
+{
+       struct nfs_client *clp;
+       int error;
+
+       dprintk("--> nfs4_set_client()\n");
+
+       /* Allocate or find a client reference we can use */
+       clp = nfs_get_client(hostname, addr, 4);
+       if (IS_ERR(clp)) {
+               error = PTR_ERR(clp);
+               goto error;
+       }
+       error = nfs4_init_client(clp, proto, timeo, retrans, authflavour);
+       if (error < 0)
+               goto error_put;
+
+       server->nfs_client = clp;
+       dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp);
+       return 0;
+
+error_put:
+       nfs_put_client(clp);
+error:
+       dprintk("<-- nfs4_set_client() = xerror %d\n", error);
+       return error;
+}
+
+/*
+ * Create a version 4 volume record
+ */
+static int nfs4_init_server(struct nfs_server *server,
+               const struct nfs4_mount_data *data, rpc_authflavor_t authflavour)
+{
+       int error;
+
+       dprintk("--> nfs4_init_server()\n");
+
+       /* Initialise the client representation from the mount data */
+       server->flags = data->flags & NFS_MOUNT_FLAGMASK;
+       server->caps |= NFS_CAP_ATOMIC_OPEN;
+
+       if (data->rsize)
+               server->rsize = nfs_block_size(data->rsize, NULL);
+       if (data->wsize)
+               server->wsize = nfs_block_size(data->wsize, NULL);
+
+       server->acregmin = data->acregmin * HZ;
+       server->acregmax = data->acregmax * HZ;
+       server->acdirmin = data->acdirmin * HZ;
+       server->acdirmax = data->acdirmax * HZ;
+
+       error = nfs_init_server_rpcclient(server, authflavour);
+
+       /* Done */
+       dprintk("<-- nfs4_init_server() = %d\n", error);
+       return error;
+}
+
+/*
+ * Create a version 4 volume record
+ * - keyed on server and FSID
+ */
+struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data,
+                                     const char *hostname,
+                                     const struct sockaddr_in *addr,
+                                     const char *mntpath,
+                                     const char *ip_addr,
+                                     rpc_authflavor_t authflavour,
+                                     struct nfs_fh *mntfh)
+{
+       struct nfs_fattr fattr;
+       struct nfs_server *server;
+       int error;
+
+       dprintk("--> nfs4_create_server()\n");
+
+       server = nfs_alloc_server();
+       if (!server)
+               return ERR_PTR(-ENOMEM);
+
+       /* Get a client record */
+       error = nfs4_set_client(server, hostname, addr, authflavour,
+                       data->proto, data->timeo, data->retrans);
+       if (error < 0)
+               goto error;
+
+       /* set up the general RPC client */
+       error = nfs4_init_server(server, data, authflavour);
+       if (error < 0)
+               goto error;
+
+       BUG_ON(!server->nfs_client);
+       BUG_ON(!server->nfs_client->rpc_ops);
+       BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
+
+       /* Probe the root fh to retrieve its FSID */
+       error = nfs4_path_walk(server, mntfh, mntpath);
+       if (error < 0)
+               goto error;
+
+       dprintk("Server FSID: %llx:%llx\n",
+               (unsigned long long) server->fsid.major,
+               (unsigned long long) server->fsid.minor);
+       dprintk("Mount FH: %d\n", mntfh->size);
+
+       error = nfs_probe_fsinfo(server, mntfh, &fattr);
+       if (error < 0)
+               goto error;
+
+       BUG_ON(!server->nfs_client);
+       BUG_ON(!server->nfs_client->rpc_ops);
+       BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
+
+       spin_lock(&nfs_client_lock);
+       list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
+       list_add_tail(&server->master_link, &nfs_volume_list);
+       spin_unlock(&nfs_client_lock);
+
+       server->mount_time = jiffies;
+       dprintk("<-- nfs4_create_server() = %p\n", server);
+       return server;
+
+error:
+       nfs_free_server(server);
+       dprintk("<-- nfs4_create_server() = error %d\n", error);
+       return ERR_PTR(error);
+}
+
+/*
+ * Create an NFS4 referral server record
+ */
+struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
+                                              struct nfs_fh *fh)
+{
+       struct nfs_client *parent_client;
+       struct nfs_server *server, *parent_server;
+       struct nfs_fattr fattr;
+       int error;
+
+       dprintk("--> nfs4_create_referral_server()\n");
+
+       server = nfs_alloc_server();
+       if (!server)
+               return ERR_PTR(-ENOMEM);
+
+       parent_server = NFS_SB(data->sb);
+       parent_client = parent_server->nfs_client;
+
+       /* Get a client representation.
+        * Note: NFSv4 always uses TCP, */
+       error = nfs4_set_client(server, data->hostname, data->addr,
+                       data->authflavor,
+                       parent_server->client->cl_xprt->prot,
+                       parent_client->retrans_timeo,
+                       parent_client->retrans_count);
+       if (error < 0)
+               goto error;
+
+       /* Initialise the client representation from the parent server */
+       nfs_server_copy_userdata(server, parent_server);
+       server->caps |= NFS_CAP_ATOMIC_OPEN;
+
+       error = nfs_init_server_rpcclient(server, data->authflavor);
+       if (error < 0)
+               goto error;
+
+       BUG_ON(!server->nfs_client);
+       BUG_ON(!server->nfs_client->rpc_ops);
+       BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
+
+       /* probe the filesystem info for this server filesystem */
+       error = nfs_probe_fsinfo(server, fh, &fattr);
+       if (error < 0)
+               goto error;
+
+       dprintk("Referral FSID: %llx:%llx\n",
+               (unsigned long long) server->fsid.major,
+               (unsigned long long) server->fsid.minor);
+
+       spin_lock(&nfs_client_lock);
+       list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
+       list_add_tail(&server->master_link, &nfs_volume_list);
+       spin_unlock(&nfs_client_lock);
+
+       server->mount_time = jiffies;
+
+       dprintk("<-- nfs_create_referral_server() = %p\n", server);
+       return server;
+
+error:
+       nfs_free_server(server);
+       dprintk("<-- nfs4_create_referral_server() = error %d\n", error);
+       return ERR_PTR(error);
+}
+
+#endif /* CONFIG_NFS_V4 */
+
+/*
+ * Clone an NFS2, NFS3 or NFS4 server record
+ */
+struct nfs_server *nfs_clone_server(struct nfs_server *source,
+                                   struct nfs_fh *fh,
+                                   struct nfs_fattr *fattr)
+{
+       struct nfs_server *server;
+       struct nfs_fattr fattr_fsinfo;
+       int error;
+
+       dprintk("--> nfs_clone_server(,%llx:%llx,)\n",
+               (unsigned long long) fattr->fsid.major,
+               (unsigned long long) fattr->fsid.minor);
+
+       server = nfs_alloc_server();
+       if (!server)
+               return ERR_PTR(-ENOMEM);
+
+       /* Copy data from the source */
+       server->nfs_client = source->nfs_client;
+       atomic_inc(&server->nfs_client->cl_count);
+       nfs_server_copy_userdata(server, source);
+
+       server->fsid = fattr->fsid;
+
+       error = nfs_init_server_rpcclient(server, source->client->cl_auth->au_flavor);
+       if (error < 0)
+               goto out_free_server;
+       if (!IS_ERR(source->client_acl))
+               nfs_init_server_aclclient(server);
+
+       /* probe the filesystem info for this server filesystem */
+       error = nfs_probe_fsinfo(server, fh, &fattr_fsinfo);
+       if (error < 0)
+               goto out_free_server;
+
+       dprintk("Cloned FSID: %llx:%llx\n",
+               (unsigned long long) server->fsid.major,
+               (unsigned long long) server->fsid.minor);
+
+       error = nfs_start_lockd(server);
+       if (error < 0)
+               goto out_free_server;
+
+       spin_lock(&nfs_client_lock);
+       list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
+       list_add_tail(&server->master_link, &nfs_volume_list);
+       spin_unlock(&nfs_client_lock);
+
+       server->mount_time = jiffies;
+
+       dprintk("<-- nfs_clone_server() = %p\n", server);
+       return server;
+
+out_free_server:
+       nfs_free_server(server);
+       dprintk("<-- nfs_clone_server() = error %d\n", error);
+       return ERR_PTR(error);
+}
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *proc_fs_nfs;
+
+static int nfs_server_list_open(struct inode *inode, struct file *file);
+static void *nfs_server_list_start(struct seq_file *p, loff_t *pos);
+static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos);
+static void nfs_server_list_stop(struct seq_file *p, void *v);
+static int nfs_server_list_show(struct seq_file *m, void *v);
+
+static struct seq_operations nfs_server_list_ops = {
+       .start  = nfs_server_list_start,
+       .next   = nfs_server_list_next,
+       .stop   = nfs_server_list_stop,
+       .show   = nfs_server_list_show,
+};
+
+static struct file_operations nfs_server_list_fops = {
+       .open           = nfs_server_list_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+static int nfs_volume_list_open(struct inode *inode, struct file *file);
+static void *nfs_volume_list_start(struct seq_file *p, loff_t *pos);
+static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos);
+static void nfs_volume_list_stop(struct seq_file *p, void *v);
+static int nfs_volume_list_show(struct seq_file *m, void *v);
+
+static struct seq_operations nfs_volume_list_ops = {
+       .start  = nfs_volume_list_start,
+       .next   = nfs_volume_list_next,
+       .stop   = nfs_volume_list_stop,
+       .show   = nfs_volume_list_show,
+};
+
+static struct file_operations nfs_volume_list_fops = {
+       .open           = nfs_volume_list_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+/*
+ * open "/proc/fs/nfsfs/servers" which provides a summary of servers with which
+ * we're dealing
+ */
+static int nfs_server_list_open(struct inode *inode, struct file *file)
+{
+       struct seq_file *m;
+       int ret;
+
+       ret = seq_open(file, &nfs_server_list_ops);
+       if (ret < 0)
+               return ret;
+
+       m = file->private_data;
+       m->private = PDE(inode)->data;
+
+       return 0;
+}
+
+/*
+ * set up the iterator to start reading from the server list and return the first item
+ */
+static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos)
+{
+       struct list_head *_p;
+       loff_t pos = *_pos;
+
+       /* lock the list against modification */
+       spin_lock(&nfs_client_lock);
+
+       /* allow for the header line */
+       if (!pos)
+               return SEQ_START_TOKEN;
+       pos--;
+
+       /* find the n'th element in the list */
+       list_for_each(_p, &nfs_client_list)
+               if (!pos--)
+                       break;
+
+       return _p != &nfs_client_list ? _p : NULL;
+}
+
+/*
+ * move to next server
+ */
+static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos)
+{
+       struct list_head *_p;
+
+       (*pos)++;
+
+       _p = v;
+       _p = (v == SEQ_START_TOKEN) ? nfs_client_list.next : _p->next;
+
+       return _p != &nfs_client_list ? _p : NULL;
+}
+
+/*
+ * clean up after reading from the transports list
+ */
+static void nfs_server_list_stop(struct seq_file *p, void *v)
+{
+       spin_unlock(&nfs_client_lock);
+}
+
+/*
+ * display a header line followed by a load of call lines
+ */
+static int nfs_server_list_show(struct seq_file *m, void *v)
+{
+       struct nfs_client *clp;
+
+       /* display header on line 1 */
+       if (v == SEQ_START_TOKEN) {
+               seq_puts(m, "NV SERVER   PORT USE HOSTNAME\n");
+               return 0;
+       }
+
+       /* display one transport per line on subsequent lines */
+       clp = list_entry(v, struct nfs_client, cl_share_link);
+
+       seq_printf(m, "v%d %02x%02x%02x%02x %4hx %3d %s\n",
+                  clp->cl_nfsversion,
+                  NIPQUAD(clp->cl_addr.sin_addr),
+                  ntohs(clp->cl_addr.sin_port),
+                  atomic_read(&clp->cl_count),
+                  clp->cl_hostname);
+
+       return 0;
+}
+
+/*
+ * open "/proc/fs/nfsfs/volumes" which provides a summary of extant volumes
+ */
+static int nfs_volume_list_open(struct inode *inode, struct file *file)
+{
+       struct seq_file *m;
+       int ret;
+
+       ret = seq_open(file, &nfs_volume_list_ops);
+       if (ret < 0)
+               return ret;
+
+       m = file->private_data;
+       m->private = PDE(inode)->data;
+
+       return 0;
+}
+
+/*
+ * set up the iterator to start reading from the volume list and return the first item
+ */
+static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos)
+{
+       struct list_head *_p;
+       loff_t pos = *_pos;
+
+       /* lock the list against modification */
+       spin_lock(&nfs_client_lock);
+
+       /* allow for the header line */
+       if (!pos)
+               return SEQ_START_TOKEN;
+       pos--;
+
+       /* find the n'th element in the list */
+       list_for_each(_p, &nfs_volume_list)
+               if (!pos--)
+                       break;
+
+       return _p != &nfs_volume_list ? _p : NULL;
+}
+
+/*
+ * move to next volume
+ */
+static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos)
+{
+       struct list_head *_p;
+
+       (*pos)++;
+
+       _p = v;
+       _p = (v == SEQ_START_TOKEN) ? nfs_volume_list.next : _p->next;
+
+       return _p != &nfs_volume_list ? _p : NULL;
+}
+
+/*
+ * clean up after reading from the transports list
+ */
+static void nfs_volume_list_stop(struct seq_file *p, void *v)
+{
+       spin_unlock(&nfs_client_lock);
+}
+
+/*
+ * display a header line followed by a load of call lines
+ */
+static int nfs_volume_list_show(struct seq_file *m, void *v)
+{
+       struct nfs_server *server;
+       struct nfs_client *clp;
+       char dev[8], fsid[17];
+
+       /* display header on line 1 */
+       if (v == SEQ_START_TOKEN) {
+               seq_puts(m, "NV SERVER   PORT DEV     FSID\n");
+               return 0;
+       }
+       /* display one transport per line on subsequent lines */
+       server = list_entry(v, struct nfs_server, master_link);
+       clp = server->nfs_client;
+
+       snprintf(dev, 8, "%u:%u",
+                MAJOR(server->s_dev), MINOR(server->s_dev));
+
+       snprintf(fsid, 17, "%llx:%llx",
+                (unsigned long long) server->fsid.major,
+                (unsigned long long) server->fsid.minor);
+
+       seq_printf(m, "v%d %02x%02x%02x%02x %4hx %-7s %-17s\n",
+                  clp->cl_nfsversion,
+                  NIPQUAD(clp->cl_addr.sin_addr),
+                  ntohs(clp->cl_addr.sin_port),
+                  dev,
+                  fsid);
+
+       return 0;
+}
+
+/*
+ * initialise the /proc/fs/nfsfs/ directory
+ */
+int __init nfs_fs_proc_init(void)
+{
+       struct proc_dir_entry *p;
+
+       proc_fs_nfs = proc_mkdir("nfsfs", proc_root_fs);
+       if (!proc_fs_nfs)
+               goto error_0;
+
+       proc_fs_nfs->owner = THIS_MODULE;
+
+       /* a file of servers with which we're dealing */
+       p = create_proc_entry("servers", S_IFREG|S_IRUGO, proc_fs_nfs);
+       if (!p)
+               goto error_1;
+
+       p->proc_fops = &nfs_server_list_fops;
+       p->owner = THIS_MODULE;
+
+       /* a file of volumes that we have mounted */
+       p = create_proc_entry("volumes", S_IFREG|S_IRUGO, proc_fs_nfs);
+       if (!p)
+               goto error_2;
+
+       p->proc_fops = &nfs_volume_list_fops;
+       p->owner = THIS_MODULE;
+       return 0;
+
+error_2:
+       remove_proc_entry("servers", proc_fs_nfs);
+error_1:
+       remove_proc_entry("nfsfs", proc_root_fs);
+error_0:
+       return -ENOMEM;
+}
+
+/*
+ * clean up the /proc/fs/nfsfs/ directory
+ */
+void nfs_fs_proc_exit(void)
+{
+       remove_proc_entry("volumes", proc_fs_nfs);
+       remove_proc_entry("servers", proc_fs_nfs);
+       remove_proc_entry("nfsfs", proc_root_fs);
+}
+
+#endif /* CONFIG_PROC_FS */
index 9540a316c05e6e103a64cffd3dad567a170fbddb..57133678db1660a9599d5b724929a8886bcf97e0 100644 (file)
@@ -18,6 +18,7 @@
 
 #include "nfs4_fs.h"
 #include "delegation.h"
+#include "internal.h"
 
 static struct nfs_delegation *nfs_alloc_delegation(void)
 {
@@ -52,7 +53,7 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_
                        case -NFS4ERR_EXPIRED:
                                /* kill_proc(fl->fl_pid, SIGLOST, 1); */
                        case -NFS4ERR_STALE_CLIENTID:
-                               nfs4_schedule_state_recovery(NFS_SERVER(inode)->nfs4_state);
+                               nfs4_schedule_state_recovery(NFS_SERVER(inode)->nfs_client);
                                goto out_err;
                }
        }
@@ -114,7 +115,7 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, st
  */
 int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res)
 {
-       struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state;
+       struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
        struct nfs_inode *nfsi = NFS_I(inode);
        struct nfs_delegation *delegation;
        int status = 0;
@@ -145,7 +146,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
                                        sizeof(delegation->stateid)) != 0 ||
                                delegation->type != nfsi->delegation->type) {
                        printk("%s: server %u.%u.%u.%u, handed out a duplicate delegation!\n",
-                                       __FUNCTION__, NIPQUAD(clp->cl_addr));
+                                       __FUNCTION__, NIPQUAD(clp->cl_addr.sin_addr));
                        status = -EIO;
                }
        }
@@ -176,7 +177,7 @@ static void nfs_msync_inode(struct inode *inode)
  */
 int __nfs_inode_return_delegation(struct inode *inode)
 {
-       struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state;
+       struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
        struct nfs_inode *nfsi = NFS_I(inode);
        struct nfs_delegation *delegation;
        int res = 0;
@@ -208,7 +209,7 @@ int __nfs_inode_return_delegation(struct inode *inode)
  */
 void nfs_return_all_delegations(struct super_block *sb)
 {
-       struct nfs4_client *clp = NFS_SB(sb)->nfs4_state;
+       struct nfs_client *clp = NFS_SB(sb)->nfs_client;
        struct nfs_delegation *delegation;
        struct inode *inode;
 
@@ -232,7 +233,7 @@ restart:
 
 int nfs_do_expire_all_delegations(void *ptr)
 {
-       struct nfs4_client *clp = ptr;
+       struct nfs_client *clp = ptr;
        struct nfs_delegation *delegation;
        struct inode *inode;
 
@@ -254,11 +255,11 @@ restart:
        }
 out:
        spin_unlock(&clp->cl_lock);
-       nfs4_put_client(clp);
+       nfs_put_client(clp);
        module_put_and_exit(0);
 }
 
-void nfs_expire_all_delegations(struct nfs4_client *clp)
+void nfs_expire_all_delegations(struct nfs_client *clp)
 {
        struct task_struct *task;
 
@@ -266,17 +267,17 @@ void nfs_expire_all_delegations(struct nfs4_client *clp)
        atomic_inc(&clp->cl_count);
        task = kthread_run(nfs_do_expire_all_delegations, clp,
                        "%u.%u.%u.%u-delegreturn",
-                       NIPQUAD(clp->cl_addr));
+                       NIPQUAD(clp->cl_addr.sin_addr));
        if (!IS_ERR(task))
                return;
-       nfs4_put_client(clp);
+       nfs_put_client(clp);
        module_put(THIS_MODULE);
 }
 
 /*
  * Return all delegations following an NFS4ERR_CB_PATH_DOWN error.
  */
-void nfs_handle_cb_pathdown(struct nfs4_client *clp)
+void nfs_handle_cb_pathdown(struct nfs_client *clp)
 {
        struct nfs_delegation *delegation;
        struct inode *inode;
@@ -299,7 +300,7 @@ restart:
 
 struct recall_threadargs {
        struct inode *inode;
-       struct nfs4_client *clp;
+       struct nfs_client *clp;
        const nfs4_stateid *stateid;
 
        struct completion started;
@@ -310,7 +311,7 @@ static int recall_thread(void *data)
 {
        struct recall_threadargs *args = (struct recall_threadargs *)data;
        struct inode *inode = igrab(args->inode);
-       struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state;
+       struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
        struct nfs_inode *nfsi = NFS_I(inode);
        struct nfs_delegation *delegation;
 
@@ -371,7 +372,7 @@ out_module_put:
 /*
  * Retrieve the inode associated with a delegation
  */
-struct inode *nfs_delegation_find_inode(struct nfs4_client *clp, const struct nfs_fh *fhandle)
+struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle)
 {
        struct nfs_delegation *delegation;
        struct inode *res = NULL;
@@ -389,7 +390,7 @@ struct inode *nfs_delegation_find_inode(struct nfs4_client *clp, const struct nf
 /*
  * Mark all delegations as needing to be reclaimed
  */
-void nfs_delegation_mark_reclaim(struct nfs4_client *clp)
+void nfs_delegation_mark_reclaim(struct nfs_client *clp)
 {
        struct nfs_delegation *delegation;
        spin_lock(&clp->cl_lock);
@@ -401,7 +402,7 @@ void nfs_delegation_mark_reclaim(struct nfs4_client *clp)
 /*
  * Reap all unclaimed delegations after reboot recovery is done
  */
-void nfs_delegation_reap_unclaimed(struct nfs4_client *clp)
+void nfs_delegation_reap_unclaimed(struct nfs_client *clp)
 {
        struct nfs_delegation *delegation, *n;
        LIST_HEAD(head);
@@ -423,7 +424,7 @@ void nfs_delegation_reap_unclaimed(struct nfs4_client *clp)
 
 int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode)
 {
-       struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state;
+       struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
        struct nfs_inode *nfsi = NFS_I(inode);
        struct nfs_delegation *delegation;
        int res = 0;
index 3858694652fa05f183613579763df09779aeacb9..2cfd4b24c7feb0d8c4e8c3ec4f5ef8964feef765 100644 (file)
@@ -29,13 +29,13 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, st
 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);
+struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle);
 void nfs_return_all_delegations(struct super_block *sb);
-void nfs_expire_all_delegations(struct nfs4_client *clp);
-void nfs_handle_cb_pathdown(struct nfs4_client *clp);
+void nfs_expire_all_delegations(struct nfs_client *clp);
+void nfs_handle_cb_pathdown(struct nfs_client *clp);
 
-void nfs_delegation_mark_reclaim(struct nfs4_client *clp);
-void nfs_delegation_reap_unclaimed(struct nfs4_client *clp);
+void nfs_delegation_mark_reclaim(struct nfs_client *clp);
+void nfs_delegation_reap_unclaimed(struct nfs_client *clp);
 
 /* NFSv4 delegation-related procedures */
 int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid);
index e7ffb4deb3e5f21973a0e165f229ddc98c7ff754..3419c2da9ba9d25e40dcbc67846ba627477cdad2 100644 (file)
@@ -30,7 +30,9 @@
 #include <linux/nfs_mount.h>
 #include <linux/pagemap.h>
 #include <linux/smp_lock.h>
+#include <linux/pagevec.h>
 #include <linux/namei.h>
+#include <linux/mount.h>
 
 #include "nfs4_fs.h"
 #include "delegation.h"
@@ -870,14 +872,14 @@ int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd)
        return (nd->intent.open.flags & O_EXCL) != 0;
 }
 
-static inline int nfs_reval_fsid(struct inode *dir,
-               struct nfs_fh *fh, struct nfs_fattr *fattr)
+static inline int nfs_reval_fsid(struct vfsmount *mnt, struct inode *dir,
+                                struct nfs_fh *fh, struct nfs_fattr *fattr)
 {
        struct nfs_server *server = NFS_SERVER(dir);
 
        if (!nfs_fsid_equal(&server->fsid, &fattr->fsid))
                /* Revalidate fsid on root dir */
-               return __nfs_revalidate_inode(server, dir->i_sb->s_root->d_inode);
+               return __nfs_revalidate_inode(server, mnt->mnt_root->d_inode);
        return 0;
 }
 
@@ -902,9 +904,15 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
 
        lock_kernel();
 
-       /* If we're doing an exclusive create, optimize away the lookup */
-       if (nfs_is_exclusive_create(dir, nd))
-               goto no_entry;
+       /*
+        * If we're doing an exclusive create, optimize away the lookup
+        * but don't hash the dentry.
+        */
+       if (nfs_is_exclusive_create(dir, nd)) {
+               d_instantiate(dentry, NULL);
+               res = NULL;
+               goto out_unlock;
+       }
 
        error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
        if (error == -ENOENT)
@@ -913,7 +921,7 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
                res = ERR_PTR(error);
                goto out_unlock;
        }
-       error = nfs_reval_fsid(dir, &fhandle, &fattr);
+       error = nfs_reval_fsid(nd->mnt, dir, &fhandle, &fattr);
        if (error < 0) {
                res = ERR_PTR(error);
                goto out_unlock;
@@ -922,8 +930,9 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
        res = (struct dentry *)inode;
        if (IS_ERR(res))
                goto out_unlock;
+
 no_entry:
-       res = d_add_unique(dentry, inode);
+       res = d_materialise_unique(dentry, inode);
        if (res != NULL)
                dentry = res;
        nfs_renew_times(dentry);
@@ -1117,11 +1126,13 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc)
                dput(dentry);
                return NULL;
        }
-       alias = d_add_unique(dentry, inode);
+
+       alias = d_materialise_unique(dentry, inode);
        if (alias != NULL) {
                dput(dentry);
                dentry = alias;
        }
+
        nfs_renew_times(dentry);
        nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
        return dentry;
@@ -1143,23 +1154,22 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
                struct inode *dir = dentry->d_parent->d_inode;
                error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
                if (error)
-                       goto out_err;
+                       return error;
        }
        if (!(fattr->valid & NFS_ATTR_FATTR)) {
                struct nfs_server *server = NFS_SB(dentry->d_sb);
-               error = server->rpc_ops->getattr(server, fhandle, fattr);
+               error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr);
                if (error < 0)
-                       goto out_err;
+                       return error;
        }
        inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
        error = PTR_ERR(inode);
        if (IS_ERR(inode))
-               goto out_err;
+               return error;
        d_instantiate(dentry, inode);
+       if (d_unhashed(dentry))
+               d_rehash(dentry);
        return 0;
-out_err:
-       d_drop(dentry);
-       return error;
 }
 
 /*
@@ -1440,48 +1450,82 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry)
        return error;
 }
 
-static int
-nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
+/*
+ * To create a symbolic link, most file systems instantiate a new inode,
+ * add a page to it containing the path, then write it out to the disk
+ * using prepare_write/commit_write.
+ *
+ * Unfortunately the NFS client can't create the in-core inode first
+ * because it needs a file handle to create an in-core inode (see
+ * fs/nfs/inode.c:nfs_fhget).  We only have a file handle *after* the
+ * symlink request has completed on the server.
+ *
+ * So instead we allocate a raw page, copy the symname into it, then do
+ * the SYMLINK request with the page as the buffer.  If it succeeds, we
+ * now have a new file handle and can instantiate an in-core NFS inode
+ * and move the raw page into its mapping.
+ */
+static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
 {
+       struct pagevec lru_pvec;
+       struct page *page;
+       char *kaddr;
        struct iattr attr;
-       struct nfs_fattr sym_attr;
-       struct nfs_fh sym_fh;
-       struct qstr qsymname;
+       unsigned int pathlen = strlen(symname);
        int error;
 
        dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s)\n", dir->i_sb->s_id,
                dir->i_ino, dentry->d_name.name, symname);
 
-#ifdef NFS_PARANOIA
-if (dentry->d_inode)
-printk("nfs_proc_symlink: %s/%s not negative!\n",
-dentry->d_parent->d_name.name, dentry->d_name.name);
-#endif
-       /*
-        * Fill in the sattr for the call.
-        * Note: SunOS 4.1.2 crashes if the mode isn't initialized!
-        */
-       attr.ia_valid = ATTR_MODE;
-       attr.ia_mode = S_IFLNK | S_IRWXUGO;
+       if (pathlen > PAGE_SIZE)
+               return -ENAMETOOLONG;
 
-       qsymname.name = symname;
-       qsymname.len  = strlen(symname);
+       attr.ia_mode = S_IFLNK | S_IRWXUGO;
+       attr.ia_valid = ATTR_MODE;
 
        lock_kernel();
+
+       page = alloc_page(GFP_KERNEL);
+       if (!page) {
+               unlock_kernel();
+               return -ENOMEM;
+       }
+
+       kaddr = kmap_atomic(page, KM_USER0);
+       memcpy(kaddr, symname, pathlen);
+       if (pathlen < PAGE_SIZE)
+               memset(kaddr + pathlen, 0, PAGE_SIZE - pathlen);
+       kunmap_atomic(kaddr, KM_USER0);
+
        nfs_begin_data_update(dir);
-       error = NFS_PROTO(dir)->symlink(dir, &dentry->d_name, &qsymname,
-                                         &attr, &sym_fh, &sym_attr);
+       error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr);
        nfs_end_data_update(dir);
-       if (!error) {
-               error = nfs_instantiate(dentry, &sym_fh, &sym_attr);
-       } else {
-               if (error == -EEXIST)
-                       printk("nfs_proc_symlink: %s/%s already exists??\n",
-                              dentry->d_parent->d_name.name, dentry->d_name.name);
+       if (error != 0) {
+               dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s) error %d\n",
+                       dir->i_sb->s_id, dir->i_ino,
+                       dentry->d_name.name, symname, error);
                d_drop(dentry);
+               __free_page(page);
+               unlock_kernel();
+               return error;
        }
+
+       /*
+        * No big deal if we can't add this page to the page cache here.
+        * READLINK will get the missing page from the server if needed.
+        */
+       pagevec_init(&lru_pvec, 0);
+       if (!add_to_page_cache(page, dentry->d_inode->i_mapping, 0,
+                                                       GFP_KERNEL)) {
+               if (!pagevec_add(&lru_pvec, page))
+                       __pagevec_lru_add(&lru_pvec);
+               SetPageUptodate(page);
+               unlock_page(page);
+       } else
+               __free_page(page);
+
        unlock_kernel();
-       return error;
+       return 0;
 }
 
 static int 
@@ -1638,35 +1682,211 @@ out:
        return error;
 }
 
+static DEFINE_SPINLOCK(nfs_access_lru_lock);
+static LIST_HEAD(nfs_access_lru_list);
+static atomic_long_t nfs_access_nr_entries;
+
+static void nfs_access_free_entry(struct nfs_access_entry *entry)
+{
+       put_rpccred(entry->cred);
+       kfree(entry);
+       smp_mb__before_atomic_dec();
+       atomic_long_dec(&nfs_access_nr_entries);
+       smp_mb__after_atomic_dec();
+}
+
+int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask)
+{
+       LIST_HEAD(head);
+       struct nfs_inode *nfsi;
+       struct nfs_access_entry *cache;
+
+       spin_lock(&nfs_access_lru_lock);
+restart:
+       list_for_each_entry(nfsi, &nfs_access_lru_list, access_cache_inode_lru) {
+               struct inode *inode;
+
+               if (nr_to_scan-- == 0)
+                       break;
+               inode = igrab(&nfsi->vfs_inode);
+               if (inode == NULL)
+                       continue;
+               spin_lock(&inode->i_lock);
+               if (list_empty(&nfsi->access_cache_entry_lru))
+                       goto remove_lru_entry;
+               cache = list_entry(nfsi->access_cache_entry_lru.next,
+                               struct nfs_access_entry, lru);
+               list_move(&cache->lru, &head);
+               rb_erase(&cache->rb_node, &nfsi->access_cache);
+               if (!list_empty(&nfsi->access_cache_entry_lru))
+                       list_move_tail(&nfsi->access_cache_inode_lru,
+                                       &nfs_access_lru_list);
+               else {
+remove_lru_entry:</