Browse Source

Import upstream version 21

Ed L. Cashin 16 years ago
parent
commit
7eff639d44
29 changed files with 798 additions and 105 deletions
  1. 1 0
      .gitignore
  2. 8 3
      Makefile
  3. 39 0
      NEWS
  4. 11 21
      README
  5. 2 3
      aoe-discover.8
  6. 7 0
      aoe-discover.in
  7. 2 1
      aoe-flush.8
  8. 8 1
      aoe-flush.in
  9. 4 4
      aoe-interfaces.8
  10. 27 4
      aoe-interfaces.in
  11. 21 1
      aoe-mkdevs
  12. 21 5
      aoe-mkdevs.8
  13. 17 4
      aoe-mkshelf.8
  14. 23 3
      aoe-mkshelf.in
  15. 2 1
      aoe-revalidate.8
  16. 8 1
      aoe-revalidate.in
  17. 23 1
      aoe-stat.8
  18. 18 2
      aoe-stat
  19. 34 0
      aoe-version
  20. 29 0
      aoe-version.8
  21. 77 0
      aoecfg.8
  22. 240 0
      aoecfg.c
  23. 26 9
      aoeping.8
  24. 72 17
      aoeping.c
  25. 45 0
      aoetools.8
  26. 10 7
      dat.h
  27. 18 15
      devnodes.txt
  28. 1 0
      fns.h
  29. 4 2
      linux.c

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+*~

+ 8 - 3
Makefile

@@ -37,12 +37,13 @@ NPERSHELF=16
 
 
 
 
 # these scripts are created from the *.in files
 # these scripts are created from the *.in files
-CONF_SCRIPTS = aoe-discover aoe-interfaces aoe-mkshelf aoe-revalidate aoe-flush
-PROGS = aoeping
-COMMANDS := ${CONF_SCRIPTS} aoe-mkdevs aoe-stat ${PROGS}
+CONF_SCRIPTS = aoe-discover aoe-interfaces aoe-mkshelf aoe-revalidate aoe-flush aoe-stat
+PROGS = aoeping aoecfg
+COMMANDS := ${CONF_SCRIPTS} aoe-mkdevs aoe-version ${PROGS}
 CFLAGS = -Wall -O -g
 CFLAGS = -Wall -O -g
 
 
 AOE_PING_OBJ = aoeping.o linux.o
 AOE_PING_OBJ = aoeping.o linux.o
+AOE_CFG_OBJ = aoecfg.o linux.o
 
 
 all : configure ${PROGS}
 all : configure ${PROGS}
 	@true
 	@true
@@ -70,3 +71,7 @@ aoeping.o : aoeping.c dat.h fns.h
 	${CC} ${CFLAGS} -o $@ -c $<
 	${CC} ${CFLAGS} -o $@ -c $<
 linux.o : linux.c config.h
 linux.o : linux.c config.h
 	${CC} ${CFLAGS} -o $@ -c $<
 	${CC} ${CFLAGS} -o $@ -c $<
+aoecfg: ${AOE_CFG_OBJ}
+	${CC} ${CFLAGS} -o $@ ${AOE_CFG_OBJ}
+aoecfg.o : aoecfg.c dat.h fns.h
+	${CC} ${CFLAGS} -o $@ -c $<

+ 39 - 0
NEWS

@@ -1,3 +1,42 @@
+2007-10-29 "Ed L. Cashin" <ecashin@coraid.com>
+	aoe-interfaces should complain about non network interfaces
+	aoe-interfaces should accept quoted list of interfaces
+	aoe-interfaces clearing and setting are exclusive actions
+	release 21
+
+2007-10-12 "Ed L. Cashin" <ecashin@coraid.com>
+	add Erik Quanstrom's aoecfg program
+	signal error when specified network interface starts with digit
+	use a tag in the AoE header
+	do not print shelf and slot when user specified both
+	have aoeping use a tag for the first packet
+	add pretty printing of ATA device identify fields
+	  based on input from Joshua Nicholas
+	release 20
+
+2007-08-27 "Ed L. Cashin" <ecashin@coraid.com>
+	add copyright information
+	support kernel.org aoe driver in aoe-version
+	add aoetools manpage
+	release 19
+
+2007-08-08 "Ed L. Cashin" <ecashin@coraid.com>
+	distinguish between missing device nodes and wrong ones
+	release 18
+
+2007-07-26 "Ed L. Cashin" <ecashin@coraid.com>
+	aoe-mkdevs and aoe-mkshelf are for systems without udev
+	aoe-stat warns when device node has wrong minor number
+	new script, aoe-version, shows installed and running sfw
+	release 17
+
+2007-07-17 "Ed L. Cashin" <ecashin@coraid.com>
+	check for char devices specifically before using them
+
+2007-06-01 "Ed L. Cashin" <ecashin@coraid.com>
+	workaround dash POSIX math bug
+	release 16
+
 2007-03-20 "Ed L. Cashin" <ecashin@coraid.com>
 2007-03-20 "Ed L. Cashin" <ecashin@coraid.com>
 	add quoting to aoe-flush
 	add quoting to aoe-flush
 	release 15
 	release 15

+ 11 - 21
README

@@ -7,19 +7,14 @@ the aoetools.  The aoe driver for 2.4 kernels is self sufficient.
 --------------------------------------------------------------------
 --------------------------------------------------------------------
 AOE DRIVER COMPATIBILITY
 AOE DRIVER COMPATIBILITY
 
 
-  ATA over Ethernet (AoE) devices have a shelf address and a slot
-  address. The aoe driver used to support only 10 slots per shelf
-  address. The 2.6.14 kernel contains an aoe driver that supports up
-  to 16 slots per shelf address. This change means that ...
-  
-     1. It's easy to use the aoetools that come bundled with the aoe
-        driver at the Coraid website.
-  
-     2. It's easy to use aoetools-8 or later with kernels 2.6.14 or
-        later.
-  
-     3. It's easy to use other combinations as long as you read the
-        information in the devnodes.txt file here.
+  If you are using udev on your system, the aoe-mkdevs and aoe-mkshelf
+  should not be used.  Just let udev create device nodes for you.  If
+  you need to configure udev, its manpages, in conjunction with the
+  example in the EtherDrive HOWTO FAQ, should help.
+
+  If you are not using udev, it is important to ensure that the device
+  nodes in /dev/etherd match the aoe driver.  Please see devnodes.txt
+  for information.
 --------------------------------------------------------------------
 --------------------------------------------------------------------
 
 
 
 
@@ -33,17 +28,12 @@ aoetools software and documentation:
 You'll need sufficient permissions to install in the default locations
 You'll need sufficient permissions to install in the default locations
 if you haven't overridden them with your own locations.
 if you haven't overridden them with your own locations.
 
 
-Here is a brief list of the tools.  Please see the man pages for
-further details.
+Please see the aoetools manpage for a brief list of the tools.
+
+These two are legacy commands for systems without udev.
 
 
-  aoe-discover		trigger discovery of ATA over Ethernet devices
-  aoe-flush		ask aoe driver to forget down devices
-  aoe-interfaces	restrict network interfaces used for AoE
   aoe-mkdevs		create character and block device files
   aoe-mkdevs		create character and block device files
   aoe-mkshelf		create block device files for one shelf address
   aoe-mkshelf		create block device files for one shelf address
-  aoe-revalidate	ask the aoe driver to update its state for a device
-  aoe-stat		print status information for AoE devices
-  aoeping		simple userland communication with AoE devices
 
 
 The aoetools homepage
 The aoetools homepage
   http://aoetools.sourceforge.net/
   http://aoetools.sourceforge.net/

+ 2 - 3
aoe-discover.8

