# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.1324 -> 1.1371 # drivers/net/8139too.c 1.59 -> 1.60 # include/linux/skbuff.h 1.16 -> 1.17 # net/ipv6/exthdrs.c 1.5 -> 1.6 # fs/xfs/xfs_qmops.c 1.8 -> 1.9 # fs/xfs/linux/xfs_lrw.c 1.182 -> 1.185 # fs/xfs/xfs_ag.h 1.18 -> 1.19 # net/ipv6/ipv6_sockglue.c 1.9 -> 1.11 # fs/xfs/xfs_alloc.c 1.43 -> 1.44 # net/sctp/chunk.c 1.3 -> 1.4 # fs/xfs/xfs_buf_item.c 1.48 -> 1.49 # fs/xfs/xfs_iomap.c 1.20 -> 1.21 # include/linux/netfilter_ipv4/listhelp.h 1.4 -> 1.5 # fs/xfs/xfs_fsops.h 1.11 -> 1.12 # fs/xfs/xfs_mount.h 1.74 -> 1.75 # fs/xfs/xfs_dir2_node.c 1.29 -> 1.30 # fs/xfs/linux/xfs_buf.c 1.149 -> 1.166 # net/ipv4/udp.c 1.12 -> 1.13 # fs/devfs/base.c 1.23 -> 1.24 # net/sctp/socket.c 1.9 -> 1.10 # fs/xfs/linux/xfs_stats.c 1.15 -> 1.16 # fs/xfs/xfs_error.c 1.23 -> 1.24 # drivers/net/r8169.c 1.11 -> 1.12 # drivers/net/ne2k-pci.c 1.12 -> 1.13 # fs/xfs/Makefile 1.58 -> 1.59 # crypto/Makefile 1.16 -> 1.18 # fs/xfs/xfs_log_priv.h 1.31 -> 1.32 # Documentation/networking/bonding.txt 1.16 -> 1.17 # fs/xfs/linux/xfs_vfs.c 1.36 -> 1.37 # drivers/net/pcnet32.c 1.34 -> 1.48 # fs/xfs/linux/xfs_sysctl.h 1.21 -> 1.22 # net/ipv4/netfilter/ipt_ECN.c 1.2 -> 1.3 # net/ipv4/ip_sockglue.c 1.7 -> 1.9 # net/ipv6/icmp.c 1.15 -> 1.16 # fs/xfs/xfs_attr_leaf.c 1.29 -> 1.30 # include/net/sctp/sctp.h 1.6 -> 1.7 # drivers/net/bonding/bond_alb.c 1.23 -> 1.26 # drivers/net/bonding/bond_main.c 1.83 -> 1.86 # net/sctp/associola.c 1.5 -> 1.6 # drivers/net/bonding/bonding.h 1.20 -> 1.23 # net/netsyms.c 1.46 -> 1.47 # net/ipv6/ipv6_syms.c 1.1 -> 1.2 # include/linux/pci_ids.h 1.83 -> 1.84 # fs/xfs/xfs_dmops.c 1.7 -> 1.8 # fs/xfs/linux/xfs_super.h 1.52 -> 1.54 # net/Makefile 1.8 -> 1.9 # fs/xfs/xfs_fs.h 1.14 -> 1.15 # net/sctp/sm_statefuns.c 1.4 -> 1.5 # include/linux/jhash.h 1.2 -> 1.3 # net/sctp/ipv6.c 1.4 -> 1.6 # fs/xfs/xfs_fsops.c 1.49 -> 1.50 # fs/xfs/linux/xfs_stats.h 1.9 -> 1.10 # fs/xfs/xfs_quota.h 1.15 -> 1.16 # crypto/internal.h 1.16 -> 1.17 # net/core/dev.c 1.43 -> 1.44 # fs/xfs/linux/xfs_iops.c 1.164 -> 1.165 # include/linux/sctp.h 1.4 -> 1.5 # drivers/video/pm3fb.c 1.1 -> 1.2 # fs/xfs/linux/xfs_lrw.h 1.31 -> 1.32 # drivers/net/bonding/bond_alb.h 1.7 -> 1.9 # drivers/net/tulip/tulip_core.c 1.44 -> 1.45 # MAINTAINERS 1.128 -> 1.129 # net/atm/lec.c 1.20 -> 1.22 # fs/xfs/xfs_vfsops.c 1.183 -> 1.184 # crypto/tcrypt.c 1.24 -> 1.25 # fs/xfs/xfs_vnodeops.c 1.173 -> 1.174 # crypto/cipher.c 1.15 -> 1.16 # include/net/sctp/structs.h 1.5 -> 1.6 # fs/xfs/linux/xfs_linux.h 1.105 -> 1.108 # fs/xfs/linux/xfs_super.c 1.221 -> 1.223 # fs/xfs/xfs_mount.c 1.126 -> 1.127 # net/core/sock.c 1.10 -> 1.11 # fs/xfs/linux/kmem.h 1.21 -> 1.22 # fs/xfs/xfs_log.c 1.79 -> 1.80 # fs/xfs/xfs_clnt.h 1.22 -> 1.23 # fs/xfs/xfs_dmapi.h 1.34 -> 1.36 # net/ipv6/udp.c 1.13 -> 1.14 # fs/xfs/linux/xfs_buf.h 1.83 -> 1.89 # net/ipv6/netfilter/ip6_tables.c 1.15 -> 1.16 # drivers/net/bonding/bond_3ad.c 1.16 -> 1.17 # crypto/Config.in 1.18 -> 1.19 # fs/xfs/linux/xfs_ioctl.c 1.98 -> 1.100 # fs/xfs/xfs_log_recover.c 1.118 -> 1.120 # fs/xfs/linux/xfs_sysctl.c 1.30 -> 1.31 # fs/xfs/linux/xfs_globals.c 1.63 -> 1.64 # Documentation/Configure.help 1.231 -> 1.232 # net/ipv4/icmp.c 1.19 -> 1.20 # drivers/net/sungem.c 1.29 -> 1.30 # crypto/tcrypt.h 1.15 -> 1.16 # fs/xfs/xfs_attr.h 1.15 -> 1.16 # fs/xfs/linux/xfs_aops.c 1.63 -> 1.69 # drivers/video/radeonfb.c 1.18 -> 1.19 # fs/xfs/xfs_macros.c 1.20 -> 1.21 # include/linux/netfilter_ipv4/ip_nat.h 1.4 -> 1.5 # Documentation/crypto/api-intro.txt 1.14 -> 1.15 # net/sctp/endpointola.c 1.4 -> 1.5 # (new) -> 1.1 crypto/scatterwalk.c # (new) -> 1.1 crypto/scatterwalk.h # (new) -> 1.1 crypto/arc4.c # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 04/02/26 xose@wanadoo.es 1.1315.15.1 # [PATCH] more RTL-8139 clone boards # -------------------------------------------- # 04/02/26 xose@wanadoo.es 1.1315.15.2 # [PATCH] more ne2k-pci clone boards # -------------------------------------------- # 04/02/26 brazilnut@us.ibm.com 1.1315.14.14 # [PATCH] pcnet32 non-mii link state fix # # This patch correctly returns the link state of an adapter which does not # have an MII. Tested by myself and the patch author Thomas Munck Steenholdt # . # -------------------------------------------- # 04/02/26 shmulik.hen@intel.com 1.1315.15.3 # [PATCH] bonding: Add support for HW accel. slaves # # Now, that 2.4.25 is out, I'm resending the enhancements for VLAN over bonding. # Tested for patch application and compilation against latest netdev-2.4 BK tree # (assuming the previous 3 patches are already applied). # # Summary: # Change the bond interface to publish full VLAN hardware acceleration # offloading capabilities, and add capability in all xmit functions to # take special care for VLAN HW accel. tagged skb's that are going out # through a slave that is not offloading capable. # # Add a mechanism to collect and save the VLAN Id's that have been # added on top of a bond interface, and propagate the register/add/kill # operations to the slaves. # # Add blocking mechanism to prevent adding VLAN interfaces on top of a # bond that contains VLAN challenged slaves and to prevent adding VLAN # challenged slaves to a bond that already has VLAN interfaces on top # of it. # # Add a section about VLAN to Documentation/networking/bonding.txt and # also correct some minor spelling/grammer errors. # -------------------------------------------- # 04/02/26 shmulik.hen@intel.com 1.1315.15.4 # [PATCH] bonding: Add VLAN support in TLB mode # # Now, that 2.4.25 is out, I'm resending the enhancements for VLAN over bonding. # Tested for patch application and compilation against latest netdev-2.4 BK tree # (assuming the previous 3 patches are already applied). # # Summary: # Add capability to tag self generated learning packets that are # required to speed up port selection in the switch after a fail # over in bonding since some switches will only update their MAC # tables from tagged packets when VLAN support is turned on. All # VLAN Id's that have been configured on top of the bond interface # will be used in cyclic order. # -------------------------------------------- # 04/02/26 shmulik.hen@intel.com 1.1315.15.5 # [PATCH] bonding: Add VLAN support in ALB mode # # Now, that 2.4.25 is out, I'm resending the enhancements for VLAN over bonding. # Tested for patch application and compilation against latest netdev-2.4 BK tree # (assuming the previous 3 patches are already applied). # # Summary: # Add capability to tag self generated ARP packets that are required # for receive load balancing in bonding. VLAN Id's are saved and used # each time a new IP connection is established since 8021q currently # supports IP binding. # # Update module version and comment blocks. # -------------------------------------------- # 04/02/26 jgarzik@redhat.com 1.1315.15.6 # Merge redhat.com:/spare/repo/netdev-2.4/pcnet32 # into redhat.com:/spare/repo/net-drivers-2.4 # -------------------------------------------- # 04/02/26 romieu@fr.zoreil.com 1.1315.15.7 # [netdrvr r8169] fix TX descriptor overflow # # Please apply attached patch. # # Without patch, bogus descriptors are parsed as soon as # tp->cur_tx%NUM_TX_DESC + (tp->cur_tx - tp->dirty_tx) > NUM_TX_DESC # (assume for instance tp->dirty_tx = NUM_TX_DESC/2, # tp->cur_tx = NUM_TX_DESC - 1 and watch entry go beyond NUM_TX_DESC). # # Missing stats update is fixed by the patch btw. # -------------------------------------------- # 04/02/26 horms@verge.net.au 1.1315.1.40 # [JHASH]: Make key arg const in jhash(). # -------------------------------------------- # 04/02/26 simon@instant802.com 1.1315.1.41 # [NET]: Capture skb->protocol after invoking bridge. # -------------------------------------------- # 04/02/26 chas@cmf.nrl.navy.mil 1.1315.1.42 # [ATM]: [lec] timer cleanup # -------------------------------------------- # 04/02/26 chas@cmf.nrl.navy.mil 1.1315.1.43 # [ATM]: [lec] send queued packets immediately after path switch # -------------------------------------------- # 04/02/26 matthias.andree@gmx.de 1.1315.1.44 # [NET]: Export sysctl_optmem_max to modules. # -------------------------------------------- # 04/02/26 ysauyuki.kozakai@toshiba.co.jp 1.1315.1.45 # [IPV6]: Fix frag hdr parsing in ipv6_skip_exthdr(). # -------------------------------------------- # 04/02/26 ysauyuki.kozakai@toshiba.co.jp 1.1315.1.46 # [IPV6]: Fix ip6_tables TCP/UDP matching when ipv6 ext hdr exists. # -------------------------------------------- # 04/02/26 davem@nuts.davemloft.net 1.1315.1.47 # Merge nuts.davemloft.net:/disk1/BK/network-2.4 # into nuts.davemloft.net:/disk1/BK/net-2.4 # -------------------------------------------- # 04/02/26 davem@nuts.davemloft.net 1.1315.1.48 # [SCTP]: Ranem MSECS_TO_JIFFIES to avoid conflict with IRDA. # -------------------------------------------- # 04/02/26 davem@nuts.davemloft.net 1.1315.1.49 # [SCTP]: Comment out buggy ipv6 debugging printk. # -------------------------------------------- # 04/02/26 davem@kernel.bkbits.net 1.1315.10.2 # Merge davem@nuts.davemloft.net:/disk1/BK/sungem-2.4 # into kernel.bkbits.net:/home/davem/sungem-2.4 # -------------------------------------------- # 04/02/27 marcelo@logos.cnet 1.1325 # Merge bk://gkernel.bkbits.net/net-drivers-2.4 # into logos.cnet:/home/marcelo/bk/linux-2.4 # -------------------------------------------- # 04/02/27 marcelo@logos.cnet 1.1326 # Merge bk://kernel.bkbits.net/davem/net-2.4 # into logos.cnet:/home/marcelo/bk/linux-2.4 # -------------------------------------------- # 04/02/27 marcelo@logos.cnet 1.1327 # Merge bk://kernel.bkbits.net/davem/sungem-2.4 # into logos.cnet:/home/marcelo/bk/linux-2.4 # -------------------------------------------- # 04/02/27 khali@linux-fr.org 1.1328 # [PATCH] Identify Radeon Ya and Yd in radeonfb # # Here is a patch that adds support for the Radeon 9200 (Ya) and 9200 SE # (Yd) to the radeonfb driver. Since it already supports the Radeon 9200 # Pro which is basically (if not exactly) the same chipset, this is just a # matter of making the driver recognize two new IDs as something it # supports. No new code here. # # I take no credit for this patch, since it is almost identical to this # one by Sven Luther: # http://marc.theaimsgroup.com/?l=linux-ppc&m=107427038129062 # # And is similar to these two other ones that are now in Linux 2.6, by # Bernardo Innocenti and Andreas Steinmetz, respectively: # http://marc.theaimsgroup.com/?l=linux-kernel&m=107345065025365 # http://lkml.org/lkml/2004/2/6/64 # -------------------------------------------- # 04/02/27 sri@us.ibm.com 1.1327.1.1 # [SCTP] Fix packed attribute usage. # -------------------------------------------- # 04/02/27 sri@us.ibm.com 1.1327.1.2 # [SCTP] Fix NIP6 macro to take a ptr to struct in6_addr. # -------------------------------------------- # 04/02/27 sri@us.ibm.com 1.1327.1.3 # [SCTP] Fix incorrect INIT process termination with sinit_max_init_timeo. # # Currently, sinit_max_init_timeo is treated as the maximum timeout # value for INIT retransmissions and the INIT process is aborted when # the timeout reaches this value. But as per the SCTP sockets API draft, # sinit_max_init_timeo only limits the timeout. The INIT process should # be aborted only after MAX_INIT_RETRANSMITS. # -------------------------------------------- # 04/02/27 geert@linux-m68k.org 1.1315.15.8 # [netdrvr tulip] fix up 21041 media selection # -------------------------------------------- # 04/02/27 davem@kernel.bkbits.net 1.1329 # Merge davem@nuts.davemloft.net:/disk1/BK/net-2.4 # into kernel.bkbits.net:/home/davem/net-2.4 # -------------------------------------------- # 04/02/27 marcelo@logos.cnet 1.1328.1.1 # Merge bk://gkernel.bkbits.net/net-drivers-2.4 # into logos.cnet:/home/marcelo/bk/linux-2.4 # -------------------------------------------- # 04/02/27 marcelo@logos.cnet 1.1330 # Merge bk://kernel.bkbits.net/davem/net-2.4 # into logos.cnet:/home/marcelo/bk/linux-2.4 # -------------------------------------------- # 04/03/03 nathans@sgi.com 1.1331 # [XFS] Fix a trivial compiler warning, remove some no-longer-used macros. # # SGI Modid: xfs-linux:xfs-kern:165155a # -------------------------------------------- # 04/03/03 hch@sgi.com 1.1332 # [XFS] Simplify pagebuf_rele / pagebuf_free # # SGI Modid: xfs-linux:xfs-kern:165500a # -------------------------------------------- # 04/03/03 hch@sgi.com 1.1333 # [XFS] Stop using sleep_on # # SGI Modid: xfs-linux:xfs-kern:165673a # -------------------------------------------- # 04/03/03 hch@sgi.com 1.1334 # [XFS] Plug a pagebuf race that got bigger with the recent cleanup # # SGI Modid: xfs-linux:xfs-kern:165722a # -------------------------------------------- # 04/03/03 hch@sgi.com 1.1335 # [XFS] Fix gcc 3.5 compilation for real # # SGI Modid: xfs-linux:xfs-kern:165783a # -------------------------------------------- # 04/03/03 hch@sgi.com 1.1336 # [XFS] Fix buffer teardown on _pagebuf_lookup_pages failure # # SGI Modid: xfs-linux:xfs-kern:166032a # -------------------------------------------- # 04/03/03 hch@sgi.com 1.1337 # [XFS] Remove the lockable/not lockable buffer distinction. All metada buffers # are lockable these days. # # SGI Modid: xfs-linux:xfs-kern:166042a # -------------------------------------------- # 04/03/03 nathans@sgi.com 1.1338 # [XFS] Use list_move for moving pagebufs between lists, not list_add/list_del # # SGI Modid: xfs-linux:xfs-kern:166046a # -------------------------------------------- # 04/03/03 hch@sgi.com 1.1339 # [XFS] Remove PBF_MAPPABLE # # SGI Modid: xfs-linux:xfs-kern:166087a # -------------------------------------------- # 04/03/03 hch@sgi.com 1.1340 # [XFS] plug a pagebuf leak # # SGI Modid: xfs-linux:xfs-kern:166109a # -------------------------------------------- # 04/03/03 hch@sgi.com 1.1341 # [XFS] "backport" d_alloc_anon (this time for real) # # SGI Modid: xfs-linux:xfs-kern:166162a # -------------------------------------------- # 04/03/03 hch@sgi.com 1.1342 # [XFS] Avoid NULL returns from pagebuf_get # # SGI Modid: xfs-linux:xfs-kern:166207a # -------------------------------------------- # 04/03/03 nathans@sgi.com 1.1343 # [XFS] Fix compile warning, ensure _pagebuf_lookup_pages return value is inited. # # SGI Modid: xfs-linux:xfs-kern:166301a # -------------------------------------------- # 04/03/03 nathans@sgi.com 1.1344 # [XFS] Fix data loss when writing into unwritten extents while memory is being reclaimed. # # SGI Modid: xfs-linux:xfs-kern:166324a # -------------------------------------------- # 04/03/03 nathans@sgi.com 1.1345 # [XFS] Remove bogus assert I added during testing of previous unwritten fix. # # SGI Modid: xfs-linux:xfs-kern:166332a # -------------------------------------------- # 04/03/03 tes@sgi.com 1.1346 # [XFS] Add XFS_FS_GOINGDOWN interface to xfs. # # SGI Modid: xfs-linux:xfs-kern:166489a # -------------------------------------------- # 04/03/03 nathans@sgi.com 1.1347 # [XFS] Add I/O path tracing code, twas useful in diagnosing that last unwritten extent problem. # # SGI Modid: xfs-linux:xfs-kern:166497a # -------------------------------------------- # 04/03/03 hch@sgi.com 1.1348 # [XFS] use generic XFS stats and sysctl infrastructure in pagebuf # # SGI Modid: xfs-linux:xfs-kern:166505a # -------------------------------------------- # 04/03/03 nathans@sgi.com 1.1349 # [XFS] Use a naming convention here thats more consistent with everything else. # # SGI Modid: xfs-linux:xfs-kern:166562a # -------------------------------------------- # 04/03/03 hch@sgi.com 1.1350 # [XFS] Fix up daemon names # # SGI Modid: xfs-linux:xfs-kern:166665a # -------------------------------------------- # 04/03/03 nathans@sgi.com 1.1351 # [XFS] Fix BUG in debug trace code, it was plain wrong for the unmapped page case. # # SGI Modid: xfs-linux:xfs-kern:166828a # -------------------------------------------- # 04/03/03 jpk@sgi.com 1.1352 # [XFS] Merge missing mount stripe-unit/width-alignment check over from IRIX. # # SGI Modid: xfs-linux:xfs-kern:166614a # -------------------------------------------- # 04/03/03 sandeen@sgi.com 1.1353 # [XFS] Add switches to make xfs compile when the nptl patch is present # # SGI Modid: xfs-linux:xfs-kern:166998a # -------------------------------------------- # 04/03/03 nathans@sgi.com 1.1354 # [XFS] Fix the by-handle attr list interface (used by xfsdump) for security attrs. # # SGI Modid: xfs-linux:xfs-kern:167038a # -------------------------------------------- # 04/03/03 hch@sgi.com 1.1355 # [XFS] only lock pagecache pages # # SGI Modid: xfs-linux:xfs-kern:167054a # -------------------------------------------- # 04/03/03 nathans@sgi.com 1.1356 # [XFS] Fix length of mount argument path strings, off by one. # # SGI Modid: xfs-linux:xfs-kern:167192a # -------------------------------------------- # 04/03/03 tes@sgi.com 1.1357 # [XFS] Fix log recovery case when have v2 log with size >32K and we have a # Log Record wrapping around the physical log end. Need to reset # the pb size back to what we were using and NOT just 32K. # # SGI Modid: xfs-linux:xfs-kern:167196a # -------------------------------------------- # 04/03/03 hch@sgi.com 1.1358 # [XFS] plug race in pagebuf freeing # # SGI Modid: xfs-linux:xfs-kern:167222a # -------------------------------------------- # 04/03/03 sandeen@sgi.com 1.1359 # [XFS] Remove some dead debug code # # SGI Modid: xfs-linux:xfs-kern:167279a # -------------------------------------------- # 04/03/03 nathans@sgi.com 1.1360 # [XFS] release i_sem before going into dmapi queues # # SGI Modid: xfs-linux:xfs-kern:166619a # -------------------------------------------- # 04/03/03 nathans@sgi.com 1.1361 # [XFS] Remove PBF_SYNC buffer flag, unused for some time now. # # SGI Modid: xfs-linux:xfs-kern:167442a # -------------------------------------------- # 04/03/03 roehrich@sgi.com 1.1362 # [XFS] Change DM_SEM_FLAG to DM_SEM_FLAG_RD. # # SGI Modid: xfs-linux:xfs-kern:167547a # -------------------------------------------- # 04/03/03 tes@sgi.com 1.1363 # [XFS] Version 2 log fixes - remove l_stripemask and add v2 log stripe # padding to ic_roundoff to cater for pad in reservation cursor updates. # # SGI Modid: xfs-linux:xfs-kern:167580a # -------------------------------------------- # 04/03/03 tes@sgi.com 1.1364 # [XFS] fix up some log debug code for when XFS_LOUD_RECOVERY is turned on. # # SGI Modid: xfs-linux:xfs-kern:167581a # -------------------------------------------- # 04/03/03 nathans@sgi.com 1.1365 # [XFS] Sort out some minor differences between trees. # -------------------------------------------- # 04/03/03 sandeen@sgi.com 1.1366 # [XFS] Make more xfs errors trappable with panic_mask # # SGI Modid: xfs-linux:xfs-kern:164051a # -------------------------------------------- # 04/03/03 hch@sgi.com 1.1367 # [XFS] kill some dead constants from pagebuf # # SGI Modid: xfs-linux:xfs-kern:167273a # -------------------------------------------- # 04/03/03 marcelo@dmt.cyclades 1.1330.1.1 # devfs: Fix truncation of mount data as 2.6 # -------------------------------------------- # 04/03/04 marcelo@dmt.cyclades 1.1368 # Merge http://xfs.org:8090/xfs-linux-2.4 # into dmt.cyclades:/home/marcelo/bk/linux-2.4 # -------------------------------------------- # 04/03/04 jon@focalhost.com 1.1369 # [CRYPTO]: Add ARC4 module. # -------------------------------------------- # 04/03/04 jmorris@redhat.com 1.1370 # [CRYPTO]: Backport Christophe Saout's 2.6.x scatterlist code extraction. # -------------------------------------------- # 04/03/05 dolbeau@irisa.fr 1.1371 # [PATCH] Small fix to pm3fb & MAINTAINERS # # The attached patch update my Permedia3 driver # to my latest version, and fix my MAINTAINERS # entry. # -------------------------------------------- # diff -Nru a/Documentation/Configure.help b/Documentation/Configure.help --- a/Documentation/Configure.help Fri Mar 5 05:02:52 2004 +++ b/Documentation/Configure.help Fri Mar 5 05:02:52 2004 @@ -28736,6 +28736,13 @@ The CAST6 encryption algorithm (synonymous with CAST-256) is described in RFC2612. +CONFIG_CRYPTO_ARC4 + ARC4 cipher algorithm. + + This is a stream cipher using keys ranging from 8 bits to 2048 + bits in length. ARC4 is commonly used in protocols such as WEP + and SSL. + CONFIG_CRYPTO_DEFLATE This is the Deflate algorithm (RFC1951), specified for use in IPSec with the IPCOMP protocol (RFC3173, RFC2394). diff -Nru a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt --- a/Documentation/crypto/api-intro.txt Fri Mar 5 05:02:52 2004 +++ b/Documentation/crypto/api-intro.txt Fri Mar 5 05:02:52 2004 @@ -185,6 +185,8 @@ Matthew Skala (Twofish) Dag Arne Osvik (Serpent) Brian Gladman (AES) + Kartikey Mahendra Bhatt (CAST6) + Jon Oberheide (ARC4) SHA1 algorithm contributors: Jean-Francois Dive diff -Nru a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt --- a/Documentation/networking/bonding.txt Fri Mar 5 05:02:51 2004 +++ b/Documentation/networking/bonding.txt Fri Mar 5 05:02:51 2004 @@ -31,6 +31,7 @@ Frequently Asked Questions High Availability Promiscuous Sniffing notes +8021q VLAN support Limitations Resources and Links @@ -140,10 +141,6 @@ Be careful not to reference bond0 itself at the end of the line, or modprobe will die in an endless recursive loop. -To have device characteristics (such as MTU size) propagate to slave devices, -set the bond characteristics before enslaving the device. The characteristics -are propagated during the enslave process. - If running SNMP agents, the bonding driver should be loaded before any network drivers participating in a bond. This requirement is due to the the interface index (ipAdEntIfIndex) being associated to the first interface found with a @@ -601,7 +598,7 @@ For ethernet cards not supporting MII status, the arp_interval and arp_ip_target parameters must be specified for bonding to work correctly. If packets have not been sent or received during the - specified arp_interval durration, an ARP request is sent to the + specified arp_interval duration, an ARP request is sent to the targets to generate send and receive traffic. If after this interval, either the successful send and/or receive count has not incremented, the next slave in the sequence will become the active @@ -669,16 +666,8 @@ that will be added. To restore your slaves' MAC addresses, you need to detach them - from the bond (`ifenslave -d bond0 eth0'), set them down - (`ifconfig eth0 down'), unload the drivers (`rmmod 3c59x', for - example) and reload them to get the MAC addresses from their - eeproms. If the driver is shared by several devices, you need - to turn them all down. Another solution is to look for the MAC - address at boot time (dmesg or tail /var/log/messages) and to - reset it by hand with ifconfig : - - # ifconfig eth0 down - # ifconfig eth0 hw ether 00:20:40:60:80:A0 + from the bond (`ifenslave -d bond0 eth0'). The bonding driver will then + restore the MAC addresses that the slaves had before they were enslaved. 9. Which transmit polices can be used? @@ -843,7 +832,7 @@ In this configuration, there is an ISL - Inter Switch Link (could be a trunk), several servers (host1, host2 ...) attached to both switches each, and one or -more ports to the outside world (port3...). One an only one slave on each host +more ports to the outside world (port3...). One and only one slave on each host is active at a time, while all links are still monitored (the system can detect a failure of active and backup links). @@ -931,6 +920,41 @@ interface, appropriately for its design functions in HA and channel capacity aggregating; but it works fine for unnumbered interfaces; just ignore all the warnings it emits. + + +8021q VLAN support +================== + +It is possible to configure VLAN devices over a bond interface using the 8021q +driver. However, only packets coming from the 8021q driver and passing through +bonding will be tagged by default. Self generated packets, like bonding's +learning packets or ARP packets generated by either ALB mode or the ARP +monitor mechanism, are tagged internally by bonding itself. As a result, +bonding has to "learn" what VLAN IDs are configured on top of it, and it uses +those IDs to tag self generated packets. + +For simplicity reasons, and to support the use of adapters that can do VLAN +hardware acceleration offloding, the bonding interface declares itself as +fully hardware offloaing capable, it gets the add_vid/kill_vid notifications +to gather the necessary information, and it propagates those actions to the +slaves. +In case of mixed adapter types, hardware accelerated tagged packets that should +go through an adapter that is not offloading capable are "un-accelerated" by the +bonding driver so the VLAN tag sits in the regular location. + +VLAN interfaces *must* be added on top of a bonding interface only after +enslaving at least one slave. This is because until the first slave is added the +bonding interface has a HW address of 00:00:00:00:00:00, which will be copied by +the VLAN interface when it is created. + +Notice that a problem would occur if all slaves are released from a bond that +still has VLAN interfaces on top of it. When later coming to add new slaves, the +bonding interface would get a HW address from the first slave, which might not +match that of the VLAN interfaces. It is recommended that either all VLANs are +removed and then re-added, or to manually set the bonding interface's HW +address so it matches the VLAN's. (Note: changing a VLAN interface's HW address +would set the underlying device -- i.e. the bonding interface -- to promiscouos +mode, which might not be what you want). Limitations diff -Nru a/MAINTAINERS b/MAINTAINERS --- a/MAINTAINERS Fri Mar 5 05:02:51 2004 +++ b/MAINTAINERS Fri Mar 5 05:02:51 2004 @@ -1456,9 +1456,9 @@ PERMEDIA 3 FRAMEBUFFER DRIVER P: Romain Dolbeau -M: dolbeau@irisa.fr +M: dolbeau@caps-entreprise.com L: linux-fbdev-devel@lists.sourceforge.net -W: http://www.irisa.fr/prive/dolbeau/pm3fb/pm3fb.html +W: http://www.caps-entreprise.com/private/dolbeau/pm3fb/pm3fb.html S: Maintained PHILIPS NINO PALM PC diff -Nru a/crypto/Config.in b/crypto/Config.in --- a/crypto/Config.in Fri Mar 5 05:02:51 2004 +++ b/crypto/Config.in Fri Mar 5 05:02:51 2004 @@ -72,6 +72,7 @@ tristate ' AES cipher algorithms' CONFIG_CRYPTO_AES tristate ' CAST5 (CAST-128) cipher algorithm' CONFIG_CRYPTO_CAST5 tristate ' CAST6 (CAST-256) cipher algorithm' CONFIG_CRYPTO_CAST6 + tristate ' ARC4 cipher algorithm' CONFIG_CRYPTO_ARC4 if [ "$CONFIG_INET_IPCOMP" = "y" -o \ "$CONFIG_INET_IPCOMP" = "m" -o \ "$CONFIG_INET6_IPCOMP" = "y" -o \ diff -Nru a/crypto/Makefile b/crypto/Makefile --- a/crypto/Makefile Fri Mar 5 05:02:51 2004 +++ b/crypto/Makefile Fri Mar 5 05:02:51 2004 @@ -9,7 +9,7 @@ autoload-crypto-$(CONFIG_KMOD) = autoload.o proc-crypto-$(CONFIG_PROC_FS) = proc.o -obj-$(CONFIG_CRYPTO) += api.o cipher.o digest.o compress.o \ +obj-$(CONFIG_CRYPTO) += api.o scatterwalk.o cipher.o digest.o compress.o \ $(autoload-crypto-y) $(proc-crypto-y) obj-$(CONFIG_CRYPTO_HMAC) += hmac.o @@ -26,6 +26,7 @@ obj-$(CONFIG_CRYPTO_AES) += aes.o obj-$(CONFIG_CRYPTO_CAST5) += cast5.o obj-$(CONFIG_CRYPTO_CAST6) += cast6.o +obj-$(CONFIG_CRYPTO_ARC4) += arc4.o obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o diff -Nru a/crypto/arc4.c b/crypto/arc4.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/arc4.c Fri Mar 5 05:02:52 2004 @@ -0,0 +1,106 @@ +/* + * Cryptographic API + * + * ARC4 Cipher Algorithm + * + * Jon Oberheide + * + * 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 +#include +#include + +#define ARC4_MIN_KEY_SIZE 1 +#define ARC4_MAX_KEY_SIZE 256 +#define ARC4_BLOCK_SIZE 1 + +struct arc4_ctx { + u8 S[256]; + u8 x, y; +}; + +static int arc4_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) +{ + struct arc4_ctx *ctx = ctx_arg; + int i, j = 0, k = 0; + + ctx->x = 1; + ctx->y = 0; + + for(i = 0; i < 256; i++) + ctx->S[i] = i; + + for(i = 0; i < 256; i++) + { + u8 a = ctx->S[i]; + j = (j + in_key[k] + a) & 0xff; + ctx->S[i] = ctx->S[j]; + ctx->S[j] = a; + if(++k >= key_len) + k = 0; + } + + /* TODO: dump the first 768 bytes generated as recommended + by Ilya Mironov (http://eprint.iacr.org/2002/067/) to + increase the statistical strength of the state table */ + + return 0; +} + +static void arc4_crypt(void *ctx_arg, u8 *out, const u8 *in) +{ + struct arc4_ctx *ctx = ctx_arg; + + u8 *const S = ctx->S; + u8 x = ctx->x; + u8 y = ctx->y; + + u8 a = S[x]; + y = (y + a) & 0xff; + u8 b = S[y]; + S[x] = b; + S[y] = a; + x = (x + 1) & 0xff; + *out++ = *in ^ S[(a + b) & 0xff]; + + ctx->x = x; + ctx->y = y; +} + +static struct crypto_alg arc4_alg = { + .cra_name = "arc4", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = ARC4_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct arc4_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(arc4_alg.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = ARC4_MIN_KEY_SIZE, + .cia_max_keysize = ARC4_MAX_KEY_SIZE, + .cia_setkey = arc4_set_key, + .cia_encrypt = arc4_crypt, + .cia_decrypt = arc4_crypt } } +}; + +static int __init arc4_init(void) +{ + return crypto_register_alg(&arc4_alg); +} + + +static void __exit arc4_exit(void) +{ + crypto_unregister_alg(&arc4_alg); +} + +module_init(arc4_init); +module_exit(arc4_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("ARC4 Cipher Algorithm"); +MODULE_AUTHOR("Jon Oberheide "); diff -Nru a/crypto/cipher.c b/crypto/cipher.c --- a/crypto/cipher.c Fri Mar 5 05:02:51 2004 +++ b/crypto/cipher.c Fri Mar 5 05:02:51 2004 @@ -4,7 +4,6 @@ * Cipher operations. * * Copyright (c) 2002 James Morris - * Generic scatterwalk code by Adam J. Richter . * * 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 @@ -17,30 +16,13 @@ #include #include #include -#include -#include #include #include "internal.h" +#include "scatterwalk.h" typedef void (cryptfn_t)(void *, u8 *, const u8 *); typedef void (procfn_t)(struct crypto_tfm *, u8 *, - u8*, cryptfn_t, int enc, void *); - -struct scatter_walk { - struct scatterlist *sg; - struct page *page; - void *data; - unsigned int len_this_page; - unsigned int len_this_segment; - unsigned int offset; -}; - -enum km_type crypto_km_types[] = { - KM_USER0, - KM_USER1, - KM_SOFTIRQ0, - KM_SOFTIRQ1, -}; + u8*, cryptfn_t, int enc, void *, int); static inline void xor_64(u8 *a, const u8 *b) { @@ -57,108 +39,6 @@ } -/* Define sg_next is an inline routine now in case we want to change - scatterlist to a linked list later. */ -static inline struct scatterlist *sg_next(struct scatterlist *sg) -{ - return sg + 1; -} - -void *which_buf(struct scatter_walk *walk, unsigned int nbytes, void *scratch) -{ - if (nbytes <= walk->len_this_page && - (((unsigned long)walk->data) & (PAGE_CACHE_SIZE - 1)) + nbytes <= - PAGE_CACHE_SIZE) - return walk->data; - else - return scratch; -} - -static void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out) -{ - if (out) - memcpy(sgdata, buf, nbytes); - else - memcpy(buf, sgdata, nbytes); -} - -static void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg) -{ - unsigned int rest_of_page; - - walk->sg = sg; - - walk->page = sg->page; - walk->len_this_segment = sg->length; - - rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1)); - walk->len_this_page = min(sg->length, rest_of_page); - walk->offset = sg->offset; -} - -static void scatterwalk_map(struct scatter_walk *walk, int out) -{ - walk->data = crypto_kmap(walk->page, out) + walk->offset; -} - -static void scatter_page_done(struct scatter_walk *walk, int out, - unsigned int more) -{ - /* walk->data may be pointing the first byte of the next page; - however, we know we transfered at least one byte. So, - walk->data - 1 will be a virutual address in the mapped page. */ - - if (out) - flush_dcache_page(walk->page); - - if (more) { - walk->len_this_segment -= walk->len_this_page; - - if (walk->len_this_segment) { - walk->page++; - walk->len_this_page = min(walk->len_this_segment, - (unsigned)PAGE_CACHE_SIZE); - walk->offset = 0; - } - else - scatterwalk_start(walk, sg_next(walk->sg)); - } -} - -static void scatter_done(struct scatter_walk *walk, int out, int more) -{ - crypto_kunmap(walk->data, out); - if (walk->len_this_page == 0 || !more) - scatter_page_done(walk, out, more); -} - -/* - * Do not call this unless the total length of all of the fragments - * has been verified as multiple of the block size. - */ -static int copy_chunks(void *buf, struct scatter_walk *walk, - size_t nbytes, int out) -{ - if (buf != walk->data) { - while (nbytes > walk->len_this_page) { - memcpy_dir(buf, walk->data, walk->len_this_page, out); - buf += walk->len_this_page; - nbytes -= walk->len_this_page; - - crypto_kunmap(walk->data, out); - scatter_page_done(walk, out, 1); - scatterwalk_map(walk, out); - } - - memcpy_dir(buf, walk->data, nbytes, out); - } - - walk->offset += nbytes; - walk->len_this_page -= nbytes; - walk->len_this_segment -= nbytes; - return 0; -} - /* * Generic encrypt/decrypt wrapper for ciphers, handles operations across * multiple page boundaries by using temporary blocks. In user context, @@ -191,19 +71,21 @@ scatterwalk_map(&walk_in, 0); scatterwalk_map(&walk_out, 1); - src_p = which_buf(&walk_in, bsize, tmp_src); - dst_p = which_buf(&walk_out, bsize, tmp_dst); + src_p = scatterwalk_whichbuf(&walk_in, bsize, tmp_src); + dst_p = scatterwalk_whichbuf(&walk_out, bsize, tmp_dst); nbytes -= bsize; - copy_chunks(src_p, &walk_in, bsize, 0); + scatterwalk_copychunks(src_p, &walk_in, bsize, 0); - prfn(tfm, dst_p, src_p, crfn, enc, info); + prfn(tfm, dst_p, src_p, crfn, enc, info, + scatterwalk_samebuf(&walk_in, &walk_out, + src_p, dst_p)); - scatter_done(&walk_in, 0, nbytes); + scatterwalk_done(&walk_in, 0, nbytes); - copy_chunks(dst_p, &walk_out, bsize, 1); - scatter_done(&walk_out, 1, nbytes); + scatterwalk_copychunks(dst_p, &walk_out, bsize, 1); + scatterwalk_done(&walk_out, 1, nbytes); if (!nbytes) return 0; @@ -212,8 +94,8 @@ } } -static void cbc_process(struct crypto_tfm *tfm, - u8 *dst, u8 *src, cryptfn_t fn, int enc, void *info) +static void cbc_process(struct crypto_tfm *tfm, u8 *dst, u8 *src, + cryptfn_t fn, int enc, void *info, int in_place) { u8 *iv = info; @@ -226,10 +108,9 @@ fn(crypto_tfm_ctx(tfm), dst, iv); memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm)); } else { - const int need_stack = (src == dst); - u8 stack[need_stack ? crypto_tfm_alg_blocksize(tfm) : 0]; - u8 *buf = need_stack ? stack : dst; - + u8 stack[in_place ? crypto_tfm_alg_blocksize(tfm) : 0]; + u8 *buf = in_place ? stack : dst; + fn(crypto_tfm_ctx(tfm), buf, src); tfm->crt_u.cipher.cit_xor_block(buf, iv); memcpy(iv, src, crypto_tfm_alg_blocksize(tfm)); @@ -239,7 +120,7 @@ } static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src, - cryptfn_t fn, int enc, void *info) + cryptfn_t fn, int enc, void *info, int in_place) { fn(crypto_tfm_ctx(tfm), dst, src); } diff -Nru a/crypto/internal.h b/crypto/internal.h --- a/crypto/internal.h Fri Mar 5 05:02:51 2004 +++ b/crypto/internal.h Fri Mar 5 05:02:51 2004 @@ -11,6 +11,7 @@ */ #ifndef _CRYPTO_INTERNAL_H #define _CRYPTO_INTERNAL_H +#include #include #include #include diff -Nru a/crypto/scatterwalk.c b/crypto/scatterwalk.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/scatterwalk.c Fri Mar 5 05:02:52 2004 @@ -0,0 +1,124 @@ +/* + * Cryptographic API. + * + * Cipher operations. + * + * Copyright (c) 2002 James Morris + * 2002 Adam J. Richter + * 2004 Jean-Luc Cooke + * + * 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 +#include +#include +#include +#include +#include "internal.h" +#include "scatterwalk.h" + +enum km_type crypto_km_types[] = { + KM_USER0, + KM_USER1, + KM_SOFTIRQ0, + KM_SOFTIRQ1, +}; + +void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch) +{ + if (nbytes <= walk->len_this_page && + (((unsigned long)walk->data) & (PAGE_CACHE_SIZE - 1)) + nbytes <= + PAGE_CACHE_SIZE) + return walk->data; + else + return scratch; +} + +static void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out) +{ + if (out) + memcpy(sgdata, buf, nbytes); + else + memcpy(buf, sgdata, nbytes); +} + +void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg) +{ + unsigned int rest_of_page; + + walk->sg = sg; + + walk->page = sg->page; + walk->len_this_segment = sg->length; + + rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1)); + walk->len_this_page = min(sg->length, rest_of_page); + walk->offset = sg->offset; +} + +void scatterwalk_map(struct scatter_walk *walk, int out) +{ + walk->data = crypto_kmap(walk->page, out) + walk->offset; +} + +static void scatterwalk_pagedone(struct scatter_walk *walk, int out, + unsigned int more) +{ + /* walk->data may be pointing the first byte of the next page; + however, we know we transfered at least one byte. So, + walk->data - 1 will be a virutual address in the mapped page. */ + + if (out) + flush_dcache_page(walk->page); + + if (more) { + walk->len_this_segment -= walk->len_this_page; + + if (walk->len_this_segment) { + walk->page++; + walk->len_this_page = min(walk->len_this_segment, + (unsigned)PAGE_CACHE_SIZE); + walk->offset = 0; + } + else + scatterwalk_start(walk, sg_next(walk->sg)); + } +} + +void scatterwalk_done(struct scatter_walk *walk, int out, int more) +{ + crypto_kunmap(walk->data, out); + if (walk->len_this_page == 0 || !more) + scatterwalk_pagedone(walk, out, more); +} + +/* + * Do not call this unless the total length of all of the fragments + * has been verified as multiple of the block size. + */ +int scatterwalk_copychunks(void *buf, struct scatter_walk *walk, + size_t nbytes, int out) +{ + if (buf != walk->data) { + while (nbytes > walk->len_this_page) { + memcpy_dir(buf, walk->data, walk->len_this_page, out); + buf += walk->len_this_page; + nbytes -= walk->len_this_page; + + crypto_kunmap(walk->data, out); + scatterwalk_pagedone(walk, out, 1); + scatterwalk_map(walk, out); + } + + memcpy_dir(buf, walk->data, nbytes, out); + } + + walk->offset += nbytes; + walk->len_this_page -= nbytes; + walk->len_this_segment -= nbytes; + return 0; +} diff -Nru a/crypto/scatterwalk.h b/crypto/scatterwalk.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/scatterwalk.h Fri Mar 5 05:02:52 2004 @@ -0,0 +1,50 @@ +/* + * Cryptographic API. + * + * Copyright (c) 2002 James Morris + * Copyright (c) 2002 Adam J. Richter + * Copyright (c) 2004 Jean-Luc Cooke + * + * 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. + * + */ + +#ifndef _CRYPTO_SCATTERWALK_H +#define _CRYPTO_SCATTERWALK_H +#include +#include + +struct scatter_walk { + struct scatterlist *sg; + struct page *page; + void *data; + unsigned int len_this_page; + unsigned int len_this_segment; + unsigned int offset; +}; + +/* Define sg_next is an inline routine now in case we want to change + scatterlist to a linked list later. */ +static inline struct scatterlist *sg_next(struct scatterlist *sg) +{ + return sg + 1; +} + +static inline int scatterwalk_samebuf(struct scatter_walk *walk_in, + struct scatter_walk *walk_out, + void *src_p, void *dst_p) +{ + return walk_in->page == walk_out->page && + walk_in->data == src_p && walk_out->data == dst_p; +} + +void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch); +void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg); +int scatterwalk_copychunks(void *buf, struct scatter_walk *walk, size_t nbytes, int out); +void scatterwalk_map(struct scatter_walk *walk, int out); +void scatterwalk_done(struct scatter_walk *walk, int out, int more); + +#endif /* _CRYPTO_SCATTERWALK_H */ diff -Nru a/crypto/tcrypt.c b/crypto/tcrypt.c --- a/crypto/tcrypt.c Fri Mar 5 05:02:51 2004 +++ b/crypto/tcrypt.c Fri Mar 5 05:02:51 2004 @@ -63,7 +63,7 @@ static char *check[] = { "des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish", "twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", - "deflate", NULL + "arc4", "deflate", NULL }; static void @@ -558,6 +558,10 @@ test_cipher ("cast6", MODE_ECB, ENCRYPT, cast6_enc_tv_template, CAST6_ENC_TEST_VECTORS); test_cipher ("cast6", MODE_ECB, DECRYPT, cast6_dec_tv_template, CAST6_DEC_TEST_VECTORS); + //ARC4 + test_cipher ("arc4", MODE_ECB, ENCRYPT, arc4_enc_tv_template, ARC4_ENC_TEST_VECTORS); + test_cipher ("arc4", MODE_ECB, DECRYPT, arc4_dec_tv_template, ARC4_DEC_TEST_VECTORS); + test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS); test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS); test_deflate(); @@ -638,6 +642,11 @@ case 15: test_cipher ("cast6", MODE_ECB, ENCRYPT, cast6_enc_tv_template, CAST6_ENC_TEST_VECTORS); test_cipher ("cast6", MODE_ECB, DECRYPT, cast6_dec_tv_template, CAST6_DEC_TEST_VECTORS); + break; + + case 16: + test_cipher ("arc4", MODE_ECB, ENCRYPT, arc4_enc_tv_template, ARC4_ENC_TEST_VECTORS); + test_cipher ("arc4", MODE_ECB, DECRYPT, arc4_dec_tv_template, ARC4_DEC_TEST_VECTORS); break; #ifdef CONFIG_CRYPTO_HMAC diff -Nru a/crypto/tcrypt.h b/crypto/tcrypt.h --- a/crypto/tcrypt.h Fri Mar 5 05:02:52 2004 +++ b/crypto/tcrypt.h Fri Mar 5 05:02:52 2004 @@ -1488,6 +1488,147 @@ }, }; +/* + * ARC4 test vectors from OpenSSL + */ +#define ARC4_ENC_TEST_VECTORS 7 +#define ARC4_DEC_TEST_VECTORS 7 + +struct cipher_testvec arc4_enc_tv_template[] = +{ + { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .ilen = 8, + .result = { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 }, + .rlen = 8, + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .ilen = 8, + .result = { 0x74, 0x94, 0xc2, 0xe7, 0x10, 0x4b, 0x08, 0x79 }, + .rlen = 8, + }, { + .key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .klen = 8, + .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .ilen = 8, + .result = { 0xde, 0x18, 0x89, 0x41, 0xa3, 0x37, 0x5d, 0x3a }, + .rlen = 8, + }, { + .key = { 0xef, 0x01, 0x23, 0x45}, + .klen = 4, + .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + .ilen = 20, + .result = { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf, + 0xbd, 0x61, 0x5a, 0x11, 0x62, 0xe1, 0xc7, 0xba, + 0x36, 0xb6, 0x78, 0x58 }, + .rlen = 20, + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .input = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, + 0x12, 0x34, 0x56, 0x78 }, + .ilen = 28, + .result = { 0x66, 0xa0, 0x94, 0x9f, 0x8a, 0xf7, 0xd6, 0x89, + 0x1f, 0x7f, 0x83, 0x2b, 0xa8, 0x33, 0xc0, 0x0c, + 0x89, 0x2e, 0xbe, 0x30, 0x14, 0x3c, 0xe2, 0x87, + 0x40, 0x01, 0x1e, 0xcf }, + .rlen = 28, + }, { + .key = { 0xef, 0x01, 0x23, 0x45 }, + .klen = 4, + .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + .ilen = 10, + .result = { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf, + 0xbd, 0x61 }, + .rlen = 10, + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .klen = 16, + .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + .ilen = 8, + .result = { 0x69, 0x72, 0x36, 0x59, 0x1B, 0x52, 0x42, 0xB1 }, + .rlen = 8, + }, +}; + +struct cipher_testvec arc4_dec_tv_template[] = +{ + { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .input = { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 }, + .ilen = 8, + .result = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .rlen = 8, + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .input = { 0x74, 0x94, 0xc2, 0xe7, 0x10, 0x4b, 0x08, 0x79 }, + .ilen = 8, + .result = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .rlen = 8, + }, { + .key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .klen = 8, + .input = { 0xde, 0x18, 0x89, 0x41, 0xa3, 0x37, 0x5d, 0x3a }, + .ilen = 8, + .result = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .rlen = 8, + }, { + .key = { 0xef, 0x01, 0x23, 0x45}, + .klen = 4, + .input = { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf, + 0xbd, 0x61, 0x5a, 0x11, 0x62, 0xe1, 0xc7, 0xba, + 0x36, 0xb6, 0x78, 0x58 }, + .ilen = 20, + .result = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + .rlen = 20, + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .input = { 0x66, 0xa0, 0x94, 0x9f, 0x8a, 0xf7, 0xd6, 0x89, + 0x1f, 0x7f, 0x83, 0x2b, 0xa8, 0x33, 0xc0, 0x0c, + 0x89, 0x2e, 0xbe, 0x30, 0x14, 0x3c, 0xe2, 0x87, + 0x40, 0x01, 0x1e, 0xcf }, + .ilen = 28, + .result = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, + 0x12, 0x34, 0x56, 0x78 }, + .rlen = 28, + }, { + .key = { 0xef, 0x01, 0x23, 0x45 }, + .klen = 4, + .input = { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf, + 0xbd, 0x61 }, + .ilen = 10, + .result = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + .rlen = 10, + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .klen = 16, + .input = { 0x69, 0x72, 0x36, 0x59, 0x1B, 0x52, 0x42, 0xB1 }, + .ilen = 8, + .result = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + .rlen = 8, + }, +}; + + /* * Compression stuff. */ diff -Nru a/drivers/net/8139too.c b/drivers/net/8139too.c --- a/drivers/net/8139too.c Fri Mar 5 05:02:51 2004 +++ b/drivers/net/8139too.c Fri Mar 5 05:02:51 2004 @@ -255,6 +255,10 @@ {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, {0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, + {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, + {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, + {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, + {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, #ifdef CONFIG_SH_SECUREEDGE5410 /* Bogus 8139 silicon reports 8129 without external PROM :-( */ diff -Nru a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c --- a/drivers/net/bonding/bond_3ad.c Fri Mar 5 05:02:51 2004 +++ b/drivers/net/bonding/bond_3ad.c Fri Mar 5 05:02:51 2004 @@ -2362,6 +2362,7 @@ int agg_id; int i; struct ad_info ad_info; + int res = 1; /* make sure that the slaves list will * not change during tx @@ -2369,12 +2370,12 @@ read_lock(&bond->lock); if (!BOND_IS_OK(bond)) { - goto free_out; + goto out; } if (bond_3ad_get_active_agg_info(bond, &ad_info)) { printk(KERN_DEBUG "ERROR: bond_3ad_get_active_agg_info failed\n"); - goto free_out; + goto out; } slaves_in_agg = ad_info.ports; @@ -2383,7 +2384,7 @@ if (slaves_in_agg == 0) { /*the aggregator is empty*/ printk(KERN_DEBUG "ERROR: active aggregator is empty\n"); - goto free_out; + goto out; } slave_agg_no = (data->h_dest[5]^bond->dev->dev_addr[5]) % slaves_in_agg; @@ -2401,7 +2402,7 @@ if (slave_agg_no >= 0) { printk(KERN_ERR DRV_NAME ": Error: Couldn't find a slave to tx on for aggregator ID %d\n", agg_id); - goto free_out; + goto out; } start_at = slave; @@ -2414,24 +2415,19 @@ slave_agg_id = agg->aggregator_identifier; } - if (SLAVE_IS_OK(slave) && - agg && (slave_agg_id == agg_id)) { - skb->dev = slave->dev; - skb->priority = 1; - dev_queue_xmit(skb); - - goto out; + if (SLAVE_IS_OK(slave) && agg && (slave_agg_id == agg_id)) { + res = bond_dev_queue_xmit(bond, skb, slave->dev); + break; } } out: + if (res) { + /* no suitable interface, frame not sent */ + dev_kfree_skb(skb); + } read_unlock(&bond->lock); return 0; - -free_out: - /* no suitable interface, frame not sent */ - dev_kfree_skb(skb); - goto out; } int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype) diff -Nru a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c --- a/drivers/net/bonding/bond_alb.c Fri Mar 5 05:02:51 2004 +++ b/drivers/net/bonding/bond_alb.c Fri Mar 5 05:02:51 2004 @@ -34,6 +34,9 @@ * * 2003/12/30 - Amir Noam * - Fixed: Cannot remove and re-enslave the original active slave. + * + * 2004/01/14 - Shmulik Hen + * - Add capability to tag self generated packets in ALB/TLB modes. */ //#define BONDING_DEBUG 1 @@ -50,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -79,7 +83,7 @@ #define TLB_NULL_INDEX 0xffffffff -#define MAX_LP_RETRY 3 +#define MAX_LP_BURST 3 /* rlb defs */ #define RLB_HASH_TABLE_SIZE 256 @@ -498,13 +502,33 @@ } for (i = 0; i < RLB_ARP_BURST_SIZE; i++) { - arp_send(ARPOP_REPLY, ETH_P_ARP, - client_info->ip_dst, - client_info->slave->dev, - client_info->ip_src, - client_info->mac_dst, - client_info->slave->dev->dev_addr, - client_info->mac_dst); + struct sk_buff *skb; + + skb = arp_create(ARPOP_REPLY, ETH_P_ARP, + client_info->ip_dst, + client_info->slave->dev, + client_info->ip_src, + client_info->mac_dst, + client_info->slave->dev->dev_addr, + client_info->mac_dst); + if (!skb) { + printk(KERN_ERR DRV_NAME + ": Error: failed to create an ARP packet\n"); + continue; + } + + skb->dev = client_info->slave->dev; + + if (client_info->tag) { + skb = vlan_put_tag(skb, client_info->vlan_id); + if (!skb) { + printk(KERN_ERR DRV_NAME + ": Error: failed to insert VLAN tag\n"); + continue; + } + } + + arp_xmit(skb); } } @@ -603,9 +627,10 @@ } /* Caller must hold both bond and ptr locks for read */ -struct slave *rlb_choose_channel(struct bonding *bond, struct arp_pkt *arp) +struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bond) { struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); + struct arp_pkt *arp = (struct arp_pkt *)skb->nh.raw; struct slave *assigned_slave; struct rlb_client_info *client_info; u32 hash_index = 0; @@ -661,6 +686,15 @@ client_info->ntt = 0; } + if (!list_empty(&bond->vlan_list)) { + unsigned short vlan_id; + int res = vlan_get_tag(skb, &vlan_id); + if (!res) { + client_info->tag = 1; + client_info->vlan_id = vlan_id; + } + } + if (!client_info->assigned) { u32 prev_tbl_head = bond_info->rx_hashtbl_head; bond_info->rx_hashtbl_head = hash_index; @@ -691,7 +725,7 @@ /* the arp must be sent on the selected * rx channel */ - tx_slave = rlb_choose_channel(bond, arp); + tx_slave = rlb_choose_channel(skb, bond); if (tx_slave) { memcpy(arp->mac_src,tx_slave->dev->dev_addr, ETH_ALEN); } @@ -702,7 +736,7 @@ * When the arp reply is received the entry will be updated * with the correct unicast address of the client. */ - rlb_choose_channel(bond, arp); + rlb_choose_channel(skb, bond); /* The ARP relpy packets must be delayed so that * they can cancel out the influence of the ARP request. @@ -809,6 +843,40 @@ kfree(bond_info->rx_hashtbl); bond_info->rx_hashtbl = NULL; + bond_info->rx_hashtbl_head = RLB_NULL_INDEX; + + _unlock_rx_hashtbl(bond); +} + +static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id) +{ + struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); + u32 curr_index; + + _lock_rx_hashtbl(bond); + + curr_index = bond_info->rx_hashtbl_head; + while (curr_index != RLB_NULL_INDEX) { + struct rlb_client_info *curr = &(bond_info->rx_hashtbl[curr_index]); + u32 next_index = bond_info->rx_hashtbl[curr_index].next; + u32 prev_index = bond_info->rx_hashtbl[curr_index].prev; + + if (curr->tag && (curr->vlan_id == vlan_id)) { + if (curr_index == bond_info->rx_hashtbl_head) { + bond_info->rx_hashtbl_head = next_index; + } + if (prev_index != RLB_NULL_INDEX) { + bond_info->rx_hashtbl[prev_index].next = next_index; + } + if (next_index != RLB_NULL_INDEX) { + bond_info->rx_hashtbl[next_index].prev = prev_index; + } + + rlb_init_table_entry(curr); + } + + curr_index = next_index; + } _unlock_rx_hashtbl(bond); } @@ -817,6 +885,7 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[]) { + struct bonding *bond = bond_get_bond_by_slave(slave); struct learning_pkt pkt; int size = sizeof(struct learning_pkt); int i; @@ -826,7 +895,7 @@ memcpy(pkt.mac_src, mac_addr, ETH_ALEN); pkt.type = __constant_htons(ETH_P_LOOP); - for (i = 0; i < MAX_LP_RETRY; i++) { + for (i = 0; i < MAX_LP_BURST; i++) { struct sk_buff *skb; char *data; @@ -844,6 +913,26 @@ skb->priority = TC_PRIO_CONTROL; skb->dev = slave->dev; + if (!list_empty(&bond->vlan_list)) { + struct vlan_entry *vlan; + + vlan = bond_next_vlan(bond, + bond->alb_info.current_alb_vlan); + + bond->alb_info.current_alb_vlan = vlan; + if (!vlan) { + kfree_skb(skb); + continue; + } + + skb = vlan_put_tag(skb, vlan->vlan_id); + if (!skb) { + printk(KERN_ERR DRV_NAME + ": Error: failed to insert VLAN tag\n"); + continue; + } + } + dev_queue_xmit(skb); } } @@ -1194,6 +1283,7 @@ int do_tx_balance = 1; u32 hash_index = 0; u8 *hash_start = NULL; + int res = 1; /* make sure that the curr_active_slave and the slaves list do * not change during tx @@ -1202,7 +1292,7 @@ read_lock(&bond->curr_slave_lock); if (!BOND_IS_OK(bond)) { - goto free_out; + goto out; } switch (ntohs(skb->protocol)) { @@ -1267,29 +1357,27 @@ } if (tx_slave && SLAVE_IS_OK(tx_slave)) { - skb->dev = tx_slave->dev; if (tx_slave != bond->curr_active_slave) { memcpy(eth_data->h_source, tx_slave->dev->dev_addr, ETH_ALEN); } - dev_queue_xmit(skb); + + res = bond_dev_queue_xmit(bond, skb, tx_slave->dev); } else { - /* no suitable interface, frame not sent */ if (tx_slave) { tlb_clear_slave(bond, tx_slave, 0); } - goto free_out; } out: + if (res) { + /* no suitable interface, frame not sent */ + dev_kfree_skb(skb); + } read_unlock(&bond->curr_slave_lock); read_unlock(&bond->lock); return 0; - -free_out: - dev_kfree_skb(skb); - goto out; } void bond_alb_monitor(struct bonding *bond) @@ -1588,5 +1676,17 @@ } return 0; +} + +void bond_alb_clear_vlan(struct bonding *bond, unsigned short vlan_id) +{ + if (bond->alb_info.current_alb_vlan && + (bond->alb_info.current_alb_vlan->vlan_id == vlan_id)) { + bond->alb_info.current_alb_vlan = NULL; + } + + if (bond->alb_info.rlb_enabled) { + rlb_clear_vlan(bond, vlan_id); + } } diff -Nru a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h --- a/drivers/net/bonding/bond_alb.h Fri Mar 5 05:02:51 2004 +++ b/drivers/net/bonding/bond_alb.h Fri Mar 5 05:02:51 2004 @@ -77,6 +77,8 @@ u8 assigned; /* checking whether this entry is assigned */ u8 ntt; /* flag - need to transmit client info */ struct slave *slave; /* the slave assigned to this client */ + u8 tag; /* flag - need to tag skb */ + unsigned short vlan_id; /* VLAN tag associated with IP address */ }; struct tlb_slave_info { @@ -122,6 +124,7 @@ * rx traffic should be * rebalanced */ + struct vlan_entry *current_alb_vlan; }; int bond_alb_initialize(struct bonding *bond, int rlb_enabled); @@ -133,6 +136,6 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev); void bond_alb_monitor(struct bonding *bond); int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr); - +void bond_alb_clear_vlan(struct bonding *bond, unsigned short vlan_id); #endif /* __BOND_ALB_H__ */ diff -Nru a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c --- a/drivers/net/bonding/bond_main.c Fri Mar 5 05:02:51 2004 +++ b/drivers/net/bonding/bond_main.c Fri Mar 5 05:02:51 2004 @@ -455,12 +455,20 @@ * * 2003/12/30 - Amir Noam * - Fixed: Cannot remove and re-enslave the original active slave. - * - Fixed: Releasing the original active slave causes mac address duplication. + * - Fixed: Releasing the original active slave causes mac address + * duplication. * - Add support for slaves that use ethtool_ops. * Set version to 2.5.3. * * 2004/01/05 - Amir Noam * - Save bonding parameters per bond instead of using the global values. + * Set version to 2.5.4. + * + * 2004/01/14 - Shmulik Hen + * - Enhance VLAN support: + * * Add support for VLAN hardware acceleration capable slaves. + * * Add capability to tag self generated packets in ALB/TLB modes. + * Set version to 2.6.0. */ //#define BONDING_DEBUG 1 @@ -502,6 +510,7 @@ #include #include #include +#include #include #include "bonding.h" #include "bond_3ad.h" @@ -620,6 +629,371 @@ } } +/*---------------------------------- VLAN -----------------------------------*/ + +/** + * bond_add_vlan - add a new vlan id on bond + * @bond: bond that got the notification + * @vlan_id: the vlan id to add + * + * Returns -ENOMEM if allocation failed. + */ +static int bond_add_vlan(struct bonding *bond, unsigned short vlan_id) +{ + struct vlan_entry *vlan; + + dprintk("bond: %s, vlan id %d\n", + (bond ? bond->dev->name: "None"), vlan_id); + + vlan = kmalloc(sizeof(struct vlan_entry), GFP_KERNEL); + if (!vlan) { + return -ENOMEM; + } + + INIT_LIST_HEAD(&vlan->vlan_list); + vlan->vlan_id = vlan_id; + + write_lock_bh(&bond->lock); + + list_add_tail(&vlan->vlan_list, &bond->vlan_list); + + write_unlock_bh(&bond->lock); + + dprintk("added VLAN ID %d on bond %s\n", vlan_id, bond->dev->name); + + return 0; +} + +/** + * bond_del_vlan - delete a vlan id from bond + * @bond: bond that got the notification + * @vlan_id: the vlan id to delete + * + * returns -ENODEV if @vlan_id was not found in @bond. + */ +static int bond_del_vlan(struct bonding *bond, unsigned short vlan_id) +{ + struct vlan_entry *vlan, *next; + int res = -ENODEV; + + dprintk("bond: %s, vlan id %d\n", bond->dev->name, vlan_id); + + write_lock_bh(&bond->lock); + + list_for_each_entry_safe(vlan, next, &bond->vlan_list, vlan_list) { + if (vlan->vlan_id == vlan_id) { + list_del(&vlan->vlan_list); + + if ((bond->params.mode == BOND_MODE_TLB) || + (bond->params.mode == BOND_MODE_ALB)) { + bond_alb_clear_vlan(bond, vlan_id); + } + + dprintk("removed VLAN ID %d from bond %s\n", vlan_id, + bond->dev->name); + + kfree(vlan); + + if (list_empty(&bond->vlan_list) && + (bond->slave_cnt == 0)) { + /* Last VLAN removed and no slaves, so + * restore block on adding VLANs. This will + * be removed once new slaves that are not + * VLAN challenged will be added. + */ + bond->dev->features |= NETIF_F_VLAN_CHALLENGED; + } + + res = 0; + goto out; + } + } + + dprintk("couldn't find VLAN ID %d in bond %s\n", vlan_id, + bond->dev->name); + +out: + write_unlock_bh(&bond->lock); + return res; +} + +/** + * bond_has_challenged_slaves + * @bond: the bond we're working on + * + * Searches the slave list. Returns 1 if a vlan challenged slave + * was found, 0 otherwise. + * + * Assumes bond->lock is held. + */ +static int bond_has_challenged_slaves(struct bonding *bond) +{ + struct slave *slave; + int i; + + bond_for_each_slave(bond, slave, i) { + if (slave->dev->features & NETIF_F_VLAN_CHALLENGED) { + dprintk("found VLAN challenged slave - %s\n", + slave->dev->name); + return 1; + } + } + + dprintk("no VLAN challenged slaves found\n"); + return 0; +} + +/** + * bond_next_vlan - safely skip to the next item in the vlans list. + * @bond: the bond we're working on + * @curr: item we're advancing from + * + * Returns %NULL if list is empty, bond->next_vlan if @curr is %NULL, + * or @curr->next otherwise (even if it is @curr itself again). + * + * Caller must hold bond->lock + */ +struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr) +{ + struct vlan_entry *next, *last; + + if (list_empty(&bond->vlan_list)) { + return NULL; + } + + if (!curr) { + next = list_entry(bond->vlan_list.next, + struct vlan_entry, vlan_list); + } else { + last = list_entry(bond->vlan_list.prev, + struct vlan_entry, vlan_list); + if (last == curr) { + next = list_entry(bond->vlan_list.next, + struct vlan_entry, vlan_list); + } else { + next = list_entry(curr->vlan_list.next, + struct vlan_entry, vlan_list); + } + } + + return next; +} + +/** + * bond_dev_queue_xmit - Prepare skb for xmit. + * + * @bond: bond device that got this skb for tx. + * @skb: hw accel VLAN tagged skb to transmit + * @slave_dev: slave that is supposed to xmit this skbuff + * + * When the bond gets an skb to tarnsmit that is + * already hardware accelerated VLAN tagged, and it + * needs to relay this skb to a slave that is not + * hw accel capable, the skb needs to be "unaccelerated", + * i.e. strip the hwaccel tag and re-insert it as part + * of the payload. + * + * Assumption - once a VLAN device is created over the bond device, all + * packets are going to be hardware accelerated VLAN tagged since the IP + * binding is done over the VLAN device + */ +int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev) +{ + unsigned short vlan_id; + int res; + + if (!list_empty(&bond->vlan_list) && + !(slave_dev->features & NETIF_F_HW_VLAN_TX)) { + res = vlan_get_tag(skb, &vlan_id); + if (res) { + return -EINVAL; + } + + skb->dev = slave_dev; + skb = vlan_put_tag(skb, vlan_id); + if (!skb) { + /* vlan_put_tag() frees the skb in case of error, + * so return success here so the calling functions + * won't attempt to free is again. + */ + return 0; + } + } else { + skb->dev = slave_dev; + } + + skb->priority = 1; + dev_queue_xmit(skb); + + return 0; +} + +/* + * In the following 3 functions, bond_vlan_rx_register(), bond_vlan_rx_add_vid + * and bond_vlan_rx_kill_vid, We don't protect the slave list iteration with a + * lock because: + * a. This operation is performed in IOCTL context, + * b. The operation is protected by the RTNL semaphore in the 8021q code, + * c. Holding a lock with BH disabled while directly calling a base driver + * entry point is generally a BAD idea. + * + * The design of synchronization/protection for this operation in the 8021q + * module is good for one or more VLAN devices over a single physical device + * and cannot be extended for a teaming solution like bonding, so there is a + * potential race condition here where a net device from the vlan group might + * be referenced (either by a base driver or the 8021q code) while it is being + * removed from the system. However, it turns out we're not making matters + * worse, and if it works for regular VLAN usage it will work here too. +*/ + +/** + * bond_vlan_rx_register - Propagates registration to slaves + * @bond_dev: bonding net device that got called + * @grp: vlan group being registered + */ +static void bond_vlan_rx_register(struct net_device *bond_dev, struct vlan_group *grp) +{ + struct bonding *bond = bond_dev->priv; + struct slave *slave; + int i; + + bond->vlgrp = grp; + + bond_for_each_slave(bond, slave, i) { + struct net_device *slave_dev = slave->dev; + + if ((slave_dev->features & NETIF_F_HW_VLAN_RX) && + slave_dev->vlan_rx_register) { + slave_dev->vlan_rx_register(slave_dev, grp); + } + } +} + +/** + * bond_vlan_rx_add_vid - Propagates adding an id to slaves + * @bond_dev: bonding net device that got called + * @vid: vlan id being added + */ +static void bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid) +{ + struct bonding *bond = bond_dev->priv; + struct slave *slave; + int i, res; + + bond_for_each_slave(bond, slave, i) { + struct net_device *slave_dev = slave->dev; + + if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) && + slave_dev->vlan_rx_add_vid) { + slave_dev->vlan_rx_add_vid(slave_dev, vid); + } + } + + res = bond_add_vlan(bond, vid); + if (res) { + printk(KERN_ERR DRV_NAME + ": %s: Failed to add vlan id %d\n", + bond_dev->name, vid); + } +} + +/** + * bond_vlan_rx_kill_vid - Propagates deleting an id to slaves + * @bond_dev: bonding net device that got called + * @vid: vlan id being removed + */ +static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid) +{ + struct bonding *bond = bond_dev->priv; + struct slave *slave; + struct net_device *vlan_dev; + int i, res; + + bond_for_each_slave(bond, slave, i) { + struct net_device *slave_dev = slave->dev; + + if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) && + slave_dev->vlan_rx_kill_vid) { + /* Save and then restore vlan_dev in the grp array, + * since the slave's driver might clear it. + */ + vlan_dev = bond->vlgrp->vlan_devices[vid]; + slave_dev->vlan_rx_kill_vid(slave_dev, vid); + bond->vlgrp->vlan_devices[vid] = vlan_dev; + } + } + + res = bond_del_vlan(bond, vid); + if (res) { + printk(KERN_ERR DRV_NAME + ": %s: Failed to remove vlan id %d\n", + bond_dev->name, vid); + } +} + +static void bond_add_vlans_on_slave(struct bonding *bond, struct net_device *slave_dev) +{ + struct vlan_entry *vlan; + + write_lock_bh(&bond->lock); + + if (list_empty(&bond->vlan_list)) { + goto out; + } + + if ((slave_dev->features & NETIF_F_HW_VLAN_RX) && + slave_dev->vlan_rx_register) { + slave_dev->vlan_rx_register(slave_dev, bond->vlgrp); + } + + if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) || + !(slave_dev->vlan_rx_add_vid)) { + goto out; + } + + list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { + slave_dev->vlan_rx_add_vid(slave_dev, vlan->vlan_id); + } + +out: + write_unlock_bh(&bond->lock); +} + +static void bond_del_vlans_from_slave(struct bonding *bond, struct net_device *slave_dev) +{ + struct vlan_entry *vlan; + struct net_device *vlan_dev; + + write_lock_bh(&bond->lock); + + if (list_empty(&bond->vlan_list)) { + goto out; + } + + if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) || + !(slave_dev->vlan_rx_kill_vid)) { + goto unreg; + } + + list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { + /* Save and then restore vlan_dev in the grp array, + * since the slave's driver might clear it. + */ + vlan_dev = bond->vlgrp->vlan_devices[vlan->vlan_id]; + slave_dev->vlan_rx_kill_vid(slave_dev, vlan->vlan_id); + bond->vlgrp->vlan_devices[vlan->vlan_id] = vlan_dev; + } + +unreg: + if ((slave_dev->features & NETIF_F_HW_VLAN_RX) && + slave_dev->vlan_rx_register) { + slave_dev->vlan_rx_register(slave_dev, NULL); + } + +out: + write_unlock_bh(&bond->lock); +} + /*------------------------------- Link status -------------------------------*/ /* @@ -1214,6 +1588,7 @@ struct dev_mc_list *dmi; struct sockaddr addr; int link_reporting; + int old_features = bond_dev->features; int res = 0; if (slave_dev->do_ioctl == NULL) { @@ -1234,6 +1609,36 @@ return -EBUSY; } + /* vlan challenged mutual exclusion */ + /* no need to lock since we're protected by rtnl_lock */ + if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) { + dprintk("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name); + if (!list_empty(&bond->vlan_list)) { + printk(KERN_ERR DRV_NAME + ": Error: cannot enslave VLAN " + "challenged slave %s on VLAN enabled " + "bond %s\n", slave_dev->name, + bond_dev->name); + return -EPERM; + } else { + printk(KERN_WARNING DRV_NAME + ": Warning: enslaved VLAN challenged " + "slave %s. Adding VLANs will be blocked as " + "long as %s is part of bond %s\n", + slave_dev->name, slave_dev->name, + bond_dev->name); + bond_dev->features |= NETIF_F_VLAN_CHALLENGED; + } + } else { + dprintk("%s: ! NETIF_F_VLAN_CHALLENGED\n", slave_dev->name); + if (bond->slave_cnt == 0) { + /* First slave, and it is not VLAN challenged, + * so remove the block of adding VLANs over the bond. + */ + bond_dev->features &= ~NETIF_F_VLAN_CHALLENGED; + } + } + if (app_abi_ver >= 1) { /* The application is using an ABI, which requires the * slave interface to be closed. @@ -1242,7 +1647,8 @@ printk(KERN_ERR DRV_NAME ": Error: %s is up\n", slave_dev->name); - return -EPERM; + res = -EPERM; + goto err_undo_flags; } if (slave_dev->set_mac_address == NULL) { @@ -1253,7 +1659,8 @@ "Your kernel likely does not support slave " "devices.\n"); - return -EOPNOTSUPP; + res = -EOPNOTSUPP; + goto err_undo_flags; } } else { /* The application is not using an ABI, which requires the @@ -1263,7 +1670,8 @@ printk(KERN_ERR DRV_NAME ": Error: %s is not running\n", slave_dev->name); - return -EINVAL; + res = -EINVAL; + goto err_undo_flags; } if ((bond->params.mode == BOND_MODE_8023AD) || @@ -1273,13 +1681,15 @@ ": Error: to use %s mode, you must upgrade " "ifenslave.\n", bond_mode_name(bond->params.mode)); - return -EOPNOTSUPP; + res = -EOPNOTSUPP; + goto err_undo_flags; } } new_slave = kmalloc(sizeof(struct slave), GFP_KERNEL); if (!new_slave) { - return -ENOMEM; + res = -ENOMEM; + goto err_undo_flags; } memset(new_slave, 0, sizeof(struct slave)); @@ -1368,6 +1778,8 @@ dev_mc_add(slave_dev, lacpdu_multicast, ETH_ALEN, 0); } + bond_add_vlans_on_slave(bond, slave_dev); + write_lock_bh(&bond->lock); bond_attach_slave(bond, new_slave); @@ -1576,6 +1988,10 @@ err_free: kfree(new_slave); + +err_undo_flags: + bond_dev->features = old_features; + return res; } @@ -1689,8 +2105,37 @@ } } + if (bond->slave_cnt == 0) { + /* if the last slave was removed, zero the mac address + * of the master so it will be set by the application + * to the mac address of the first slave + */ + memset(bond_dev->dev_addr, 0, bond_dev->addr_len); + + if (list_empty(&bond->vlan_list)) { + bond_dev->features |= NETIF_F_VLAN_CHALLENGED; + } else { + printk(KERN_WARNING DRV_NAME + ": Warning: clearing HW address of %s while it " + "still has VLANs.\n", + bond_dev->name); + printk(KERN_WARNING DRV_NAME + ": When re-adding slaves, make sure the bond's " + "HW address matches its VLANs'.\n"); + } + } else if ((bond_dev->features & NETIF_F_VLAN_CHALLENGED) && + !bond_has_challenged_slaves(bond)) { + printk(KERN_INFO DRV_NAME + ": last VLAN challenged slave %s " + "left bond %s. VLAN blocking is removed\n", + slave_dev->name, bond_dev->name); + bond_dev->features &= ~NETIF_F_VLAN_CHALLENGED; + } + write_unlock_bh(&bond->lock); + bond_del_vlans_from_slave(bond, slave_dev); + /* If the mode USES_PRIMARY, then we should only remove its * promisc and mc settings if it was the curr_active_slave, but that was * already taken care of above when we detached the slave @@ -1732,14 +2177,6 @@ kfree(slave); - /* if the last slave was removed, zero the mac address - * of the master so it will be set by the application - * to the mac address of the first slave - */ - if (bond->slave_cnt == 0) { - memset(bond_dev->dev_addr, 0, bond_dev->addr_len); - } - return 0; /* deletion OK */ } @@ -1788,6 +2225,8 @@ */ write_unlock_bh(&bond->lock); + bond_del_vlans_from_slave(bond, slave_dev); + /* If the mode USES_PRIMARY, then we should only remove its * promisc and mc settings if it was the curr_active_slave, but that was * already taken care of above when we detached the slave @@ -1838,6 +2277,18 @@ */ memset(bond_dev->dev_addr, 0, bond_dev->addr_len); + if (list_empty(&bond->vlan_list)) { + bond_dev->features |= NETIF_F_VLAN_CHALLENGED; + } else { + printk(KERN_WARNING DRV_NAME + ": Warning: clearing HW address of %s while it " + "still has VLANs.\n", + bond_dev->name); + printk(KERN_WARNING DRV_NAME + ": When re-adding slaves, make sure the bond's " + "HW address matches its VLANs'.\n"); + } + printk(KERN_INFO DRV_NAME ": %s: released all slaves\n", bond_dev->name); @@ -3570,11 +4021,12 @@ struct bonding *bond = bond_dev->priv; struct slave *slave, *start_at; int i; + int res = 1; read_lock(&bond->lock); if (!BOND_IS_OK(bond)) { - goto free_out; + goto out; } read_lock(&bond->curr_slave_lock); @@ -3582,33 +4034,31 @@ read_unlock(&bond->curr_slave_lock); if (!slave) { - goto free_out; + goto out; } bond_for_each_slave_from(bond, slave, i, start_at) { if (IS_UP(slave->dev) && (slave->link == BOND_LINK_UP) && (slave->state == BOND_STATE_ACTIVE)) { - skb->dev = slave->dev; - skb->priority = 1; - dev_queue_xmit(skb); + res = bond_dev_queue_xmit(bond, skb, slave->dev); write_lock(&bond->curr_slave_lock); bond->curr_active_slave = slave->next; write_unlock(&bond->curr_slave_lock); - goto out; + break; } } + out: + if (res) { + /* no suitable interface, frame not sent */ + dev_kfree_skb(skb); + } read_unlock(&bond->lock); return 0; - -free_out: - /* no suitable interface, frame not sent */ - dev_kfree_skb(skb); - goto out; } /* @@ -3618,6 +4068,7 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_dev) { struct bonding *bond = bond_dev->priv; + int res = 1; /* if we are sending arp packets, try to at least identify our own ip address */ @@ -3634,26 +4085,21 @@ read_lock(&bond->curr_slave_lock); if (!BOND_IS_OK(bond)) { - goto free_out; + goto out; } if (bond->curr_active_slave) { /* one usable interface */ - skb->dev = bond->curr_active_slave->dev; - skb->priority = 1; - dev_queue_xmit(skb); - goto out; - } else { - goto free_out; + res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev); } + out: + if (res) { + /* no suitable interface, frame not sent */ + dev_kfree_skb(skb); + } read_unlock(&bond->curr_slave_lock); read_unlock(&bond->lock); return 0; - -free_out: - /* no suitable interface, frame not sent */ - dev_kfree_skb(skb); - goto out; } /* @@ -3668,11 +4114,12 @@ struct slave *slave, *start_at; int slave_no; int i; + int res = 1; read_lock(&bond->lock); if (!BOND_IS_OK(bond)) { - goto free_out; + goto out; } slave_no = (data->h_dest[5]^bond_dev->dev_addr[5]) % bond->slave_cnt; @@ -3690,22 +4137,18 @@ if (IS_UP(slave->dev) && (slave->link == BOND_LINK_UP) && (slave->state == BOND_STATE_ACTIVE)) { - skb->dev = slave->dev; - skb->priority = 1; - dev_queue_xmit(skb); - - goto out; + res = bond_dev_queue_xmit(bond, skb, slave->dev); + break; } } out: + if (res) { + /* no suitable interface, frame not sent */ + dev_kfree_skb(skb); + } read_unlock(&bond->lock); return 0; - -free_out: - /* no suitable interface, frame not sent */ - dev_kfree_skb(skb); - goto out; } /* @@ -3717,11 +4160,12 @@ struct slave *slave, *start_at; struct net_device *tx_dev = NULL; int i; + int res = 1; read_lock(&bond->lock); if (!BOND_IS_OK(bond)) { - goto free_out; + goto out; } read_lock(&bond->curr_slave_lock); @@ -3729,7 +4173,7 @@ read_unlock(&bond->curr_slave_lock); if (!start_at) { - goto free_out; + goto out; } bond_for_each_slave_from(bond, slave, i, start_at) { @@ -3745,31 +4189,28 @@ continue; } - skb2->dev = tx_dev; - skb2->priority = 1; - dev_queue_xmit(skb2); + res = bond_dev_queue_xmit(bond, skb2, tx_dev); + if (res) { + dev_kfree_skb(skb2); + continue; + } } tx_dev = slave->dev; } } if (tx_dev) { - skb->dev = tx_dev; - skb->priority = 1; - dev_queue_xmit(skb); - } else { - goto free_out; + res = bond_dev_queue_xmit(bond, skb, tx_dev); } out: + if (res) { + /* no suitable interface, frame not sent */ + dev_kfree_skb(skb); + } /* frame sent to all suitable interfaces */ read_unlock(&bond->lock); return 0; - -free_out: - /* no suitable interface, frame not sent */ - dev_kfree_skb(skb); - goto out; } #ifdef CONFIG_NET_FASTROUTE @@ -3838,6 +4279,7 @@ bond->current_arp_slave = NULL; bond->primary_slave = NULL; bond->dev = bond_dev; + INIT_LIST_HEAD(&bond->vlan_list); /* Initialize the device entry points */ bond_dev->open = bond_open; @@ -3858,6 +4300,25 @@ bond_dev->tx_queue_len = 0; bond_dev->flags |= IFF_MASTER|IFF_MULTICAST; + /* At first, we block adding VLANs. That's the only way to + * prevent problems that occur when adding VLANs over an + * empty bond. The block will be removed once non-challenged + * slaves are enslaved. + */ + bond_dev->features |= NETIF_F_VLAN_CHALLENGED; + + /* By default, we declare the bond to be fully + * VLAN hardware accelerated capable. Special + * care is taken in the various xmit functions + * when there are slaves that are not hw accel + * capable + */ + bond_dev->vlan_rx_register = bond_vlan_rx_register; + bond_dev->vlan_rx_add_vid = bond_vlan_rx_add_vid; + bond_dev->vlan_rx_kill_vid = bond_vlan_rx_kill_vid; + bond_dev->features |= (NETIF_F_HW_VLAN_TX | + NETIF_F_HW_VLAN_RX | + NETIF_F_HW_VLAN_FILTER); #ifdef CONFIG_PROC_FS bond_create_proc_entry(bond); diff -Nru a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h --- a/drivers/net/bonding/bonding.h Fri Mar 5 05:02:51 2004 +++ b/drivers/net/bonding/bonding.h Fri Mar 5 05:02:51 2004 @@ -36,8 +36,8 @@ #include "bond_3ad.h" #include "bond_alb.h" -#define DRV_VERSION "2.5.4" -#define DRV_RELDATE "December 30, 2003" +#define DRV_VERSION "2.6.0" +#define DRV_RELDATE "January 14, 2004" #define DRV_NAME "bonding" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" @@ -147,6 +147,11 @@ u32 arp_targets[BOND_MAX_ARP_TARGETS]; }; +struct vlan_entry { + struct list_head vlan_list; + unsigned short vlan_id; +}; + struct slave { struct net_device *dev; /* first - usefull for panic debug */ struct slave *next; @@ -196,6 +201,8 @@ struct ad_bond_info ad_info; struct alb_bond_info alb_info; struct bond_params params; + struct list_head vlan_list; + struct vlan_group *vlgrp; }; /** @@ -237,6 +244,9 @@ slave->state = BOND_STATE_ACTIVE; slave->dev->flags &= ~IFF_NOARP; } + +struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr); +int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev); #endif /* _LINUX_BONDING_H */ diff -Nru a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c --- a/drivers/net/ne2k-pci.c Fri Mar 5 05:02:51 2004 +++ b/drivers/net/ne2k-pci.c Fri Mar 5 05:02:51 2004 @@ -116,6 +116,7 @@ CH_Winbond_W89C940F, CH_Holtek_HT80232, CH_Holtek_HT80229, + CH_Winbond_89C940_8c4a, }; @@ -133,6 +134,7 @@ {"Winbond W89C940F", 0}, {"Holtek HT80232", ONLY_16BIT_IO | HOLTEK_FDX}, {"Holtek HT80229", ONLY_32BIT_IO | HOLTEK_FDX | STOP_PG_0x60 }, + {"Winbond W89C940(misprogrammed)", 0}, {0,} }; @@ -148,6 +150,7 @@ { 0x1050, 0x5a5a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Winbond_W89C940F }, { 0x12c3, 0x0058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Holtek_HT80232 }, { 0x12c3, 0x5598, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Holtek_HT80229 }, + { 0x8c4a, 0x1980, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Winbond_89C940_8c4a }, { 0, } }; MODULE_DEVICE_TABLE(pci, ne2k_pci_tbl); diff -Nru a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c --- a/drivers/net/pcnet32.c Fri Mar 5 05:02:51 2004 +++ b/drivers/net/pcnet32.c Fri Mar 5 05:02:51 2004 @@ -22,8 +22,8 @@ *************************************************************************/ #define DRV_NAME "pcnet32" -#define DRV_VERSION "1.27a" -#define DRV_RELDATE "10.02.2002" +#define DRV_VERSION "1.28" +#define DRV_RELDATE "02.20.2004" #define PFX DRV_NAME ": " static const char *version = @@ -61,6 +61,12 @@ static struct pci_device_id pcnet32_pci_tbl[] __devinitdata = { { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + /* + * Adapters that were sold with IBM's RS/6000 or pSeries hardware have + * the incorrect vendor id. + */ + { PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_AMD_LANCE, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, 0 }, { 0, } }; @@ -76,7 +82,7 @@ -static int pcnet32_debug = 1; +static int pcnet32_debug = 0; static int tx_start = 1; /* Mapping -- 0:20, 1:64, 2:128, 3:~220 (depends on chip vers) */ static int pcnet32vlb; /* check for VLB cards ? */ @@ -120,6 +126,11 @@ PCNET32_PORT_ASEL /* 15 not supported */ }; +static const char pcnet32_gstrings_test[][ETH_GSTRING_LEN] = { + "Loopback test (offline)" +}; +#define PCNET32_TEST_LEN (sizeof(pcnet32_gstrings_test) / ETH_GSTRING_LEN) + #define MAX_UNITS 8 /* More are supported, limit only on options */ static int options[MAX_UNITS]; static int full_duplex[MAX_UNITS]; @@ -212,6 +223,11 @@ * fix pci probe not increment cards_found * FD auto negotiate error workaround for xSeries250 * clean up and using new mii module + * v1.28 20 Feb 2004 Don Fry + * Jon Lewis , Chinmay Albal + * Now uses ethtool_ops, netif_msg_* and generic_mii_ioctl. + * Fixes bogus 'Bus master arbitration failure', pci_[un]map_single + * length errors, and transmit hangs. Cleans up after errors in open. */ @@ -319,6 +335,7 @@ mii:1; /* mii port available */ struct net_device *next; struct mii_if_info mii_if; + u32 msg_enable; /* debug message level */ }; static void pcnet32_probe_vlbus(void); @@ -336,6 +353,10 @@ static int pcnet32_ioctl(struct net_device *, struct ifreq *, int); static int mdio_read(struct net_device *dev, int phy_id, int reg_num); static void mdio_write(struct net_device *dev, int phy_id, int reg_num, int val); +static void pcnet32_restart(struct net_device *dev, unsigned int csr0_bits); +static void pcnet32_ethtool_test(struct net_device *dev, + struct ethtool_test *eth_test, u64 *data); +static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1); enum pci_flags_bit { PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, @@ -389,13 +410,13 @@ } static struct pcnet32_access pcnet32_wio = { - read_csr: pcnet32_wio_read_csr, - write_csr: pcnet32_wio_write_csr, - read_bcr: pcnet32_wio_read_bcr, - write_bcr: pcnet32_wio_write_bcr, - read_rap: pcnet32_wio_read_rap, - write_rap: pcnet32_wio_write_rap, - reset: pcnet32_wio_reset + .read_csr = pcnet32_wio_read_csr, + .write_csr = pcnet32_wio_write_csr, + .read_bcr = pcnet32_wio_read_bcr, + .write_bcr = pcnet32_wio_write_bcr, + .read_rap = pcnet32_wio_read_rap, + .write_rap = pcnet32_wio_write_rap, + .reset = pcnet32_wio_reset }; static u16 pcnet32_dwio_read_csr (unsigned long addr, int index) @@ -444,17 +465,283 @@ } static struct pcnet32_access pcnet32_dwio = { - read_csr: pcnet32_dwio_read_csr, - write_csr: pcnet32_dwio_write_csr, - read_bcr: pcnet32_dwio_read_bcr, - write_bcr: pcnet32_dwio_write_bcr, - read_rap: pcnet32_dwio_read_rap, - write_rap: pcnet32_dwio_write_rap, - reset: pcnet32_dwio_reset + .read_csr = pcnet32_dwio_read_csr, + .write_csr = pcnet32_dwio_write_csr, + .read_bcr = pcnet32_dwio_read_bcr, + .write_bcr = pcnet32_dwio_write_bcr, + .read_rap = pcnet32_dwio_read_rap, + .write_rap = pcnet32_dwio_write_rap, + .reset = pcnet32_dwio_reset }; +static int pcnet32_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct pcnet32_private *lp = dev->priv; + unsigned long flags; + int r = -EOPNOTSUPP; + + if (lp->mii) { + spin_lock_irqsave(&lp->lock, flags); + mii_ethtool_gset(&lp->mii_if, cmd); + spin_unlock_irqrestore(&lp->lock, flags); + r = 0; + } + return r; +} + +static int pcnet32_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct pcnet32_private *lp = dev->priv; + unsigned long flags; + int r = -EOPNOTSUPP; + + if (lp->mii) { + spin_lock_irqsave(&lp->lock, flags); + r = mii_ethtool_sset(&lp->mii_if, cmd); + spin_unlock_irqrestore(&lp->lock, flags); + } + return r; +} + +static void pcnet32_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct pcnet32_private *lp = dev->priv; + + strcpy (info->driver, DRV_NAME); + strcpy (info->version, DRV_VERSION); + if (lp->pci_dev) + strcpy (info->bus_info, pci_name(lp->pci_dev)); + else + sprintf(info->bus_info, "VLB 0x%lx", dev->base_addr); +} + +static u32 pcnet32_get_link(struct net_device *dev) +{ + struct pcnet32_private *lp = dev->priv; + unsigned long flags; + int r; + + spin_lock_irqsave(&lp->lock, flags); + if (lp->mii) { + r = mii_link_ok(&lp->mii_if); + } else { + ulong ioaddr = dev->base_addr; /* card base I/O address */ + r = (lp->a.read_bcr(ioaddr, 4) != 0xc0); + } + spin_unlock_irqrestore(&lp->lock, flags); + + return r; +} + +static u32 pcnet32_get_msglevel(struct net_device *dev) +{ + struct pcnet32_private *lp = dev->priv; + return lp->msg_enable; +} + +static void pcnet32_set_msglevel(struct net_device *dev, u32 value) +{ + struct pcnet32_private *lp = dev->priv; + lp->msg_enable = value; +} + +static int pcnet32_nway_reset(struct net_device *dev) +{ + struct pcnet32_private *lp = dev->priv; + unsigned long flags; + int r = -EOPNOTSUPP; + + if (lp->mii) { + spin_lock_irqsave(&lp->lock, flags); + r = mii_nway_restart(&lp->mii_if); + spin_unlock_irqrestore(&lp->lock, flags); + } + return r; +} + +static void pcnet32_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) +{ + struct pcnet32_private *lp = dev->priv; + + ering->tx_max_pending = TX_RING_SIZE - 1; + ering->tx_pending = lp->cur_tx - lp->dirty_tx; + ering->rx_max_pending = RX_RING_SIZE - 1; + ering->rx_pending = lp->cur_rx & RX_RING_MOD_MASK; +} + +static void pcnet32_get_strings(struct net_device *dev, u32 stringset, u8 *data) +{ + memcpy(data, pcnet32_gstrings_test, sizeof(pcnet32_gstrings_test)); +} + +static int pcnet32_self_test_count(struct net_device *dev) +{ + return PCNET32_TEST_LEN; +} + +static void pcnet32_ethtool_test(struct net_device *dev, + struct ethtool_test *test, u64 *data) +{ + struct pcnet32_private *lp = dev->priv; + int rc; + + if (test->flags == ETH_TEST_FL_OFFLINE) { + rc = pcnet32_loopback_test(dev, data); + if (rc) { + if (netif_msg_hw(lp)) + printk(KERN_DEBUG "%s: Loopback test failed.\n", dev->name); + test->flags |= ETH_TEST_FL_FAILED; + } else if (netif_msg_hw(lp)) + printk(KERN_DEBUG "%s: Loopback test passed.\n", dev->name); + } else + printk(KERN_DEBUG "%s: No tests to run (specify 'Offline' on ethtool).", dev->name); +} /* end pcnet32_ethtool_test */ + +static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1) +{ + struct pcnet32_private *lp = dev->priv; + struct pcnet32_access *a = &lp->a; /* access to registers */ + ulong ioaddr = dev->base_addr; /* card base I/O address */ + struct sk_buff *skb; /* sk buff */ + int x, y, i; /* counters */ + int numbuffs = 4; /* number of TX/RX buffers and descs */ + u16 status = 0x8300; /* TX ring status */ + int rc; /* return code */ + int size; /* size of packets */ + unsigned char *packet; /* source packet data */ + static int data_len = 60; /* length of source packets */ + unsigned long flags; + + *data1 = 1; /* status of test, default to fail */ + rc = 1; /* default to fail */ + + spin_lock_irqsave(&lp->lock, flags); + lp->a.write_csr(ioaddr, 0, 0x7904); + + netif_stop_queue(dev); + + /* purge & init rings but don't actually restart */ + pcnet32_restart(dev, 0x0000); + + lp->a.write_csr(ioaddr, 0, 0x0004); /* Set STOP bit */ + + x = a->read_bcr(ioaddr, 32); /* set internal loopback in BSR32 */ + x = x | 0x00000002; + a->write_bcr(ioaddr, 32, x); + + /* Initialize Transmit buffers. */ + size = data_len + 15; + for (x=0; xname, __LINE__); + goto clean_up; + } else { + packet = skb->data; + skb_put(skb, size); /* create space for data */ + lp->tx_skbuff[x] = skb; + lp->tx_ring[x].length = le16_to_cpu(-skb->len); + lp->tx_ring[x].misc = 0x00000000; + + /* put DA and SA into the skb */ + for (i=0; i<12; i++) + *packet++ = 0xff; + /* type */ + *packet++ = 0x08; + *packet++ = 0x06; + /* packet number */ + *packet++ = x; + /* fill packet with data */ + for (y=0; ytx_dma_addr[x] = pci_map_single(lp->pci_dev, skb->data, + skb->len, PCI_DMA_TODEVICE); + lp->tx_ring[x].base = (u32)le32_to_cpu(lp->tx_dma_addr[x]); + wmb(); /* Make sure owner changes after all others are visible */ + lp->tx_ring[x].status = le16_to_cpu(status); + } + } + + lp->a.write_csr(ioaddr, 0, 0x0002); /* Set STRT bit */ + spin_unlock_irqrestore(&lp->lock, flags); + + mdelay(50); /* wait a bit */ + + spin_lock_irqsave(&lp->lock, flags); + lp->a.write_csr(ioaddr, 0, 0x0004); /* Set STOP bit */ + + if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) { + printk(KERN_DEBUG "%s: RX loopback packets:\n", dev->name); + + for (x=0; xname, x); + skb=lp->rx_skbuff[x]; + for (i=0; idata+i)); + } + printk("\n"); + } + } + + x = 0; + rc = 0; + while (xrx_skbuff[x]; + packet = lp->tx_skbuff[x]->data; + for (i=0; idata+i) != packet[i]) { + if (netif_msg_hw(lp)) + printk(KERN_DEBUG "%s: Error in compare! %2x - %02x %02x\n", + dev->name, i, *(skb->data+i), packet[i]); + rc = 1; + break; + } + } + x++; + } + if (!rc) { + *data1 = 0; + } + +clean_up: + x = a->read_csr(ioaddr, 15) & 0xFFFF; + a->write_csr(ioaddr, 15, (x & ~0x0044)); /* reset bits 6 and 2 */ + + x = a->read_bcr(ioaddr, 32); /* reset internal loopback */ + x = x & ~0x00000002; + a->write_bcr(ioaddr, 32, x); + + pcnet32_restart(dev, 0x0042); /* resume normal operation */ + + netif_wake_queue(dev); + + /* Clear interrupts, and set interrupt enable. */ + lp->a.write_csr(ioaddr, 0, 0x7940); + spin_unlock_irqrestore(&lp->lock, flags); + + return(rc); +} /* end pcnet32_loopback_test */ + +static struct ethtool_ops pcnet32_ethtool_ops = { + .get_settings = pcnet32_get_settings, + .set_settings = pcnet32_set_settings, + .get_drvinfo = pcnet32_get_drvinfo, + .get_msglevel = pcnet32_get_msglevel, + .set_msglevel = pcnet32_set_msglevel, + .nway_reset = pcnet32_nway_reset, + .get_link = pcnet32_get_link, + .get_ringparam = pcnet32_get_ringparam, + .get_tx_csum = ethtool_op_get_tx_csum, + .get_sg = ethtool_op_get_sg, + .get_strings = pcnet32_get_strings, + .self_test_count = pcnet32_self_test_count, + .self_test = pcnet32_ethtool_test, +}; + /* only probes for non-PCI devices, the rest are handled by * pci_register_driver via pcnet32_probe_pci */ @@ -535,10 +822,12 @@ } chip_version = a->read_csr(ioaddr, 88) | (a->read_csr(ioaddr,89) << 16); - if (pcnet32_debug > 2) + if (pcnet32_debug & NETIF_MSG_PROBE) printk(KERN_INFO " PCnet chip version is %#x.\n", chip_version); - if ((chip_version & 0xfff) != 0x003) + if ((chip_version & 0xfff) != 0x003) { + printk(KERN_INFO PFX "Unsupported chip version.\n"); return -ENODEV; + } /* initialize variables */ fdx = mii = fset = dxsuflo = ltint = 0; @@ -589,7 +878,7 @@ media &= ~3; media |= 1; #endif - if (pcnet32_debug > 2) + if (pcnet32_debug & NETIF_MSG_PROBE) printk(KERN_DEBUG PFX "media reset to %#x.\n", media); a->write_bcr(ioaddr, 49, media); break; @@ -619,8 +908,10 @@ } dev = alloc_etherdev(0); - if(!dev) + if (!dev) { + printk(KERN_ERR PFX "Memory allocation failed.\n"); return -ENOMEM; + } printk(KERN_INFO PFX "%s at %#3lx,", chipname, ioaddr); @@ -693,6 +984,7 @@ /* pci_alloc_consistent returns page-aligned memory, so we do not have to check the alignment */ if ((lp = pci_alloc_consistent(pdev, sizeof(*lp), &lp_dma_addr)) == NULL) { + printk(KERN_ERR PFX "Consistent memory allocation failed.\n"); release_region(ioaddr, PCNET32_TOTAL_SIZE); return -ENOMEM; } @@ -707,9 +999,12 @@ lp->name = chipname; lp->shared_irq = shared; lp->mii_if.full_duplex = fdx; + lp->mii_if.phy_id_mask = 0x1f; + lp->mii_if.reg_num_mask = 0x1f; lp->dxsuflo = dxsuflo; lp->ltint = ltint; lp->mii = mii; + lp->msg_enable = pcnet32_debug; if ((cards_found >= MAX_UNITS) || (options[cards_found] > sizeof(options_mapping))) lp->options = PCNET32_PORT_ASEL; else @@ -778,6 +1073,9 @@ } } + /* Set the mii phy_id so that we can query the link state */ + if (lp->mii) + lp->mii_if.phy_id = ((lp->a.read_bcr (ioaddr, 33)) >> 5) & 0x1f; /* The PCNET32-specific entries in the device structure. */ dev->open = &pcnet32_open; @@ -786,11 +1084,16 @@ dev->get_stats = &pcnet32_get_stats; dev->set_multicast_list = &pcnet32_set_multicast_list; dev->do_ioctl = &pcnet32_ioctl; + dev->ethtool_ops = &pcnet32_ethtool_ops; dev->tx_timeout = pcnet32_tx_timeout; dev->watchdog_timeo = (5*HZ); - lp->next = pcnet32_dev; - pcnet32_dev = dev; + if (pdev) { + pci_set_drvdata(pdev, dev); + } else { + lp->next = pcnet32_dev; + pcnet32_dev = dev; + } /* Fill in the generic fields of the device structure. */ register_netdev(dev); @@ -807,6 +1110,7 @@ unsigned long ioaddr = dev->base_addr; u16 val; int i; + int rc; if (dev->irq == 0 || request_irq(dev->irq, &pcnet32_interrupt, @@ -815,8 +1119,10 @@ } /* Check for a valid station address */ - if( !is_valid_ether_addr(dev->dev_addr) ) - return -EINVAL; + if (!is_valid_ether_addr(dev->dev_addr)) { + rc = -EINVAL; + goto err_free_irq; + } /* Reset the PCNET32 */ lp->a.reset (ioaddr); @@ -824,7 +1130,7 @@ /* switch pcnet32 to 32bit mode */ lp->a.write_bcr (ioaddr, 20, 2); - if (pcnet32_debug > 1) + if (netif_msg_ifup(lp)) printk(KERN_DEBUG "%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.\n", dev->name, dev->irq, (u32) (lp->dma_addr + offsetof(struct pcnet32_private, tx_ring)), @@ -890,8 +1196,10 @@ lp->init_block.mode = le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7); lp->init_block.filter[0] = 0x00000000; lp->init_block.filter[1] = 0x00000000; - if (pcnet32_init_ring(dev)) - return -ENOMEM; + if (pcnet32_init_ring(dev)) { + rc = -ENOMEM; + goto err_free_ring; + } /* Re-initialize the PCNET32, and start it when done. */ lp->a.write_csr (ioaddr, 1, (lp->dma_addr + offsetof(struct pcnet32_private, init_block)) &0xffff); @@ -912,7 +1220,7 @@ */ lp->a.write_csr (ioaddr, 0, 0x0042); - if (pcnet32_debug > 2) + if (netif_msg_ifup(lp)) printk(KERN_DEBUG "%s: pcnet32 open after %d ticks, init block %#x csr0 %4.4x.\n", dev->name, i, (u32) (lp->dma_addr + offsetof(struct pcnet32_private, init_block)), lp->a.read_csr(ioaddr, 0)); @@ -921,6 +1229,28 @@ MOD_INC_USE_COUNT; return 0; /* Always succeed */ + +err_free_ring: + /* free any allocated skbuffs */ + for (i = 0; i < RX_RING_SIZE; i++) { + lp->rx_ring[i].status = 0; + if (lp->rx_skbuff[i]) { + pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], PKT_BUF_SZ-2, + PCI_DMA_FROMDEVICE); + dev_kfree_skb(lp->rx_skbuff[i]); + } + lp->rx_skbuff[i] = NULL; + lp->rx_dma_addr[i] = 0; + } + /* + * Switch back to 16bit mode to avoid problems with dumb + * DOS packet driver after a warm reboot + */ + lp->a.write_bcr (ioaddr, 20, 4); + +err_free_irq: + free_irq(dev->irq, dev); + return rc; } /* @@ -976,9 +1306,10 @@ } if (lp->rx_dma_addr[i] == 0) - lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev, rx_skbuff->tail, rx_skbuff->len, PCI_DMA_FROMDEVICE); + lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev, + rx_skbuff->tail, PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE); lp->rx_ring[i].base = (u32)le32_to_cpu(lp->rx_dma_addr[i]); - lp->rx_ring[i].buf_length = le16_to_cpu(-PKT_BUF_SZ); + lp->rx_ring[i].buf_length = le16_to_cpu(2-PKT_BUF_SZ); lp->rx_ring[i].status = le16_to_cpu(0x8000); } /* The Tx buffer address is filled in as needed, but we do need to clear @@ -988,6 +1319,7 @@ lp->tx_ring[i].status = 0; lp->tx_dma_addr[i] = 0; } + wmb(); /* Make sure all changes are visible */ lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS); for (i = 0; i < 6; i++) @@ -1031,7 +1363,7 @@ dev->name, lp->a.read_csr(ioaddr, 0)); lp->a.write_csr (ioaddr, 0, 0x0004); lp->stats.tx_errors++; - if (pcnet32_debug > 2) { + if (netif_msg_tx_err(lp)) { int i; printk(KERN_DEBUG " Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.", lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "", @@ -1049,7 +1381,7 @@ pcnet32_restart(dev, 0x0042); dev->trans_start = jiffies; - netif_start_queue(dev); + netif_wake_queue(dev); spin_unlock_irqrestore(&lp->lock, flags); } @@ -1064,7 +1396,7 @@ int entry; unsigned long flags; - if (pcnet32_debug > 3) { + if (netif_msg_tx_queued(lp)) { printk(KERN_DEBUG "%s: pcnet32_start_xmit() called, csr0 %4.4x.\n", dev->name, lp->a.read_csr(ioaddr, 0)); } @@ -1075,12 +1407,14 @@ * interrupt when that option is available to us. */ status = 0x8300; + entry = (lp->cur_tx - lp->dirty_tx) & TX_RING_MOD_MASK; if ((lp->ltint) && - ((lp->cur_tx - lp->dirty_tx == TX_RING_SIZE/2) || - (lp->cur_tx - lp->dirty_tx >= TX_RING_SIZE-2))) + ((entry == TX_RING_SIZE/3) || + (entry == (TX_RING_SIZE*2)/3) || + (entry >= TX_RING_SIZE-2))) { /* Enable Successful-TxDone interrupt if we have - * 1/2 of, or nearly all of, our ring buffer Tx'd + * 1/3, 2/3 or nearly all of, our ring buffer Tx'd * but not yet cleaned up. Thus, most of the time, * we will not enable Successful-TxDone interrupts. */ @@ -1092,7 +1426,7 @@ /* Mask to ring buffer boundary. */ entry = lp->cur_tx & TX_RING_MOD_MASK; - /* Caution: the write order is important here, set the base address + /* Caution: the write order is important here, set the status with the "ownership" bits last. */ lp->tx_ring[entry].length = le16_to_cpu(-skb->len); @@ -1113,9 +1447,7 @@ dev->trans_start = jiffies; - if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base == 0) - netif_start_queue(dev); - else { + if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base != 0) { lp->tx_full = 1; netif_stop_queue(dev); } @@ -1147,12 +1479,15 @@ rap = lp->a.read_rap(ioaddr); while ((csr0 = lp->a.read_csr (ioaddr, 0)) & 0x8600 && --boguscnt >= 0) { + if (csr0 == 0xffff) { + break; /* PCMCIA remove happened */ + } /* Acknowledge all of the current interrupt sources ASAP. */ lp->a.write_csr (ioaddr, 0, csr0 & ~0x004f); must_restart = 0; - if (pcnet32_debug > 5) + if (netif_msg_intr(lp)) printk(KERN_DEBUG "%s: interrupt csr0=%#2.2x new csr=%#2.2x.\n", dev->name, csr0, lp->a.read_csr (ioaddr, 0)); @@ -1161,8 +1496,9 @@ if (csr0 & 0x0200) { /* Tx-done interrupt */ unsigned int dirty_tx = lp->dirty_tx; + int delta; - while (dirty_tx < lp->cur_tx) { + while (dirty_tx != lp->cur_tx) { int entry = dirty_tx & TX_RING_MOD_MASK; int status = (short)le16_to_cpu(lp->tx_ring[entry].status); @@ -1216,15 +1552,17 @@ dirty_tx++; } - if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) { + delta = (lp->cur_tx - dirty_tx) & (TX_RING_MOD_MASK + TX_RING_SIZE); + if (delta >= TX_RING_SIZE) { printk(KERN_ERR "%s: out-of-sync dirty pointer, %d vs. %d, full=%d.\n", dev->name, dirty_tx, lp->cur_tx, lp->tx_full); dirty_tx += TX_RING_SIZE; + delta -= TX_RING_SIZE; } if (lp->tx_full && netif_queue_stopped(dev) && - dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) { + delta < TX_RING_SIZE - 2) { /* The ring is no longer full, clear tbusy. */ lp->tx_full = 0; netif_wake_queue (dev); @@ -1264,7 +1602,7 @@ lp->a.write_csr (ioaddr, 0, 0x7940); lp->a.write_rap (ioaddr,rap); - if (pcnet32_debug > 4) + if (netif_msg_intr(lp)) printk(KERN_DEBUG "%s: exiting interrupt, csr0=%#4.4x.\n", dev->name, lp->a.read_csr (ioaddr, 0)); @@ -1312,13 +1650,14 @@ if ((newskb = dev_alloc_skb (PKT_BUF_SZ))) { skb_reserve (newskb, 2); skb = lp->rx_skbuff[entry]; - pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[entry], skb->len, PCI_DMA_FROMDEVICE); + pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[entry], + PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE); skb_put (skb, pkt_len); lp->rx_skbuff[entry] = newskb; newskb->dev = dev; lp->rx_dma_addr[entry] = pci_map_single(lp->pci_dev, newskb->tail, - newskb->len, PCI_DMA_FROMDEVICE); + PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE); lp->rx_ring[entry].base = le32_to_cpu(lp->rx_dma_addr[entry]); rx_in_place = 1; } else @@ -1347,7 +1686,7 @@ skb_put(skb,pkt_len); /* Make room */ pci_dma_sync_single(lp->pci_dev, lp->rx_dma_addr[entry], - PKT_BUF_SZ, + PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE); eth_copy_and_sum(skb, (unsigned char *)(lp->rx_skbuff[entry]->tail), @@ -1364,7 +1703,8 @@ * The docs say that the buffer length isn't touched, but Andrew Boyd * of QNX reports that some revs of the 79C965 clear it. */ - lp->rx_ring[entry].buf_length = le16_to_cpu(-PKT_BUF_SZ); + lp->rx_ring[entry].buf_length = le16_to_cpu(2-PKT_BUF_SZ); + wmb(); /* Make sure owner changes after all others are visible */ lp->rx_ring[entry].status |= le16_to_cpu(0x8000); entry = (++lp->cur_rx) & RX_RING_MOD_MASK; } @@ -1383,7 +1723,7 @@ lp->stats.rx_missed_errors = lp->a.read_csr (ioaddr, 112); - if (pcnet32_debug > 1) + if (netif_msg_ifdown(lp)) printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", dev->name, lp->a.read_csr (ioaddr, 0)); @@ -1402,7 +1742,8 @@ for (i = 0; i < RX_RING_SIZE; i++) { lp->rx_ring[i].status = 0; if (lp->rx_skbuff[i]) { - pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], lp->rx_skbuff[i]->len, PCI_DMA_FROMDEVICE); + pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], PKT_BUF_SZ-2, + PCI_DMA_FROMDEVICE); dev_kfree_skb(lp->rx_skbuff[i]); } lp->rx_skbuff[i] = NULL; @@ -1472,7 +1813,9 @@ crc = ether_crc_le(6, addrs); crc = crc >> 26; - mcast_table [crc >> 4] |= cpu_to_le16(1 << (crc & 0xf)); + mcast_table [crc >> 4] = le16_to_cpu( + le16_to_cpu(mcast_table [crc >> 4]) | (1 << (crc & 0xf)) + ); } return; } @@ -1537,136 +1880,49 @@ lp->a.write_bcr(ioaddr, 33, phyaddr); } -static int pcnet32_ethtool_ioctl (struct net_device *dev, void *useraddr) +static int pcnet32_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - struct pcnet32_private *lp = dev->priv; - u32 ethcmd; - int phyaddr = 0; - int phy_id = 0; - unsigned long ioaddr = dev->base_addr; - - if (lp->mii) { - phyaddr = lp->a.read_bcr (ioaddr, 33); - phy_id = (phyaddr >> 5) & 0x1f; - lp->mii_if.phy_id = phy_id; - } - - if (copy_from_user (ðcmd, useraddr, sizeof (ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strcpy (info.driver, DRV_NAME); - strcpy (info.version, DRV_VERSION); - if (lp->pci_dev) - strcpy (info.bus_info, lp->pci_dev->slot_name); - else - sprintf(info.bus_info, "VLB 0x%lx", dev->base_addr); - if (copy_to_user (useraddr, &info, sizeof (info))) - return -EFAULT; - return 0; - } - - /* get settings */ - case ETHTOOL_GSET: { - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; - spin_lock_irq(&lp->lock); - mii_ethtool_gset(&lp->mii_if, &ecmd); - spin_unlock_irq(&lp->lock); - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - /* set settings */ - case ETHTOOL_SSET: { - int r; - struct ethtool_cmd ecmd; - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; - spin_lock_irq(&lp->lock); - r = mii_ethtool_sset(&lp->mii_if, &ecmd); - spin_unlock_irq(&lp->lock); - return r; - } - /* restart autonegotiation */ - case ETHTOOL_NWAY_RST: { - return mii_nway_restart(&lp->mii_if); - } - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = {ETHTOOL_GLINK}; - edata.data = mii_link_ok(&lp->mii_if); - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } + struct pcnet32_private *lp = dev->priv; + struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data; + int rc; + unsigned long flags; - /* get message-level */ - case ETHTOOL_GMSGLVL: { - struct ethtool_value edata = {ETHTOOL_GMSGLVL}; - edata.data = pcnet32_debug; - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - /* set message-level */ - case ETHTOOL_SMSGLVL: { - struct ethtool_value edata; - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - pcnet32_debug = edata.data; - return 0; - } - default: - break; - } + /* SIOC[GS]MIIxxx ioctls */ + if (lp->mii) { + spin_lock_irqsave(&lp->lock, flags); + rc = generic_mii_ioctl(&lp->mii_if, data, cmd, NULL); + spin_unlock_irqrestore(&lp->lock, flags); + } else { + rc = -EOPNOTSUPP; + } - return -EOPNOTSUPP; + return rc; } -static int pcnet32_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +static void __devexit pcnet32_remove_one(struct pci_dev *pdev) { - unsigned long ioaddr = dev->base_addr; - struct pcnet32_private *lp = dev->priv; - struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data; - int phyaddr = lp->a.read_bcr (ioaddr, 33); + struct net_device *dev = pci_get_drvdata(pdev); - if (cmd == SIOCETHTOOL) - return pcnet32_ethtool_ioctl(dev, (void *) rq->ifr_data); + if (dev) { + struct pcnet32_private *lp = dev->priv; - if (lp->mii) { - switch(cmd) { - case SIOCGMIIPHY: /* Get address of MII PHY in use. */ - data->phy_id = (phyaddr >> 5) & 0x1f; - /* Fall Through */ - case SIOCGMIIREG: /* Read MII PHY register. */ - lp->a.write_bcr (ioaddr, 33, ((data->phy_id & 0x1f) << 5) | (data->reg_num & 0x1f)); - data->val_out = lp->a.read_bcr (ioaddr, 34); - lp->a.write_bcr (ioaddr, 33, phyaddr); - return 0; - case SIOCSMIIREG: /* Write MII PHY register. */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - lp->a.write_bcr (ioaddr, 33, ((data->phy_id & 0x1f) << 5) | (data->reg_num & 0x1f)); - lp->a.write_bcr (ioaddr, 34, data->val_in); - lp->a.write_bcr (ioaddr, 33, phyaddr); - return 0; - default: - return -EOPNOTSUPP; - } + unregister_netdev(dev); + release_region(dev->base_addr, PCNET32_TOTAL_SIZE); + pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); + free_netdev(dev); + pci_set_drvdata(pdev, NULL); } - return -EOPNOTSUPP; } static struct pci_driver pcnet32_driver = { - name: DRV_NAME, - probe: pcnet32_probe_pci, - id_table: pcnet32_pci_tbl, + .name = DRV_NAME, + .probe = pcnet32_probe_pci, + .remove = __devexit_p(pcnet32_remove_one), + .id_table = pcnet32_pci_tbl, }; MODULE_PARM(debug, "i"); -MODULE_PARM_DESC(debug, DRV_NAME " debug level (0-6)"); +MODULE_PARM_DESC(debug, DRV_NAME " debug level"); MODULE_PARM(max_interrupt_work, "i"); MODULE_PARM_DESC(max_interrupt_work, DRV_NAME " maximum events handled per interrupt"); MODULE_PARM(rx_copybreak, "i"); @@ -1687,19 +1943,21 @@ /* An additional parameter that may be passed in... */ static int debug = -1; static int tx_start_pt = -1; +static int pcnet32_have_pci; static int __init pcnet32_init_module(void) { printk(KERN_INFO "%s", version); - if (debug > 0) - pcnet32_debug = debug; + if (debug >= 0 && debug < (sizeof(int) - 1)) + pcnet32_debug = 1 << debug; if ((tx_start_pt >= 0) && (tx_start_pt <= 3)) tx_start = tx_start_pt; /* find the PCI devices */ - pci_module_init(&pcnet32_driver); + if (!pci_module_init(&pcnet32_driver)) + pcnet32_have_pci = 1; /* should we find any remaining VLbus devices ? */ if (pcnet32vlb) @@ -1708,7 +1966,7 @@ if (cards_found) printk(KERN_INFO PFX "%d cards_found.\n", cards_found); - return cards_found ? 0 : -ENODEV; + return (pcnet32_have_pci + cards_found) ? 0 : -ENODEV; } static void __exit pcnet32_cleanup_module(void) @@ -1721,12 +1979,12 @@ next_dev = lp->next; unregister_netdev(pcnet32_dev); release_region(pcnet32_dev->base_addr, PCNET32_TOTAL_SIZE); - if (lp->pci_dev) - pci_unregister_driver(&pcnet32_driver); pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); - kfree(pcnet32_dev); + free_netdev(pcnet32_dev); pcnet32_dev = next_dev; } + if (pcnet32_have_pci) + pci_unregister_driver(&pcnet32_driver); } module_init(pcnet32_init_module); diff -Nru a/drivers/net/r8169.c b/drivers/net/r8169.c --- a/drivers/net/r8169.c Fri Mar 5 05:02:51 2004 +++ b/drivers/net/r8169.c Fri Mar 5 05:02:51 2004 @@ -874,7 +874,6 @@ void *ioaddr) { unsigned long dirty_tx, tx_left = 0; - int entry = tp->cur_tx % NUM_TX_DESC; assert(dev != NULL); assert(tp != NULL); @@ -884,14 +883,18 @@ tx_left = tp->cur_tx - dirty_tx; while (tx_left > 0) { + int entry = dirty_tx % NUM_TX_DESC; + if ((tp->TxDescArray[entry].status & OWNbit) == 0) { - dev_kfree_skb_irq(tp-> - Tx_skbuff[dirty_tx % NUM_TX_DESC]); - tp->Tx_skbuff[dirty_tx % NUM_TX_DESC] = NULL; + struct sk_buff *skb = tp->Tx_skbuff[entry]; + + tp->stats.tx_bytes += skb->len >= ETH_ZLEN ? + skb->len : ETH_ZLEN; tp->stats.tx_packets++; + dev_kfree_skb_irq(skb); + tp->Tx_skbuff[entry] = NULL; dirty_tx++; tx_left--; - entry++; } } diff -Nru a/drivers/net/sungem.c b/drivers/net/sungem.c --- a/drivers/net/sungem.c Fri Mar 5 05:02:52 2004 +++ b/drivers/net/sungem.c Fri Mar 5 05:02:52 2004 @@ -677,6 +677,7 @@ static void gem_rx(struct gem *gp) { int entry, drops; + u32 done; if (netif_msg_intr(gp)) printk(KERN_DEBUG "%s: rx interrupt, done: %d, rx_new: %d\n", @@ -684,6 +685,7 @@ entry = gp->rx_new; drops = 0; + done = readl(gp->regs + RXDMA_DONE); for (;;) { struct gem_rxd *rxd = &gp->init_block->rxd[entry]; struct sk_buff *skb; @@ -693,6 +695,19 @@ if ((status & RXDCTRL_OWN) != 0) break; + + /* When writing back RX descriptor, GEM writes status + * then buffer address, possibly in seperate transactions. + * If we don't wait for the chip to write both, we could + * post a new buffer to this descriptor then have GEM spam + * on the buffer address. We sync on the RX completion + * register to prevent this from happening. + */ + if (entry == done) { + done = readl(gp->regs + RXDMA_DONE); + if (entry == done) + break; + } skb = gp->rx_skbs[entry]; diff -Nru a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c --- a/drivers/net/tulip/tulip_core.c Fri Mar 5 05:02:51 2004 +++ b/drivers/net/tulip/tulip_core.c Fri Mar 5 05:02:51 2004 @@ -579,7 +579,7 @@ dev->if_port = 2 - dev->if_port; } else dev->if_port = 0; - else + else if (dev->if_port != 0 || (csr12 & 0x0004) != 0) dev->if_port = 1; tulip_select_media(dev, 0); } diff -Nru a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c --- a/drivers/video/pm3fb.c Fri Mar 5 05:02:51 2004 +++ b/drivers/video/pm3fb.c Fri Mar 5 05:02:51 2004 @@ -19,6 +19,7 @@ * $Header: /cvsroot/linux/drivers/video/pm3fb.c,v 1.1 2002/02/25 19:11:06 marcelo Exp $ * * CHANGELOG: + * Wed Nov 13 11:19:34 MET 2002, v 1.4.11C: option flatpanel: wasn't available in module, fixed. * Mon Feb 11 10:35:48 MET 2002, v 1.4.11B: Cosmetic update. * Wed Jan 23 14:16:59 MET 2002, v 1.4.11: Preliminary 2.5.x support, patch for 2.5.2. * Wed Nov 28 11:08:29 MET 2001, v 1.4.10: potential bug fix for SDRAM-based board, patch for 2.4.16. @@ -3756,6 +3757,8 @@ MODULE_PARM_DESC(printtimings, "print the memory timings of the card(s)"); MODULE_PARM(forcesize, PM3_MAX_BOARD_MODULE_ARRAY_SHORT); MODULE_PARM_DESC(forcesize, "force specified memory size"); +MODULE_PARM(flatpanel, PM3_MAX_BOARD_MODULE_ARRAY_SHORT); +MODULE_PARM_DESC(flatpanel, "flatpanel (LCD) support (preliminary)"); /* MODULE_SUPPORTED_DEVICE("Permedia3 PCI boards") MODULE_GENERIC_TABLE(gtype,name) @@ -3798,6 +3801,11 @@ if (depth[i]) { sprintf(ts, ",depth:%d:%d", i, depth[i]); + strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options)); + } + if (flatpanel[i]) + { + sprintf(ts, ",flatpanel:%d:", i); strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options)); } } diff -Nru a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c --- a/drivers/video/radeonfb.c Fri Mar 5 05:02:52 2004 +++ b/drivers/video/radeonfb.c Fri Mar 5 05:02:52 2004 @@ -202,6 +202,8 @@ RADEON_If, RADEON_Ig, RADEON_Y_, + RADEON_Ya, + RADEON_Yd, RADEON_Ld, RADEON_Le, RADEON_Lf, @@ -261,6 +263,8 @@ { "9000 If", RADEON_RV250 }, { "9000 Ig", RADEON_RV250 }, { "9200 Y", RADEON_RV280 }, + { "9200 Ya", RADEON_RV280 }, + { "9200 Yd", RADEON_RV280 }, { "M9 Ld", RADEON_M9 }, { "M9 Le", RADEON_M9 }, { "M9 Lf", RADEON_M9 }, @@ -326,6 +330,8 @@ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NH, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NH}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NI, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NI}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Y_, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Y_}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ya, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Ya}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Yd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Yd}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_AD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_AD}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_AP, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_AP}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_AR, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_AR}, diff -Nru a/fs/devfs/base.c b/fs/devfs/base.c --- a/fs/devfs/base.c Fri Mar 5 05:02:51 2004 +++ b/fs/devfs/base.c Fri Mar 5 05:02:51 2004 @@ -3549,7 +3549,7 @@ int err; if ( !(boot_options & OPTION_MOUNT) ) return; - err = do_mount ("none", "/dev", "devfs", 0, ""); + err = do_mount ("none", "/dev", "devfs", 0, NULL); if (err == 0) printk (KERN_INFO "Mounted devfs on /dev\n"); else PRINTK ("(): unable to mount devfs, err: %d\n", err); } /* End Function mount_devfs_fs */ diff -Nru a/fs/xfs/Makefile b/fs/xfs/Makefile --- a/fs/xfs/Makefile Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/Makefile Fri Mar 5 05:02:51 2004 @@ -108,7 +108,9 @@ xfs_vfsops.o \ xfs_vnodeops.o \ xfs_refcache.o \ - xfs_rw.o + xfs_rw.o \ + xfs_dmops.o \ + xfs_qmops.o # Objects not built in this directory obj-y += linux/linux_xfs.o \ @@ -119,15 +121,11 @@ ifeq ($(CONFIG_XFS_DMAPI),y) subdir-$(CONFIG_XFS_FS) += dmapi obj-y += dmapi/xfs_dmapi.o -else - obj-y += xfs_dmops.o endif ifeq ($(CONFIG_XFS_QUOTA),y) subdir-$(CONFIG_XFS_FS) += quota obj-y += quota/xfs_quota.o -else - obj-y += xfs_qmops.o endif include $(TOPDIR)/Rules.make diff -Nru a/fs/xfs/linux/kmem.h b/fs/xfs/linux/kmem.h --- a/fs/xfs/linux/kmem.h Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/linux/kmem.h Fri Mar 5 05:02:51 2004 @@ -59,6 +59,12 @@ current->flags |= PF_FSTRANS; \ } while (0) +#define PFLAGS_CLEAR_FSTRANS(STATEP) do { \ + *(STATEP) = current->flags; \ + current->flags &= ~PF_FSTRANS; \ +} while (0) + + #define PFLAGS_RESTORE(STATEP) do { \ current->flags = *(STATEP); \ } while (0) diff -Nru a/fs/xfs/linux/xfs_aops.c b/fs/xfs/linux/xfs_aops.c --- a/fs/xfs/linux/xfs_aops.c Fri Mar 5 05:02:52 2004 +++ b/fs/xfs/linux/xfs_aops.c Fri Mar 5 05:02:52 2004 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -54,8 +54,54 @@ #include "xfs_iomap.h" #include -STATIC void convert_page(struct inode *, struct page *, - xfs_iomap_t *, void *, int, int); +STATIC void xfs_count_page_state(struct page *, int *, int *, int *); +STATIC void xfs_convert_page(struct inode *, struct page *, + xfs_iomap_t *, void *, int, int); + +#if defined(XFS_RW_TRACE) +void +xfs_page_trace( + int tag, + struct inode *inode, + struct page *page, + int mask) +{ + xfs_inode_t *ip; + bhv_desc_t *bdp; + vnode_t *vp = LINVFS_GET_VP(inode); + loff_t isize = i_size_read(inode); + loff_t offset = page->index << PAGE_CACHE_SHIFT; + int delalloc = -1, unmapped = -1, unwritten = -1; + + if (page_has_buffers(page)) + xfs_count_page_state(page, &delalloc, &unmapped, &unwritten); + + bdp = vn_bhv_lookup(VN_BHV_HEAD(vp), &xfs_vnodeops); + ip = XFS_BHVTOI(bdp); + if (!ip->i_rwtrace) + return; + + ktrace_enter(ip->i_rwtrace, + (void *)((unsigned long)tag), + (void *)ip, + (void *)inode, + (void *)page, + (void *)((unsigned long)mask), + (void *)((unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff)), + (void *)((unsigned long)(ip->i_d.di_size & 0xffffffff)), + (void *)((unsigned long)((isize >> 32) & 0xffffffff)), + (void *)((unsigned long)(isize & 0xffffffff)), + (void *)((unsigned long)((offset >> 32) & 0xffffffff)), + (void *)((unsigned long)(offset & 0xffffffff)), + (void *)((unsigned long)delalloc), + (void *)((unsigned long)unmapped), + (void *)((unsigned long)unwritten), + (void *)NULL, + (void *)NULL); +} +#else +#define xfs_page_trace(tag, inode, page, mask) +#endif void linvfs_unwritten_done( @@ -97,7 +143,7 @@ } STATIC int -map_blocks( +xfs_map_blocks( struct inode *inode, loff_t offset, ssize_t count, @@ -127,12 +173,11 @@ } /* - * match_offset_to_mapping * Finds the corresponding mapping in block @map array of the * given @offset within a @page. */ STATIC xfs_iomap_t * -match_offset_to_mapping( +xfs_offset_to_map( struct page *page, xfs_iomap_t *iomapp, unsigned long offset) @@ -153,7 +198,7 @@ } STATIC void -map_buffer_at_offset( +xfs_map_at_offset( struct page *page, struct buffer_head *bh, unsigned long offset, @@ -194,7 +239,7 @@ * in units of filesystem blocks. */ STATIC struct page * -probe_unwritten_page( +xfs_probe_unwritten_page( struct address_space *mapping, unsigned long index, xfs_iomap_t *iomapp, @@ -218,11 +263,11 @@ do { if (!buffer_unwritten(bh)) break; - if (!match_offset_to_mapping(page, iomapp, p_offset)) + if (!xfs_offset_to_map(page, iomapp, p_offset)) break; if (p_offset >= max_offset) break; - map_buffer_at_offset(page, bh, p_offset, bbits, iomapp); + xfs_map_at_offset(page, bh, p_offset, bbits, iomapp); set_buffer_unwritten_io(bh); bh->b_private = pb; p_offset += bh->b_size; @@ -242,7 +287,7 @@ * yet - clustering for mmap write case. */ STATIC unsigned int -probe_unmapped_page( +xfs_probe_unmapped_page( struct address_space *mapping, unsigned long index, unsigned int pg_offset) @@ -275,7 +320,7 @@ } STATIC unsigned int -probe_unmapped_cluster( +xfs_probe_unmapped_cluster( struct inode *inode, struct page *startpage, struct buffer_head *bh, @@ -300,7 +345,7 @@ /* Prune this back to avoid pathological behavior */ tloff = min(tlast, startpage->index + 64); for (tindex = startpage->index + 1; tindex < tloff; tindex++) { - len = probe_unmapped_page(mapping, tindex, + len = xfs_probe_unmapped_page(mapping, tindex, PAGE_CACHE_SIZE); if (!len) return total; @@ -308,7 +353,8 @@ } if (tindex == tlast && (tloff = i_size_read(inode) & (PAGE_CACHE_SIZE - 1))) { - total += probe_unmapped_page(mapping, tindex, tloff); + total += xfs_probe_unmapped_page(mapping, + tindex, tloff); } } return total; @@ -320,7 +366,7 @@ * reference count. */ STATIC struct page * -probe_delalloc_page( +xfs_probe_delalloc_page( struct inode *inode, unsigned long index) { @@ -353,7 +399,7 @@ } STATIC int -map_unwritten( +xfs_map_unwritten( struct inode *inode, struct page *start_page, struct buffer_head *head, @@ -401,22 +447,16 @@ do { if (!buffer_unwritten(bh)) break; - tmp = match_offset_to_mapping(start_page, iomapp, p_offset); + tmp = xfs_offset_to_map(start_page, iomapp, p_offset); if (!tmp) break; - map_buffer_at_offset(start_page, bh, p_offset, block_bits, iomapp); + xfs_map_at_offset(start_page, bh, p_offset, block_bits, iomapp); set_buffer_unwritten_io(bh); bh->b_private = pb; p_offset += bh->b_size; nblocks++; } while ((bh = bh->b_this_page) != head); - if (unlikely(nblocks == 0)) { - printk("XFS: bad unwritten extent map: bh=0x%p, iomapp=0x%p\n", - curr, iomapp); - BUG(); - } - atomic_add(nblocks, &pb->pb_io_remaining); /* If we reached the end of the page, map forwards in any @@ -432,13 +472,15 @@ tloff = (iomapp->iomap_offset + iomapp->iomap_bsize) >> PAGE_CACHE_SHIFT; tloff = min(tlast, tloff); for (tindex = start_page->index + 1; tindex < tloff; tindex++) { - page = probe_unwritten_page(mapping, tindex, iomapp, pb, + page = xfs_probe_unwritten_page(mapping, + tindex, iomapp, pb, PAGE_CACHE_SIZE, &bs, bbits); if (!page) break; nblocks += bs; atomic_add(bs, &pb->pb_io_remaining); - convert_page(inode, page, iomapp, pb, startio, all_bh); + xfs_convert_page(inode, page, iomapp, pb, + startio, all_bh); /* stop if converting the next page might add * enough blocks that the corresponding byte * count won't fit in our ulong page buf length */ @@ -448,12 +490,14 @@ if (tindex == tlast && (tloff = (i_size_read(inode) & (PAGE_CACHE_SIZE - 1)))) { - page = probe_unwritten_page(mapping, tindex, iomapp, pb, + page = xfs_probe_unwritten_page(mapping, + tindex, iomapp, pb, tloff, &bs, bbits); if (page) { nblocks += bs; atomic_add(bs, &pb->pb_io_remaining); - convert_page(inode, page, iomapp, pb, startio, all_bh); + xfs_convert_page(inode, page, iomapp, pb, + startio, all_bh); if (nblocks >= ((ULONG_MAX - PAGE_SIZE) >> block_bits)) goto enough; } @@ -480,7 +524,7 @@ } STATIC void -submit_page( +xfs_submit_page( struct page *page, struct buffer_head *bh_arr[], int cnt) @@ -511,7 +555,7 @@ * that the page has no mapping at all. */ STATIC void -convert_page( +xfs_convert_page( struct inode *inode, struct page *page, xfs_iomap_t *iomapp, @@ -544,7 +588,7 @@ } continue; } - tmp = match_offset_to_mapping(page, mp, offset); + tmp = xfs_offset_to_map(page, mp, offset); if (!tmp) continue; ASSERT(!(tmp->iomap_flags & IOMAP_HOLE)); @@ -556,10 +600,10 @@ */ if (buffer_unwritten(bh) && !bh->b_end_io) { ASSERT(tmp->iomap_flags & IOMAP_UNWRITTEN); - map_unwritten(inode, page, head, bh, + xfs_map_unwritten(inode, page, head, bh, offset, bbits, tmp, startio, all_bh); } else if (! (buffer_unwritten(bh) && buffer_locked(bh))) { - map_buffer_at_offset(page, bh, offset, bbits, tmp); + xfs_map_at_offset(page, bh, offset, bbits, tmp); if (buffer_unwritten(bh)) { set_buffer_unwritten_io(bh); bh->b_private = private; @@ -575,7 +619,7 @@ } while (i++, (bh = bh->b_this_page) != head); if (startio) { - submit_page(page, bh_arr, index); + xfs_submit_page(page, bh_arr, index); } else { unlock_page(page); } @@ -586,7 +630,7 @@ * by mp and following the start page. */ STATIC void -cluster_write( +xfs_cluster_write( struct inode *inode, unsigned long tindex, xfs_iomap_t *iomapp, @@ -598,10 +642,10 @@ tlast = (iomapp->iomap_offset + iomapp->iomap_bsize) >> PAGE_CACHE_SHIFT; for (; tindex < tlast; tindex++) { - page = probe_delalloc_page(inode, tindex); + page = xfs_probe_delalloc_page(inode, tindex); if (!page) break; - convert_page(inode, page, iomapp, NULL, startio, all_bh); + xfs_convert_page(inode, page, iomapp, NULL, startio, all_bh); } } @@ -625,7 +669,7 @@ */ STATIC int -page_state_convert( +xfs_page_state_convert( struct inode *inode, struct page *page, int startio, @@ -668,7 +712,7 @@ continue; if (iomp) { - iomp = match_offset_to_mapping(page, &iomap, p_offset); + iomp = xfs_offset_to_map(page, &iomap, p_offset); } /* @@ -677,17 +721,17 @@ */ if (buffer_unwritten(bh)) { if (!iomp) { - err = map_blocks(inode, offset, len, &iomap, + err = xfs_map_blocks(inode, offset, len, &iomap, BMAPI_READ|BMAPI_IGNSTATE); if (err) { goto error; } - iomp = match_offset_to_mapping(page, &iomap, + iomp = xfs_offset_to_map(page, &iomap, p_offset); } - if (iomp) { + if (iomp && startio) { if (!bh->b_end_io) { - err = map_unwritten(inode, page, + err = xfs_map_unwritten(inode, page, head, bh, p_offset, inode->i_blkbits, iomp, startio, unmapped); @@ -695,12 +739,7 @@ goto error; } } - if (startio) { - bh_arr[cnt++] = bh; - } else { - unlock_buffer(bh); - mark_buffer_dirty(bh); - } + bh_arr[cnt++] = bh; page_dirty = 0; } /* @@ -709,17 +748,17 @@ */ } else if (buffer_delay(bh)) { if (!iomp) { - err = map_blocks(inode, offset, len, &iomap, - BMAPI_ALLOCATE | flags); + err = xfs_map_blocks(inode, offset, len, &iomap, + BMAPI_ALLOCATE | flags); if (err) { goto error; } - iomp = match_offset_to_mapping(page, &iomap, + iomp = xfs_offset_to_map(page, &iomap, p_offset); } if (iomp) { - map_buffer_at_offset(page, bh, p_offset, - inode->i_blkbits, iomp); + xfs_map_at_offset(page, bh, p_offset, + inode->i_blkbits, iomp); if (startio) { bh_arr[cnt++] = bh; } else { @@ -740,19 +779,19 @@ * need to write the whole page out. */ if (!iomp) { - size = probe_unmapped_cluster( + size = xfs_probe_unmapped_cluster( inode, page, bh, head); - err = map_blocks(inode, offset, - size, &iomap, - BMAPI_WRITE | BMAPI_MMAP); + err = xfs_map_blocks(inode, offset, + size, &iomap, + BMAPI_WRITE|BMAPI_MMAP); if (err) { goto error; } - iomp = match_offset_to_mapping(page, &iomap, + iomp = xfs_offset_to_map(page, &iomap, p_offset); } if (iomp) { - map_buffer_at_offset(page, + xfs_map_at_offset(page, bh, p_offset, inode->i_blkbits, iomp); if (startio) { @@ -778,10 +817,10 @@ SetPageUptodate(page); if (startio) - submit_page(page, bh_arr, cnt); + xfs_submit_page(page, bh_arr, cnt); if (iomp) - cluster_write(inode, page->index + 1, iomp, startio, unmapped); + xfs_cluster_write(inode, page->index + 1, iomp, startio, unmapped); return page_dirty; @@ -841,9 +880,9 @@ loff_t delta; /* For unwritten extents do not report a disk address on - * the read case. + * the read case (treat as if we're reading into a hole). */ - if (create || ((iomap.iomap_flags & IOMAP_UNWRITTEN) == 0)) { + if (create || !(iomap.iomap_flags & IOMAP_UNWRITTEN)) { delta = offset - iomap.iomap_offset; delta >>= inode->i_blkbits; @@ -853,10 +892,7 @@ bh_result->b_blocknr = bn; set_buffer_mapped(bh_result); } - if (iomap.iomap_flags & IOMAP_UNWRITTEN) { - if (create) { - set_buffer_mapped(bh_result); - } + if (create && (iomap.iomap_flags & IOMAP_UNWRITTEN)) { set_buffer_unwritten(bh_result); set_buffer_delay(bh_result); } @@ -946,7 +982,7 @@ } STATIC void -count_page_state( +xfs_count_page_state( struct page *page, int *delalloc, int *unmapped, @@ -998,13 +1034,15 @@ int need_trans; int delalloc, unmapped, unwritten; struct inode *inode = page->mapping->host; - xfs_pflags_t pflags; + xfs_pflags_t pflags; + + xfs_page_trace(XFS_WRITEPAGE_ENTER, inode, page, 0); /* * We need a transaction if: * 1. There are delalloc buffers on the page - * 2. The page is upto date and we have unmapped buffers - * 3. The page is upto date and we have no buffers + * 2. The page is uptodate and we have unmapped buffers + * 3. The page is uptodate and we have no buffers * 4. There are unwritten buffers on the page */ @@ -1012,7 +1050,7 @@ unmapped = 1; need_trans = 1; } else { - count_page_state(page, &delalloc, &unmapped, &unwritten); + xfs_count_page_state(page, &delalloc, &unmapped, &unwritten); if (!PageUptodate(page)) unmapped = 0; need_trans = delalloc + unmapped + unwritten; @@ -1041,7 +1079,7 @@ */ if (need_trans) PFLAGS_SET_NOIO(&pflags); - error = page_state_convert(inode, page, 1, unmapped); + error = xfs_page_state_convert(inode, page, 1, unmapped); if (need_trans) PFLAGS_RESTORE(&pflags); if (error == -EAGAIN) @@ -1085,22 +1123,31 @@ int gfp_mask) { struct inode *inode = page->mapping->host; - int delalloc, unmapped, unwritten; + int dirty, delalloc, unmapped, unwritten; + + xfs_page_trace(XFS_RELEASEPAGE_ENTER, inode, page, gfp_mask); - count_page_state(page, &delalloc, &unmapped, &unwritten); + xfs_count_page_state(page, &delalloc, &unmapped, &unwritten); if (!delalloc && !unwritten) return 1; if (!(gfp_mask & __GFP_FS)) return 0; + /* If we are already inside a transaction or the thread cannot + * do I/O, we cannot release this page. + */ + if (PFLAGS_TEST_FSTRANS() || PFLAGS_TEST_NOIO()) + return 0; + /* * Convert delalloc space to real space, do not flush the * data out to disk, that will be done by the caller. * Never need to allocate space here - we will always * come back to writepage in that case. */ - return (page_state_convert(inode, page, 0, 0) == 0) ? 1 : 0; + dirty = xfs_page_state_convert(inode, page, 0, 0); + return (dirty == 0 && !unwritten) ? 1 : 0; } STATIC int @@ -1155,7 +1202,7 @@ map_flags = (rw ? BMAPI_WRITE : BMAPI_READ) | BMAPI_DIRECT; pb_flags = (rw ? PBF_WRITE : PBF_READ) | PBF_FORCEIO | PBF_DIRECTIO; while (length) { - error = map_blocks(inode, offset, length, &iomap, map_flags); + error = xfs_map_blocks(inode, offset, length, &iomap, map_flags); if (error) break; BUG_ON(iomap.iomap_flags & IOMAP_DELAY); diff -Nru a/fs/xfs/linux/xfs_buf.c b/fs/xfs/linux/xfs_buf.c --- a/fs/xfs/linux/xfs_buf.c Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/linux/xfs_buf.c Fri Mar 5 05:02:51 2004 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -56,18 +56,8 @@ #include #include -#include -#include -#include "kmem.h" - -#include "xfs_types.h" -#include "xfs_cred.h" -#include "xfs_lrw.h" -#include "xfs_buf.h" - -#define NBBY 8 -#define BBSHIFT 9 -#define BBMASK ((1 << BBSHIFT) - 1) +#include "xfs_linux.h" + #define BN_ALIGN_MASK ((1 << (PAGE_CACHE_SHIFT - BBSHIFT)) - 1) #ifndef GFP_READAHEAD @@ -128,63 +118,12 @@ struct buffer_head *pb_resv_bh = NULL; /* list of bh */ int pb_resv_bh_cnt = 0; /* # of bh available */ -STATIC void pagebuf_daemon_wakeup(int); +STATIC void pagebuf_daemon_wakeup(void); STATIC void _pagebuf_ioapply(page_buf_t *); STATIC void pagebuf_delwri_queue(page_buf_t *, int); STATIC void pagebuf_runall_queues(struct list_head[]); /* - * Pagebuf module configuration parameters, exported via - * /proc/sys/vm/pagebuf - */ - -typedef struct pb_sysctl_val { - int min; - int val; - int max; -} pb_sysctl_val_t; - -struct { - pb_sysctl_val_t flush_interval; /* interval between runs of the - * delwri flush daemon. */ - pb_sysctl_val_t age_buffer; /* time for buffer to age before - * we flush it. */ - pb_sysctl_val_t stats_clear; /* clear the pagebuf stats */ - pb_sysctl_val_t debug; /* debug tracing on or off */ -} pb_params = { - /* MIN DFLT MAX */ - .flush_interval = { HZ/2, HZ, 30*HZ }, - .age_buffer = { 1*HZ, 15*HZ, 300*HZ }, - .stats_clear = { 0, 0, 1 }, - .debug = { 0, 0, 1 }, -}; - -enum { - PB_FLUSH_INT = 1, - PB_FLUSH_AGE = 2, - PB_STATS_CLEAR = 3, - PB_DEBUG = 4, -}; - -/* - * Pagebuf statistics variables - */ - -struct { - u_int32_t pb_get; - u_int32_t pb_create; - u_int32_t pb_get_locked; - u_int32_t pb_get_locked_waited; - u_int32_t pb_busy_locked; - u_int32_t pb_miss_locked; - u_int32_t pb_page_retries; - u_int32_t pb_page_found; - u_int32_t pb_get_read; -} pbstats; - -#define PB_STATS_INC(count) ( pbstats.count++ ) - -/* * Pagebuf debugging */ @@ -196,8 +135,6 @@ void *data, void *ra) { - if (!pb_params.debug.val) - return; ktrace_enter(pagebuf_trace_buf, pb, id, (void *)(unsigned long)pb->pb_flags, @@ -254,7 +191,6 @@ typedef struct { struct list_head pb_hash; - int pb_count; spinlock_t pb_hash_lock; } pb_hash_t; @@ -372,7 +308,7 @@ atomic_set(&pb->pb_pin_count, 0); init_waitqueue_head(&pb->pb_waiters); - PB_STATS_INC(pb_create); + XFS_STATS_INC(pb_create); PB_TRACE(pb, "initialize", target); } @@ -386,8 +322,6 @@ int page_count, page_buf_flags_t flags) { - int gpf_mask = pb_to_gfp(flags); - /* Make sure that we have a page list */ if (pb->pb_pages == NULL) { pb->pb_offset = page_buf_poff(pb->pb_file_offset); @@ -395,8 +329,8 @@ if (page_count <= PB_PAGES) { pb->pb_pages = pb->pb_page_array; } else { - pb->pb_pages = kmalloc(sizeof(struct page *) * - page_count, gpf_mask); + pb->pb_pages = kmem_alloc(sizeof(struct page *) * + page_count, pb_to_km(flags)); if (pb->pb_pages == NULL) return -ENOMEM; } @@ -425,53 +359,41 @@ } /* - * _pagebuf_free_object + * pagebuf_free * - * _pagebuf_free_object releases the contents specified buffer. - * The modification state of any associated pages is left unchanged. + * pagebuf_free releases the specified buffer. The modification + * state of any associated pages is left unchanged. */ void -_pagebuf_free_object( - pb_hash_t *hash, /* hash bucket for buffer */ - page_buf_t *pb) /* buffer to deallocate */ -{ - page_buf_flags_t pb_flags = pb->pb_flags; - - PB_TRACE(pb, "free_object", 0); - pb->pb_flags |= PBF_FREED; - - if (hash) { - if (!list_empty(&pb->pb_hash_list)) { - hash->pb_count--; - list_del_init(&pb->pb_hash_list); - } - spin_unlock(&hash->pb_hash_lock); - } +pagebuf_free( + page_buf_t *pb) +{ + PB_TRACE(pb, "free", 0); + + ASSERT(list_empty(&pb->pb_hash_list)); - if (!(pb_flags & PBF_FREED)) { - /* release any virtual mapping */ ; - if (pb->pb_flags & _PBF_ADDR_ALLOCATED) { - void *vaddr = pagebuf_mapout_locked(pb); - if (vaddr) { - free_address(vaddr); - } + /* release any virtual mapping */ ; + if (pb->pb_flags & _PBF_ADDR_ALLOCATED) { + void *vaddr = pagebuf_mapout_locked(pb); + if (vaddr) { + free_address(vaddr); } + } - if (pb->pb_flags & _PBF_MEM_ALLOCATED) { - if (pb->pb_pages) { - /* release the pages in the address list */ - if ((pb->pb_pages[0]) && - (pb->pb_flags & _PBF_MEM_SLAB)) { - kfree(pb->pb_addr); - } else { - _pagebuf_freepages(pb); - } - if (pb->pb_pages != pb->pb_page_array) - kfree(pb->pb_pages); - pb->pb_pages = NULL; + if (pb->pb_flags & _PBF_MEM_ALLOCATED) { + if (pb->pb_pages) { + /* release the pages in the address list */ + if ((pb->pb_pages[0]) && + (pb->pb_flags & _PBF_MEM_SLAB)) { + kfree(pb->pb_addr); + } else { + _pagebuf_freepages(pb); } - pb->pb_flags &= ~(_PBF_MEM_ALLOCATED|_PBF_MEM_SLAB); + if (pb->pb_pages != pb->pb_page_array) + kfree(pb->pb_pages); + pb->pb_pages = NULL; } + pb->pb_flags &= ~(_PBF_MEM_ALLOCATED|_PBF_MEM_SLAB); } pagebuf_deallocate(pb); @@ -496,32 +418,11 @@ loff_t next_buffer_offset; unsigned long page_count, pi, index; struct page *page; - int gfp_mask, retry_count = 5, rval = 0; - int all_mapped, good_pages; + int gfp_mask = pb_to_gfp(flags); + int all_mapped, good_pages, rval, retries; size_t blocksize; - /* For pagebufs where we want to map an address, do not use - * highmem pages - so that we do not need to use kmap resources - * to access the data. - * - * For pages where the caller has indicated there may be resource - * contention (e.g. called from a transaction) do not flush - * delalloc pages to obtain memory. - */ - - if (flags & PBF_READ_AHEAD) { - gfp_mask = GFP_READAHEAD; - retry_count = 0; - } else if (flags & PBF_DONT_BLOCK) { - gfp_mask = GFP_NOFS; - } else if (flags & PBF_MAPPABLE) { - gfp_mask = GFP_KERNEL; - } else { - gfp_mask = GFP_HIGHUSER; - } - next_buffer_offset = pb->pb_file_offset + pb->pb_buffer_length; - good_pages = page_count = (page_buf_btoc(next_buffer_offset) - page_buf_btoct(pb->pb_file_offset)); @@ -532,6 +433,7 @@ } if ((flags & PBF_MAPPED) && !(pb->pb_flags & PBF_MAPPED)) { all_mapped = 1; + rval = 0; goto mapit; } return 0; @@ -549,21 +451,30 @@ index = (pb->pb_file_offset - pb->pb_offset) >> PAGE_CACHE_SHIFT; for (pi = 0; pi < page_count; pi++, index++) { if (pb->pb_pages[pi] == 0) { + retries = 0; retry: page = find_or_create_page(aspace, index, gfp_mask); if (!page) { - if (--retry_count > 0) { - PB_STATS_INC(pb_page_retries); - pagebuf_daemon_wakeup(1); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(10); - goto retry; + if (flags & PBF_READ_AHEAD) + return -ENOMEM; + /* + * This could deadlock. But until all the + * XFS lowlevel code is revamped to handle + * buffer allocation failures we can't do + * much. + */ + if (!(++retries % 100)) { + printk(KERN_ERR + "possibly deadlocking in %s\n", + __FUNCTION__); } - rval = -ENOMEM; - all_mapped = 0; - continue; + XFS_STATS_INC(pb_page_retries); + pagebuf_daemon_wakeup(); + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(10); + goto retry; } - PB_STATS_INC(pb_page_found); + XFS_STATS_INC(pb_page_found); mark_page_accessed(page); pb->pb_pages[pi] = page; } else { @@ -587,6 +498,7 @@ } } + pb->pb_flags |= _PBF_PAGECACHE; mapit: pb->pb_flags |= _PBF_MEM_ALLOCATED; if (all_mapped) { @@ -780,16 +692,14 @@ list_for_each(p, &h->pb_hash) { pb = list_entry(p, page_buf_t, pb_hash_list); - if ((target == pb->pb_target) && - (pb->pb_file_offset == range_base) && - (pb->pb_buffer_length == range_length)) { - if (pb->pb_flags & PBF_FREED) - break; + if (pb->pb_target == target && + pb->pb_file_offset == range_base && + pb->pb_buffer_length == range_length) { /* If we look at something bring it to the * front of the list for next time */ - list_del(&pb->pb_hash_list); - list_add(&pb->pb_hash_list, &h->pb_hash); + atomic_inc(&pb->pb_hold); + list_move(&pb->pb_hash_list, &h->pb_hash); goto found; } } @@ -797,19 +707,17 @@ /* No match found */ if (new_pb) { _pagebuf_initialize(new_pb, target, range_base, - range_length, flags | _PBF_LOCKABLE); + range_length, flags); new_pb->pb_hash_index = hval; - h->pb_count++; list_add(&new_pb->pb_hash_list, &h->pb_hash); } else { - PB_STATS_INC(pb_miss_locked); + XFS_STATS_INC(pb_miss_locked); } spin_unlock(&h->pb_hash_lock); return (new_pb); found: - atomic_inc(&pb->pb_hold); spin_unlock(&h->pb_hash_lock); /* Attempt to get the semaphore without sleeping, @@ -822,7 +730,7 @@ /* wait for buffer ownership */ PB_TRACE(pb, "get_lock", 0); pagebuf_lock(pb); - PB_STATS_INC(pb_get_locked_waited); + XFS_STATS_INC(pb_get_locked_waited); } else { /* We asked for a trylock and failed, no need * to look at file offset and length here, we @@ -832,7 +740,7 @@ */ pagebuf_rele(pb); - PB_STATS_INC(pb_busy_locked); + XFS_STATS_INC(pb_busy_locked); return (NULL); } } else { @@ -841,15 +749,13 @@ } if (pb->pb_flags & PBF_STALE) - pb->pb_flags &= PBF_MAPPABLE | \ - PBF_MAPPED | \ - _PBF_LOCKABLE | \ + pb->pb_flags &= PBF_MAPPED | \ _PBF_ALL_PAGES_MAPPED | \ _PBF_ADDR_ALLOCATED | \ _PBF_MEM_ALLOCATED | \ _PBF_MEM_SLAB; PB_TRACE(pb, "got_lock", 0); - PB_STATS_INC(pb_get_locked); + XFS_STATS_INC(pb_get_locked); return (pb); } @@ -905,13 +811,14 @@ return (NULL); } - PB_STATS_INC(pb_get); + XFS_STATS_INC(pb_get); /* fill in any missing pages */ error = _pagebuf_lookup_pages(pb, pb->pb_target->pbr_mapping, flags); if (unlikely(error)) { - pagebuf_free(pb); - return (NULL); + printk(KERN_WARNING + "pagebuf_get: warning, failed to lookup pages\n"); + goto no_buffer; } /* @@ -924,7 +831,7 @@ if (flags & PBF_READ) { if (PBF_NOT_DONE(pb)) { PB_TRACE(pb, "get_read", (unsigned long)flags); - PB_STATS_INC(pb_get_read); + XFS_STATS_INC(pb_get_read); pagebuf_iostart(pb, flags); } else if (flags & PBF_ASYNC) { PB_TRACE(pb, "get_read_async", (unsigned long)flags); @@ -932,10 +839,7 @@ * Read ahead call which is already satisfied, * drop the buffer */ - if (flags & (PBF_LOCK | PBF_TRYLOCK)) - pagebuf_unlock(pb); - pagebuf_rele(pb); - return NULL; + goto no_buffer; } else { PB_TRACE(pb, "get_read_done", (unsigned long)flags); /* We do not want read in the flags */ @@ -944,7 +848,14 @@ } else { PB_TRACE(pb, "get_write", (unsigned long)flags); } - return (pb); + + return pb; + +no_buffer: + if (flags & (PBF_LOCK | PBF_TRYLOCK)) + pagebuf_unlock(pb); + pagebuf_rele(pb); + return NULL; } /* @@ -959,7 +870,7 @@ { page_buf_t *pb; - flags |= _PBF_PRIVATE_BH | _PBF_LOCKABLE; + flags |= _PBF_PRIVATE_BH; pb = pagebuf_allocate(flags); if (pb) { _pagebuf_initialize(pb, target, ioff, isize, flags); @@ -978,7 +889,7 @@ size_t isize, page_buf_flags_t flags) { - flags |= (PBF_TRYLOCK|PBF_READ|PBF_ASYNC|PBF_MAPPABLE|PBF_READ_AHEAD); + flags |= (PBF_TRYLOCK|PBF_READ|PBF_ASYNC|PBF_READ_AHEAD); pagebuf_get(target, ioff, isize, flags); } @@ -989,9 +900,9 @@ { page_buf_t *pb; - pb = pagebuf_allocate(_PBF_LOCKABLE); + pb = pagebuf_allocate(0); if (pb) - _pagebuf_initialize(pb, target, 0, len, _PBF_LOCKABLE); + _pagebuf_initialize(pb, target, 0, len, 0); return pb; } @@ -1065,7 +976,7 @@ { int rval; void *rmem = NULL; - page_buf_flags_t flags = _PBF_LOCKABLE | PBF_FORCEIO; + page_buf_flags_t flags = PBF_FORCEIO; page_buf_t *pb; size_t tlen = 0; @@ -1124,26 +1035,6 @@ } /* - * pagebuf_free - * - * pagebuf_free releases the specified buffer. The modification - * state of any associated pages is left unchanged. - */ -void -pagebuf_free( - page_buf_t *pb) -{ - if (pb->pb_flags & _PBF_LOCKABLE) { - pb_hash_t *h = pb_hash(pb); - - spin_lock(&h->pb_hash_lock); - _pagebuf_free_object(h, pb); - } else { - _pagebuf_free_object(NULL, pb); - } -} - -/* * pagebuf_rele * * pagebuf_rele releases a hold on the specified buffer. If the @@ -1153,44 +1044,37 @@ pagebuf_rele( page_buf_t *pb) { - pb_hash_t *h; + pb_hash_t *hash = pb_hash(pb); PB_TRACE(pb, "rele", pb->pb_relse); - if (pb->pb_flags & _PBF_LOCKABLE) { - h = pb_hash(pb); - spin_lock(&h->pb_hash_lock); - } else { - h = NULL; - } - if (atomic_dec_and_test(&pb->pb_hold)) { + if (atomic_dec_and_lock(&pb->pb_hold, &hash->pb_hash_lock)) { int do_free = 1; if (pb->pb_relse) { atomic_inc(&pb->pb_hold); - if (h) - spin_unlock(&h->pb_hash_lock); + spin_unlock(&hash->pb_hash_lock); (*(pb->pb_relse)) (pb); + spin_lock(&hash->pb_hash_lock); do_free = 0; } + if (pb->pb_flags & PBF_DELWRI) { pb->pb_flags |= PBF_ASYNC; atomic_inc(&pb->pb_hold); - if (h && do_free) - spin_unlock(&h->pb_hash_lock); pagebuf_delwri_queue(pb, 0); do_free = 0; } else if (pb->pb_flags & PBF_FS_MANAGED) { - if (h) - spin_unlock(&h->pb_hash_lock); do_free = 0; } if (do_free) { - _pagebuf_free_object(h, pb); + list_del_init(&pb->pb_hash_list); + spin_unlock(&hash->pb_hash_lock); + pagebuf_free(pb); + } else { + spin_unlock(&hash->pb_hash_lock); } - } else if (h) { - spin_unlock(&h->pb_hash_lock); } } @@ -1221,7 +1105,6 @@ { int locked; - ASSERT(pb->pb_flags & _PBF_LOCKABLE); locked = down_trylock(&pb->pb_sema) == 0; if (locked) { PB_SET_OWNER(pb); @@ -1239,7 +1122,6 @@ pagebuf_lock_value( page_buf_t *pb) { - ASSERT(pb->pb_flags & _PBF_LOCKABLE); return(atomic_read(&pb->pb_sema.count)); } @@ -1255,8 +1137,6 @@ pagebuf_lock( page_buf_t *pb) { - ASSERT(pb->pb_flags & _PBF_LOCKABLE); - PB_TRACE(pb, "lock", 0); if (atomic_read(&pb->pb_io_remaining)) blk_run_queues(); @@ -1277,7 +1157,6 @@ pagebuf_unlock( /* unlock buffer */ page_buf_t *pb) /* buffer to unlock */ { - ASSERT(pb->pb_flags & _PBF_LOCKABLE); PB_CLEAR_OWNER(pb); up(&pb->pb_sema); PB_TRACE(pb, "unlock", 0); @@ -1387,7 +1266,7 @@ } if (pb->pb_flags & PBF_ASYNC) { - if ((pb->pb_flags & _PBF_LOCKABLE) && !pb->pb_relse) + if (!pb->pb_relse) pagebuf_unlock(pb); pagebuf_rele(pb); } @@ -1457,7 +1336,7 @@ page_buf_t *pb, /* buffer to start */ page_buf_flags_t flags) /* PBF_LOCK, PBF_ASYNC, PBF_READ, */ /* PBF_WRITE, PBF_DELWRI, */ - /* PBF_SYNC, PBF_DONT_BLOCK */ + /* PBF_DONT_BLOCK */ { int status = 0; @@ -1465,16 +1344,15 @@ if (flags & PBF_DELWRI) { pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC); - pb->pb_flags |= flags & - (PBF_DELWRI | PBF_ASYNC | PBF_SYNC); + pb->pb_flags |= flags & (PBF_DELWRI | PBF_ASYNC); pagebuf_delwri_queue(pb, 1); return status; } - pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC | \ - PBF_DELWRI | PBF_READ_AHEAD | PBF_RUN_QUEUES); + pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC | PBF_DELWRI | \ + PBF_READ_AHEAD | PBF_RUN_QUEUES); pb->pb_flags |= flags & (PBF_READ | PBF_WRITE | PBF_ASYNC | \ - PBF_SYNC | PBF_READ_AHEAD | PBF_RUN_QUEUES); + PBF_READ_AHEAD | PBF_RUN_QUEUES); BUG_ON(pb->pb_bn == PAGE_BUF_DADDR_NULL); @@ -1510,7 +1388,7 @@ return pb->pb_locked; if (pb->pb_flags & PBF_READ) return pb->pb_locked; - return (!(pb->pb_flags & _PBF_LOCKABLE)); + return (pb->pb_flags & _PBF_PAGECACHE); } STATIC void @@ -2000,7 +1878,6 @@ * Pagebuf delayed write buffer handling */ -STATIC int pbd_active = 1; STATIC LIST_HEAD(pbd_delwrite_queue); STATIC spinlock_t pbd_delwrite_lock = SPIN_LOCK_UNLOCKED; @@ -2020,12 +1897,11 @@ } list_add_tail(&pb->pb_list, &pbd_delwrite_queue); - pb->pb_flushtime = jiffies + pb_params.age_buffer.val; + pb->pb_flushtime = jiffies + xfs_age_buffer; spin_unlock(&pbd_delwrite_lock); - if (unlock && (pb->pb_flags & _PBF_LOCKABLE)) { + if (unlock) pagebuf_unlock(pb); - } } void @@ -2062,10 +1938,10 @@ daemonize(); /* Avoid signals */ - spin_lock_irq(¤t->sigmask_lock); + sigmask_lock(); sigfillset(¤t->blocked); recalc_sigpending(current); - spin_unlock_irq(¤t->sigmask_lock); + sigmask_unlock(); /* Migrate to the right CPU */ migrate_to_cpu(cpu); @@ -2134,21 +2010,19 @@ /* Defines for pagebuf daemon */ -DECLARE_WAIT_QUEUE_HEAD(pbd_waitq); +STATIC DECLARE_COMPLETION(pagebuf_daemon_done); +STATIC struct task_struct *pagebuf_daemon_task; +STATIC int pagebuf_daemon_active; STATIC int force_flush; STATIC void -pagebuf_daemon_wakeup( - int flag) +pagebuf_daemon_wakeup(void) { - force_flush = flag; - if (waitqueue_active(&pbd_waitq)) { - wake_up_interruptible(&pbd_waitq); - } + force_flush = 1; + barrier(); + wake_up_process(pagebuf_daemon_task); } -typedef void (*timeout_fn)(unsigned long); - STATIC int pagebuf_daemon( void *data) @@ -2156,32 +2030,28 @@ int count; page_buf_t *pb; struct list_head *curr, *next, tmp; - struct timer_list pb_daemon_timer = - { {NULL, NULL}, 0, 0, (timeout_fn)pagebuf_daemon_wakeup }; /* Set up the thread */ daemonize(); + /* Mark it active */ + pagebuf_daemon_task = current; + pagebuf_daemon_active = 1; + barrier(); + /* Avoid signals */ - spin_lock_irq(¤t->sigmask_lock); + sigmask_lock(); sigfillset(¤t->blocked); recalc_sigpending(current); - spin_unlock_irq(¤t->sigmask_lock); + sigmask_unlock(); - strcpy(current->comm, "pagebufd"); + strcpy(current->comm, "xfsbufd"); current->flags |= PF_MEMALLOC; INIT_LIST_HEAD(&tmp); do { - if (pbd_active == 1) { - mod_timer(&pb_daemon_timer, - jiffies + pb_params.flush_interval.val); - interruptible_sleep_on(&pbd_waitq); - } - - if (pbd_active == 0) { - del_timer_sync(&pb_daemon_timer); - } + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(xfs_flush_interval); spin_lock(&pbd_delwrite_lock); @@ -2191,10 +2061,8 @@ PB_TRACE(pb, "walkq1", (long)pagebuf_ispin(pb)); - if ((pb->pb_flags & PBF_DELWRI) && !pagebuf_ispin(pb) && - (((pb->pb_flags & _PBF_LOCKABLE) == 0) || - !pagebuf_cond_lock(pb))) { - + if ((pb->pb_flags & PBF_DELWRI) && + !pagebuf_ispin(pb) && !pagebuf_cond_lock(pb)) { if (!force_flush && time_before(jiffies, pb->pb_flushtime)) { pagebuf_unlock(pb); @@ -2203,10 +2071,7 @@ pb->pb_flags &= ~PBF_DELWRI; pb->pb_flags |= PBF_WRITE; - - list_del(&pb->pb_list); - list_add(&pb->pb_list, &tmp); - + list_move(&pb->pb_list, &tmp); count++; } } @@ -2225,12 +2090,9 @@ blk_run_queues(); force_flush = 0; - } while (pbd_active == 1); - - pbd_active = -1; - wake_up_interruptible(&pbd_waitq); + } while (pagebuf_daemon_active); - return 0; + complete_and_exit(&pagebuf_daemon_done, 0); } void @@ -2359,10 +2221,9 @@ { int cpu, pcpu; - pbd_active = 0; - - wake_up_interruptible(&pbd_waitq); - wait_event_interruptible(pbd_waitq, pbd_active); + pagebuf_daemon_active = 0; + barrier(); + wait_for_completion(&pagebuf_daemon_done); for (pcpu = 0; pcpu < min(smp_num_cpus, MAX_IO_DAEMONS); pcpu++) { cpu = CPU_TO_DAEMON(cpu_logical_map(pcpu)); @@ -2380,107 +2241,10 @@ } -/* - * Pagebuf sysctl interface - */ - -STATIC int -pb_stats_clear_handler( - ctl_table *ctl, - int write, - struct file *filp, - void *buffer, - size_t *lenp) -{ - int ret; - int *valp = ctl->data; - - ret = proc_dointvec_minmax(ctl, write, filp, buffer, lenp); - - if (!ret && write && *valp) { - printk("XFS Clearing pbstats\n"); - memset(&pbstats, 0, sizeof(pbstats)); - pb_params.stats_clear.val = 0; - } - - return ret; -} - -STATIC struct ctl_table_header *pagebuf_table_header; - -STATIC ctl_table pagebuf_table[] = { - {PB_FLUSH_INT, "flush_int", &pb_params.flush_interval.val, - sizeof(int), 0644, NULL, &proc_dointvec_minmax, - &sysctl_intvec, NULL, - &pb_params.flush_interval.min, &pb_params.flush_interval.max}, - - {PB_FLUSH_AGE, "flush_age", &pb_params.age_buffer.val, - sizeof(int), 0644, NULL, &proc_dointvec_minmax, - &sysctl_intvec, NULL, - &pb_params.age_buffer.min, &pb_params.age_buffer.max}, - - {PB_STATS_CLEAR, "stats_clear", &pb_params.stats_clear.val, - sizeof(int), 0644, NULL, &pb_stats_clear_handler, - &sysctl_intvec, NULL, - &pb_params.stats_clear.min, &pb_params.stats_clear.max}, - -#ifdef PAGEBUF_TRACE - {PB_DEBUG, "debug", &pb_params.debug.val, - sizeof(int), 0644, NULL, &proc_dointvec_minmax, - &sysctl_intvec, NULL, - &pb_params.debug.min, &pb_params.debug.max}, -#endif - {0} -}; - -STATIC ctl_table pagebuf_dir_table[] = { - {VM_PAGEBUF, "pagebuf", NULL, 0, 0555, pagebuf_table}, - {0} -}; - -STATIC ctl_table pagebuf_root_table[] = { - {CTL_VM, "vm", NULL, 0, 0555, pagebuf_dir_table}, - {0} -}; - -#ifdef CONFIG_PROC_FS -STATIC int -pagebuf_readstats( - char *buffer, - char **start, - off_t offset, - int count, - int *eof, - void *data) -{ - int i, len; - - len = 0; - len += sprintf(buffer + len, "pagebuf"); - for (i = 0; i < sizeof(pbstats) / sizeof(u_int32_t); i++) { - len += sprintf(buffer + len, " %u", - *(((u_int32_t*)&pbstats) + i)); - } - buffer[len++] = '\n'; - - if (offset >= len) { - *start = buffer; - *eof = 1; - return 0; - } - *start = buffer + offset; - if ((len -= offset) > count) - return count; - *eof = 1; - - return len; -} -#endif /* CONFIG_PROC_FS */ - STATIC int pagebuf_shaker(int number, unsigned int mask) { - pagebuf_daemon_wakeup(1); + pagebuf_daemon_wakeup(); return 0; } @@ -2494,14 +2258,6 @@ { int i; - pagebuf_table_header = register_sysctl_table(pagebuf_root_table, 1); - -#ifdef CONFIG_PROC_FS - if (proc_mkdir("fs/pagebuf", 0)) - create_proc_read_entry( - "fs/pagebuf/stat", 0, 0, pagebuf_readstats, NULL); -#endif - pagebuf_cache = kmem_cache_create("page_buf_t", sizeof(page_buf_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); if (pagebuf_cache == NULL) { @@ -2549,10 +2305,4 @@ kmem_cache_destroy(pagebuf_cache); kmem_shake_deregister(pagebuf_shaker); - - unregister_sysctl_table(pagebuf_table_header); -#ifdef CONFIG_PROC_FS - remove_proc_entry("fs/pagebuf/stat", NULL); - remove_proc_entry("fs/pagebuf", NULL); -#endif } diff -Nru a/fs/xfs/linux/xfs_buf.h b/fs/xfs/linux/xfs_buf.h --- a/fs/xfs/linux/xfs_buf.h Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/linux/xfs_buf.h Fri Mar 5 05:02:51 2004 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -47,6 +47,16 @@ #include #include +/* nptl patch changes where the sigmask_lock is defined */ +#ifdef CLONE_SIGNAL /* stock */ +#define sigmask_lock() spin_lock_irq(¤t->sigmask_lock); +#define sigmask_unlock() spin_unlock_irq(¤t->sigmask_lock); +#define recalc_sigpending(x) recalc_sigpending(x) +#else /* nptl */ +#define sigmask_lock() spin_lock_irq(¤t->sighand->siglock); +#define sigmask_unlock() spin_unlock_irq(¤t->sighand->siglock); +#define recalc_sigpending(x) recalc_sigpending() +#endif /* * Base types */ @@ -76,9 +86,6 @@ PBF_ASYNC = (1 << 4), /* initiator will not wait for completion */ PBF_NONE = (1 << 5), /* buffer not read at all */ PBF_DELWRI = (1 << 6), /* buffer has dirty pages */ - PBF_FREED = (1 << 7), /* buffer has been freed and is invalid */ - PBF_SYNC = (1 << 8), /* force updates to disk */ - PBF_MAPPABLE = (1 << 9),/* use directly-addressable pages */ PBF_STALE = (1 << 10), /* buffer has been staled, do not find it */ PBF_FS_MANAGED = (1 << 11), /* filesystem controls freeing memory */ PBF_FS_DATAIOD = (1 << 12), /* schedule IO completion on fs datad */ @@ -89,7 +96,7 @@ PBF_DONT_BLOCK = (1 << 15), /* do not block in current thread */ /* flags used only internally */ - _PBF_LOCKABLE = (1 << 16), /* page_buf_t may be locked */ + _PBF_PAGECACHE = (1 << 16), /* backed by pagecache */ _PBF_PRIVATE_BH = (1 << 17), /* do not use public buffer heads */ _PBF_ALL_PAGES_MAPPED = (1 << 18), /* all pages in range mapped */ _PBF_ADDR_ALLOCATED = (1 << 19), /* pb_addr space was allocated */ @@ -205,7 +212,7 @@ loff_t, /* starting offset of range */ size_t, /* length of range */ page_buf_flags_t); /* PBF_READ, PBF_WRITE, */ - /* PBF_FORCEIO, _PBF_LOCKABLE */ + /* PBF_FORCEIO, */ extern page_buf_t *pagebuf_get_empty( /* allocate pagebuf struct with */ /* no memory or disk address */ @@ -270,7 +277,7 @@ page_buf_t *, /* buffer to start */ page_buf_flags_t); /* PBF_LOCK, PBF_ASYNC, */ /* PBF_READ, PBF_WRITE, */ - /* PBF_DELWRI, PBF_SYNC */ + /* PBF_DELWRI */ extern int pagebuf_iorequest( /* start real I/O */ page_buf_t *); /* buffer to convey to device */ @@ -403,7 +410,7 @@ #define XFS_BUF_BFLAGS(x) ((x)->pb_flags) #define XFS_BUF_ZEROFLAGS(x) \ - ((x)->pb_flags &= ~(PBF_READ|PBF_WRITE|PBF_ASYNC|PBF_SYNC|PBF_DELWRI)) + ((x)->pb_flags &= ~(PBF_READ|PBF_WRITE|PBF_ASYNC|PBF_DELWRI)) #define XFS_BUF_STALE(x) ((x)->pb_flags |= XFS_B_STALE) #define XFS_BUF_UNSTALE(x) ((x)->pb_flags &= ~XFS_B_STALE) @@ -555,17 +562,15 @@ #define xfs_buf_read(target, blkno, len, flags) \ pagebuf_get((target), (blkno), (len), \ - PBF_LOCK | PBF_READ | PBF_MAPPED | PBF_MAPPABLE) + PBF_LOCK | PBF_READ | PBF_MAPPED) #define xfs_buf_get(target, blkno, len, flags) \ pagebuf_get((target), (blkno), (len), \ - PBF_LOCK | PBF_MAPPED | PBF_MAPPABLE) + PBF_LOCK | PBF_MAPPED) #define xfs_buf_read_flags(target, blkno, len, flags) \ - pagebuf_get((target), (blkno), (len), \ - PBF_READ | PBF_MAPPABLE | flags) + pagebuf_get((target), (blkno), (len), PBF_READ | (flags)) #define xfs_buf_get_flags(target, blkno, len, flags) \ - pagebuf_get((target), (blkno), (len), \ - PBF_MAPPABLE | flags) + pagebuf_get((target), (blkno), (len), (flags)) static inline int xfs_bawrite(void *mp, page_buf_t *bp) { @@ -577,7 +582,7 @@ static inline void xfs_buf_relse(page_buf_t *bp) { - if ((bp->pb_flags & _PBF_LOCKABLE) && !bp->pb_relse) + if (!bp->pb_relse) pagebuf_unlock(bp); pagebuf_rele(bp); } @@ -608,7 +613,6 @@ int iowait = (pb->pb_flags & PBF_ASYNC) == 0; int error = 0; - pb->pb_flags |= PBF_SYNC; if (!iowait) pb->pb_flags |= PBF_RUN_QUEUES; diff -Nru a/fs/xfs/linux/xfs_globals.c b/fs/xfs/linux/xfs_globals.c --- a/fs/xfs/linux/xfs_globals.c Fri Mar 5 05:02:52 2004 +++ b/fs/xfs/linux/xfs_globals.c Fri Mar 5 05:02:52 2004 @@ -64,6 +64,8 @@ .inherit_sync = { 0, 1, 1 }, .inherit_nodump = { 0, 1, 1 }, .inherit_noatim = { 0, 1, 1 }, + .flush_interval = { HZ/2, HZ, 30*HZ }, + .age_buffer = { 1*HZ, 15*HZ, 300*HZ }, }; /* diff -Nru a/fs/xfs/linux/xfs_ioctl.c b/fs/xfs/linux/xfs_ioctl.c --- a/fs/xfs/linux/xfs_ioctl.c Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/linux/xfs_ioctl.c Fri Mar 5 05:02:51 2004 @@ -310,7 +310,6 @@ struct dentry *dentry; vnode_t *vp; xfs_fsop_handlereq_t hreq; - struct list_head *lp; error = xfs_vget_fsop_handlereq(mp, parinode, CAP_SYS_ADMIN, arg, sizeof(xfs_fsop_handlereq_t), @@ -356,32 +355,13 @@ return new_fd; } - /* Now to find a dentry. If possible, get a well-connected one. */ - spin_lock(&dcache_lock); - for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) { - dentry = list_entry(lp, struct dentry, d_alias); - if (! (dentry->d_flags & DCACHE_NFSD_DISCONNECTED)) { - dget_locked(dentry); - dentry->d_vfs_flags |= DCACHE_REFERENCED; - spin_unlock(&dcache_lock); - iput(inode); - goto found; - } - } - spin_unlock(&dcache_lock); - - /* ELSE didn't find dentry. Create anonymous dcache entry. */ - dentry = d_alloc_root(inode); + dentry = d_alloc_anon(inode); if (dentry == NULL) { iput(inode); put_unused_fd(new_fd); return -XFS_ERROR(ENOMEM); } - /* Keep nfsd happy. */ - dentry->d_flags |= DCACHE_NFSD_DISCONNECTED; - - found: /* Ensure umount returns EBUSY on umounts while this file is open. */ mntget(parfilp->f_vfsmnt); @@ -721,9 +701,7 @@ error = xfs_set_dmattrs(bdp, dmi.fsd_dmevmask, dmi.fsd_dmstate, NULL); - if (error) - return -error; - return 0; + return -error; } case XFS_IOC_GETBMAP: @@ -755,9 +733,7 @@ case XFS_IOC_SWAPEXT: { error = xfs_swapext((struct xfs_swapext *)arg); - if (error) - return -error; - return 0; + return -error; } case XFS_IOC_FSCOUNTS: { @@ -785,6 +761,8 @@ /* input parameter is passed in resblks field of structure */ in = inout.resblks; error = xfs_reserve_blocks(mp, &in, &inout); + if (error) + return -error; if (copy_to_user((char *)arg, &inout, sizeof(inout))) return -XFS_ERROR(EFAULT); @@ -817,9 +795,7 @@ return -XFS_ERROR(EFAULT); error = xfs_growfs_data(mp, &in); - if (error) - return -error; - return 0; + return -error; } case XFS_IOC_FSGROWFSLOG: { @@ -832,9 +808,7 @@ return -XFS_ERROR(EFAULT); error = xfs_growfs_log(mp, &in); - if (error) - return -error; - return 0; + return -error; } case XFS_IOC_FSGROWFSRT: { @@ -847,9 +821,7 @@ return -XFS_ERROR(EFAULT); error = xfs_growfs_rt(mp, &in); - if (error) - return -error; - return 0; + return -error; } case XFS_IOC_FREEZE: @@ -864,6 +836,19 @@ xfs_fs_thaw(mp); return 0; + case XFS_IOC_GOINGDOWN: { + __uint32_t in; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (get_user(in, (__uint32_t *)arg)) + return -XFS_ERROR(EFAULT); + + error = xfs_fs_goingdown(mp, in); + return -error; + } + case XFS_IOC_ERROR_INJECTION: { xfs_error_injection_t in; @@ -871,9 +856,7 @@ return -XFS_ERROR(EFAULT); error = xfs_errortag_add(in.errtag, mp); - if (error) - return -error; - return 0; + return -error; } case XFS_IOC_ERROR_CLEARALL: diff -Nru a/fs/xfs/linux/xfs_iops.c b/fs/xfs/linux/xfs_iops.c --- a/fs/xfs/linux/xfs_iops.c Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/linux/xfs_iops.c Fri Mar 5 05:02:51 2004 @@ -616,8 +616,7 @@ if (!size) xflags |= ATTR_KERNOVAL; - if (capable(CAP_SYS_ADMIN)) - xflags |= ATTR_KERNFULLS; + xflags |= capable(CAP_SYS_ADMIN) ? ATTR_KERNFULLS : ATTR_KERNORMALS; error = attr_generic_list(vp, data, size, xflags, &result); if (error < 0) diff -Nru a/fs/xfs/linux/xfs_linux.h b/fs/xfs/linux/xfs_linux.h --- a/fs/xfs/linux/xfs_linux.h Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/linux/xfs_linux.h Fri Mar 5 05:02:51 2004 @@ -135,6 +135,8 @@ #define xfs_inherit_sync xfs_params.inherit_sync.val #define xfs_inherit_nodump xfs_params.inherit_nodump.val #define xfs_inherit_noatime xfs_params.inherit_noatim.val +#define xfs_flush_interval xfs_params.flush_interval.val +#define xfs_age_buffer xfs_params.age_buffer.val #define current_cpu() smp_processor_id() #define current_pid() (current->pid) diff -Nru a/fs/xfs/linux/xfs_lrw.c b/fs/xfs/linux/xfs_lrw.c --- a/fs/xfs/linux/xfs_lrw.c Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/linux/xfs_lrw.c Fri Mar 5 05:02:51 2004 @@ -311,9 +311,10 @@ !(ioflags & IO_INVIS)) { int error; vrwlock_t locktype = VRWLOCK_READ; + int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags); error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), *offset, size, - FILP_DELAY_FLAG(file), &locktype); + dmflags, &locktype); if (error) { if (!(ioflags & IO_ISLOCKED)) xfs_iunlock(ip, XFS_IOLOCK_SHARED); @@ -322,9 +323,13 @@ } if (unlikely(ioflags & IO_ISDIRECT)) { + xfs_rw_enter_trace(XFS_DIORD_ENTER, &ip->i_iocore, + buf, size, *offset, ioflags); ret = do_generic_direct_read(file, buf, size, offset); UPDATE_ATIME(file->f_dentry->d_inode); } else { + xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore, + buf, size, *offset, ioflags); ret = generic_file_read(file, buf, size, offset); } @@ -593,7 +598,7 @@ if (size == 0) return 0; - io = &(xip->i_iocore); + io = &xip->i_iocore; mp = io->io_mount; xfs_check_frozen(mp, bdp, XFS_FREEZE_WRITE); @@ -645,11 +650,12 @@ if ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) && !(ioflags & IO_INVIS) && !eventsent)) { loff_t savedsize = *offset; + int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags); xfs_iunlock(xip, XFS_ILOCK_EXCL); error = XFS_SEND_DATA(xip->i_mount, DM_EVENT_WRITE, vp, *offset, size, - FILP_DELAY_FLAG(file), &locktype); + dmflags, &locktype); if (error) { if (iolock) xfs_iunlock(xip, iolock); return -error; diff -Nru a/fs/xfs/linux/xfs_lrw.h b/fs/xfs/linux/xfs_lrw.h --- a/fs/xfs/linux/xfs_lrw.h Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/linux/xfs_lrw.h Fri Mar 5 05:02:51 2004 @@ -45,9 +45,7 @@ /* * Defines for the trace mechanisms in xfs_lrw.c. */ -#define XFS_RW_KTRACE_SIZE 64 -#define XFS_STRAT_KTRACE_SIZE 64 -#define XFS_STRAT_GTRACE_SIZE 512 +#define XFS_RW_KTRACE_SIZE 128 #define XFS_READ_ENTER 1 #define XFS_WRITE_ENTER 2 @@ -69,6 +67,12 @@ #define XFS_INVAL_CACHED 18 #define XFS_DIORD_ENTER 19 #define XFS_DIOWR_ENTER 20 +#define XFS_SENDFILE_ENTER 21 +#define XFS_WRITEPAGE_ENTER 22 +#define XFS_RELEASEPAGE_ENTER 23 +#define XFS_IOMAP_ALLOC_ENTER 24 +#define XFS_IOMAP_ALLOC_MAP 25 +#define XFS_IOMAP_UNWRITTEN 26 extern void xfs_rw_enter_trace(int, struct xfs_iocore *, const char *, size_t, loff_t, int); extern void xfs_inval_cached_trace(struct xfs_iocore *, diff -Nru a/fs/xfs/linux/xfs_stats.c b/fs/xfs/linux/xfs_stats.c --- a/fs/xfs/linux/xfs_stats.c Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/linux/xfs_stats.c Fri Mar 5 05:02:51 2004 @@ -63,6 +63,7 @@ { "attr", XFSSTAT_END_ATTRIBUTE_OPS }, { "icluster", XFSSTAT_END_INODE_CLUSTER }, { "vnodes", XFSSTAT_END_VNODE_OPS }, + { "buf", XFSSTAT_END_BUF }, }; for (i=j=len = 0; i < sizeof(xstats)/sizeof(struct xstats_entry); i++) { diff -Nru a/fs/xfs/linux/xfs_stats.h b/fs/xfs/linux/xfs_stats.h --- a/fs/xfs/linux/xfs_stats.h Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/linux/xfs_stats.h Fri Mar 5 05:02:51 2004 @@ -120,6 +120,16 @@ __uint32_t vn_reclaim; /* # times vn_reclaim called */ __uint32_t vn_remove; /* # times vn_remove called */ __uint32_t vn_free; /* # times vn_free called */ +#define XFSSTAT_END_BUF (XFSSTAT_END_VNODE_OPS+9) + __uint32_t pb_get; + __uint32_t pb_create; + __uint32_t pb_get_locked; + __uint32_t pb_get_locked_waited; + __uint32_t pb_busy_locked; + __uint32_t pb_miss_locked; + __uint32_t pb_page_retries; + __uint32_t pb_page_found; + __uint32_t pb_get_read; /* Extra precision counters */ __uint64_t xs_xstrat_bytes; __uint64_t xs_write_bytes; diff -Nru a/fs/xfs/linux/xfs_super.c b/fs/xfs/linux/xfs_super.c --- a/fs/xfs/linux/xfs_super.c Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/linux/xfs_super.c Fri Mar 5 05:02:51 2004 @@ -260,6 +260,30 @@ xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC); } +struct dentry * +d_alloc_anon(struct inode *inode) +{ + struct dentry *dentry; + + spin_lock(&dcache_lock); + list_for_each_entry(dentry, &inode->i_dentry, d_alias) { + if (!(dentry->d_flags & DCACHE_NFSD_DISCONNECTED)) + goto found; + } + spin_unlock(&dcache_lock); + + dentry = d_alloc_root(inode); + if (likely(dentry != NULL)) + dentry->d_flags |= DCACHE_NFSD_DISCONNECTED; + return dentry; + found: + dget_locked(dentry); + dentry->d_vfs_flags |= DCACHE_REFERENCED; + spin_unlock(&dcache_lock); + iput(inode); + return dentry; +} + /*ARGSUSED*/ int xfs_blkdev_get( @@ -484,10 +508,10 @@ daemonize(); reparent_to_init(); - spin_lock_irq(¤t->sigmask_lock); + sigmask_lock(); sigfillset(¤t->blocked); recalc_sigpending(current); - spin_unlock_irq(¤t->sigmask_lock); + sigmask_unlock(); sprintf(current->comm, "xfssyncd"); @@ -686,7 +710,6 @@ { vnode_t *vp; struct inode *inode = NULL; - struct list_head *lp; struct dentry *result; xfs_fid2_t xfid; vfs_t *vfsp = LINVFS_GET_VFS(sb); @@ -711,24 +734,12 @@ return ERR_PTR(-ESTALE) ; inode = LINVFS_GET_IP(vp); - spin_lock(&dcache_lock); - for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) { - result = list_entry(lp,struct dentry, d_alias); - if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) { - dget_locked(result); - result->d_vfs_flags |= DCACHE_REFERENCED; - spin_unlock(&dcache_lock); - iput(inode); - return result; - } - } - spin_unlock(&dcache_lock); - result = d_alloc_root(inode); - if (result == NULL) { + + result = d_alloc_anon(inode); + if (unlikely(result == NULL)) { iput(inode); return ERR_PTR(-ENOMEM); } - result->d_flags |= DCACHE_NFSD_DISCONNECTED; return result; } diff -Nru a/fs/xfs/linux/xfs_super.h b/fs/xfs/linux/xfs_super.h --- a/fs/xfs/linux/xfs_super.h Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/linux/xfs_super.h Fri Mar 5 05:02:51 2004 @@ -44,6 +44,8 @@ #ifdef CONFIG_XFS_QUOTA # define vfs_insertquota(vfs) vfs_insertops(vfsp, &xfs_qmops) +extern void xfs_qm_init(void); +extern void xfs_qm_exit(void); # define vfs_initquota() xfs_qm_init() # define vfs_exitquota() xfs_qm_exit() #else @@ -132,5 +134,8 @@ extern int xfs_readonly_buftarg(struct pb_target *); extern void xfs_setsize_buftarg(struct pb_target *, unsigned int, unsigned int); extern unsigned int xfs_getsize_buftarg(struct pb_target *); + +/* matching a 2.6 kernel export, thus no xfs_ prefix */ +extern struct dentry *d_alloc_anon(struct inode *inode); #endif /* __XFS_SUPER_H__ */ diff -Nru a/fs/xfs/linux/xfs_sysctl.c b/fs/xfs/linux/xfs_sysctl.c --- a/fs/xfs/linux/xfs_sysctl.c Fri Mar 5 05:02:52 2004 +++ b/fs/xfs/linux/xfs_sysctl.c Fri Mar 5 05:02:52 2004 @@ -149,6 +149,16 @@ sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL, &xfs_params.inherit_noatim.min, &xfs_params.inherit_noatim.max}, + + {XFS_FLUSH_INTERVAL, "flush_interval", &xfs_params.flush_interval.val, + sizeof(int), 0644, NULL, &proc_dointvec_minmax, + &sysctl_intvec, NULL, + &xfs_params.flush_interval.min, &xfs_params.flush_interval.max}, + + {XFS_AGE_BUFFER, "age_buffer", &xfs_params.age_buffer.val, + sizeof(int), 0644, NULL, &proc_dointvec_minmax, + &sysctl_intvec, NULL, + &xfs_params.age_buffer.min, &xfs_params.age_buffer.max}, /* please keep this the last entry */ #ifdef CONFIG_PROC_FS diff -Nru a/fs/xfs/linux/xfs_sysctl.h b/fs/xfs/linux/xfs_sysctl.h --- a/fs/xfs/linux/xfs_sysctl.h Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/linux/xfs_sysctl.h Fri Mar 5 05:02:51 2004 @@ -60,6 +60,10 @@ xfs_sysctl_val_t inherit_sync; /* Inherit the "sync" inode flag. */ xfs_sysctl_val_t inherit_nodump;/* Inherit the "nodump" inode flag. */ xfs_sysctl_val_t inherit_noatim;/* Inherit the "noatime" inode flag. */ + xfs_sysctl_val_t flush_interval;/* interval between runs of the + * delwri flush daemon. */ + xfs_sysctl_val_t age_buffer; /* time for buffer to age before + * we flush it. */ } xfs_param_t; /* @@ -90,6 +94,8 @@ XFS_INHERIT_SYNC = 13, XFS_INHERIT_NODUMP = 14, XFS_INHERIT_NOATIME = 15, + XFS_FLUSH_INTERVAL = 16, + XFS_AGE_BUFFER = 17, }; extern xfs_param_t xfs_params; diff -Nru a/fs/xfs/linux/xfs_vfs.c b/fs/xfs/linux/xfs_vfs.c --- a/fs/xfs/linux/xfs_vfs.c Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/linux/xfs_vfs.c Fri Mar 5 05:02:51 2004 @@ -117,7 +117,6 @@ return ((*bhvtovfsops(next)->vfs_mntupdate)(next, fl, args)); } - int vfs_root( struct bhv_desc *bdp, diff -Nru a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h --- a/fs/xfs/xfs_ag.h Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/xfs_ag.h Fri Mar 5 05:02:51 2004 @@ -230,39 +230,6 @@ xfs_perag_busy_t *pagb_list; /* unstable blocks */ } xfs_perag_t; -#define XFS_AG_MIN_BYTES (1LL << 24) /* 16 MB */ -#define XFS_AG_BEST_BYTES (1LL << 30) /* 1 GB */ -#define XFS_AG_MAX_BYTES (1LL << 32) /* 4 GB */ - -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_AG_MIN_BLOCKS) -xfs_extlen_t xfs_ag_min_blocks(int bl); -#define XFS_AG_MIN_BLOCKS(bl) xfs_ag_min_blocks(bl) -#else -#define XFS_AG_MIN_BLOCKS(bl) ((xfs_extlen_t)(XFS_AG_MIN_BYTES >> bl)) -#endif -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_AG_BEST_BLOCKS) -xfs_extlen_t xfs_ag_best_blocks(int bl, xfs_drfsbno_t blks); -#define XFS_AG_BEST_BLOCKS(bl,blks) xfs_ag_best_blocks(bl,blks) -#else -/*--#define XFS_AG_BEST_BLOCKS(bl) ((xfs_extlen_t)(XFS_AG_BEST_BYTES >> bl))*/ -/* - * Best is XFS_AG_BEST_BLOCKS at and below 64 Gigabyte filesystems, and - * XFS_AG_MAX_BLOCKS above 64 Gigabytes. - */ -#define XFS_AG_BEST_BLOCKS(bl,blks) \ - ((xfs_extlen_t)((1LL << (36 - bl)) >= blks) ? \ - ((xfs_extlen_t)(XFS_AG_BEST_BYTES >> bl)) : \ - XFS_AG_MAX_BLOCKS(bl)) -#endif -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_AG_MAX_BLOCKS) -xfs_extlen_t xfs_ag_max_blocks(int bl); -#define XFS_AG_MAX_BLOCKS(bl) xfs_ag_max_blocks(bl) -#else -#define XFS_AG_MAX_BLOCKS(bl) ((xfs_extlen_t)(XFS_AG_MAX_BYTES >> bl)) -#endif - -#define XFS_MAX_AGNUMBER ((xfs_agnumber_t)(NULLAGNUMBER - 1)) - #if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_AG_MAXLEVELS) int xfs_ag_maxlevels(struct xfs_mount *mp); #define XFS_AG_MAXLEVELS(mp) xfs_ag_maxlevels(mp) diff -Nru a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c --- a/fs/xfs/xfs_alloc.c Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/xfs_alloc.c Fri Mar 5 05:02:51 2004 @@ -780,14 +780,8 @@ /* * Randomly don't execute the first algorithm. */ - static int seed; /* randomizing seed value */ int dofirst; /* set to do first algorithm */ - timespec_t now; /* current time */ - if (!seed) { - nanotime(&now); - seed = (int)now.tv_sec ^ (int)now.tv_nsec; - } dofirst = random() & 1; #endif /* diff -Nru a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h --- a/fs/xfs/xfs_attr.h Fri Mar 5 05:02:52 2004 +++ b/fs/xfs/xfs_attr.h Fri Mar 5 05:02:52 2004 @@ -91,10 +91,14 @@ #define ATTR_CREATE 0x0010 /* pure create: fail if attr already exists */ #define ATTR_REPLACE 0x0020 /* pure set: fail if attr does not exist */ #define ATTR_SYSTEM 0x0100 /* use attrs in system (pseudo) namespace */ + #define ATTR_KERNOTIME 0x1000 /* [kernel] don't update inode timestamps */ #define ATTR_KERNOVAL 0x2000 /* [kernel] get attr size only, not value */ #define ATTR_KERNAMELS 0x4000 /* [kernel] list attr names (simple list) */ -#define ATTR_KERNFULLS 0x8000 /* [kernel] full attr list, ie. root+user */ + +#define ATTR_KERNORMALS 0x0800 /* [kernel] normal attr list: user+secure */ +#define ATTR_KERNROOTLS 0x8000 /* [kernel] include root in the attr list */ +#define ATTR_KERNFULLS (ATTR_KERNORMALS|ATTR_KERNROOTLS) /* * The maximum size (into the kernel or returned from the kernel) of an diff -Nru a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c --- a/fs/xfs/xfs_attr_leaf.c Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/xfs_attr_leaf.c Fri Mar 5 05:02:51 2004 @@ -460,9 +460,15 @@ i < INT_GET(sf->hdr.count, ARCH_CONVERT); i++) { attrnames_t *namesp; + if (((context->flags & ATTR_SECURE) != 0) != + ((sfe->flags & XFS_ATTR_SECURE) != 0) && + !(context->flags & ATTR_KERNORMALS)) { + sfe = XFS_ATTR_SF_NEXTENTRY(sfe); + continue; + } if (((context->flags & ATTR_ROOT) != 0) != ((sfe->flags & XFS_ATTR_ROOT) != 0) && - !(context->flags & ATTR_KERNFULLS)) { + !(context->flags & ATTR_KERNROOTLS)) { sfe = XFS_ATTR_SF_NEXTENTRY(sfe); continue; } @@ -511,9 +517,15 @@ kmem_free(sbuf, sbsize); return XFS_ERROR(EFSCORRUPTED); } + if (((context->flags & ATTR_SECURE) != 0) != + ((sfe->flags & XFS_ATTR_SECURE) != 0) && + !(context->flags & ATTR_KERNORMALS)) { + sfe = XFS_ATTR_SF_NEXTENTRY(sfe); + continue; + } if (((context->flags & ATTR_ROOT) != 0) != ((sfe->flags & XFS_ATTR_ROOT) != 0) && - !(context->flags & ATTR_KERNFULLS)) { + !(context->flags & ATTR_KERNROOTLS)) { sfe = XFS_ATTR_SF_NEXTENTRY(sfe); continue; } @@ -2309,9 +2321,13 @@ if (entry->flags & XFS_ATTR_INCOMPLETE) continue; /* skip incomplete entries */ + if (((context->flags & ATTR_SECURE) != 0) != + ((entry->flags & XFS_ATTR_SECURE) != 0) && + !(context->flags & ATTR_KERNORMALS)) + continue; /* skip non-matching entries */ if (((context->flags & ATTR_ROOT) != 0) != ((entry->flags & XFS_ATTR_ROOT) != 0) && - !(context->flags & ATTR_KERNFULLS)) + !(context->flags & ATTR_KERNROOTLS)) continue; /* skip non-matching entries */ namesp = (entry->flags & XFS_ATTR_SECURE) ? &attr_secure : diff -Nru a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c --- a/fs/xfs/xfs_buf_item.c Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/xfs_buf_item.c Fri Mar 5 05:02:51 2004 @@ -429,7 +429,7 @@ */ if (bip->bli_flags & XFS_BLI_STALE_INODE) { xfs_buf_do_callbacks(bp, (xfs_log_item_t *)bip); - XFS_BUF_FSPRIVATE(bp, void *) = NULL; + XFS_BUF_SET_FSPRIVATE(bp, NULL); XFS_BUF_CLR_IODONE_FUNC(bp); } else { AIL_LOCK(mp,s); diff -Nru a/fs/xfs/xfs_clnt.h b/fs/xfs/xfs_clnt.h --- a/fs/xfs/xfs_clnt.h Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/xfs_clnt.h Fri Mar 5 05:02:51 2004 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -57,10 +57,10 @@ int flags; /* flags -> see XFSMNT_... macros below */ int logbufs; /* Number of log buffers, -1 to default */ int logbufsize; /* Size of log buffers, -1 to default */ - char fsname[MAXNAMELEN]; /* data device name */ - char rtname[MAXNAMELEN]; /* realtime device filename */ - char logname[MAXNAMELEN]; /* journal device filename */ - char mtpt[MAXNAMELEN]; /* filesystem mount point */ + char fsname[MAXNAMELEN+1]; /* data device name */ + char rtname[MAXNAMELEN+1]; /* realtime device filename */ + char logname[MAXNAMELEN+1]; /* journal device filename */ + char mtpt[MAXNAMELEN+1]; /* filesystem mount point */ int sunit; /* stripe unit (BBs) */ int swidth; /* stripe width (BBs), multiple of sunit */ uchar_t iosizelog; /* log2 of the preferred I/O size */ diff -Nru a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c --- a/fs/xfs/xfs_dir2_node.c Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/xfs_dir2_node.c Fri Mar 5 05:02:51 2004 @@ -1573,15 +1573,16 @@ "%llu needed freesp block %lld for\n" " data block %lld, got %lld\n" " ifbno %llu lastfbno %d\n", - dp->i_ino, - XFS_DIR2_DB_TO_FDB(mp, dbno), - dbno, fbno, - ifbno, lastfbno); + (unsigned long long)dp->i_ino, + (long long)XFS_DIR2_DB_TO_FDB(mp, dbno), + (long long)dbno, (long long)fbno, + (unsigned long long)ifbno, lastfbno); if (fblk) { cmn_err(CE_ALERT, - " fblk 0x%llu blkno %llu " + " fblk 0x%p blkno %llu " "index %d magic 0x%x\n", - fblk, fblk->blkno, + fblk, + (unsigned long long)fblk->blkno, fblk->index, fblk->magic); } else { diff -Nru a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h --- a/fs/xfs/xfs_dmapi.h Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/xfs_dmapi.h Fri Mar 5 05:02:51 2004 @@ -165,6 +165,27 @@ #define DM_FLAGS_NDELAY 0x001 /* return EAGAIN after dm_pending() */ #define DM_FLAGS_UNWANTED 0x002 /* event not in fsys dm_eventset_t */ +#define DM_FLAGS_ISEM 0x004 /* thread holds i_sem */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21) +/* i_alloc_sem was added in 2.4.22-pre1 */ +#define DM_FLAGS_IALLOCSEM_RD 0x010 /* thread holds i_alloc_sem rd */ +#define DM_FLAGS_IALLOCSEM_WR 0x020 /* thread holds i_alloc_sem wr */ +#endif +#endif + +/* + * Based on IO_ISDIRECT, decide which i_ flag is set. + */ +#ifdef DM_FLAGS_IALLOCSEM_RD +#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \ + DM_FLAGS_IALLOCSEM_RD : DM_FLAGS_ISEM) +#define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_ISEM) +#else +#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \ + 0 : DM_FLAGS_ISEM) +#define DM_SEM_FLAG_WR (DM_FLAGS_ISEM) +#endif /* * Macros to turn caller specified delay/block flags into diff -Nru a/fs/xfs/xfs_dmops.c b/fs/xfs/xfs_dmops.c --- a/fs/xfs/xfs_dmops.c Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/xfs_dmops.c Fri Mar 5 05:02:51 2004 @@ -43,7 +43,7 @@ #include "xfs_dmapi.h" #include "xfs_mount.h" -xfs_dmops_t xfs_dmcore_xfs = { +xfs_dmops_t xfs_dmcore_stub = { .xfs_send_data = (xfs_send_data_t)fs_nosys, .xfs_send_mmap = (xfs_send_mmap_t)fs_noerr, .xfs_send_destroy = (xfs_send_destroy_t)fs_nosys, diff -Nru a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c --- a/fs/xfs/xfs_error.c Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/xfs_error.c Fri Mar 5 05:02:51 2004 @@ -218,13 +218,17 @@ static void xfs_fs_vcmn_err(int level, xfs_mount_t *mp, char *fmt, va_list ap) { - char *newfmt; - int len = 16 + mp->m_fsname_len + strlen(fmt); - - newfmt = kmem_alloc(len, KM_SLEEP); - sprintf(newfmt, "Filesystem \"%s\": %s", mp->m_fsname, fmt); - icmn_err(level, newfmt, ap); - kmem_free(newfmt, len); + if (mp != NULL) { + char *newfmt; + int len = 16 + mp->m_fsname_len + strlen(fmt); + + newfmt = kmem_alloc(len, KM_SLEEP); + sprintf(newfmt, "Filesystem \"%s\": %s", mp->m_fsname, fmt); + icmn_err(level, newfmt, ap); + kmem_free(newfmt, len); + } else { + icmn_err(level, fmt, ap); + } } void @@ -267,16 +271,10 @@ inst_t *ra) { if (level <= xfs_error_level) { - if (mp != NULL) { - xfs_cmn_err(XFS_PTAG_ERROR_REPORT, - CE_ALERT, mp, - "XFS internal error %s at line %d of file %s. Caller 0x%p\n", - tag, linenum, fname, ra); - } else { - cmn_err(CE_ALERT, + xfs_cmn_err(XFS_PTAG_ERROR_REPORT, + CE_ALERT, mp, "XFS internal error %s at line %d of file %s. Caller 0x%p\n", - tag, linenum, fname, ra); - } + tag, linenum, fname, ra); xfs_stack_trace(); } diff -Nru a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h --- a/fs/xfs/xfs_fs.h Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/xfs_fs.h Fri Mar 5 05:02:51 2004 @@ -437,6 +437,12 @@ #define FSHSIZE sizeof(fsid_t) +/* + * Flags for going down operation + */ +#define XFS_FSOP_GOING_FLAGS_DEFAULT 0x0 /* going down */ +#define XFS_FSOP_GOING_FLAGS_LOGFLUSH 0x1 /* flush log but not data */ +#define XFS_FSOP_GOING_FLAGS_NOLOGFLUSH 0x2 /* don't flush log nor data */ /* * ioctl commands that replace IRIX fcntl()'s @@ -490,6 +496,7 @@ #define XFS_IOC_ATTRLIST_BY_HANDLE _IOW ('X', 122, struct xfs_fsop_attrlist_handlereq) #define XFS_IOC_ATTRMULTI_BY_HANDLE _IOW ('X', 123, struct xfs_fsop_attrmulti_handlereq) #define XFS_IOC_FSGEOMETRY _IOR ('X', 124, struct xfs_fsop_geom) +#define XFS_IOC_GOINGDOWN _IOR ('X', 125, __uint32_t) /* XFS_IOC_GETFSUUID ---------- deprecated 140 */ diff -Nru a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c --- a/fs/xfs/xfs_fsops.c Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/xfs_fsops.c Fri Mar 5 05:02:51 2004 @@ -626,3 +626,28 @@ xfs_finish_freeze(mp); return 0; } + +int +xfs_fs_goingdown( + xfs_mount_t *mp, + __uint32_t inflags) +{ + switch (inflags) + { + case XFS_FSOP_GOING_FLAGS_DEFAULT: + xfs_fs_freeze(mp); + xfs_force_shutdown(mp, XFS_FORCE_UMOUNT); + xfs_fs_thaw(mp); + break; + case XFS_FSOP_GOING_FLAGS_LOGFLUSH: + xfs_force_shutdown(mp, XFS_FORCE_UMOUNT); + break; + case XFS_FSOP_GOING_FLAGS_NOLOGFLUSH: + xfs_force_shutdown(mp, XFS_FORCE_UMOUNT|XFS_LOG_IO_ERROR); + break; + default: + return XFS_ERROR(EINVAL); + } + + return 0; +} diff -Nru a/fs/xfs/xfs_fsops.h b/fs/xfs/xfs_fsops.h --- a/fs/xfs/xfs_fsops.h Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/xfs_fsops.h Fri Mar 5 05:02:51 2004 @@ -67,4 +67,9 @@ xfs_fs_thaw( xfs_mount_t *mp); +int +xfs_fs_goingdown( + xfs_mount_t *mp, + __uint32_t inflags); + #endif /* __XFS_FSOPS_H__ */ diff -Nru a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c --- a/fs/xfs/xfs_iomap.c Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/xfs_iomap.c Fri Mar 5 05:02:51 2004 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -69,6 +69,76 @@ #include "xfs_utils.h" #include "xfs_iomap.h" +#if defined(XFS_RW_TRACE) +void +xfs_iomap_enter_trace( + int tag, + xfs_iocore_t *io, + xfs_off_t offset, + ssize_t count) +{ + xfs_inode_t *ip = XFS_IO_INODE(io); + + if (!ip->i_rwtrace) + return; + + ktrace_enter(ip->i_rwtrace, + (void *)((unsigned long)tag), + (void *)ip, + (void *)((unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff)), + (void *)((unsigned long)(ip->i_d.di_size & 0xffffffff)), + (void *)((unsigned long)((offset >> 32) & 0xffffffff)), + (void *)((unsigned long)(offset & 0xffffffff)), + (void *)((unsigned long)count), + (void *)((unsigned long)((io->io_new_size >> 32) & 0xffffffff)), + (void *)((unsigned long)(io->io_new_size & 0xffffffff)), + (void *)NULL, + (void *)NULL, + (void *)NULL, + (void *)NULL, + (void *)NULL, + (void *)NULL, + (void *)NULL); +} + +void +xfs_iomap_map_trace( + int tag, + xfs_iocore_t *io, + xfs_off_t offset, + ssize_t count, + xfs_iomap_t *iomapp, + xfs_bmbt_irec_t *imapp, + int flags) +{ + xfs_inode_t *ip = XFS_IO_INODE(io); + + if (!ip->i_rwtrace) + return; + + ktrace_enter(ip->i_rwtrace, + (void *)((unsigned long)tag), + (void *)ip, + (void *)((unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff)), + (void *)((unsigned long)(ip->i_d.di_size & 0xffffffff)), + (void *)((unsigned long)((offset >> 32) & 0xffffffff)), + (void *)((unsigned long)(offset & 0xffffffff)), + (void *)((unsigned long)count), + (void *)((unsigned long)flags), + (void *)((unsigned long)((iomapp->iomap_offset >> 32) & 0xffffffff)), + (void *)((unsigned long)(iomapp->iomap_offset & 0xffffffff)), + (void *)((unsigned long)(iomapp->iomap_delta)), + (void *)((unsigned long)(iomapp->iomap_bsize)), + (void *)((unsigned long)(iomapp->iomap_bn)), + (void *)(__psint_t)(imapp->br_startoff), + (void *)((unsigned long)(imapp->br_blockcount)), + (void *)(__psint_t)(imapp->br_startblock)); +} +#else +#define xfs_iomap_enter_trace(tag, io, offset, count) +#define xfs_iomap_map_trace(tag, io, offset, count, iomapp, imapp, flags) +#endif + #define XFS_WRITEIO_ALIGN(mp,off) (((off) >> mp->m_writeio_log) \ << mp->m_writeio_log) #define XFS_STRAT_WRITE_IMAPS 2 @@ -149,17 +219,20 @@ (BMAPI_READ | BMAPI_WRITE | BMAPI_ALLOCATE | BMAPI_UNWRITTEN | BMAPI_DEVICE)) { case BMAPI_READ: + xfs_iomap_enter_trace(XFS_IOMAP_READ_ENTER, io, offset, count); lockmode = XFS_LCK_MAP_SHARED(mp, io); bmapi_flags = XFS_BMAPI_ENTIRE; if (flags & BMAPI_IGNSTATE) bmapi_flags |= XFS_BMAPI_IGSTATE; break; case BMAPI_WRITE: + xfs_iomap_enter_trace(XFS_IOMAP_WRITE_ENTER, io, offset, count); lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR; bmapi_flags = 0; XFS_ILOCK(mp, io, lockmode); break; case BMAPI_ALLOCATE: + xfs_iomap_enter_trace(XFS_IOMAP_ALLOC_ENTER, io, offset, count); lockmode = XFS_ILOCK_SHARED|XFS_EXTSIZE_RD; bmapi_flags = XFS_BMAPI_ENTIRE; /* Attempt non-blocking lock */ @@ -201,8 +274,11 @@ switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) { case BMAPI_WRITE: /* If we found an extent, return it */ - if (nimaps && (imap.br_startblock != HOLESTARTBLOCK)) + if (nimaps && (imap.br_startblock != HOLESTARTBLOCK)) { + xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io, + offset, count, iomapp, &imap, flags); break; + } if (flags & (BMAPI_DIRECT|BMAPI_MMAP)) { error = XFS_IOMAP_WRITE_DIRECT(mp, io, offset, @@ -211,6 +287,10 @@ error = XFS_IOMAP_WRITE_DELAY(mp, io, offset, count, flags, &imap, &nimaps); } + if (!error) { + xfs_iomap_map_trace(XFS_IOMAP_ALLOC_MAP, io, + offset, count, iomapp, &imap, flags); + } iomap_flags = IOMAP_NEW; break; case BMAPI_ALLOCATE: @@ -218,8 +298,11 @@ XFS_IUNLOCK(mp, io, lockmode); lockmode = 0; - if (nimaps && !ISNULLSTARTBLOCK(imap.br_startblock)) + if (nimaps && !ISNULLSTARTBLOCK(imap.br_startblock)) { + xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io, + offset, count, iomapp, &imap, flags); break; + } error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, &imap, &nimaps); break; @@ -309,7 +392,6 @@ * Make sure that the dquots are there. This doesn't hold * the ilock across a disk read. */ - error = XFS_QM_DQATTACH(ip->i_mount, ip, XFS_QMOPT_ILOCKED); if (error) return XFS_ERROR(error); @@ -540,8 +622,9 @@ * If bmapi returned us nothing, and if we didn't get back EDQUOT, * then we must have run out of space. */ - if (nimaps == 0) { + xfs_iomap_enter_trace(XFS_IOMAP_WRITE_NOSPACE, + io, offset, count); if (xfs_flush_space(ip, &fsynced, &ioflag)) return XFS_ERROR(ENOSPC); @@ -584,7 +667,6 @@ /* * Make sure that the dquots are there. */ - if ((error = XFS_QM_DQATTACH(mp, ip, 0))) return XFS_ERROR(error); @@ -612,7 +694,6 @@ XFS_WRITE_LOG_RES(mp), 0, XFS_TRANS_PERM_LOG_RES, XFS_WRITE_LOG_COUNT); - if (error == ENOSPC) { error = xfs_trans_reserve(tp, 0, XFS_WRITE_LOG_RES(mp), @@ -653,19 +734,16 @@ error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb, XFS_BMAPI_WRITE, &first_block, 1, imap, &nimaps, &free_list); - if (error) goto trans_cancel; error = xfs_bmap_finish(&tp, &free_list, first_block, &committed); - if (error) goto trans_cancel; error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL); - if (error) goto error0; @@ -724,6 +802,9 @@ int nimaps; xfs_fsblock_t firstfsb; xfs_bmap_free_t free_list; + + xfs_iomap_enter_trace(XFS_IOMAP_UNWRITTEN, + &ip->i_iocore, offset, count); offset_fsb = XFS_B_TO_FSBT(mp, offset); count_fsb = XFS_B_TO_FSB(mp, count); diff -Nru a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c --- a/fs/xfs/xfs_log.c Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/xfs_log.c Fri Mar 5 05:02:51 2004 @@ -759,8 +759,9 @@ /* Also an invalid lsn. 1 implies that we aren't passing in a valid * tail_lsn. */ - if (tail_lsn != 1) + if (tail_lsn != 1) { log->l_tail_lsn = tail_lsn; + } if ((tic = log->l_write_headq)) { #ifdef DEBUG @@ -866,10 +867,11 @@ tail_lsn = xfs_trans_tail_ail(mp); s = GRANT_LOCK(log); - if (tail_lsn != 0) + if (tail_lsn != 0) { log->l_tail_lsn = tail_lsn; - else + } else { tail_lsn = log->l_tail_lsn = log->l_last_sync_lsn; + } GRANT_UNLOCK(log, s); return tail_lsn; @@ -921,10 +923,8 @@ * In this case we just want to return the size of the * log as the amount of space left. */ -/* This assert does not take into account padding from striped log writes * ASSERT((tail_cycle == (cycle + 1)) || ((bytes + log->l_roundoff) >= tail_bytes)); -*/ free_bytes = log->l_logsize; } return free_bytes; @@ -1183,14 +1183,6 @@ log->l_grant_reserve_cycle = 1; log->l_grant_write_cycle = 1; - if (XFS_SB_VERSION_HASLOGV2(&mp->m_sb)) { - if (mp->m_sb.sb_logsunit <= 1) { - log->l_stripemask = 1; - } else { - log->l_stripemask = 1 << - xfs_highbit32(mp->m_sb.sb_logsunit >> BBSHIFT); - } - } if (XFS_SB_VERSION_HASSECTOR(&mp->m_sb)) { log->l_sectbb_log = mp->m_sb.sb_logsectlog - BBSHIFT; ASSERT(log->l_sectbb_log <= mp->m_sectbb_log); @@ -1401,45 +1393,35 @@ xfs_caddr_t dptr; /* pointer to byte sized element */ xfs_buf_t *bp; int i, ops; - uint roundup; uint count; /* byte count of bwrite */ + uint count_init; /* initial count before roundup */ int split = 0; /* split write into two regions */ int error; XFS_STATS_INC(xs_log_writes); ASSERT(iclog->ic_refcnt == 0); + /* Add for LR header */ + count_init = log->l_iclog_hsize + iclog->ic_offset; + /* Round out the log write size */ - if (iclog->ic_offset & BBMASK) { - /* count of 0 is already accounted for up in - * xlog_state_sync_all(). Once in this routine, - * operations on the iclog are single threaded. - * - * Difference between rounded up size and size - */ - count = iclog->ic_offset & BBMASK; - iclog->ic_roundoff += BBSIZE - count; - } - if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) { - unsigned sunit = BTOBB(log->l_mp->m_sb.sb_logsunit); - if (!sunit) - sunit = 1; - - count = BTOBB(log->l_iclog_hsize + iclog->ic_offset); - if (count & (sunit - 1)) { - roundup = sunit - (count & (sunit - 1)); - } else { - roundup = 0; - } - iclog->ic_offset += BBTOB(roundup); + if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb) && + log->l_mp->m_sb.sb_logsunit > 1) { + /* we have a v2 stripe unit to use */ + count = XLOG_LSUNITTOB(log, XLOG_BTOLSUNIT(log, count_init)); + } else { + count = BBTOB(BTOBB(count_init)); } - + iclog->ic_roundoff = count - count_init; log->l_roundoff += iclog->ic_roundoff; xlog_pack_data(log, iclog); /* put cycle number in every block */ /* real byte length */ - INT_SET(iclog->ic_header.h_len, ARCH_CONVERT, iclog->ic_offset); + INT_SET(iclog->ic_header.h_len, + ARCH_CONVERT, + iclog->ic_offset + iclog->ic_roundoff); + /* put ops count in correct order */ ops = iclog->ic_header.h_num_logops; INT_SET(iclog->ic_header.h_num_logops, ARCH_CONVERT, ops); @@ -1449,12 +1431,6 @@ XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)2); XFS_BUF_SET_ADDR(bp, BLOCK_LSN(iclog->ic_header.h_lsn, ARCH_CONVERT)); - /* Count is already rounded up to a BBSIZE above */ - count = iclog->ic_offset + iclog->ic_roundoff; - ASSERT((count & BBMASK) == 0); - - /* Add for LR header */ - count += log->l_iclog_hsize; XFS_STATS_ADD(xs_log_blocks, BTOBB(count)); /* Do we need to split this write into 2 parts? */ @@ -2783,8 +2759,6 @@ xlog_in_core_t *iclog, int eventual_size) { - uint roundup; - ASSERT(iclog->ic_state == XLOG_STATE_ACTIVE); if (!eventual_size) eventual_size = iclog->ic_offset; @@ -2797,14 +2771,10 @@ log->l_curr_block += BTOBB(eventual_size)+BTOBB(log->l_iclog_hsize); /* Round up to next log-sunit */ - if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) { - if (log->l_curr_block & (log->l_stripemask - 1)) { - roundup = log->l_stripemask - - (log->l_curr_block & (log->l_stripemask - 1)); - } else { - roundup = 0; - } - log->l_curr_block += roundup; + if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb) && + log->l_mp->m_sb.sb_logsunit > 1) { + __uint32_t sunit_bb = BTOBB(log->l_mp->m_sb.sb_logsunit); + log->l_curr_block = roundup(log->l_curr_block, sunit_bb); } if (log->l_curr_block >= log->l_logBBsize) { diff -Nru a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h --- a/fs/xfs/xfs_log_priv.h Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/xfs_log_priv.h Fri Mar 5 05:02:51 2004 @@ -63,6 +63,9 @@ #else #define XLOG_BTOLRBB(b) (((b)+XLOG_RECORD_BSIZE-1) >> XLOG_RECORD_BSHIFT) #endif +#define XLOG_BTOLSUNIT(log, b) (((b)+(log)->l_mp->m_sb.sb_logsunit-1) / \ + (log)->l_mp->m_sb.sb_logsunit) +#define XLOG_LSUNITTOB(log, su) ((su) * (log)->l_mp->m_sb.sb_logsunit) #define XLOG_HEADER_SIZE 512 @@ -531,7 +534,6 @@ uint l_flags; uint l_quotaoffs_flag; /* XFS_DQ_*, for QUOTAOFFs */ struct xfs_buf_cancel **l_buf_cancel_table; - int l_stripemask; /* log stripe mask */ int l_iclog_hsize; /* size of iclog header */ int l_iclog_heads; /* # of iclog header sectors */ uint l_sectbb_log; /* log2 of sector size in BBs */ diff -Nru a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c --- a/fs/xfs/xfs_log_recover.c Fri Mar 5 05:02:52 2004 +++ b/fs/xfs/xfs_log_recover.c Fri Mar 5 05:02:52 2004 @@ -3416,6 +3416,7 @@ { uint *up = (uint *)dp; uint chksum = 0; + int i; /* divide length by 4 to get # words */ for (i=0; i < INT_GET(rhead->h_len, ARCH_CONVERT) >> 2; i++) { @@ -3476,7 +3477,7 @@ xlog_rec_header_t *rhead, xfs_daddr_t blkno) { - int bblks; + int hlen; if (unlikely( (INT_GET(rhead->h_magicno, ARCH_CONVERT) != @@ -3495,8 +3496,8 @@ } /* LR body must have data or it wouldn't have been written */ - bblks = INT_GET(rhead->h_len, ARCH_CONVERT); - if (unlikely( bblks <= 0 || bblks > INT_MAX )) { + hlen = INT_GET(rhead->h_len, ARCH_CONVERT); + if (unlikely( hlen <= 0 || hlen > INT_MAX )) { XFS_ERROR_REPORT("xlog_valid_rec_header(2)", XFS_ERRLEVEL_LOW, log->l_mp); return XFS_ERROR(EFSCORRUPTED); @@ -3658,7 +3659,7 @@ error = xlog_bread(log, 0, wrapped_hblks, hbp); if (error) goto bread_err2; - XFS_BUF_SET_PTR(hbp, bufaddr, hblks); + XFS_BUF_SET_PTR(hbp, bufaddr, BBTOB(hblks)); if (!offset) offset = xlog_align(log, 0, wrapped_hblks, hbp); @@ -3716,8 +3717,7 @@ if ((error = xlog_bread(log, wrapped_hblks, bblks - split_bblks, dbp))) goto bread_err2; - XFS_BUF_SET_PTR(dbp, bufaddr, - XLOG_BIG_RECORD_BSIZE); + XFS_BUF_SET_PTR(dbp, bufaddr, h_size); if (!offset) offset = xlog_align(log, wrapped_hblks, bblks - split_bblks, dbp); @@ -4042,7 +4042,7 @@ XFS_FSS_TO_BB(mp, 1), 0); if (XFS_BUF_ISERROR(agibp)) { xfs_ioerror_alert("xlog_recover_check_summary(agi)", - log->l_mp, agibp, agidaddr); + mp, agibp, agidaddr); } agip = XFS_BUF_TO_AGI(agibp); ASSERT(XFS_AGI_MAGIC == @@ -4058,7 +4058,8 @@ sbbp = xfs_getsb(mp, 0); #ifdef XFS_LOUD_RECOVERY - sbp = XFS_BUF_TO_SBP(sbbp); + sbp = &mp->m_sb; + xfs_xlatesb(XFS_BUF_TO_SBP(sbbp), sbp, 1, ARCH_CONVERT, XFS_SB_ALL_BITS); cmn_err(CE_NOTE, "xlog_recover_check_summary: sb_icount %Lu itotal %Lu", sbp->sb_icount, itotal); diff -Nru a/fs/xfs/xfs_macros.c b/fs/xfs/xfs_macros.c --- a/fs/xfs/xfs_macros.c Fri Mar 5 05:02:52 2004 +++ b/fs/xfs/xfs_macros.c Fri Mar 5 05:02:52 2004 @@ -115,35 +115,11 @@ } #endif -#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_AG_BEST_BLOCKS) -xfs_extlen_t -xfs_ag_best_blocks(int bl, xfs_drfsbno_t blks) -{ - return XFS_AG_BEST_BLOCKS(bl, blks); -} -#endif - -#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_AG_MAX_BLOCKS) -xfs_extlen_t -xfs_ag_max_blocks(int bl) -{ - return XFS_AG_MAX_BLOCKS(bl); -} -#endif - #if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_AG_MAXLEVELS) int xfs_ag_maxlevels(xfs_mount_t *mp) { return XFS_AG_MAXLEVELS(mp); -} -#endif - -#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_AG_MIN_BLOCKS) -xfs_extlen_t -xfs_ag_min_blocks(int bl) -{ - return XFS_AG_MIN_BLOCKS(bl); } #endif diff -Nru a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c --- a/fs/xfs/xfs_mount.c Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/xfs_mount.c Fri Mar 5 05:02:51 2004 @@ -675,6 +675,7 @@ error = XFS_ERROR(EINVAL); goto error1; } + mp->m_dalign = mp->m_swidth = 0; } else { /* * Convert the stripe unit and width to FSBs. diff -Nru a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h --- a/fs/xfs/xfs_mount.h Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/xfs_mount.h Fri Mar 5 05:02:51 2004 @@ -571,8 +571,8 @@ extern struct vfsops xfs_vfsops; extern struct vnodeops xfs_vnodeops; -extern struct xfs_dmops xfs_dmcore_xfs; -extern struct xfs_qmops xfs_qmcore_xfs; +extern struct xfs_dmops xfs_dmcore_stub; +extern struct xfs_qmops xfs_qmcore_stub; extern struct xfs_ioops xfs_iocore_xfs; extern int xfs_init(void); diff -Nru a/fs/xfs/xfs_qmops.c b/fs/xfs/xfs_qmops.c --- a/fs/xfs/xfs_qmops.c Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/xfs_qmops.c Fri Mar 5 05:02:51 2004 @@ -54,7 +54,7 @@ return NULL; } -xfs_qmops_t xfs_qmcore_xfs = { +xfs_qmops_t xfs_qmcore_stub = { .xfs_qminit = (xfs_qminit_t) fs_noerr, .xfs_qmdone = (xfs_qmdone_t) fs_noerr, .xfs_qmmount = (xfs_qmmount_t) fs_noerr, diff -Nru a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h --- a/fs/xfs/xfs_quota.h Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/xfs_quota.h Fri Mar 5 05:02:51 2004 @@ -347,9 +347,6 @@ extern struct bhv_vfsops xfs_qmops; -extern void xfs_qm_init(void); -extern void xfs_qm_exit(void); - #endif /* __KERNEL__ */ #endif /* __XFS_QUOTA_H__ */ diff -Nru a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c --- a/fs/xfs/xfs_vfsops.c Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/xfs_vfsops.c Fri Mar 5 05:02:51 2004 @@ -451,9 +451,9 @@ * Setup xfs_mount function vectors from available behaviors */ p = vfs_bhv_lookup(vfsp, VFS_POSITION_DM); - mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_xfs; + mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_stub; p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM); - mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_xfs; + mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_stub; p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO); mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs; diff -Nru a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c --- a/fs/xfs/xfs_vnodeops.c Fri Mar 5 05:02:51 2004 +++ b/fs/xfs/xfs_vnodeops.c Fri Mar 5 05:02:51 2004 @@ -413,8 +413,9 @@ } else { if (DM_EVENT_ENABLED (vp->v_vfsp, ip, DM_EVENT_TRUNCATE) && !(flags & ATTR_DMI)) { + int dmflags = AT_DELAY_FLAG(flags) | DM_SEM_FLAG_WR; code = XFS_SEND_DATA(mp, DM_EVENT_TRUNCATE, vp, - vap->va_size, 0, AT_DELAY_FLAG(flags), NULL); + vap->va_size, 0, dmflags, NULL); if (code) { lock_flags = 0; goto error_return; diff -Nru a/include/linux/jhash.h b/include/linux/jhash.h --- a/include/linux/jhash.h Fri Mar 5 05:02:51 2004 +++ b/include/linux/jhash.h Fri Mar 5 05:02:51 2004 @@ -41,10 +41,10 @@ * of bytes. No alignment or length assumptions are made about * the input key. */ -static inline u32 jhash(void *key, u32 length, u32 initval) +static inline u32 jhash(const void *key, u32 length, u32 initval) { u32 a, b, c, len; - u8 *k = key; + const u8 *k = key; len = length; a = b = JHASH_GOLDEN_RATIO; diff -Nru a/include/linux/netfilter_ipv4/ip_nat.h b/include/linux/netfilter_ipv4/ip_nat.h --- a/include/linux/netfilter_ipv4/ip_nat.h Fri Mar 5 05:02:52 2004 +++ b/include/linux/netfilter_ipv4/ip_nat.h Fri Mar 5 05:02:52 2004 @@ -105,9 +105,6 @@ /* Manipulations to be done on this conntrack. */ struct ip_nat_info_manip manips[IP_NAT_MAX_MANIPS]; - /* The mapping type which created us (NULL for null mapping). */ - const struct ip_nat_mapping_type *mtype; - struct ip_nat_hash bysource, byipsproto; /* Helper (NULL if none). */ diff -Nru a/include/linux/netfilter_ipv4/listhelp.h b/include/linux/netfilter_ipv4/listhelp.h --- a/include/linux/netfilter_ipv4/listhelp.h Fri Mar 5 05:02:51 2004 +++ b/include/linux/netfilter_ipv4/listhelp.h Fri Mar 5 05:02:51 2004 @@ -28,7 +28,7 @@ \ ASSERT_WRITE_LOCK(head); \ list_for_each(__i, (head)) \ - if (cmpfn((const type)__i , ## args)) { \ + if (cmpfn((type)__i , ## args)) { \ __j = __i; \ break; \ } \ diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h --- a/include/linux/pci_ids.h Fri Mar 5 05:02:51 2004 +++ b/include/linux/pci_ids.h Fri Mar 5 05:02:51 2004 @@ -287,6 +287,8 @@ #define PCI_DEVICE_ID_ATI_RADEON_Ig 0x4967 /* Radeon RV280 (9200) */ #define PCI_DEVICE_ID_ATI_RADEON_Y_ 0x5960 +#define PCI_DEVICE_ID_ATI_RADEON_Ya 0x5961 +#define PCI_DEVICE_ID_ATI_RADEON_Yd 0x5964 /* Radeon R300 (9700) */ #define PCI_DEVICE_ID_ATI_RADEON_ND 0x4e44 #define PCI_DEVICE_ID_ATI_RADEON_NE 0x4e45 diff -Nru a/include/linux/sctp.h b/include/linux/sctp.h --- a/include/linux/sctp.h Fri Mar 5 05:02:51 2004 +++ b/include/linux/sctp.h Fri Mar 5 05:02:51 2004 @@ -61,14 +61,14 @@ __u16 dest; __u32 vtag; __u32 checksum; -} sctp_sctphdr_t __attribute__((packed)); +} __attribute__((packed)) sctp_sctphdr_t; /* Section 3.2. Chunk Field Descriptions. */ typedef struct sctp_chunkhdr { __u8 type; __u8 flags; __u16 length; -} sctp_chunkhdr_t __attribute__((packed)); +} __attribute__((packed)) sctp_chunkhdr_t; /* Section 3.2. Chunk Type Values. @@ -152,7 +152,7 @@ typedef struct sctp_paramhdr { __u16 type; __u16 length; -} sctp_paramhdr_t __attribute((packed)); +} __attribute__((packed)) sctp_paramhdr_t; typedef enum { @@ -202,12 +202,12 @@ __u16 ssn; __u32 ppid; __u8 payload[0]; -} sctp_datahdr_t __attribute__((packed)); +} __attribute__((packed)) sctp_datahdr_t; typedef struct sctp_data_chunk { sctp_chunkhdr_t chunk_hdr; sctp_datahdr_t data_hdr; -} sctp_data_chunk_t __attribute__((packed)); +} __attribute__((packed)) sctp_data_chunk_t; /* DATA Chuck Specific Flags */ enum { @@ -232,48 +232,48 @@ __u16 num_inbound_streams; __u32 initial_tsn; __u8 params[0]; -} sctp_inithdr_t __attribute__((packed)); +} __attribute__((packed)) sctp_inithdr_t; typedef struct sctp_init_chunk { sctp_chunkhdr_t chunk_hdr; sctp_inithdr_t init_hdr; -} sctp_init_chunk_t __attribute__((packed)); +} __attribute__((packed)) sctp_init_chunk_t; /* Section 3.3.2.1. IPv4 Address Parameter (5) */ typedef struct sctp_ipv4addr_param { sctp_paramhdr_t param_hdr; struct in_addr addr; -} sctp_ipv4addr_param_t __attribute__((packed)); +} __attribute__((packed)) sctp_ipv4addr_param_t; /* Section 3.3.2.1. IPv6 Address Parameter (6) */ typedef struct sctp_ipv6addr_param { sctp_paramhdr_t param_hdr; struct in6_addr addr; -} sctp_ipv6addr_param_t __attribute__((packed)); +} __attribute__((packed)) sctp_ipv6addr_param_t; /* Section 3.3.2.1 Cookie Preservative (9) */ typedef struct sctp_cookie_preserve_param { sctp_paramhdr_t param_hdr; uint32_t lifespan_increment; -} sctp_cookie_preserve_param_t __attribute__((packed)); +} __attribute__((packed)) sctp_cookie_preserve_param_t; /* Section 3.3.2.1 Host Name Address (11) */ typedef struct sctp_hostname_param { sctp_paramhdr_t param_hdr; uint8_t hostname[0]; -} sctp_hostname_param_t __attribute__((packed)); +} __attribute__((packed)) sctp_hostname_param_t; /* Section 3.3.2.1 Supported Address Types (12) */ typedef struct sctp_supported_addrs_param { sctp_paramhdr_t param_hdr; uint16_t types[0]; -} sctp_supported_addrs_param_t __attribute__((packed)); +} __attribute__((packed)) sctp_supported_addrs_param_t; /* Appendix A. ECN Capable (32768) */ typedef struct sctp_ecn_capable_param { sctp_paramhdr_t param_hdr; -} sctp_ecn_capable_param_t __attribute__((packed)); +} __attribute__((packed)) sctp_ecn_capable_param_t; @@ -287,13 +287,13 @@ typedef struct sctp_cookie_param { sctp_paramhdr_t p; __u8 body[0]; -} sctp_cookie_param_t __attribute__((packed)); +} __attribute__((packed)) sctp_cookie_param_t; /* Section 3.3.3.1 Unrecognized Parameters (8) */ typedef struct sctp_unrecognized_param { sctp_paramhdr_t param_hdr; sctp_paramhdr_t unrecognized; -} sctp_unrecognized_param_t __attribute__((packed)); +} __attribute__((packed)) sctp_unrecognized_param_t; @@ -308,7 +308,7 @@ typedef struct sctp_gap_ack_block { __u16 start; __u16 end; -} sctp_gap_ack_block_t __attribute__((packed)); +} __attribute__((packed)) sctp_gap_ack_block_t; typedef uint32_t sctp_dup_tsn_t; @@ -323,12 +323,12 @@ __u16 num_gap_ack_blocks; __u16 num_dup_tsns; sctp_sack_variable_t variable[0]; -} sctp_sackhdr_t __attribute__((packed)); +} __attribute__((packed)) sctp_sackhdr_t; typedef struct sctp_sack_chunk { sctp_chunkhdr_t chunk_hdr; sctp_sackhdr_t sack_hdr; -} sctp_sack_chunk_t __attribute__((packed)); +} __attribute__((packed)) sctp_sack_chunk_t; /* RFC 2960. Section 3.3.5 Heartbeat Request (HEARTBEAT) (4): @@ -340,12 +340,12 @@ typedef struct sctp_heartbeathdr { sctp_paramhdr_t info; -} sctp_heartbeathdr_t __attribute__((packed)); +} __attribute__((packed)) sctp_heartbeathdr_t; typedef struct sctp_heartbeat_chunk { sctp_chunkhdr_t chunk_hdr; sctp_heartbeathdr_t hb_hdr; -} sctp_heartbeat_chunk_t __attribute__((packed)); +} __attribute__((packed)) sctp_heartbeat_chunk_t; /* For the abort and shutdown ACK we must carry the init tag in the @@ -354,7 +354,7 @@ */ typedef struct sctp_abort_chunk { sctp_chunkhdr_t uh; -} sctp_abort_chunkt_t __attribute__((packed)); +} __attribute__((packed)) sctp_abort_chunkt_t; /* For the graceful shutdown we must carry the tag (in common header) @@ -362,14 +362,12 @@ */ typedef struct sctp_shutdownhdr { __u32 cum_tsn_ack; -} sctp_shutdownhdr_t __attribute__((packed)); +} __attribute__((packed)) sctp_shutdownhdr_t; struct sctp_shutdown_chunk_t { sctp_chunkhdr_t chunk_hdr; sctp_shutdownhdr_t shutdown_hdr; -} __attribute__((packed)); - - +} __attribute__ ((packed)); /* RFC 2960. Section 3.3.10 Operation Error (ERROR) (9) */ @@ -377,12 +375,12 @@ __u16 cause; __u16 length; __u8 variable[0]; -} sctp_errhdr_t __attribute__((packed)); +} __attribute__((packed)) sctp_errhdr_t; typedef struct sctp_operr_chunk { sctp_chunkhdr_t chunk_hdr; sctp_errhdr_t err_hdr; -} sctp_operr_chunk_t __attribute__((packed)); +} __attribute__((packed)) sctp_operr_chunk_t; /* RFC 2960 3.3.10 - Operation Error * @@ -460,7 +458,7 @@ typedef struct sctp_ecne_chunk { sctp_chunkhdr_t chunk_hdr; sctp_ecnehdr_t ence_hdr; -} sctp_ecne_chunk_t __attribute__((packed)); +} __attribute__((packed)) sctp_ecne_chunk_t; /* RFC 2960. Appendix A. Explicit Congestion Notification. * Congestion Window Reduced (CWR) (13) @@ -472,7 +470,7 @@ typedef struct sctp_cwr_chunk { sctp_chunkhdr_t chunk_hdr; sctp_cwrhdr_t cwr_hdr; -} sctp_cwr_chunk_t __attribute__((packed)); +} __attribute__((packed)) sctp_cwr_chunk_t; /* * ADDIP Section 3.1 New Chunk Types @@ -513,16 +511,16 @@ typedef struct sctp_addip_param { sctp_paramhdr_t param_hdr; __u32 crr_id; -}sctp_addip_param_t __attribute__((packed)); +} __attribute__((packed)) sctp_addip_param_t; typedef struct sctp_addiphdr { __u32 serial; __u8 params[0]; -} sctp_addiphdr_t __attribute__((packed)); +} __attribute__((packed)) sctp_addiphdr_t; typedef struct sctp_addip_chunk { sctp_chunkhdr_t chunk_hdr; sctp_addiphdr_t addip_hdr; -} sctp_addip_chunk_t __attribute__((packed)); +} __attribute__((packed)) sctp_addip_chunk_t; #endif /* __LINUX_SCTP_H__ */ diff -Nru a/include/linux/skbuff.h b/include/linux/skbuff.h --- a/include/linux/skbuff.h Fri Mar 5 05:02:51 2004 +++ b/include/linux/skbuff.h Fri Mar 5 05:02:51 2004 @@ -221,9 +221,6 @@ #endif }; -#define SK_WMEM_MAX 65535 -#define SK_RMEM_MAX 65535 - #ifdef __KERNEL__ /* * Handling routines are only of interest to the kernel diff -Nru a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h --- a/include/net/sctp/sctp.h Fri Mar 5 05:02:51 2004 +++ b/include/net/sctp/sctp.h Fri Mar 5 05:02:51 2004 @@ -115,7 +115,7 @@ #define SCTP_STATIC static #endif -#define MSECS_TO_JIFFIES(msec) \ +#define SCTP_MSECS_TO_JIFFIES(msec) \ (((msec / 1000) * HZ) + ((msec % 1000) * HZ) / 1000) #define JIFFIES_TO_MSECS(jiff) \ (((jiff / HZ) * 1000) + ((jiff % HZ) * 1000) / HZ) diff -Nru a/include/net/sctp/structs.h b/include/net/sctp/structs.h --- a/include/net/sctp/structs.h Fri Mar 5 05:02:51 2004 +++ b/include/net/sctp/structs.h Fri Mar 5 05:02:51 2004 @@ -369,7 +369,7 @@ struct sctp_paramhdr param_hdr; union sctp_addr daddr; unsigned long sent_at; -} sctp_sender_hb_info_t __attribute__((packed)); +} __attribute__((packed)) sctp_sender_hb_info_t; /* * RFC 2960 1.3.2 Sequenced Delivery within Streams diff -Nru a/net/Makefile b/net/Makefile --- a/net/Makefile Fri Mar 5 05:02:51 2004 +++ b/net/Makefile Fri Mar 5 05:02:51 2004 @@ -15,10 +15,10 @@ subdir-$(CONFIG_NET) += 802 sched netlink +subdir-$(CONFIG_IPV6) += ipv6 subdir-$(CONFIG_INET) += ipv4 subdir-$(CONFIG_NETFILTER) += ipv4/netfilter subdir-$(CONFIG_UNIX) += unix -subdir-$(CONFIG_IPV6) += ipv6 subdir-$(CONFIG_IP_SCTP) += sctp ifneq ($(CONFIG_IPV6),n) diff -Nru a/net/atm/lec.c b/net/atm/lec.c --- a/net/atm/lec.c Fri Mar 5 05:02:51 2004 +++ b/net/atm/lec.c Fri Mar 5 05:02:51 2004 @@ -208,6 +208,22 @@ return 0; } +static __inline__ void +lec_send(struct atm_vcc *vcc, struct sk_buff *skb, struct lec_priv *priv) +{ + if (atm_may_send(vcc, skb->len)) { + atomic_add(skb->truesize, &vcc->sk->wmem_alloc); + ATM_SKB(skb)->vcc = vcc; + ATM_SKB(skb)->atm_options = vcc->atm_options; + priv->stats.tx_packets++; + priv->stats.tx_bytes += skb->len; + vcc->send(vcc, skb); + } else { + priv->stats.tx_dropped++; + dev_kfree_skb(skb); + } +} + static int lec_send_packet(struct sk_buff *skb, struct net_device *dev) { @@ -352,33 +368,10 @@ DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n", lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2], lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]); - ATM_SKB(skb2)->vcc = send_vcc; - ATM_SKB(skb2)->atm_options = send_vcc->atm_options; - DPRINTK("%s:sending to vpi:%d vci:%d\n", dev->name, - send_vcc->vpi, send_vcc->vci); - if (atm_may_send(send_vcc, skb2->len)) { - atomic_add(skb2->truesize, &send_vcc->sk->wmem_alloc); - priv->stats.tx_packets++; - priv->stats.tx_bytes += skb2->len; - send_vcc->send(send_vcc, skb2); - } else { - priv->stats.tx_dropped++; - dev_kfree_skb(skb2); - } + lec_send(send_vcc, skb2, priv); } - ATM_SKB(skb)->vcc = send_vcc; - ATM_SKB(skb)->atm_options = send_vcc->atm_options; - if (atm_may_send(send_vcc, skb->len)) { - atomic_add(skb->truesize, &send_vcc->sk->wmem_alloc); - priv->stats.tx_packets++; - priv->stats.tx_bytes += skb->len; - send_vcc->send(send_vcc, skb); - } else { - priv->stats.tx_dropped++; - dev_kfree_skb(skb); - } - + lec_send(send_vcc, skb, priv); #if 0 /* Should we wait for card's device driver to notify us? */ dev->tbusy=0; @@ -1043,7 +1036,7 @@ #define LEC_ARP_REFRESH_INTERVAL (3*HZ) static void lec_arp_check_expire(unsigned long data); -static __inline__ void lec_arp_expire_arp(unsigned long data); +static void lec_arp_expire_arp(unsigned long data); void dump_arp_table(struct lec_priv *priv); /* @@ -1383,7 +1376,7 @@ struct lec_arp_table *entry, *next; int i; - del_timer(&priv->lec_arp_timer); + del_timer_sync(&priv->lec_arp_timer); /* * Remove all entries @@ -1398,7 +1391,7 @@ entry = priv->lec_arp_empty_ones; while(entry) { next = entry->next; - del_timer(&entry->timer); + del_timer_sync(&entry->timer); lec_arp_clear_vccs(entry); kfree(entry); entry = next; @@ -1407,7 +1400,7 @@ entry = priv->lec_no_forward; while(entry) { next = entry->next; - del_timer(&entry->timer); + del_timer_sync(&entry->timer); lec_arp_clear_vccs(entry); kfree(entry); entry = next; @@ -1416,7 +1409,7 @@ entry = priv->mcast_fwds; while(entry) { next = entry->next; - del_timer(&entry->timer); + /* No timer, LANEv2 7.1.20 and 2.3.5.3 */ lec_arp_clear_vccs(entry); kfree(entry); entry = next; @@ -1490,8 +1483,6 @@ entry = (struct lec_arp_table *)data; - del_timer(&entry->timer); - DPRINTK("lec_arp_expire_arp\n"); if (entry->status == ESI_ARP_PENDING) { if (entry->no_tries <= entry->priv->max_retry_count) { @@ -1501,8 +1492,7 @@ send_to_lecd(entry->priv, l_arp_xmt, entry->mac_addr, NULL, NULL); entry->no_tries++; } - entry->timer.expires = jiffies + (1*HZ); - add_timer(&entry->timer); + mod_timer(&entry->timer, jiffies + (1*HZ)); } } @@ -1574,8 +1564,6 @@ unsigned long time_to_check; int i; - del_timer(&priv->lec_arp_timer); - DPRINTK("lec_arp_check_expire %p,%d\n",priv, atomic_read(&priv->lec_arp_users)); DPRINTK("expire: eo:%p nf:%p\n",priv->lec_arp_empty_ones, @@ -1619,6 +1607,10 @@ && time_after_eq(now, entry->timestamp+ priv->path_switching_delay)) { + struct sk_buff *skb; + + while ((skb = skb_dequeue(&entry->tx_wait))) + lec_send(entry->vcc, skb, entry->priv); entry->last_used = jiffies; entry->status = ESI_FORWARD_DIRECT; @@ -1629,8 +1621,8 @@ } lec_arp_put(priv); } - priv->lec_arp_timer.expires = jiffies + LEC_ARP_REFRESH_INTERVAL; - add_timer(&priv->lec_arp_timer); + + mod_timer(&priv->lec_arp_timer, jiffies + LEC_ARP_REFRESH_INTERVAL); } /* * Try to find vcc where mac_address is attached. @@ -2012,6 +2004,10 @@ for (entry=priv->lec_arp_tables[i];entry;entry=entry->next) { if (entry->flush_tran_id == tran_id && entry->status == ESI_FLUSH_PENDING) { + struct sk_buff *skb; + + while ((skb = skb_dequeue(&entry->tx_wait))) + lec_send(entry->vcc, skb, entry->priv); entry->status = ESI_FORWARD_DIRECT; DPRINTK("LEC_ARP: Flushed\n"); } diff -Nru a/net/core/dev.c b/net/core/dev.c --- a/net/core/dev.c Fri Mar 5 05:02:51 2004 +++ b/net/core/dev.c Fri Mar 5 05:02:51 2004 @@ -1462,7 +1462,7 @@ { struct packet_type *ptype, *pt_prev; int ret = NET_RX_DROP; - unsigned short type = skb->protocol; + unsigned short type; if (skb->stamp.tv_sec == 0) do_gettimeofday(&skb->stamp); @@ -1507,6 +1507,7 @@ } #endif + type = skb->protocol; for (ptype=ptype_base[ntohs(type)&15];ptype;ptype=ptype->next) { if (ptype->type == type && (!ptype->dev || ptype->dev == skb->dev)) { diff -Nru a/net/core/sock.c b/net/core/sock.c --- a/net/core/sock.c Fri Mar 5 05:02:51 2004 +++ b/net/core/sock.c Fri Mar 5 05:02:51 2004 @@ -128,6 +128,16 @@ #include #endif +/* Take into consideration the size of the struct sk_buff overhead in the + * determination of these values, since that is non-constant across + * platforms. This makes socket queueing behavior and performance + * not depend upon such differences. + */ +#define _SK_MEM_PACKETS 256 +#define _SK_MEM_OVERHEAD (sizeof(struct sk_buff) + 256) +#define SK_WMEM_MAX (_SK_MEM_OVERHEAD * _SK_MEM_PACKETS) +#define SK_RMEM_MAX (_SK_MEM_OVERHEAD * _SK_MEM_PACKETS) + /* Run time adjustable parameters. */ __u32 sysctl_wmem_max = SK_WMEM_MAX; __u32 sysctl_rmem_max = SK_RMEM_MAX; diff -Nru a/net/ipv4/icmp.c b/net/ipv4/icmp.c --- a/net/ipv4/icmp.c Fri Mar 5 05:02:52 2004 +++ b/net/ipv4/icmp.c Fri Mar 5 05:02:52 2004 @@ -984,7 +984,13 @@ panic("Failed to create the ICMP control socket.\n"); icmp_socket_cpu(i)->sk->allocation=GFP_ATOMIC; - icmp_socket_cpu(i)->sk->sndbuf = SK_WMEM_MAX*2; + + /* Enough space for 2 64K ICMP packets, including + * sk_buff struct overhead. + */ + icmp_socket_cpu(i)->sk->sndbuf = + (2 * ((64 * 1024) + sizeof(struct sk_buff))); + icmp_socket_cpu(i)->sk->protinfo.af_inet.ttl = MAXTTL; icmp_socket_cpu(i)->sk->protinfo.af_inet.pmtudisc = IP_PMTUDISC_DONT; diff -Nru a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c --- a/net/ipv4/ip_sockglue.c Fri Mar 5 05:02:51 2004 +++ b/net/ipv4/ip_sockglue.c Fri Mar 5 05:02:51 2004 @@ -608,10 +608,15 @@ } case IP_MSFILTER: { + extern int sysctl_optmem_max; struct ip_msfilter *msf; if (optlen < IP_MSFILTER_SIZE(0)) goto e_inval; + if (optlen > sysctl_optmem_max) { + err = -ENOBUFS; + break; + } msf = (struct ip_msfilter *)kmalloc(optlen, GFP_KERNEL); if (msf == 0) { err = -ENOBUFS; @@ -620,6 +625,13 @@ err = -EFAULT; if (copy_from_user(msf, optval, optlen)) { kfree(msf); + break; + } + if (IP_MSFILTER_SIZE(msf->imsf_numsrc) < + IP_MSFILTER_SIZE(0) || + IP_MSFILTER_SIZE(msf->imsf_numsrc) > optlen) { + kfree(msf); + err = -EINVAL; break; } err = ip_mc_msfilter(sk, msf, 0); diff -Nru a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c --- a/net/ipv4/netfilter/ipt_ECN.c Fri Mar 5 05:02:51 2004 +++ b/net/ipv4/netfilter/ipt_ECN.c Fri Mar 5 05:02:51 2004 @@ -4,7 +4,7 @@ * * This software is distributed under GNU GPL v2, 1991 * - * ipt_ECN.c,v 1.4 2002/08/05 19:36:51 laforge Exp + * ipt_ECN.c,v 1.7 2003/12/15 15:18:06 laforge Exp */ #include @@ -59,8 +59,8 @@ const struct ipt_ECN_info *einfo) { - struct tcphdr *tcph = (void *) iph + iph->ihl * 4; - u_int16_t *tcpflags = (u_int16_t *)tcph + 6; + struct tcphdr *tcph; + u_int16_t *tcpflags; u_int16_t diffs[2]; /* raw socket (tcpdump) may have clone of incoming @@ -71,8 +71,11 @@ return NF_DROP; kfree_skb(*pskb); *pskb = nskb; - iph = (*pskb)->nh.iph; } + + iph = (*pskb)->nh.iph; + tcph = (void *) iph + iph->ihl * 4; + tcpflags = (u_int16_t *)tcph + 6; diffs[0] = *tcpflags; diff -Nru a/net/ipv4/udp.c b/net/ipv4/udp.c --- a/net/ipv4/udp.c Fri Mar 5 05:02:51 2004 +++ b/net/ipv4/udp.c Fri Mar 5 05:02:51 2004 @@ -657,6 +657,7 @@ if (flags & MSG_ERRQUEUE) return ip_recv_error(sk, msg, len); +try_again: skb = skb_recv_datagram(sk, flags, noblock, &err); if (!skb) goto out; @@ -722,7 +723,9 @@ skb_free_datagram(sk, skb); - return -EAGAIN; + if (noblock) + return -EAGAIN; + goto try_again; } int udp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) diff -Nru a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c --- a/net/ipv6/exthdrs.c Fri Mar 5 05:02:51 2004 +++ b/net/ipv6/exthdrs.c Fri Mar 5 05:02:51 2004 @@ -798,8 +798,16 @@ if (skb_copy_bits(skb, start, &hdr, sizeof(hdr))) BUG(); if (nexthdr == NEXTHDR_FRAGMENT) { - struct frag_hdr *fhdr = (struct frag_hdr *) &hdr; - if (ntohs(fhdr->frag_off) & ~0x7) + unsigned short frag_off; + if (skb_copy_bits(skb, + start+offsetof(struct frag_hdr, + frag_off), + &frag_off, + sizeof(frag_off))) { + return -1; + } + + if (ntohs(frag_off) & ~0x7) break; hdrlen = 8; } else if (nexthdr == NEXTHDR_AUTH) diff -Nru a/net/ipv6/icmp.c b/net/ipv6/icmp.c --- a/net/ipv6/icmp.c Fri Mar 5 05:02:51 2004 +++ b/net/ipv6/icmp.c Fri Mar 5 05:02:51 2004 @@ -648,7 +648,13 @@ sk = icmpv6_socket_cpu(i)->sk; sk->allocation = GFP_ATOMIC; - sk->sndbuf = SK_WMEM_MAX*2; + + /* Enough space for 2 64K ICMP packets, including + * sk_buff struct overhead. + */ + sk->sndbuf = + (2 * ((64 * 1024) + sizeof(struct sk_buff))); + sk->prot->unhash(sk); } diff -Nru a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c --- a/net/ipv6/ipv6_sockglue.c Fri Mar 5 05:02:51 2004 +++ b/net/ipv6/ipv6_sockglue.c Fri Mar 5 05:02:51 2004 @@ -452,10 +452,15 @@ } case MCAST_MSFILTER: { + extern int sysctl_optmem_max; struct group_filter *gsf; if (optlen < GROUP_FILTER_SIZE(0)) goto e_inval; + if (optlen > sysctl_optmem_max) { + retv = -ENOBUFS; + break; + } gsf = (struct group_filter *)kmalloc(optlen,GFP_KERNEL); if (gsf == 0) { retv = -ENOBUFS; @@ -464,6 +469,12 @@ retv = -EFAULT; if (copy_from_user(gsf, optval, optlen)) { kfree(gsf); + break; + } + if (GROUP_FILTER_SIZE(gsf->gf_numsrc) < GROUP_FILTER_SIZE(0) || + GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) { + kfree(gsf); + retv = -EINVAL; break; } retv = ip6_mc_msfilter(sk, gsf); diff -Nru a/net/ipv6/ipv6_syms.c b/net/ipv6/ipv6_syms.c --- a/net/ipv6/ipv6_syms.c Fri Mar 5 05:02:51 2004 +++ b/net/ipv6/ipv6_syms.c Fri Mar 5 05:02:51 2004 @@ -33,3 +33,5 @@ EXPORT_SYMBOL(ipv6_get_saddr); EXPORT_SYMBOL(ipv6_chk_addr); EXPORT_SYMBOL(in6_dev_finish_destroy); +EXPORT_SYMBOL(ipv6_skip_exthdr); + diff -Nru a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c --- a/net/ipv6/netfilter/ip6_tables.c Fri Mar 5 05:02:51 2004 +++ b/net/ipv6/netfilter/ip6_tables.c Fri Mar 5 05:02:51 2004 @@ -1568,8 +1568,10 @@ u_int16_t datalen, int *hotdrop) { - const struct tcphdr *tcp = hdr; + const struct tcphdr *tcp; const struct ip6t_tcp *tcpinfo = matchinfo; + int tcpoff; + u8 nexthdr = skb->nh.ipv6h->nexthdr; /* To quote Alan: @@ -1590,6 +1592,24 @@ return 0; } + tcpoff = (u8*)(skb->nh.ipv6h + 1) - skb->data; + tcpoff = ipv6_skip_exthdr(skb, tcpoff, &nexthdr, skb->len - tcpoff); + if (tcpoff < 0 || tcpoff > skb->len) { + duprintf("tcp_match: cannot skip exthdr. Dropping.\n"); + *hotdrop = 1; + return 0; + } else if (nexthdr == IPPROTO_FRAGMENT) + return 0; + else if (nexthdr != IPPROTO_TCP || + skb->len - tcpoff < sizeof(struct tcphdr)) { + /* cannot be occured */ + duprintf("tcp_match: cannot get TCP header. Dropping.\n"); + *hotdrop = 1; + return 0; + } + + tcp = (struct tcphdr *)(skb->data + tcpoff); + /* FIXME: Try tcp doff >> packet len against various stacks --RR */ #define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg)) @@ -1640,8 +1660,10 @@ u_int16_t datalen, int *hotdrop) { - const struct udphdr *udp = hdr; + const struct udphdr *udp; const struct ip6t_udp *udpinfo = matchinfo; + int udpoff; + u8 nexthdr = skb->nh.ipv6h->nexthdr; if (offset == 0 && datalen < sizeof(struct udphdr)) { /* We've been asked to examine this packet, and we @@ -1650,6 +1672,23 @@ *hotdrop = 1; return 0; } + + udpoff = (u8*)(skb->nh.ipv6h + 1) - skb->data; + udpoff = ipv6_skip_exthdr(skb, udpoff, &nexthdr, skb->len - udpoff); + if (udpoff < 0 || udpoff > skb->len) { + duprintf("udp_match: cannot skip exthdr. Dropping.\n"); + *hotdrop = 1; + return 0; + } else if (nexthdr == IPPROTO_FRAGMENT) + return 0; + else if (nexthdr != IPPROTO_UDP || + skb->len - udpoff < sizeof(struct udphdr)) { + duprintf("udp_match: cannot get UDP header. Dropping.\n"); + *hotdrop = 1; + return 0; + } + + udp = (struct udphdr *)(skb->data + udpoff); /* Must not be a fragment. */ return !offset diff -Nru a/net/ipv6/udp.c b/net/ipv6/udp.c --- a/net/ipv6/udp.c Fri Mar 5 05:02:51 2004 +++ b/net/ipv6/udp.c Fri Mar 5 05:02:51 2004 @@ -400,6 +400,7 @@ if (flags & MSG_ERRQUEUE) return ipv6_recv_error(sk, msg, len); +try_again: skb = skb_recv_datagram(sk, flags, noblock, &err); if (!skb) goto out; @@ -476,12 +477,13 @@ kfree_skb(skb); } - /* Error for blocking case is chosen to masquerade - as some normal condition. - */ - err = (flags&MSG_DONTWAIT) ? -EAGAIN : -EHOSTUNREACH; - UDP6_INC_STATS_USER(UdpInErrors); - goto out_free; + skb_free_datagram(sk, skb); + + if (flags & MSG_DONTWAIT) { + UDP6_INC_STATS_USER(UdpInErrors); + return -EAGAIN; + } + goto try_again; } void udpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, diff -Nru a/net/netsyms.c b/net/netsyms.c --- a/net/netsyms.c Fri Mar 5 05:02:51 2004 +++ b/net/netsyms.c Fri Mar 5 05:02:51 2004 @@ -40,6 +40,7 @@ #ifdef CONFIG_NET extern __u32 sysctl_wmem_max; extern __u32 sysctl_rmem_max; +extern int sysctl_optmem_max; #endif #ifdef CONFIG_INET @@ -550,6 +551,7 @@ #ifdef CONFIG_SYSCTL EXPORT_SYMBOL(sysctl_wmem_max); EXPORT_SYMBOL(sysctl_rmem_max); +EXPORT_SYMBOL(sysctl_optmem_max); #ifdef CONFIG_INET EXPORT_SYMBOL(sysctl_ip_default_ttl); #endif diff -Nru a/net/sctp/associola.c b/net/sctp/associola.c --- a/net/sctp/associola.c Fri Mar 5 05:02:51 2004 +++ b/net/sctp/associola.c Fri Mar 5 05:02:51 2004 @@ -142,9 +142,9 @@ * socket values. */ asoc->max_retrans = sp->assocparams.sasoc_asocmaxrxt; - asoc->rto_initial = MSECS_TO_JIFFIES(sp->rtoinfo.srto_initial); - asoc->rto_max = MSECS_TO_JIFFIES(sp->rtoinfo.srto_max); - asoc->rto_min = MSECS_TO_JIFFIES(sp->rtoinfo.srto_min); + asoc->rto_initial = SCTP_MSECS_TO_JIFFIES(sp->rtoinfo.srto_initial); + asoc->rto_max = SCTP_MSECS_TO_JIFFIES(sp->rtoinfo.srto_max); + asoc->rto_min = SCTP_MSECS_TO_JIFFIES(sp->rtoinfo.srto_min); asoc->overall_error_count = 0; @@ -170,7 +170,7 @@ asoc->max_init_attempts = sp->initmsg.sinit_max_attempts; asoc->max_init_timeo = - MSECS_TO_JIFFIES(sp->initmsg.sinit_max_init_timeo); + SCTP_MSECS_TO_JIFFIES(sp->initmsg.sinit_max_init_timeo); /* Allocate storage for the ssnmap after the inbound and outbound * streams have been negotiated during Init. @@ -510,7 +510,7 @@ /* Initialize the peer's heartbeat interval based on the * sock configured value. */ - peer->hb_interval = MSECS_TO_JIFFIES(sp->paddrparam.spp_hbinterval); + peer->hb_interval = SCTP_MSECS_TO_JIFFIES(sp->paddrparam.spp_hbinterval); /* Set the path max_retrans. */ peer->max_retrans = asoc->max_retrans; diff -Nru a/net/sctp/chunk.c b/net/sctp/chunk.c --- a/net/sctp/chunk.c Fri Mar 5 05:02:51 2004 +++ b/net/sctp/chunk.c Fri Mar 5 05:02:51 2004 @@ -184,7 +184,7 @@ if (sinfo->sinfo_timetolive) { /* sinfo_timetolive is in milliseconds */ msg->expires_at = jiffies + - MSECS_TO_JIFFIES(sinfo->sinfo_timetolive); + SCTP_MSECS_TO_JIFFIES(sinfo->sinfo_timetolive); msg->can_expire = 1; } diff -Nru a/net/sctp/endpointola.c b/net/sctp/endpointola.c --- a/net/sctp/endpointola.c Fri Mar 5 05:02:52 2004 +++ b/net/sctp/endpointola.c Fri Mar 5 05:02:52 2004 @@ -129,7 +129,7 @@ ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] = SCTP_DEFAULT_TIMEOUT_T1_INIT; ep->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] = - MSECS_TO_JIFFIES(sp->rtoinfo.srto_initial); + SCTP_MSECS_TO_JIFFIES(sp->rtoinfo.srto_initial); ep->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0; ep->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = 0; @@ -138,7 +138,7 @@ * recommended value of 5 times 'RTO.Max'. */ ep->timeouts[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD] - = 5 * MSECS_TO_JIFFIES(sp->rtoinfo.srto_max); + = 5 * SCTP_MSECS_TO_JIFFIES(sp->rtoinfo.srto_max); ep->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = SCTP_DEFAULT_TIMEOUT_HEARTBEAT; diff -Nru a/net/sctp/ipv6.c b/net/sctp/ipv6.c --- a/net/sctp/ipv6.c Fri Mar 5 05:02:51 2004 +++ b/net/sctp/ipv6.c Fri Mar 5 05:02:51 2004 @@ -82,14 +82,14 @@ /* FIXME: This macro needs to be moved to a common header file. */ #define NIP6(addr) \ - ntohs((addr).s6_addr16[0]), \ - ntohs((addr).s6_addr16[1]), \ - ntohs((addr).s6_addr16[2]), \ - ntohs((addr).s6_addr16[3]), \ - ntohs((addr).s6_addr16[4]), \ - ntohs((addr).s6_addr16[5]), \ - ntohs((addr).s6_addr16[6]), \ - ntohs((addr).s6_addr16[7]) + ntohs((addr)->s6_addr16[0]), \ + ntohs((addr)->s6_addr16[1]), \ + ntohs((addr)->s6_addr16[2]), \ + ntohs((addr)->s6_addr16[3]), \ + ntohs((addr)->s6_addr16[4]), \ + ntohs((addr)->s6_addr16[5]), \ + ntohs((addr)->s6_addr16[6]), \ + ntohs((addr)->s6_addr16[7]) /* ICMP error handler. */ void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, @@ -226,7 +226,7 @@ SCTP_DEBUG_PRINTK( "rt6_dst:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x " "rt6_src:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", - NIP6(rt->rt6i_dst.addr), NIP6(rt->rt6i_src.addr)); + NIP6(&rt->rt6i_dst.addr), NIP6(&rt->rt6i_src.addr)); } else { SCTP_DEBUG_PRINTK("NO ROUTE\n"); } @@ -273,13 +273,13 @@ SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p " "daddr:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", - __FUNCTION__, asoc, dst, NIP6(daddr->v6.sin6_addr)); + __FUNCTION__, asoc, dst, NIP6(&daddr->v6.sin6_addr)); if (!asoc) { ipv6_get_saddr(dst, &daddr->v6.sin6_addr,&saddr->v6.sin6_addr); SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: " "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", - NIP6(saddr->v6.sin6_addr)); + NIP6(&saddr->v6.sin6_addr)); return; } @@ -308,12 +308,12 @@ memcpy(saddr, baddr, sizeof(union sctp_addr)); SCTP_DEBUG_PRINTK("saddr: " "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", - NIP6(saddr->v6.sin6_addr)); + NIP6(&saddr->v6.sin6_addr)); } else { printk(KERN_ERR "%s: asoc:%p Could not find a valid source " "address for the " "dest:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", - __FUNCTION__, asoc, NIP6(daddr->v6.sin6_addr)); + __FUNCTION__, asoc, NIP6(&daddr->v6.sin6_addr)); } sctp_read_unlock(addr_lock); @@ -678,7 +678,7 @@ static void sctp_v6_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr) { seq_printf(seq, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", - NIP6(addr->v6.sin6_addr)); + NIP6(&addr->v6.sin6_addr)); } /* Initialize a PF_INET6 socket msg_name. */ diff -Nru a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c --- a/net/sctp/sm_statefuns.c Fri Mar 5 05:02:51 2004 +++ b/net/sctp/sm_statefuns.c Fri Mar 5 05:02:51 2004 @@ -4272,8 +4272,7 @@ SCTP_DEBUG_PRINTK("Timer T1 expired.\n"); - if ((timeout < asoc->max_init_timeo) && - (attempts < asoc->max_init_attempts)) { + if (attempts < asoc->max_init_attempts) { switch (timer) { case SCTP_EVENT_TIMEOUT_T1_INIT: bp = (struct sctp_bind_addr *) &asoc->base.bind_addr; diff -Nru a/net/sctp/socket.c b/net/sctp/socket.c --- a/net/sctp/socket.c Fri Mar 5 05:02:51 2004 +++ b/net/sctp/socket.c Fri Mar 5 05:02:51 2004 @@ -1216,7 +1216,7 @@ } if (sinit->sinit_max_init_timeo) { asoc->max_init_timeo = - MSECS_TO_JIFFIES(sinit->sinit_max_init_timeo); + SCTP_MSECS_TO_JIFFIES(sinit->sinit_max_init_timeo); } } @@ -1654,7 +1654,7 @@ if (params.spp_hbinterval) { trans->hb_allowed = 1; trans->hb_interval = - MSECS_TO_JIFFIES(params.spp_hbinterval); + SCTP_MSECS_TO_JIFFIES(params.spp_hbinterval); } else trans->hb_allowed = 0; } @@ -1827,11 +1827,11 @@ if (asoc) { if (rtoinfo.srto_initial != 0) asoc->rto_initial = - MSECS_TO_JIFFIES(rtoinfo.srto_initial); + SCTP_MSECS_TO_JIFFIES(rtoinfo.srto_initial); if (rtoinfo.srto_max != 0) - asoc->rto_max = MSECS_TO_JIFFIES(rtoinfo.srto_max); + asoc->rto_max = SCTP_MSECS_TO_JIFFIES(rtoinfo.srto_max); if (rtoinfo.srto_min != 0) - asoc->rto_min = MSECS_TO_JIFFIES(rtoinfo.srto_min); + asoc->rto_min = SCTP_MSECS_TO_JIFFIES(rtoinfo.srto_min); } else { /* If there is no association or the association-id = 0 * set the values to the endpoint.