@@ -57,8 +57,7 @@ nai:~# aoe-stat
 .EE
 .EE
 .SH "SEE ALSO"
 .SH "SEE ALSO"
 .IR aoe-interfaces (8),
 .IR aoe-interfaces (8),
-.IR aoe-mkdevs (8),
-.IR aoe-mkshelf (8),
-.IR aoe-stat (8).
+.IR aoe-stat (8),
+.IR aoetools (8).
 .SH AUTHOR
 .SH AUTHOR
 Ed L. Cashin (ecashin@coraid.com)
 Ed L. Cashin (ecashin@coraid.com)

+ 7 - 0
aoe-discover.in

@@ -1,5 +1,6 @@
 #! /bin/sh
 #! /bin/sh
 # aoe-discover - trigger an AoE device discovery
 # aoe-discover - trigger an AoE device discovery
+# Copyright 2007, Coraid, Inc., and licensed under GPL v.2.
 
 
 zero=`basename $0`
 zero=`basename $0`
 f=@devdir@/discover
 f=@devdir@/discover
@@ -8,4 +9,10 @@ if ! test -w $f; then
 	echo 1>&2 $zero: $f does not exist or is not writeable.
 	echo 1>&2 $zero: $f does not exist or is not writeable.
 	exit 1
 	exit 1
 fi
 fi
+if ! test -c $f; then
+	exec 1>&2
+	echo "$zero: $f is not a character device file"
+	echo "$zero: use udev or aoe-mkdevs to create it"
+	exit 1
+fi
 echo > $f
 echo > $f

+ 2 - 1
aoe-flush.8

@@ -38,6 +38,7 @@ beacon.
 may be used to force this behaviour.
 may be used to force this behaviour.
 .SH "SEE ALSO"
 .SH "SEE ALSO"
 .IR aoe-stat (8),
 .IR aoe-stat (8),
-.IR aoe-discover (8).
+.IR aoe-discover (8),
+.IR aoetools (8).
 .SH AUTHOR
 .SH AUTHOR
 Sam Hopkins (sah@coraid.com)
 Sam Hopkins (sah@coraid.com)

+ 8 - 1
aoe-flush.in

@@ -1,5 +1,6 @@
 #! /bin/sh
 #! /bin/sh
-# aoe-flush
+# aoe-flush - ask aoe driver to forget about devices
+# Copyright 2007, Coraid, Inc., and licensed under GPL v.2.
 
 
 zero="`basename $0`"
 zero="`basename $0`"
 f="@devdir@/flush"
 f="@devdir@/flush"
@@ -9,6 +10,12 @@ if ! test -w "$f"; then
 	echo 1>&2 "$zero: $f does not exist or is not writeable."
 	echo 1>&2 "$zero: $f does not exist or is not writeable."
 	exit 1
 	exit 1
 fi
 fi
+if ! test -c $f; then
+	exec 1>&2
+	echo "$zero: $f is not a character device file"
+	echo "$zero: use udev or aoe-mkdevs to create it"
+	exit 1
+fi
 
 
 if test "$1" = "-a"; then
 if test "$1" = "-a"; then
 	spec=all
 	spec=all

+ 4 - 4
aoe-interfaces.8

@@ -3,7 +3,8 @@
 aoe-interfaces \- restrict aoe driver to specified network interfaces
 aoe-interfaces \- restrict aoe driver to specified network interfaces
 .SH SYNOPSIS
 .SH SYNOPSIS
 .nf
 .nf
-.B aoe-interfaces [-c] [dev1] [dev2 ...]
+.B aoe-interfaces [dev1] [dev2 ...]
+.B aoe-interfaces -c
 .fi
 .fi
 .SH DESCRIPTION
 .SH DESCRIPTION
 The
 The
@@ -65,8 +66,7 @@ eth0 eth3
 .EE
 .EE
 .SH "SEE ALSO"
 .SH "SEE ALSO"
 .IR aoe-discover (8),
 .IR aoe-discover (8),
-.IR aoe-mkdevs (8),
-.IR aoe-mkshelf (8),
-.IR aoe-stat (8).
+.IR aoe-stat (8),
+.IR aoetools (8).
 .SH AUTHOR
 .SH AUTHOR
 Ed L. Cashin (ecashin@coraid.com)
 Ed L. Cashin (ecashin@coraid.com)

+ 27 - 4
aoe-interfaces.in

@@ -1,5 +1,6 @@
 #! /bin/sh
 #! /bin/sh
-# aoe-interfaces
+# aoe-interfaces - set or list the allowed AoE network interfaces
+# Copyright 2007, Coraid, Inc., and licensed under GPL v.2.
 
 
 zero="`basename $0`"
 zero="`basename $0`"
 devf=@devdir@/interfaces
 devf=@devdir@/interfaces
@@ -15,16 +16,38 @@ if test -z "$*"; then
 	exit
 	exit
 fi
 fi
 
 
-if test $1 = "-c"; then
+if test "$1" = "-c"; then
 	shift
 	shift
+	if test "$#" != "0"; then
+		echo "$zero Error: -c flag takes no arguments" 1>&2
+		exit 1
+	fi
+fi
+netifs="$*"
+
+err=no
+for i in $netifs; do
+	test -d "/sys/class/net/$i" || {
+		echo "$zero Error: \"$i\" is not a network interface" 1>&2
+		err=yes
+	}
+done
+if test "$err" = "yes"; then
+	exit 1
 fi
 fi
 
 
 if test -w "$sysf"; then
 if test -w "$sysf"; then
-	printf '%s\0' "$*" > "$sysf"
+	printf '%s\0' "$netifs" > "$sysf"
 else
 else
 	if test ! -w "$devf"; then
 	if test ! -w "$devf"; then
 		echo 1>&2 "$zero: $devf does not exist or is not writeable."
 		echo 1>&2 "$zero: $devf does not exist or is not writeable."
 		exit 1
 		exit 1
 	fi
 	fi
-	printf '%s\0' "$*" > "$devf"
+	if test ! -c "$devf"; then
+		exec 1>&2
+		echo "$zero: $devf is not a character device file"
+		echo "$zero: use udev or aoe-mkdevs to create it"
+		exit 1
+	fi
+	printf '%s\0' "$netifs" > "$devf"
 fi
 fi

+ 21 - 1
aoe-mkdevs

@@ -1,4 +1,6 @@
 #!/bin/sh
 #!/bin/sh
+# aoe-mkdevs - make static device nodes on systems without udev
+# Copyright 2007, Coraid, Inc., and licensed under GPL v.2.
 
 
 n_shelves=${n_shelves:-10}
 n_shelves=${n_shelves:-10}
 n_partitions=${n_partitions:-16}
 n_partitions=${n_partitions:-16}
@@ -9,9 +11,27 @@ if test "$#" != "1"; then
 	exit 1
 	exit 1
 fi
 fi
 dir=$1
 dir=$1
-
+zero="`basename $0`"
 MAJOR=152
 MAJOR=152
 
 
+dyn=/sys/module/aoe/parameters/aoe_dyndevs
+if test -r "$dyn" && test "`cat $dyn`" = 1; then
+	cat 1>&2 <<EOF
+$zero Error: aoe module is using dynamic devices.
+$zero: Please see the aoe-mkdevs manpage.
+$zero: Exiting.
+EOF
+	exit 1
+fi
+if test "`ps axwwww | grep 'udev[d]'`" || test -d "/dev/.udev"; then
+	cat 1>&2 <<EOF
+$zero Error: udev detected.  You shouldn't need to use $zero.
+$zero: Please see the aoe-mkdevs manpage.
+$zero: Exiting.
+EOF
+	exit 1
+fi
+
 set -e
 set -e
 
 
 mkdir -p $dir
 mkdir -p $dir

+ 21 - 5
aoe-mkdevs.8

@@ -9,12 +9,26 @@ aoe-mkdevs \- create special device files for aoe driver
 .SH DESCRIPTION
 .SH DESCRIPTION
 The
 The
 .I aoe-mkdevs
 .I aoe-mkdevs
-command uses mknod to create the character special files necessary to
-control the aoe driver.  It also uses 
+command is deprecated in favor of udev.  Systems with udev do not need
+to use the \fIaoe-mkdevs\fP or \fIaoe-mkself\fP commands, because udev
+will create device nodes as needed.
+.PP
+Systems without udev use \fIaoe-mkdevs\fP to create the character
+special files necessary to 
+control the aoe driver.  The \fIaoe-mkdevs\fP command uses 
 .I aoe-mkshelf
 .I aoe-mkshelf
-to create block special files.
+to also create block special files.
+.PP
+The aoe drivers after version 49 support dynamic minor device numbers
+so that a greater number of devices can be supported.  The
+\fIaoe-mkdevs\fP command is incompatible with dynamic device numbers.
+If your system lacks udev, and you are using an aoe driver version 50
+or above, use the aoe_dyndevs=0 module option to force the aoe driver
+to use static device numbers.
 .PP
 .PP
-If your aoe driver supports only one partition per device (whole-disk
+If you are not using dynamic device numbers, and you built your aoe
+driver to support only one partition per device 
+(whole-disk 
 partitions), then the device files must match, and you should use the 
 partitions), then the device files must match, and you should use the 
 .I n_partitions
 .I n_partitions
 environment variable described below.
 environment variable described below.
@@ -52,6 +66,8 @@ nai:~# ls /dev/etherd | wc -l
 .IR aoe-discover (8),
 .IR aoe-discover (8),
 .IR aoe-interfaces (8),
 .IR aoe-interfaces (8),
 .IR aoe-mkshelf (8),
 .IR aoe-mkshelf (8),
-.IR aoe-stat (8).
+.IR aoe-stat (8),
+.IR aoetools (8),
+.IR udev (7).
 .SH AUTHOR
 .SH AUTHOR
 Ed L. Cashin (ecashin@coraid.com)
 Ed L. Cashin (ecashin@coraid.com)

+ 17 - 4
aoe-mkshelf.8

@@ -9,10 +9,21 @@ aoe-mkshelf \- create special device files for one shelf address
 .SH DESCRIPTION
 .SH DESCRIPTION
 The
 The
 .I aoe-mkshelf
 .I aoe-mkshelf
-command uses mknod to create the block special files necessary to
-access the AoE devices with the given shelf address.
+command is not needed on systems that have udev installed and 
+is incompatible with aoe drivers that have the \fIaoe_dyndevs\fP
+module parameter set to 1.
 .PP
 .PP
-If your aoe driver supports only one partition per device (whole-disk
+Systems lacking udev and having an aoe driver that uses static minor
+device numbers can use \fIaoe-mkshelf\fP to create the block special
+files necessary to access the AoE devices with the given shelf
+address.
+.PP
+All aoe drivers prior to \fIaoe6-50\fP use static minor device
+numbers.  Versions 50 and up use dynamic minor device numbers
+when the module parameter aoe_dyndevs=1 is set.
+.PP
+If you are using static minor device numbers and your aoe driver
+supports only one partition per device (whole-disk 
 partitions), then the device files must match, and you should use the 
 partitions), then the device files must match, and you should use the 
 .I n_partitions
 .I n_partitions
 environment variable described below.
 environment variable described below.
@@ -54,6 +65,8 @@ nai:~#
 .IR aoe-discover (8),
 .IR aoe-discover (8),
 .IR aoe-interfaces (8),
 .IR aoe-interfaces (8),
 .IR aoe-mkdevs (8),
 .IR aoe-mkdevs (8),
-.IR aoe-stat (8).
+.IR aoe-stat (8),
+.IR aoetools (8),
+.IR udev (7).
 .SH AUTHOR
 .SH AUTHOR
 Ed L. Cashin (ecashin@coraid.com)
 Ed L. Cashin (ecashin@coraid.com)

+ 23 - 3
aoe-mkshelf.in

@@ -1,4 +1,6 @@
 #! /bin/sh
 #! /bin/sh
+# aoe-mkshelf - device nodes for one shelf without udev
+# Copyright 2007, Coraid, Inc., and licensed under GPL v.2.
 
 
 zero=`basename $0`
 zero=`basename $0`
 
 
@@ -7,17 +9,35 @@ if test "$#" != "2"; then
 	echo "       n_partitions=16 $zero {dir} {shelfaddress}" 1>&2
 	echo "       n_partitions=16 $zero {dir} {shelfaddress}" 1>&2
 	exit 1
 	exit 1
 fi
 fi
+dyn=/sys/module/aoe/parameters/aoe_dyndevs
+if test -r "$dyn" && test "`cat $dyn`" = 1; then
+	cat 1>&2 <<EOF
+$zero Error: aoe module is using dynamic devices.
+$zero: Please see the aoe-mkshelf manpage.
+$zero: Exiting.
+EOF
+	exit 1
+fi
+if test "`ps axwwww | grep 'udev[d]'`" || test -d "/dev/.udev"; then
+	cat 1>&2 <<EOF
+$zero Error: udev detected.  You shouldn't need to use $zero.
+$zero: Please see the aoe-mkshelf manpage.
+$zero: Exiting.
+EOF
+	exit 1
+fi
+
 n_partitions=${n_partitions:-16}
 n_partitions=${n_partitions:-16}
 dir=$1
 dir=$1
 shelf=$2
 shelf=$2
 nslots=@npershelf@
 nslots=@npershelf@
-maxslot=$((nslots - 1))
+maxslot=$(($nslots - 1))
 MAJOR=152
 MAJOR=152
 
 
 set -e
 set -e
 
 
-minor=$((nslots * shelf * n_partitions))
-endp=$((n_partitions - 1))
+minor=$(($nslots * $shelf * $n_partitions))
+endp=$(($n_partitions - 1))
 for slot in `seq 0 $maxslot`; do
 for slot in `seq 0 $maxslot`; do
 	for part in `seq 0 $endp`; do
 	for part in `seq 0 $endp`; do
 		name=e$shelf.$slot
 		name=e$shelf.$slot

+ 2 - 1
aoe-revalidate.8

@@ -27,6 +27,7 @@ nai# aoe-stat | grep e1.9
 .fi
 .fi
 .EE
 .EE
 .SH "SEE ALSO"
 .SH "SEE ALSO"
-.IR aoe-stat (8).
+.IR aoe-stat (8),
+.IR aoetools (8).
 .SH AUTHOR
 .SH AUTHOR
 Sam Hopkins (sah@coraid.com)
 Sam Hopkins (sah@coraid.com)

+ 8 - 1
aoe-revalidate.in

@@ -1,5 +1,6 @@
 #! /bin/sh
 #! /bin/sh
-# aoe-revalidate
+# aoe-revalidate - ask aoe driver to query AoE target
+# Copyright 2007, Coraid, Inc., and licensed under GPL v.2.
 
 
 zero=`basename $0`
 zero=`basename $0`
 f=@devdir@/revalidate
 f=@devdir@/revalidate
@@ -12,6 +13,12 @@ if ! test -w $f; then
 	echo 1>&2 $zero: $f does not exist or is not writeable
 	echo 1>&2 $zero: $f does not exist or is not writeable
 	exit 1
 	exit 1
 fi
 fi
+if ! test -c $f; then
+	exec 1>&2
+	echo "$zero: $f is not a character device file"
+	echo "$zero: use udev or aoe-mkdevs to create it"
+	exit 1
+fi
 echo "$*" > $f || {
 echo "$*" > $f || {
 	echo "$zero: revalidate failed" 1>&2
 	echo "$zero: revalidate failed" 1>&2
 	exit 1
 	exit 1

+ 23 - 1
aoe-stat.8

@@ -47,6 +47,26 @@ location where
 .I aoe-stat
 .I aoe-stat
 will look for 
 will look for 
 sysfs, namely \fI /sys\fR.
 sysfs, namely \fI /sys\fR.
+.SH WARNINGS
+If the minor device number of a device node does not match that of its
+namesake, \fIaoe-stat\fP will print a warning as shown below.
+.IP
+.EX
+.nf
+nai:~# aoe-stat
+      e0.3         0.104GB   eth0 up            
+      e0.4      4398.046GB   eth0 up            
+     e20.0      1000.215GB   eth0 up            
+     e42.0      2000.431GB   eth0 up            
+aoe-stat Warning: device node /dev/etherd/e45.1 has wrong minor device number
+     e45.1      1152.874GB   eth0 up            
+.fi
+.EE
+.PP
+Using such a device node is dangerous, because its name doesn't match
+the actual device that you would be reading from and writing to.  Such
+a broken device node should be removed.  Device nodes are created by
+\fIudev\fP or (on systems without \fIudev\fP) by \fIaoe-mkdevs\fP.
 .SH EXAMPLE
 .SH EXAMPLE
 In this example, the root user on a host named
 In this example, the root user on a host named
 .I nai
 .I nai
@@ -74,6 +94,8 @@ nai:~#
 .IR aoe-discover (8),
 .IR aoe-discover (8),
 .IR aoe-interfaces (8),
 .IR aoe-interfaces (8),
 .IR aoe-mkdevs (8),
 .IR aoe-mkdevs (8),
-.IR aoe-mkshelf (8).
+.IR aoe-mkshelf (8),
+.IR aoetools (8),
+.IR udev (7).
 .SH AUTHOR
 .SH AUTHOR
 Ed L. Cashin (ecashin@coraid.com)
 Ed L. Cashin (ecashin@coraid.com)

+ 18 - 2
aoe-stat

@@ -1,5 +1,6 @@
 #! /bin/bash
 #! /bin/bash
-# collate and present sysfs information about AoE storage
+# aoe-stat - collate and present information about AoE storage
+# Copyright 2007, Coraid, Inc., and licensed under GPL v.2.
 
 
 set -e
 set -e
 format="%10s %15s %6s %-14s\n"
 format="%10s %15s %6s %-14s\n"
@@ -15,13 +16,28 @@ test ! -d "$sysd/block" && {
 	exit 1
 	exit 1
 }
 }
 
 
+function checknode () {
+	devname="$1"
+	m_sysfs="$2"
+	if test -b "@devdir@/$devname"; then
+		m_node="`ls -l \"@devdir@/$devname\" | awk '{print $6}'`"
+		test "$m_sysfs" = "$m_node" || {
+			cat 1>&2 <<EOF
+$me Warning: device node @devdir@/$devname has wrong minor device number
+EOF
+		}
+	fi
+}
+
 for d in `ls -d $sysd/block/*e[0-9]*\.[0-9]* 2>/dev/null | grep -v p` end; do
 for d in `ls -d $sysd/block/*e[0-9]*\.[0-9]* 2>/dev/null | grep -v p` end; do
 	# maybe ls comes up empty, so we use "end"
 	# maybe ls comes up empty, so we use "end"
 	test $d = end && continue
 	test $d = end && continue
 
 
 	dev=`echo "$d" | sed 's/.*!//'`
 	dev=`echo "$d" | sed 's/.*!//'`
 	sectors="`cat \"$d/size\"`"
 	sectors="`cat \"$d/size\"`"
-	psize=$(((512000 * sectors) / (1000 * 1000 * 1000)))
+	minor="`awk -F: '{print $2}' \"$d/dev\"`"
+	checknode "$dev" "$minor"
+	psize=$(((512000 * $sectors) / (1000 * 1000 * 1000)))
 	psize=`printf "%04d\n" $psize | sed 's!\(...\)$!.\1!'`
 	psize=`printf "%04d\n" $psize | sed 's!\(...\)$!.\1!'`
 	printf "$format" \
 	printf "$format" \
 		"$dev" \
 		"$dev" \

+ 34 - 0
aoe-version

@@ -0,0 +1,34 @@
+#! /bin/sh
+# aoe-version - display versions of AoE-related software
+# Copyright 2007, Coraid, Inc., and licensed under GPL v.2.
+
+aoetools=21
+
+# standalone aoe drivers have a module parameter "version"
+installed="`modinfo aoe 2>/dev/null | awk '/srcversion/ {next} /^parm:.*version:aoe module/ {print $NF; exit 0}'`"
+if test -z "$installed"; then
+	# Recent kernels have a "version" of their own, so
+	# they didn't want our module parameter, so we look
+	# for that, too, in case user is using kernel.org driver.
+	installed="`modinfo aoe 2>/dev/null | awk '/^version:/ {print $NF; exit 0}'`"
+fi
+if test "$?" != "0" || test -z "$installed"; then
+	installed="(unknown)"
+fi
+
+if test -d /sys/module/aoe; then
+	running="`find /sys/module/aoe -name version | xargs cat`"
+	if test "$?" != "0"; then
+		running="(unknown)"
+	fi
+else
+	running="(none)"
+fi
+
+while read val desc; do
+	printf "%22s:\t%s\n" "$desc" "$val"
+done <<EOF
+$aoetools aoetools
+$installed installed aoe driver
+$running running aoe driver
+EOF

+ 29 - 0
aoe-version.8

@@ -0,0 +1,29 @@
+.TH aoe-version 8
+.SH NAME
+aoe-version \- print AoE-related software version information
+.SH SYNOPSIS
+.nf
+.B aoe-version
+.fi
+.SH DESCRIPTION
+The
+.I aoe-version
+script collects information on running and installed ATA over Ethernet
+software, displaying a summary.
+.SH EXAMPLE
+.IP
+.EX
+.nf
+ellijay:~# aoe-version  
+              aoetools: 17
+  installed aoe driver: 50
+    running aoe driver: 50
+.fi
+.EE
+.SH "SEE ALSO"
+.IR aoe-discover (8),
+.IR aoe-interfaces (8),
+.IR aoetools (8),
+.IR aoe-stat (8).
+.SH AUTHOR
+Ed L. Cashin (ecashin@coraid.com)

+ 77 - 0
aoecfg.8

@@ -0,0 +1,77 @@
+.TH aoecfg 8
+.SH NAME
+aoecfg \- manipulate AoE configuration strings
+.SH SYNOPSIS
+.B aoecfg
+[-c \fIcmd\fR] [-s \fIcfgstr\fR] [-t \fItimeout\fR] [\fIshelf slot\fR] [\fInetif\fR]
+.fi
+.SH DESCRIPTION
+.IR Aoecfg (8)
+sends AoE configuration commands that control the retrivial, conditional
+or unconditional setting of AoE configuration strings.  Since configuration
+happens before the MAC address of the target is known, the packet is
+broadcast.  AoE targets with a matching shelf and slot respond.  Since
+the default shelf and slot are the wildcard values 0xffff and 0xff,
+with no arguments
+.IR aoecfg (8)
+will return configuration strings from all targets visible
+on the default interface,
+.IR eth0 .
+.SH OPTIONS
+.TP 8
+.BI \-c " cmd"
+specify the AoE configuration command.  The default is
+.IR read .
+The available commands are
+.HP 8
+.B read
+Read the server config string without performing any test and
+respond.
+.HP 8
+.B test
+Respond only if the specified string exactly matches the server
+configuration string.
+.HP 8
+.B prefix
+Respond only if the specified string is a prefix of the server
+configuration string.
+.HP 8
+.B set
+If the current server config string is empty, set the server config
+string to the argument string and respond.  If the current server
+config string is not empty, return a response with Flags bit E set
+and Error set to 4.
+.HP 8
+.B fset
+Force set the server config string to the argument string and respond.
+.TP
+.BI \-c " cfgstr"
+specify the config string.
+.TP
+.BI \-t " timeout"
+specify the timeout in seconds.  The default is no timeout.  If neither the shelf
+nor the slot are specified,
+.IR aoecfg (8)
+will exit after the first result.  Otherwise,
+.IR aoecfg (8)
+will exit only after the timeout has expired since it does not know
+how many responses to expect.
+.TP
+.B shelf slot
+specify the shelf and slot used in the query.  If unspecified, they
+default to broadcast.
+.TP
+.B netif
+specifiy the network interface.  The default is
+.IR eth0 .
+.SH "SEE ALSO"
+.IR aoe-discover (8),
+.IR aoe-interfaces (8),
+.IR aoe-mkdevs (8),
+.IR aoe-mkshelf (8),
+.IR aoe-stat (8),
+.IR aoeping (8),
+\fIAoE (ATA over Ethernet)\fP: http://www.coraid.com/documents/AoEr10.txt,
+\fIATA specification\fP
+.SH AUTHOR
+Erik Quanstrom (quanstro@coraid.com)

+ 240 - 0
aoecfg.c

@@ -0,0 +1,240 @@
+/*
+ * aoecfgstr.c - fiddle aoe configuration strings.
+ * Copyright 2007, Erik Quanstrom, Coraid, Inc., Licenced under GPL v2
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <ctype.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <time.h>
+#include <arpa/inet.h>
+#include "dat.h"
+#include "fns.h"
+
+int	sfd;
+uchar	mac[6];
+int	timeout;
+u16	shelf	= 0xffff;
+uchar	slot	= 0xff;
+char	*net 	= "eth0";
+char	*cfgstr;
+int	cfgstrlen;
+
+char *errtab[7] = {
+	"*GOK*",
+	"*badcmd*",
+	"*badarg*",
+	"*baddev*",
+	"*badcfg*",
+	"*badvers*",
+	"*GOK*",
+};
+
+void
+resp(Conf *c)
+{
+	Aoehdr *h;
+	char *s;
+	int l;
+
+	h = (Aoehdr*) c;
+	if (h->flags & Error) {
+		s = errtab[h->error & 7];
+		l = strlen(s);
+	} else {
+		s = (char*) c->data;
+		l = ntohs(c->len);
+	}
+	if (shelf != 0xffff && slot != 0xff)
+		printf("%.*s\n", l, s);
+	else
+		printf("%d.%d\t%.*s\n", ntohs(h->maj), h->min, l, s);
+}
+
+int
+readto(int fd, void *buf, int size)
+{
+	fd_set rfd;
+	struct timeval tv;
+	static int to;
+
+	if (timeout == 0)
+		goto f1;
+	if (to == 0)
+		to = time(0) + timeout;
+	FD_ZERO(&rfd);
+	FD_SET(fd, &rfd);
+
+	tv.tv_sec = to - time(0);
+	tv.tv_usec = 0;
+
+	switch (select(fd+1, &rfd, 0, 0, &tv)) {
+	case -1:
+		perror("select");
+		exit(1);
+	case 0:
+		exit(0);
+	}
+f1:
+	return read(fd, buf, size);
+}
+
+u32
+aoe_tag(void)
+{
+	u32 n;
+	struct timeval t = { 0, 0 };
+
+	/* Tag should be just enough to avoid conflicts with other
+	 * aoeping and aoecfg processes, and should set high bit
+	 * to avoid conflicting with in-kernel AoE.
+	 */
+	if (gettimeofday(&t, NULL)) {
+		perror("gettimeofday");
+		exit(1);
+	}
+	n = t.tv_usec | 1UL << 31;
+	return htonl(n);
+}
+
+void
+cfgquery(int cmd, int shelf, int slot)
+{
+	int n;
+	Aoehdr *h;
+	Conf *c;
+	uchar buf[1024 + sizeof *h];
+	u32 tag;
+
+	c = (Conf*) buf;
+	h = (Aoehdr*) c;
+	memset(h, 0, sizeof *h);
+	memset(h->dst, 0xff, sizeof h->dst);
+	memmove(h->src, mac, sizeof h->src);
+	
+	h->type = htons(AOE_ETH_PROTO);
+	h->flags = AoEver << 4;
+	h->maj = htons(shelf);
+	h->min = slot;
+	h->cmd = Config;
+	tag = aoe_tag();
+	memmove(h->tag, &tag, sizeof h->tag);
+	c->bufcnt = 3;
+	c->vercmd = 0x10 | cmd;
+	memmove(c->data, cfgstr, cfgstrlen);
+	c->len = htons(cfgstrlen);
+	if (write(sfd, c, sizeof *c) == -1) {
+		perror("send config query");
+		exit(1);
+	}
+	for (;;) {
+		n = readto(sfd, buf, sizeof buf);
+		if (n < 0) {
+			perror("read network");
+			exit(1);
+		}
+		if (n < 60)
+			continue;
+		h = (Aoehdr *) buf;
+		if (ntohs(h->type) != AOE_ETH_PROTO)
+			continue;
+		if (ntohs(h->maj) == 0xffff || h->min == 0xff)
+			continue;
+		if (shelf != 0xffff && ntohs(h->maj) != shelf)
+			continue;
+		if (slot != 0xff && h->min != slot)
+			continue;
+		if (memcmp(h->tag, &tag, sizeof h->tag))
+			continue;
+		resp((Conf*) buf);
+		if (shelf != 0xffff && slot != 0xff)
+			break;
+	}
+}
+
+void
+usage(void)
+{
+	fputs("usage: aoecfg "
+		"[-c cmd] [-s cfgstr] [-t timeout] "
+		"[shelf slot] [net]\n", stderr);
+	exit(1);
+}
+
+typedef struct{
+	char	*s;
+	int	cmd;
+} Tab;
+
+Tab tab[] = {
+	{ "read",	Qread, },
+	{ "test",	Qtest, },
+	{ "prefix",	Qprefix, },
+	{ "set",	Qset, },
+	{ "fset",	Qfset, },
+};
+
+int
+xlatecmd(char *s)
+{
+	int i;
+
+	for (i = 0; i < nelem(tab); i++)
+		if (strcmp(tab[i].s, s) == 0)
+			return tab[i].cmd;
+	usage();
+	return -1;	// whine whine whine
+}
+
+int
+main(int argc, char *argv[])
+{
+	int c, cmd;
+
+	cmd = Qread;
+	while ((c = getopt(argc, argv, "s:c:t:v")) != -1) {
+		switch (c) {
+		case 'c':
+			cmd = xlatecmd(optarg);
+			break;
+		case 's':
+			cfgstr = optarg;
+			cfgstrlen = strlen(cfgstr);
+			break;
+		case 't':
+			timeout = atoi(optarg);
+			break;
+		default:
+			usage();
+		}
+	}
+
+	c = argc - optind;
+	argv += optind;
+	if (c < 2)
+		goto f1;
+	if (c != 3 && c != 2)
+		usage();
+	shelf = strtoul(*argv++, 0, 0);
+	slot = strtoul(*argv++, 0, 0);
+f1:
+	if (*argv) {
+		net = *argv;
+		if (isdigit((int) *net)) {
+			fprintf(stderr,
+				"aoecfg Error: \"%s\" %s\n", net,
+				"is not a valid network interface");
+			usage();
+		}
+	}
+	sfd = dial(net);
+	if (getea(sfd, net, mac) == 0)
+		exit(1);
+	cfgquery(cmd, shelf, slot);
+	return 0;
+}

+ 26 - 9
aoeping.8

@@ -2,19 +2,22 @@
 .SH NAME
 .SH NAME
 aoeping \- simple communication with AoE device
 aoeping \- simple communication with AoE device
 .SH SYNOPSIS
 .SH SYNOPSIS
-.nf
 .B aoeping [options] {shelf} {slot} {netif}
 .B aoeping [options] {shelf} {slot} {netif}
 .fi
 .fi
 .SH DESCRIPTION
 .SH DESCRIPTION
 The
 The
-.I aoeping
+.IR aoeping (8)
 program performs simple one or two-round-trip communication with an
 program performs simple one or two-round-trip communication with an
 ATA over Ethernet (AoE) device.
 ATA over Ethernet (AoE) device.
 .PP
 .PP
-Running \fBaoeping\fP without command line arguments will result in a 
+Running
+.IR aoeping (8)
+without command line arguments will result in a 
 short usage summary being displayed.
 short usage summary being displayed.
 .PP
 .PP
-The \fBaoeping\fP program will wait forever if if doesn't receive
+The
+.IR aoeping (8)
+program will wait forever if if doesn't receive
 an expected response.  The caller should use a time out to catch
 an expected response.  The caller should use a time out to catch
 this situation.
 this situation.
 .SS Arguments
 .SS Arguments
@@ -38,6 +41,12 @@ device's Config
 Query response.  The "ident" response will be printed on standard
 Query response.  The "ident" response will be printed on standard
 output as a hexidecimal dump.
 output as a hexidecimal dump.
 .TP
 .TP
+\fB-I\fP
+Issue an ATA "identify device" command after receiving the AoE
+device's Config
+Query response.  The "ident" response will be pretty-printed on standard
+output as selected human-readable fields.
+.TP
 \fB-v\fP
 \fB-v\fP
 Turn on 
 Turn on 
 more copious output, including a hexidecimal dump of the Config Query
 more copious output, including a hexidecimal dump of the Config Query
@@ -46,7 +55,9 @@ response from the AoE device (see AoE spec at URL below).
 \fB-s\fP
 \fB-s\fP
 This option takes an argument.  The
 This option takes an argument.  The
 argument is a decimal integer that specifies the number of seconds
 argument is a decimal integer that specifies the number of seconds
-that \fBaoeping\fP will wait for a response before timing out and
+that
+.IR aoeping (8)
+will wait for a response before timing out and
 exiting with a non-zero status.
 exiting with a non-zero status.
 .TP
 .TP
 \fB-S\fP
 \fB-S\fP
@@ -68,11 +79,15 @@ read_log:1".
   disable
   disable
   return_status
   return_status
 
 
-For \fBwrite_log\fP, \fBaoeping\fP reads from
+For \fBwrite_log\fP,
+.IR aoeping (8)
+reads from
 standard input the one sector of data to be
 standard input the one sector of data to be
 written to the specified log.
 written to the specified log.
 
 
-The aoeping command just sends and receives SMART commands, without
+The
+.IR aoeping (8)
+command just sends and receives SMART commands, without
 interpreting them.  See the ATA specification for more information on
 interpreting them.  See the ATA specification for more information on
 using SMART.
 using SMART.
 .LP
 .LP
@@ -89,7 +104,9 @@ incremented by one.
 Show a usage summary.
 Show a usage summary.
 .SH EXAMPLE
 .SH EXAMPLE
 In this example, the root user
 In this example, the root user
-uses \fBaoeping\fP to check for the presence of aoe device e10.9 on
+uses
+.IR aoeping (8)
+to check for the presence of aoe device e10.9 on
 network interface eth0.
 network interface eth0.
 .IP
 .IP
 .EX
 .EX
@@ -148,7 +165,7 @@ device fault bit (bit 5) set.
 .IR aoe-mkshelf (8),
 .IR aoe-mkshelf (8),
 .IR aoe-stat (8),
 .IR aoe-stat (8),
 
 
-\fIAoE (ATA over Ethernet)\fP: http://www.coraid.com/documents/AoEr8.txt,
+\fIAoE (ATA over Ethernet)\fP: http://www.coraid.com/documents/AoEr10.txt,
 
 
 \fIATA specification\fP
 \fIATA specification\fP
 .SH AUTHOR
 .SH AUTHOR

+ 72 - 17
aoeping.c

@@ -1,4 +1,5 @@
 /* aoeping.c - userland aoe pinger
 /* aoeping.c - userland aoe pinger
+ * Copyright 2007, Coraid, Inc., and licensed under GPL v.2.
  *
  *
  * run without arguments for usage
  * run without arguments for usage
  */
  */
@@ -9,6 +10,7 @@
 #include <stdint.h>
 #include <stdint.h>
 #include <ctype.h>
 #include <ctype.h>
 #include <netinet/in.h>
 #include <netinet/in.h>
+#include <linux/hdreg.h>
 #include <errno.h>
 #include <errno.h>
 #include "dat.h"
 #include "dat.h"
 #include "fns.h"
 #include "fns.h"
@@ -22,6 +24,7 @@ struct progopts {
 	u32 tag;
 	u32 tag;
 	char *smart;
 	char *smart;
 	char ata_ident;
 	char ata_ident;
+	char pp_ataid;		/* pretty print ATA device identify response */
 };
 };
 
 
 static struct progopts defaults = {
 static struct progopts defaults = {
@@ -33,6 +36,7 @@ static struct progopts defaults = {
 	.tag = 0,
 	.tag = 0,
 	.smart = NULL,
 	.smart = NULL,
 	.ata_ident = 0,
 	.ata_ident = 0,
+	.pp_ataid = 0,
 };
 };
 static struct progopts opts;
 static struct progopts opts;
 
 
@@ -76,9 +80,10 @@ usage(void)
 	fprintf(stderr,
 	fprintf(stderr,
 		"usage:\t%s [options] {shelf} {slot} {netif}\n",
 		"usage:\t%s [options] {shelf} {slot} {netif}\n",
 		progname);
 		progname);
-	fprintf(stderr, "%s\n\t%s\n\t%s\n\t%s\n",
+	fprintf(stderr, "%s\n\t%s\n\t%s\n\t%s\n\t%s\n",
 		"options:",
 		"options:",
-		"-i\tdo ATA device identify",
+		"-i\tdo ATA device identify dump as raw hex",
+		"-I\tdo ATA device identify print fields",
 		"-v\tbe verbose",
 		"-v\tbe verbose",
 		"-h\tshow this usage summary");
 		"-h\tshow this usage summary");
 	fprintf(stderr, "%s\n\t%s\n\t%s\n\t%s\n",
 	fprintf(stderr, "%s\n\t%s\n\t%s\n\t%s\n",
@@ -102,10 +107,11 @@ hex_print(FILE *out, uchar *buf, int n, char *sep)
 }
 }
 
 
 void
 void
-find_blade(Conf *c, int shelf, int slot)
+find_blade(Conf *c, struct progopts *opts)
 {
 {
 	int n;
 	int n;
 	uchar buf[1400];
 	uchar buf[1400];
+	u32 tag;
 
 
 	Aoehdr *h = &c->h;
 	Aoehdr *h = &c->h;
 
 
@@ -115,9 +121,11 @@ find_blade(Conf *c, int shelf, int slot)
 	
 	
 	h->type = htons(AOE_ETH_PROTO);
 	h->type = htons(AOE_ETH_PROTO);
 	h->flags = AoEver << 4;
 	h->flags = AoEver << 4;
-	h->maj = htons(shelf);
-	h->min = slot;
+	h->maj = htons(opts->shelf);
+	h->min = opts->slot;
 	h->cmd = Config;
 	h->cmd = Config;
+	tag = htonl(opts->tag);
+	memmove(h->tag, &tag, sizeof h->tag);
 	c->bufcnt = 3;
 	c->bufcnt = 3;
 	c->vercmd = 0x10 | Qread;
 	c->vercmd = 0x10 | Qread;
 	memset(c->data, 0xED, sizeof c->data);
 	memset(c->data, 0xED, sizeof c->data);
@@ -136,12 +144,13 @@ find_blade(Conf *c, int shelf, int slot)
 			continue;
 			continue;
 		h = (Aoehdr *) buf;
 		h = (Aoehdr *) buf;
 		if (ntohs(h->type) != AOE_ETH_PROTO
 		if (ntohs(h->type) != AOE_ETH_PROTO
-			|| ntohs(h->maj) != shelf
-			|| h->min != slot)
+			|| ntohs(h->maj) != opts->shelf
+			|| h->min != opts->slot
+			|| memcmp(h->tag, &tag, sizeof h->tag))
 			continue;
 			continue;
 		break;
 		break;
 	}
 	}
-	if (opts.verbose) {
+	if (opts->verbose) {
 		puts("config query response:");
 		puts("config query response:");
 		hex_print(stdout, buf, n, " ");
 		hex_print(stdout, buf, n, " ");
 		putchar('\n');
 		putchar('\n');
@@ -152,13 +161,14 @@ find_blade(Conf *c, int shelf, int slot)
 /* read a packet that was sent by the device that returned *c earlier
 /* read a packet that was sent by the device that returned *c earlier
  */
  */
 int
 int
-aoe_pkt_read(int fd, uchar *buf, size_t siz, Conf *c)
+aoe_pkt_read(uchar *buf, size_t siz, Conf *c, u32 tag)
 {
 {
 	Aoehdr *h;
 	Aoehdr *h;
 	int n;
 	int n;
 
 
+	tag = htonl(tag);
 	for (;;) {
 	for (;;) {
-		n = read(fd, buf, siz);
+		n = read(sfd, buf, siz);
 		if (n < 0) {
 		if (n < 0) {
 			perror("read network");
 			perror("read network");
 			exit(EXIT_FAILURE);
 			exit(EXIT_FAILURE);
@@ -168,7 +178,8 @@ aoe_pkt_read(int fd, uchar *buf, size_t siz, Conf *c)
 		h = (Aoehdr *) buf;
 		h = (Aoehdr *) buf;
 		if (ntohs(h->type) != AOE_ETH_PROTO
 		if (ntohs(h->type) != AOE_ETH_PROTO
 			|| h->maj != c->h.maj
 			|| h->maj != c->h.maj
-			|| h->min != c->h.min)
+			|| h->min != c->h.min
+			|| memcmp(&tag, h->tag, sizeof h->tag))
 			continue;
 			continue;
 		break;
 		break;
 	}
 	}
@@ -192,6 +203,25 @@ ata_prep(Ata *a, Conf *c, u32 tag)
 	memmove(a->h.tag, &tag, sizeof a->h.tag);
 	memmove(a->h.tag, &tag, sizeof a->h.tag);
 }
 }
 
 
+/* pretty print ATA device identify text field
+ * bytes have already been swapped
+ */
+void
+pp_idtext(char *prefix, unsigned char *p, size_t len)
+{
+	int i;
+
+	fputs(prefix, stdout);
+	for (i = 0; i < len; ++i, ++p) {
+		if (*p == '\0')
+			break;
+		if (!isgraph((int) *p) && *p != ' ')
+			break;
+		putchar(*p);
+	}		
+	putchar('\n');
+}
+
 void
 void
 disk_identify(Conf *c, u32 tag)
 disk_identify(Conf *c, u32 tag)
 {
 {
@@ -199,6 +229,7 @@ disk_identify(Conf *c, u32 tag)
 	uchar buf[1400];
 	uchar buf[1400];
 	Ata a;
 	Ata a;
 	Ata *p;
 	Ata *p;
+	struct hd_driveid *id;
 
 
 	ata_prep(&a, c, tag);
 	ata_prep(&a, c, tag);
 	a.sectors = 1;
 	a.sectors = 1;
@@ -210,10 +241,29 @@ disk_identify(Conf *c, u32 tag)
 		exit(EXIT_FAILURE);
 		exit(EXIT_FAILURE);
 	}
 	}
 
 
-	n = aoe_pkt_read(sfd, buf, sizeof buf, c);
+	n = aoe_pkt_read(buf, sizeof buf, c, tag);
 	p = (Ata *) buf;
 	p = (Ata *) buf;
-	puts("device identify response:");
-	hex_print(stdout, p->data, 512, " ");
+
+	if (!opts.pp_ataid) {
+		puts("device identify response:");
+		hex_print(stdout, p->data, 512, " ");
+		return;
+	}
+
+	for (n = 0; n < 1024; n += 2) {
+		unsigned char ch;
+		ch = p->data[n];
+		p->data[n] = p->data[n+1];
+		p->data[n+1] = ch;
+	}
+	id = (struct hd_driveid *) p->data;
+	puts("device identify fields:");
+	printf("vendor_specific_0: 0x%X\n", id->vendor0);
+	printf("vendor_specific_1: 0x%X\n", id->vendor1);
+	printf("vendor_specific_2: 0x%X\n", id->vendor2);
+	pp_idtext("serial_number: ", id->serial_no, sizeof id->serial_no);
+	pp_idtext("firmware_rev: ", id->fw_rev, sizeof id->fw_rev);
+	pp_idtext("model: ", id->model, sizeof id->model);
 }
 }
 
 
 struct smartcmd *
 struct smartcmd *
@@ -295,7 +345,7 @@ smart(Conf *c, u32 tag, char *smart_cmd)
 		perror("send ATA identify device");
 		perror("send ATA identify device");
 		exit(EXIT_FAILURE);
 		exit(EXIT_FAILURE);
 	}
 	}
-	n = aoe_pkt_read(sfd, buf, sizeof buf, c);
+	n = aoe_pkt_read(buf, sizeof buf, c, tag);
 	p = (Ata *) buf;
 	p = (Ata *) buf;
 	show_smart_regs(p);
 	show_smart_regs(p);
 	if (s->data & SmartDataRet) {
 	if (s->data & SmartDataRet) {
@@ -330,7 +380,7 @@ init_opts(struct progopts *opts, int argc, char *argv[])
 {
 {
 	int c;
 	int c;
 
 
-	while ( (c = getopt(argc, argv, "hvit:s:S:")) != -1) {
+	while ( (c = getopt(argc, argv, "hviIt:s:S:")) != -1) {
 		switch (c) {
 		switch (c) {
 		case 'h':
 		case 'h':
 			usage();
 			usage();
@@ -342,6 +392,10 @@ init_opts(struct progopts *opts, int argc, char *argv[])
 		case 'i':
 		case 'i':
 			opts->ata_ident = 1;
 			opts->ata_ident = 1;
 			break;
 			break;
+		case 'I':
+			opts->ata_ident = 1;
+			opts->pp_ataid = 1;
+			break;
 		case 't':
 		case 't':
 			opts->tag = atoi(optarg);
 			opts->tag = atoi(optarg);
 			break;
 			break;
@@ -395,7 +449,8 @@ main(int argc, char *argv[])
 		exit(EXIT_FAILURE);
 		exit(EXIT_FAILURE);
 	
 	
 	alarm(opts.timeout);
 	alarm(opts.timeout);
-	find_blade(&c, opts.shelf, opts.slot);
+	find_blade(&c, &opts);
+	opts.tag += 1;
 	alarm(0);
 	alarm(0);
 	if (opts.verbose) {
 	if (opts.verbose) {
 		printf("found e%d.%d with mac ",
 		printf("found e%d.%d with mac ",

+ 45 - 0
aoetools.8

@@ -0,0 +1,45 @@
+.TH aoetools 8
+.SH NAME
+aoetools \- utilities for AoE on systems running Linux 2.6
+.SH DESCRIPTION
+The
+.I aoetools
+package contains scripts and commands that interact with,
+support, and supplement the
+aoe driver in the Linux kernel.
+.TP
+.BI aoe-discover
+tell aoe driver to discover AoE devices
+.TP
+.BI aoe-flush
+flush the down devices out of the aoe driver
+.TP
+.BI aoe-interfaces
+restrict aoe driver to specified network interfaces
+.TP
+.BI aoe-mkdevs
+create special device files for system without udev
+.TP
+.BI aoe-mkshelf
+create device files for one shelf address for system without udev
+.TP
+.BI aoe-revalidate
+revalidate the disk size of an aoe device
+.TP
+.BI aoe-stat
+collate and present information about AoE storage
+.TP
+.BI aoe-version
+display version numbers of AoE-related software
+.SH "SEE ALSO"
+.IR aoe-discover (8),
+.IR aoe-flush (8),
+.IR aoe-interfaces (8),
+.IR aoe-mkdevs (8),
+.IR aoe-mkshelf (8),
+.IR aoe-revalidate (8),
+.IR aoe-stat (8),
+.IR aoe-version (8),
+.IR aoecfg (8),
+.IR aoeping (8),
+.IR udev (7).

+ 10 - 7
dat.h

@@ -1,8 +1,9 @@
 /* dat.h - aoetools type definitions and macros
 /* dat.h - aoetools type definitions and macros
+ * Copyright 2007, Coraid, Inc., and licensed under GPL v.2.
  */
  */
 
 
 #define	nil	NULL
 #define	nil	NULL
-#define AOE_ETH_PROTO 0x88a2
+#define	nelem(x)	(sizeof(x)/sizeof((x)[0]))
 
 
 typedef unsigned char uchar;
 typedef unsigned char uchar;
 typedef struct Aoehdr Aoehdr;
 typedef struct Aoehdr Aoehdr;
@@ -62,13 +63,15 @@ struct Conf {
 };
 };
 
 
 enum {
 enum {
+	AOE_ETH_PROTO = 0x88a2,
+
 	AoEver = 1,
 	AoEver = 1,
 
 
 	ATAcmd = 0,		// command codes
 	ATAcmd = 0,		// command codes
 	Config,
 	Config,
 
 
-	Resp = (1<<3),		// flags
-	Error = (1<<2),
+	Resp = 1<<3,		// flags
+	Error = 1<<2,
 
 
 	BadCmd = 1,
 	BadCmd = 1,
 	BadArg,
 	BadArg,
@@ -76,10 +79,10 @@ enum {
 	ConfigErr,
 	ConfigErr,
 	BadVersion,
 	BadVersion,
 
 
-	Write = (1<<0),
-	Async = (1<<1),
-	Device = (1<<4),
-	Extend = (1<<6),
+	Write = 1<<0,
+	Async = 1<<1,
+	Device = 1<<4,
+	Extend = 1<<6,
 
 
 	Qread = 0,
 	Qread = 0,
 	Qtest,
 	Qtest,

+ 18 - 15
devnodes.txt

@@ -1,19 +1,28 @@
 			 Driver Compatibility
 			 Driver Compatibility
 
 
 Users of udev have device nodes like /dev/etherd/e0.0 created for them
 Users of udev have device nodes like /dev/etherd/e0.0 created for them
-automatically, as needed. These are dynamic device nodes.
+automatically, as needed. These are dynamic device nodes.  The aoe
+driver version 50 and above use dynamic device node minor numbers in
+order to support a greater number of AoE devices.
 
 
 Some systems use static device nodes, which are present in /dev
 Some systems use static device nodes, which are present in /dev
-regardless of what devices are really available to the system. The
+regardless of what AoE devices are really available to the system. The
 aoetools contain the aoe-mkdevs and aoe-mkshelf commands, which create
 aoetools contain the aoe-mkdevs and aoe-mkshelf commands, which create
-static device nodes.
+these static device nodes.
 
 
-To guard against confusion, it's important to have an aoetools
-installation that is compatible with your aoe driver. If you use an
-aoe driver from the Coraid website
+If the static device nodes do not match the static device minor
+numbers in the kernel, you could accidentally perform reads and writes
+to the wrong AoE device.  (It really is easier to let udev take care
+of the device nodes.)
+
+If you use an aoe driver from the Coraid website
 (http://www.coraid.com/support/linux/) then just use the aoetools that
 (http://www.coraid.com/support/linux/) then just use the aoetools that
-come bundled with that deiver. If you didn't get your aoe driver from
-the Coraid website, then here's what to do:
+come bundled with that deiver.  If you don't have udev, make sure you
+always load the aoe module with the aoe_dyndevs=0 option for any
+driver version above 49.
+
+If you didn't get your aoe driver from the Coraid website, and you
+can't use udev, then here's what to do:
 
 
     * Of course, read the README file in the aoetools sources.
     * Of course, read the README file in the aoetools sources.
 
 
@@ -23,13 +32,7 @@ the Coraid website, then here's what to do:
 
 
         make NPERSHELF=10
         make NPERSHELF=10
 
 
-    * To use aoetools-5 through aoetools-7 with newer 2.6 kernels
-      (2.6.14 and later), build the aoetools with an extra parameter
-      for "make", like this:
-
-        make NPERSHELF=16
-
-    * Using aoetools-4 and earlier with newer 2.6 kernels (2.6.14 and
+    * Using aoetools-7 and earlier with newer 2.6 kernels (2.6.14 and
       later) is not recommended.
       later) is not recommended.
 
 
 Other combinations should work with the default settings.
 Other combinations should work with the default settings.

+ 1 - 0
fns.h

@@ -1,3 +1,4 @@
+/* Copyright 2007, Coraid, Inc., and licensed under GPL v.2. */
 int dial(char *eth);
 int dial(char *eth);
 int getea(int s, char *name, uchar *ea);
 int getea(int s, char *name, uchar *ea);
 
 

+ 4 - 2
linux.c

@@ -1,4 +1,6 @@
-// linux.c: low level access routines for Linux
+/* linux.c: low level access routines for Linux
+ * Copyright 2007, Coraid, Inc., and licensed under GPL v.2.
+ */
 #include "config.h"
 #include "config.h"
 #include <sys/socket.h>
 #include <sys/socket.h>
 #include <stdio.h>
 #include <stdio.h>
@@ -71,7 +73,7 @@ getea(int s, char *name, uchar *ea)
 	struct ifreq xx;
 	struct ifreq xx;
 	int n;
 	int n;
 
 
-        strcpy(xx.ifr_name, name);
+	strcpy(xx.ifr_name, name);
 	n = ioctl(s, SIOCGIFHWADDR, &xx);
 	n = ioctl(s, SIOCGIFHWADDR, &xx);
 	if (n == -1) {
 	if (n == -1) {
 		perror("Can't get hw addr");
 		perror("Can't get hw addr");