aoetools-30/0000755000175000017500000000000011155505331012730 5ustar ecashinecashinaoetools-30/aoe-discover.80000644000175000017500000000334011102351275015377 0ustar ecashinecashin.TH aoe-discover 8 .SH NAME aoe-discover \- tell aoe driver to discover AoE devices .SH SYNOPSIS .nf .B aoe-discover .fi .SH DESCRIPTION The .I aoe-discover command tells the aoe driver to discover ATA over Ethernet (AoE) devices on the network. All network interfaces will be probed with a AoE config query broadcast. .PP If the .I aoe-interfaces command has limited the allowable network interfaces, only devices discovered via allowable interfaces will become available. The default is to make available all AoE devices found on all accessible ethernet networks. .PP It's good to run the .I aoe-discover command after running \fIaoe-interfaces\fP. .SH EXAMPLE In this example, the root user on a host named .I nai loads the aoe module with only eth0 allowable for AoE traffic. After remembering that shelf 7 is on eth3, this sysadmin uses .I aoe-interfaces to add eth3 to the list of allowable network interfaces and then calls .I aoe-discover to ask the aoe driver to look for new AoE devices. .IP .EX .nf nai:~# modprobe aoe aoe_iflist="eth0" nai:~# aoe-stat e10.9 eth0 up nai:~# aoe-interfaces eth0 eth3 nai:~# aoe-discover nai:~# aoe-stat e7.0 eth3 up e7.1 eth3 up e7.2 eth3 up e7.3 eth3 up e7.4 eth3 up e7.5 eth3 up e7.6 eth3 up e7.7 eth3 up e7.8 eth3 up e7.9 eth3 up e10.9 eth0 up .fi .EE .SH "SEE ALSO" .IR aoe-interfaces (8), .IR aoe-stat (8), .IR aoetools (8). .SH AUTHOR Ed L. Cashin (ecashin@coraid.com) aoetools-30/COPYING0000644000175000017500000004311010325226272013764 0ustar ecashinecashin GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. aoetools-30/HACKING0000644000175000017500000000171710325226272013727 0ustar ecashinecashinContributing Thanks for your interest in contributing to the aoetools. The best way to submit proposed changes is in plain-text "patches". These patches are generated by the diff program. Patches should be clean (to the point and easy to read) and should do one thing. Send multiple patches if necessary. Patches should be generated with "diff -uprN" if possible, and should be designed to be applied with "patch -p1". Design note: The aoe-mkdevs and aoe-mkshelf scripts are expected to work with special device files forever, but the aoe-discover script will likely someday use sysfs or something similar instead of /dev/etherd/discover. The same goes for aoe-interfaces. For that reason, there is no runtime interface for giving aoe-discover an alternative to /dev/etherd at runtime. Instead, the device directory is set once and for all by make. That way, the user interface won't change or become obsolete when aoe-discover stops using /dev/etherd/discover. aoetools-30/Makefile0000644000175000017500000000437511153324130014373 0ustar ecashinecashin# Makefile # You can edit this file or override these variables on # the commandline. For example, "make install MANDIR=/tmp/man" # would use defaults for all variables except ${MANDIR}. # You can set this to something like /opt/aoetools-x # if you want to install everything in one place. # # Note that even with ${PREFIX} set, the devices in # /dev/etherd will be used unless you override ${DEVDIR}. PREFIX = # Your aoe-driver device files should be in ${DEVDIR}. DEVDIR = /dev/etherd # The programs will be installed in ${SBINDIR}. SBINDIR = ${PREFIX}/usr/sbin MANDIR = ${PREFIX}/usr/share/man # NPERSHELF is the number of slot addresses per shelf address. # This number must match the same setting in the aoe driver. # # Older aoe drivers have NPERSHELF set to 10, and newer ones # use 16. # # You can see the setting in your driver like this in the driver # source directory. (Change into the "linux" directory if you're # using the standalone driver from CORAID.) # # grep 'NPERSHELF.*=' drivers/block/aoe/aoe.h # NPERSHELF=16 # end of user-configurable variables # these scripts are created from the *.in files CONF_SCRIPTS = aoe-discover aoe-interfaces aoe-mkshelf aoe-revalidate aoe-flush aoe-stat PROGS = aoeping aoecfg COMMANDS := ${CONF_SCRIPTS} aoe-mkdevs aoe-version coraid-update ${PROGS} CFLAGS = -Wall -O -g AOE_PING_OBJ = aoeping.o linux.o AOE_CFG_OBJ = aoecfg.o linux.o all : configure ${PROGS} @true configure : @for f in ${CONF_SCRIPTS}; do \ sh -xc "sed -e 's!@devdir@!${DEVDIR}!g' -e 's!@npershelf@!${NPERSHELF}!g' $$f.in > $$f" || break; \ done # DESTDIR was put in for Rob Holland to make gentoo packaging easier install : all mkdir -p ${DESTDIR}${SBINDIR} mkdir -p ${DESTDIR}${MANDIR}/man8 @for f in ${COMMANDS}; do \ sh -xc "install -m 700 $$f ${DESTDIR}${SBINDIR}/$$f" || break; \ sh -xc "install -m 664 $$f.8 ${DESTDIR}${MANDIR}/man8/$$f.8" || break; \ done clean : rm -f ${CONF_SCRIPTS} ${AOE_PING_OBJ} ${AOE_CFG_OBJ} ${PROGS} aoeping : ${AOE_PING_OBJ} ${CC} ${CFLAGS} -o $@ ${AOE_PING_OBJ} aoeping.o : aoeping.c dat.h fns.h ${CC} ${CFLAGS} -o $@ -c $< linux.o : linux.c config.h ${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 $< aoetools-30/NEWS0000644000175000017500000001154311155505131013431 0ustar ecashinecashin2009-03-03 Ed Cashin aoe-version modinfo workaround: cd to a directory without aoe release 30 2008-12-09 Ed Cashin mention that aoeping uses raw sockets in manpage use absolute path to aoe.ko when ./aoe is readable release 29 2008-11-11 Ed Cashin remove "function" reserved word from aoe-flush (for dash shell) release 28 2008-08-01 Ed Cashin use ".txt" extension for output file of sos-linux 2008-06-27 Ed Cashin aoeping: recognize errors in SMART command response aoe-stat manpage improvements release 27 2008-05-14 "Ed L. Cashin" add sos-linux tool for collecting localhost information release 26 2008-04-11 "Ed L. Cashin" create coraid-update for uploading update file to an update target create coraid-update manpage release 25 2008-03-25 "Ed L. Cashin" clean up aoecfg object files in "clean" target 2008-02-22 "Ed L. Cashin" make aoeping and aoecfg more conforming to AoE protocol release 24 2008-01-09 "Ed L. Cashin" release 23 2008-01-09 Sam Hopkins support new payload size information from aoe driver 2008-01-08 "Ed L. Cashin" handle aoe-flush without arguments correctly 2007-12-19 "Ed L. Cashin" fix aoecfg manpage typo (-s for string) 2007-12-10 "Ed L. Cashin" aoe-flush: support flushing specific devices release 22 2007-10-29 "Ed L. Cashin" 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" 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" add copyright information support kernel.org aoe driver in aoe-version add aoetools manpage release 19 2007-08-08 "Ed L. Cashin" distinguish between missing device nodes and wrong ones release 18 2007-07-26 "Ed L. Cashin" 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" check for char devices specifically before using them 2007-06-01 "Ed L. Cashin" workaround dash POSIX math bug release 16 2007-03-20 "Ed L. Cashin" add quoting to aoe-flush release 15 2007-02-26 Marcus Rueckert create the same directories we install to 2007-02-06 Sam Hopkins add support for -c flag to aoe-interfaces add support for -a flag to aoe-flush update manpages for aoe-interfaces, aoe-flush release 14 2006-12-21 Sam Hopkins support aoe devices without "etherd" prefix in name create new character device nodes release 13 2006-10-30 Sam Hopkins formatting cleanup of man pages cleanup of scripts, adding error checking add aoe-flush command release 12 2006-10-13 David Martinez Moreno aoe-stat: POSIX shell math can't count as high as bash 2006-09-07 Anthony Wright use POSIX shell math instead of relying on dc or bc release 11 2006-05-25 "Ed L. Cashin" update README: aoetools are for 2.6 systems release 10 2006-01-18 "Ed L. Cashin" aoe-revalidate: notice error in writing to revalidate device release 9 2005-11-09 Sam Hopkins add aoe-revalidate document driver compatibility release 8 2005-08-18 "Ed L. Cashin" format sub-gigabyte device sizes correctly release 7 2005-08-17 "Ed L. Cashin" make aoe-stat show device size release 6 2005-07-13 "Ed L. Cashin" make number of slots per shelf configurable Rob Holland : install using PREFIX "make install" builds aoeping avoid gcc 4 warnings by specifying uchar in params release 5 2005-05-17 "Ed L. Cashin" fix typo in Makefile preventing aoeping installation: s/PROG/PROGS/ add TODO file release 4 2005-04-14 "Ed L. Cashin" add very basic SMART support to aoeping release 3 2005-04-12 "Ed L. Cashin" add aoeping, a userland tool for simple AoE communications release 2 2005-03-23 "Ed L. Cashin" initial release of aoetools, version 1 aoetools-30/README0000644000175000017500000000315411153324161013611 0ustar ecashinecashinThe aoetools are programs that assist in using ATA over Ethernet on systems with version 2.6 Linux kernels. Systems running 2.4 Linux kernels do not need and should not install the aoetools. The aoe driver for 2.4 kernels is self sufficient. -------------------------------------------------------------------- AOE DRIVER COMPATIBILITY 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. -------------------------------------------------------------------- If you need to configure the software, look at the variables at the top of the Makefile. The defaults should work for most people. When using the defaults there's only one step to configure and install the aoetools software and documentation: make install You'll need sufficient permissions to install in the default locations if you haven't overridden them with your own locations. Please see the aoetools manpage for a brief list of the tools. These two are legacy commands for systems without udev. aoe-mkdevs create character and block device files aoe-mkshelf create block device files for one shelf address The aoetools homepage http://aoetools.sourceforge.net/ The CORAID homepage http://www.coraid.com/ The Linux Support Page at CORAID http://support.coraid.com/support/linux/ aoetools-30/aoe-interfaces.in0000644000175000017500000000202611153324176016151 0ustar ecashinecashin#! /bin/sh # aoe-interfaces - set or list the allowed AoE network interfaces # Copyright 2009, CORAID, Inc., and licensed under GPL v.2. zero="`basename $0`" devf=@devdir@/interfaces sysf=/sys/module/aoe/parameters/aoe_iflist if test -z "$*"; then if test -r "$sysf"; then cat "$sysf" else # can't read from interfaces device false fi exit fi if test "$1" = "-c"; then 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 if test -w "$sysf"; then printf '%s\0' "$netifs" > "$sysf" else if test ! -w "$devf"; then echo 1>&2 "$zero: $devf does not exist or is not writeable." exit 1 fi 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 aoetools-30/aoe-discover.in0000644000175000017500000000062511153324171015642 0ustar ecashinecashin#! /bin/sh # aoe-discover - trigger an AoE device discovery # Copyright 2009, CORAID, Inc., and licensed under GPL v.2. zero=`basename $0` f=@devdir@/discover if ! test -w $f; then echo 1>&2 $zero: $f does not exist or is not writeable. exit 1 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 aoetools-30/aoe-flush.80000644000175000017500000000252211102351275014703 0ustar ecashinecashin.TH aoe-flush 8 .SH NAME aoe-flush \- flush the down devices out of the aoe driver .SH SYNOPSIS .nf .B aoe-flush [-a] .B aoe-flush dev1 [dev2 ...] .fi .SH DESCRIPTION The .I aoe-flush command tells the aoe driver to remove devices from the system and forget about them. Normally the aoe driver will remember all devices it has seen until the module is unloaded. By default, .I aoe-flush will only flush downed devices. With the \fB-a\fP flag all devices are candidates for removal. .PP .I aoe-flush will not remove devices that are in use. This includes devices in the closewait state or those in the process of being installed. .PP By specifying a series of specific aoe devices, e.g., \fBe7.0 e3.2\fP, it is possible to ask the aoe driver to forget these devices. This feature may be convenient after a temporary AoE target is no longer being used. .SH OPTIONS .TP \fB-a\fP The \fB-a\fP option tells the aoe driver to forget all unused devices. .SH EXAMPLE .EX .nf nai# aoe-stat | grep e12.0 e12.0 0.000GB eth1 down nai# aoe-flush nai# aoe-stat | grep e12.0 .fi .EE .SH BUGS Flushed devices may reappear when they are discovered by the periodic discovery beacon. .I aoe-discover may be used to force this behaviour. .SH "SEE ALSO" .IR aoe-stat (8), .IR aoe-discover (8), .IR aoetools (8). .SH AUTHOR Sam Hopkins (sah@coraid.com) aoetools-30/aoe-flush.in0000644000175000017500000000173711153324015015147 0ustar ecashinecashin#! /bin/sh # aoe-flush - ask aoe driver to forget about devices # Copyright 2009, CORAID, Inc., and licensed under GPL v.2. zero="`basename $0`" f="@devdir@/flush" spec="" if ! test -w "$f"; then echo 1>&2 "$zero: $f does not exist or is not writeable." exit 1 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 # make sure that each device in the whitespace-separated # list exists verify_devs () { err="" for d; do aoe-stat | awk -vd="$d" '$1==d{print $1}' | test "`cat`" || { exec 2>&1 echo "$zero Error: \"$d\" is not an aoe device" err="$err $d" } done test ! "$err" } err="" if test "$1"; then if test "$1" = "-a"; then spec=all else spec="$*" verify_devs $spec || exit 1 fi for i in $spec; do printf "$i" > "$f" || { echo 1>&2 "$zero: flush failed" err="$err $i" } done else echo > "$f" || err=no_args fi if test "$err"; then exit 1 fi aoetools-30/aoe-interfaces.80000644000175000017500000000445111102351275015710 0ustar ecashinecashin.TH aoe-interfaces 8 .SH NAME aoe-interfaces \- restrict aoe driver to specified network interfaces .SH SYNOPSIS .nf .B aoe-interfaces [dev1] [dev2 ...] .B aoe-interfaces -c .fi .SH DESCRIPTION The .I aoe-interfaces command tells the aoe driver to ignore ATA over Ethernet (AoE) traffic on all but the specified network interfaces. It is analogous to the \fIaoe_iflist\fP module load option. .PP If neither the \fIaoe_iflist\fP module load option nor the \fIaoe-interfaces\fP command are used, the aoe driver will use any network interface for AoE traffic. Using \fIaoe-interfaces\fP to limit AoE to only trusted networks prevents the case where a rogue AoE target appears on a public network, diverting data from the legitimate AoE target. Such an imposter target effectively corrupts the data on the legitimate target. .PP If the aoe driver is a module, then calling .I aoe-interfaces without arguments will display the current interfaces list. If it hasn't been set then the output will be blank. .PP It's good to run the .I aoe-discover command after setting the AoE interfaces list. .SH OPTIONS .TP \fB-c\fP The \fB-c\fP flag will clear the interface access list, permitting any interface to be used. .SH EXAMPLE In this example, the root user on a host named .I nai loads the aoe module with only eth0 allowable for AoE traffic. After remembering that shelf 7 is on eth3, this sysadmin uses .I aoe-interfaces to add eth3 to the list of allowable network interfaces and then calls .I aoe-discover to ask the aoe driver to look for new AoE devices. .IP .EX .nf nai:~# modprobe aoe aoe_iflist="eth0" nai:~# aoe-stat e10.9 eth0 up nai:~# aoe-interfaces eth0 eth3 nai:~# aoe-discover nai:~# aoe-stat e7.0 eth3 up e7.1 eth3 up e7.2 eth3 up e7.3 eth3 up e7.4 eth3 up e7.5 eth3 up e7.6 eth3 up e7.7 eth3 up e7.8 eth3 up e7.9 eth3 up e10.9 eth0 up nai:~# aoe-interfaces eth0 eth3 .fi .EE .SH "SEE ALSO" .IR aoe-discover (8), .IR aoe-stat (8), .IR aoetools (8). .SH AUTHOR Ed L. Cashin (ecashin@coraid.com) aoetools-30/aoe-mkshelf.80000644000175000017500000000423511102351275015216 0ustar ecashinecashin.TH aoe-mkshelf 8 .SH NAME aoe-mkshelf \- create special device files for one shelf address .SH SYNOPSIS .nf .B aoe-mkshelf {device-dir} {shelf-address} .B env n_partitions=1 aoe-mkshelf {device-dir} {shelf-address} .fi .SH DESCRIPTION The .I aoe-mkshelf 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 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 .I n_partitions environment variable described below. .SS Arguments .TP \fBdevice-dir\fP This should be the name of the directory where the block device files will be created. .TP \fBshelf-address\fP This is the AoE major address, or shelf address, for which to create device nodes. For example, specifying a shelf address of 1 means that the e1.* device nodes will be created in \fBdevice-dir\fP. .SH ENVIRONMENT VARIABLES If the .I n_partitions variable is set in the environment, it will override the default number of partitions per aoe disk, namely 16. .SH EXAMPLE In this example, the root user on a host named .I nai creates special files for using the aoe disks in shelf 7. Then he remembers that the driver doesn't have partition support, so the command is called again with \fIn_partitions\fP set to 1. .IP .EX .nf nai:~# aoe-mkshelf /dev/etherd 7 nai:~# ls /dev/etherd/e7.* | wc -l 160 nai:~# rm /dev/etherd/e7.* nai:~# n_partitions=1 aoe-mkshelf /dev/etherd 7 nai:~# ls /dev/etherd/e7.* | wc -l 10 nai:~# .fi .EE .SH "SEE ALSO" .IR aoe-discover (8), .IR aoe-interfaces (8), .IR aoe-mkdevs (8), .IR aoe-stat (8), .IR aoetools (8), .IR udev (7). .SH AUTHOR Ed L. Cashin (ecashin@coraid.com) aoetools-30/aoe-mkdevs0000755000175000017500000000261011153324547014716 0ustar ecashinecashin#!/bin/sh # aoe-mkdevs - make static device nodes on systems without udev # Copyright 2009, CORAID, Inc., and licensed under GPL v.2. n_shelves=${n_shelves:-10} n_partitions=${n_partitions:-16} if test "$#" != "1"; then echo "Usage: `basename $0` {dir}" 1>&2 echo " n_partitions=16 `basename $0` {dir}" 1>&2 exit 1 fi dir=$1 zero="`basename $0`" MAJOR=152 dyn=/sys/module/aoe/parameters/aoe_dyndevs if test -r "$dyn" && test "`cat $dyn`" = 1; then cat 1>&2 <&2 <&2 Usage: $zero 'e{major}.{minor}' exit 1 fi if ! test -w $f; then echo 1>&2 $zero: $f does not exist or is not writeable exit 1 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 "$zero: revalidate failed" 1>&2 exit 1 } aoetools-30/aoe-mkshelf.in0000755000175000017500000000221211153324555015460 0ustar ecashinecashin#! /bin/sh # aoe-mkshelf - device nodes for one shelf without udev # Copyright 2009, CORAID, Inc., and licensed under GPL v.2. zero=`basename $0` if test "$#" != "2"; then echo "Usage: $zero {dir} {shelfaddress}" 1>&2 echo " n_partitions=16 $zero {dir} {shelfaddress}" 1>&2 exit 1 fi dyn=/sys/module/aoe/parameters/aoe_dyndevs if test -r "$dyn" && test "`cat $dyn`" = 1; then cat 1>&2 <&2 <&2 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 </dev/null | grep -v p` end; do # maybe ls comes up empty, so we use "end" test $d = end && continue test -r "$d/payload" && payload=yes done if test "$payload" = "yes"; then format="%10s %15s %10s %-5s %-14s\n" else format="%10s %15s %6s %-14s\n" fi for d in `ls -d $sysd/block/*e[0-9]*\.[0-9]* 2>/dev/null | grep -v p` end; do test $d = end && continue dev=`echo "$d" | sed 's/.*!//'` sectors="`cat \"$d/size\"`" minor="`awk -F: '{print $2}' \"$d/dev\"`" checknode "$dev" "$minor" psize=$(((512000 * $sectors) / (1000 * 1000 * 1000))) psize=`printf "%04d\n" $psize | sed 's!\(...\)$!.\1!'` if test "$payload" = "yes"; then printf "$format" \ "$dev" \ "${psize}GB" \ "`cat \"$d/netif\"`" \ "`cat \"$d/payload\"`" \ "`cat \"$d/state\"`" else printf "$format" \ "$dev" \ "${psize}GB" \ "`cat \"$d/netif\"`" \ "`cat \"$d/state\"`" fi done | sort | grep $re aoetools-30/aoe-version0000644000175000017500000000316711155505223015111 0ustar ecashinecashin#! /bin/sh # aoe-version - display versions of AoE-related software # Copyright 2009, CORAID, Inc., and licensed under GPL v.2. aoetools=30 # modinfo doesn't always work correctly when there is a file # in the current working directory called "aoe", but it's # not hard to change the current working directory. for wd in . / /sys /var/run /usr /proc /etc /home; do a=`{ cd "$wd" 2> /dev/null && test ! -r aoe && echo yes; } || echo no` if test "$a" = "yes"; then cd "$wd" break fi done # The aoe module isn't guaranteed to be in the location below, # but if we only try to use it when each of the directories # above was not usable, we shouldn't use the hard-coded location # often. aoe=aoe if test -r ./aoe; then aoe="/lib/modules/`uname -r`/kernel/drivers/block/aoe/aoe.ko" fi # 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 < /dev/null \\ && echo ok ok .fi .EE .LP The next example uses SMART to determine whether the disk on e10.9 thinks it has exceeded its error threshold. The ATA spec says that the LBA Mid register will be 0x4f when the disk has not exceeded its error threshold. .IP .EX .nf bash# aoeping -S return_status \\ 10 9 eth0 | grep 'LBA Mid: 0x4f' \\ > /dev/null \\ && echo ok ok .fi .EE .LP Note that in a script, it would be prudent to specify and handle a timeout. Also, a good script would make sure the \fBStatus\fP register does not have the error bit (bit zero) or the device fault bit (bit 5) set. .SH "SEE ALSO" .IR aoe-discover (8), .IR aoe-interfaces (8), .IR aoe-mkdevs (8), .IR aoe-mkshelf (8), .IR aoe-stat (8), \fIAoE (ATA over Ethernet)\fP: http://support.coraid.com/documents/AoEr10.txt, \fIATA specification\fP .SH AUTHOR Ed L. Cashin (ecashin@coraid.com) aoetools-30/aoecfg.80000644000175000017500000000431511037442034014247 0ustar ecashinecashin.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 \-s " 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://support.coraid.com/documents/AoEr10.txt, \fIATA specification\fP .SH AUTHOR Erik Quanstrom (quanstro@coraid.com) aoetools-30/aoecfg.c0000644000175000017500000000776211153324000014322 0ustar ecashinecashin/* * aoecfgstr.c - fiddle aoe configuration strings. * Copyright 2009, Erik Quanstrom, CORAID, Inc., Licenced under GPL v2 */ #include #include #include #include #include #include #include #include #include #include #include #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 = 0; c->firmware = 0; c->scnt = 0; c->vercmd = 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; } aoetools-30/coraid-update0000755000175000017500000000421011153326111015367 0ustar ecashinecashin#! /bin/sh # usage: coraid-update {update file} {AoE target} # coraid-update depends upon sysfs mounted on /sys # The destination must be, # 1) an AoE target ready for I/O, and # 2) not too big to be an update target # # Later, when CORAID appliances mark update targets with special ATA # device identify content or special target content, a prompt should # be added after the check of the target's size if the identifying # content is not detected. # # The update file must either, # 1) be an SR tarc file that looks OK to the local tar, or # 2) any file not ending in ".tarc". # size of update LUN in /proc/partitions is 40000 max=70000 usage="usage: coraid-update {update file} {AoE device}" if test "$#" != 2; then echo "$usage" 1>&2 exit 1 fi update="$1" ulb="$2" # if it's an update target, it should be in `aoe-stat` aoe-stat | awk -vt="`basename $ulb`" ' BEGIN{fail=1} $1==t{fail=0} END{exit fail}' || { exec 1>&2 echo "coraid-update Error: \"$ulb\" is not an AoE target" echo "$usage" exit 1 } # it should have a size no larger than $max in /proc/partitions t="`echo $ulb | sed 's!^/dev/!!'`" awk -vt="$t" '$NF==t{print $3}' /proc/partitions | awk -vhi=$max -vdev="$ulb" ' BEGIN{ err = "could not get size of " dev } { err = "none" if ($1 > hi) { err = dev " is too large to be an update target" exit } } END{ if (err != "none") { print "Error coraid-update: " err > "/dev/stderr" exit 1 } exit 0 }' || exit 1 # this test should be removed when it is performed on the appliance # # For a 2734080-byte tarc file, an incomplete file of 2727450 bytes passes # this test, but one of 2727400 does not. So this test isn't fullproof. # if test "`echo \"$update\" | grep '\.tarc$'`"; then tar tf "$update" > /dev/null 2>&1 || { exec 1>&2 echo "coraid-update Error: \"$update\" does not appear to be a valid tarc file" exit 1 } fi if test ! -r "$update"; then echo "coraid-update Error: \"$update\" is not readable" 1>&2 exit 1 fi # send it over and complain on error if ! dd if="$update" of="$ulb" 2> /dev/null || ! sync; then exec 1>&2 echo "coraid-update Error: could not successfully write \"$update\" to \"$ulb\"" exit 1 fi aoetools-30/aoeping.c0000644000175000017500000002331311153324563014524 0ustar ecashinecashin/* aoeping.c - userland aoe pinger * Copyright 2009, CORAID, Inc., and licensed under GPL v.2. * * run without arguments for usage */ #include #include #include #include #include #include #include #include #include #include "dat.h" #include "fns.h" struct progopts { int shelf; int slot; char *netif; int verbose; int timeout; u32 tag; char *smart; char ata_ident; char pp_ataid; /* pretty print ATA device identify response */ }; static struct progopts defaults = { .shelf = 0, .slot = 0, .netif = NULL, .verbose = 0, .timeout = 0, .tag = 0, .smart = NULL, .ata_ident = 0, .pp_ataid = 0, }; static struct progopts opts; struct smartcmd { char *name; /* subcommand name from ATA spec */ int cmd; /* for features register */ char data; /* does this subcommand xfer data? */ }; static struct smartcmd smarts[] = { { "read_data", 0xd0, SmartDataRet }, // { "attr_autosave", 0xd2, 0 }, (unsupported b/c it overloads sector count) { "offline_immediate", 0xd4, 0 }, { "read_log", 0xd5, SmartDataRet }, { "write_log", 0xd6, SmartDataPut }, { "enable", 0xd8, 0 }, { "disable", 0xd9, 0 }, { "return_status", 0xda, 0 }, }; static char *progname; static int sfd; /* raw socket file descriptor */ static uchar mac[6]; void usage(void) { fprintf(stderr, "usage:\t%s [options] {shelf} {slot} {netif}\n", progname); fprintf(stderr, "%s\n\t%s\n\t%s\n\t%s\n\t%s\n", "options:", "-i\tdo ATA device identify dump as raw hex", "-I\tdo ATA device identify print fields", "-v\tbe verbose", "-h\tshow this usage summary"); fprintf(stderr, "%s\n\t%s\n\t%s\n\t%s\n", "options taking arguments:", "-s\ttimeout in seconds", "-S\tperform SMART command", "-t\tspecify number for starting AoE tag"); } void hex_print(FILE *out, uchar *buf, int n, char *sep) { int i; int per_line = 16; for (i = 0; i < n;) { fprintf(out, "%02x%s", *buf++ & 0xff, sep); if (!(++i % per_line)) putc('\n', out); } } void find_blade(Conf *c, struct progopts *opts) { int n; uchar buf[1400]; u32 tag; Aoehdr *h = &c->h; 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(opts->shelf); h->min = opts->slot; h->cmd = Config; tag = htonl(opts->tag); memmove(h->tag, &tag, sizeof h->tag); c->bufcnt = 0; c->firmware = 0; c->scnt = 0; c->vercmd = Qread; c->len = htons(1024); memset(c->data, 0xED, sizeof c->data); if (write(sfd, c, sizeof *c) == -1) { perror("send config query"); exit(EXIT_FAILURE); } for (;;) { n = read(sfd, buf, sizeof buf); if (n < 0) { perror("read network"); exit(EXIT_FAILURE); } if (n < 60) continue; h = (Aoehdr *) buf; if (ntohs(h->type) != AOE_ETH_PROTO || ntohs(h->maj) != opts->shelf || h->min != opts->slot || memcmp(h->tag, &tag, sizeof h->tag)) continue; break; } if (opts->verbose) { puts("config query response:"); hex_print(stdout, buf, n, " "); putchar('\n'); } memcpy(c, buf, sizeof *c); } /* read a packet that was sent by the device that returned *c earlier */ int aoe_pkt_read(uchar *buf, size_t siz, Conf *c, u32 tag) { Aoehdr *h; int n; tag = htonl(tag); for (;;) { n = read(sfd, buf, siz); if (n < 0) { perror("read network"); exit(EXIT_FAILURE); } if (n < 60) continue; h = (Aoehdr *) buf; if (ntohs(h->type) != AOE_ETH_PROTO || h->maj != c->h.maj || h->min != c->h.min || memcmp(&tag, h->tag, sizeof h->tag)) continue; break; } return n; } /* prepare a packet for doing ATA to a device that gave us Conf *c */ void ata_prep(Ata *a, Conf *c, u32 tag) { memset(a, 0, sizeof *a); memcpy(a->h.dst, c->h.src, sizeof a->h.dst); memcpy(a->h.src, mac, sizeof a->h.src); a->h.type = htons(AOE_ETH_PROTO); a->h.flags = AoEver << 4; a->h.maj = c->h.maj; a->h.min = c->h.min; a->h.cmd = ATAcmd; tag = htonl(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'); } int smart_supported(unsigned char *p) { u16 w; p += 82 * 2; /* skip to word 82 */ w = *p++; w |= *p << 8; /* word 82 bit 0 is SMART support per ATA spec */ return !!(w & 1); } void disk_identify(Conf *c, struct progopts *opts, int *smart) { int n; uchar buf[1400]; Ata a; Ata *p; struct hd_driveid *id; ata_prep(&a, c, opts->tag); a.sectors = 1; a.cmd = ATAid_dev; a.lba[3] = 0xa0; if (write(sfd, &a, sizeof a) == -1) { perror("send ATA identify device"); exit(EXIT_FAILURE); } n = aoe_pkt_read(buf, sizeof buf, c, opts->tag); p = (Ata *) buf; *smart = smart_supported(p->data); if (opts->ata_ident && !opts->pp_ataid) { puts("device identify response:"); hex_print(stdout, p->data, 512, " "); return; } if (!opts->pp_ataid) 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 * smartcmd_lookup(char *nam) { int n = sizeof smarts / sizeof smarts[0]; int i; for (i = 0; i < n; ++i) { char *p = strchr(nam, ':'); if (p && !strncmp(smarts[i].name, nam, p - nam)) return &smarts[i]; else if (!strcmp(smarts[i].name, nam)) return &smarts[i]; } return nil; } void smart_registers(Ata *a, char *opts, struct smartcmd *s) { a->err = s->cmd; a->lba[1] = 0x4f; a->lba[2] = 0xc2; if (opts++) a->lba[0] = strtol(opts, NULL, 0); } int show_smart_regs(Ata *a) { if (a->err & ATAabrt) { fputs("SMART command aborted on target.\n", stderr); return -1; } puts("ATA registers:"); char *names[] = { "Features", "Sector Count", "LBA Low", "LBA Mid", "LBA High", "Status", }; int regs[] = { a->err, a->sectors, a->lba[0], a->lba[1], a->lba[2], a->cmd, }; int i; for (i = 0; i < sizeof regs / sizeof regs[0]; ++i) printf("%20s: 0x%02x\n", names[i], regs[i]); return 0; } void smart(Conf *c, u32 tag, char *smart_cmd) { int n; uchar buf[1400]; Ata a; Ata *p; struct smartcmd *s = smartcmd_lookup(smart_cmd); if (!s) { fprintf(stderr, "%s Error: no such SMART command: %s\n", progname, smart_cmd); exit(EXIT_FAILURE); } ata_prep(&a, c, tag); a.sectors = !!s->data; /* we only support one-sector data xfer */ a.cmd = ATAsmart; smart_registers(&a, strchr(smart_cmd, ':'), s); if (s->data & SmartDataPut) { if (read(STDIN_FILENO, a.data, 512) == -1) { perror("reading smart data from stdin"); exit(EXIT_FAILURE); } a.h.flags |= Write; } if (write(sfd, &a, sizeof a) == -1) { perror("send ATA identify device"); exit(EXIT_FAILURE); } n = aoe_pkt_read(buf, sizeof buf, c, tag); p = (Ata *) buf; if (show_smart_regs(p) != 0) exit(EXIT_FAILURE); if (s->data & SmartDataRet) { puts("SMART data:"); hex_print(stdout, p->data, 512, " "); } } void bad_option(char c) { fprintf(stderr, "%s Error: unrecognized option: ", progname); if (isprint(c)) fprintf(stderr, "%c\n", c); else fprintf(stderr, "0x%02x\n", c & 0xff); } void check_timeout(int secs) { if (secs < 1) { fprintf(stderr, "%s Error: timeout seconds must be one or more\n", progname); exit(EXIT_FAILURE); } } void init_opts(struct progopts *opts, int argc, char *argv[]) { int c; while ( (c = getopt(argc, argv, "hviIt:s:S:")) != -1) { switch (c) { case 'h': usage(); exit(EXIT_SUCCESS); break; case 'v': ++opts->verbose; break; case 'i': opts->ata_ident = 1; break; case 'I': opts->ata_ident = 1; opts->pp_ataid = 1; break; case 't': opts->tag = atoi(optarg); break; case 's': opts->timeout = atoi(optarg); check_timeout(opts->timeout); break; case 'S': opts->smart = optarg; break; case '?': bad_option(optopt); usage(); exit(EXIT_FAILURE); break; default: abort(); /* shouldn't happen */ } } if (argc - optind != 3) { usage(); exit(EXIT_FAILURE); } opts->shelf = atoi(argv[optind]); opts->slot = atoi(argv[optind+1]); opts->netif = argv[optind+2]; } int main(int argc, char *argv[]) { Conf c; int smartable = 0; opts = defaults; progname = strrchr(argv[0], '/'); if (progname) progname += 1; else progname = argv[0]; init_opts(&opts, argc, argv); opts.tag |= 1UL << 31; /* set high bit for userland AoE */ if (opts.verbose) { printf("tag: %x\neth: %s\nshelf: %u\nslot: %u\n", opts.tag, opts.netif, opts.shelf, opts.slot); fflush(stdout); } sfd = dial(opts.netif); if (!getea(sfd, opts.netif, mac)) exit(EXIT_FAILURE); alarm(opts.timeout); find_blade(&c, &opts); opts.tag += 1; alarm(0); if (opts.verbose) { printf("found e%d.%d with mac ", ntohs(c.h.maj), c.h.min); hex_print(stdout, c.h.src, sizeof c.h.src, ""); putchar('\n'); fflush(stdout); } if (opts.ata_ident || opts.smart) { alarm(opts.timeout); disk_identify(&c, &opts, &smartable); alarm(0); opts.tag += 1; } if (opts.smart) { if (!smartable) { fprintf(stderr, "Error: e%d.%d does not support SMART\n", ntohs(c.h.maj), c.h.min); exit(EXIT_FAILURE); } alarm(opts.timeout); smart(&c, opts.tag, opts.smart); alarm(0); opts.tag += 1; } return 0; } aoetools-30/aoetools.80000644000175000017500000000224411153325133014646 0ustar ecashinecashin.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 .TP .BI coraid-update send updates to CORAID appliances .TP .BI sos-linux collect AoE-related information about the localhost .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 coraid-update (8), .IR sos-linux (8), .IR udev (7). aoetools-30/config.h0000644000175000017500000000003610325226272014347 0ustar ecashinecashin#define _FILE_OFFSET_BITS 64 aoetools-30/coraid-update.80000644000175000017500000000163411153325157015552 0ustar ecashinecashin.TH coraid-update 8 .SH NAME coraid-update \- upload an update file to a CORAID appliance .SH SYNOPSIS .nf .B coraid-update {update file} {AoE device} .fi .SH DESCRIPTION The .I coraid-update script performs a few sanity checks before copying the local update file to the remote update AoE target on the CORAID appliance. .PP Two arguments are provided: 1) the name of the update file to be uploaded, and 2) the special block device file corresponding to the update target, e.g., \fI/dev/etherd/e100.40\fP. .PP It generates no output and exits with a zero status when the update file has been successfully uploaded to the update target on the appliance. Otherwise, an error message is printed to standard error and \fI coraid-update\fR exits with a non-zero status. .SH "SEE ALSO" .IR aoe-discover (8), .IR aoe-interfaces (8), .IR aoe-stat (8), .IR aoetools (8), .IR udev (7). .SH AUTHOR Ed L. Cashin (ecashin@coraid.com) aoetools-30/dat.h0000644000175000017500000000270411153324754013662 0ustar ecashinecashin/* dat.h - aoetools type definitions and macros * Copyright 2009, CORAID, Inc., and licensed under GPL v.2. */ #define nil NULL #define nelem(x) (sizeof(x)/sizeof((x)[0])) typedef unsigned char uchar; typedef struct Aoehdr Aoehdr; typedef struct Ata Ata; typedef struct Conf Conf; typedef struct Ataregs Ataregs; /* use C99's stdint.h for fixed-width types * * There's no guarantee an unsigned short is 16-bits wide, * but uint16_t is always correct. */ typedef uint64_t vlong; typedef uint32_t u32; typedef uint16_t u16; struct Ataregs { vlong lba; uchar cmd; uchar status; uchar err; uchar feature; uchar sectors; }; struct Aoehdr { uchar dst[6]; uchar src[6]; u16 type; uchar flags; uchar error; u16 maj; uchar min; uchar cmd; uchar tag[4]; }; struct Ata { Aoehdr h; uchar aflag; uchar err; uchar sectors; uchar cmd; uchar lba[6]; uchar resvd[2]; uchar data[1024]; }; struct Conf { Aoehdr h; u16 bufcnt; u16 firmware; uchar scnt; uchar vercmd; u16 len; uchar data[1024]; }; enum { AOE_ETH_PROTO = 0x88a2, AoEver = 1, ATAcmd = 0, // command codes Config, Resp = 1<<3, // flags Error = 1<<2, BadCmd = 1, BadArg, DevUnavailable, ConfigErr, BadVersion, Write = 1<<0, Async = 1<<1, Device = 1<<4, Extend = 1<<6, Qread = 0, Qtest, Qprefix, Qset, Qfset, Nretries = 3, ATAid_dev = 0xec, // ATA commands ATAsmart = 0xb0, ATAabrt = 0x4, // ATA error bits SmartDataPut = 0x01, SmartDataRet = 0x10, }; aoetools-30/devnodes.txt0000644000175000017500000000301511153325006015274 0ustar ecashinecashin Driver Compatibility Users of udev have device nodes like /dev/etherd/e0.0 created for them 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 regardless of what AoE devices are really available to the system. The aoetools contain the aoe-mkdevs and aoe-mkshelf commands, which create these static device nodes. 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://support.coraid.com/support/linux/) then just use the aoetools that 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. * To use aoetools-8 and later with older 2.6 kernels (2.6.13 and earlier), build the aoetools with an extra parameter for "make", like this: make NPERSHELF=10 * Using aoetools-7 and earlier with newer 2.6 kernels (2.6.14 and later) is not recommended. Other combinations should work with the default settings. aoetools-30/fns.h0000644000175000017500000000017711153324761013700 0ustar ecashinecashin/* Copyright 2009, CORAID, Inc., and licensed under GPL v.2. */ int dial(char *eth); int getea(int s, char *name, uchar *ea); aoetools-30/linux.c0000644000175000017500000000324411153323762014242 0ustar ecashinecashin/* linux.c: low level access routines for Linux * Copyright 2009, CORAID, Inc., and licensed under GPL v.2. */ #include "config.h" #include #include #include #include #include #include #include /* for the glibc version number */ #if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1 #include #include /* the L2 protocols */ #else #include #include #include /* The L2 protocols */ #endif #include #include #include #include #include #include #include "dat.h" #include "fns.h" static int getindx(int s, char *name) // return the index of device 'name' { struct ifreq xx; int n; strcpy(xx.ifr_name, name); n = ioctl(s, SIOCGIFINDEX, &xx); if (n == -1) return -1; return xx.ifr_ifindex; } int dial(char *eth) // get us a raw connection to an interface { int i; int n, s; struct sockaddr_ll sa; enum { aoe_type = 0x88a2 }; memset(&sa, 0, sizeof sa); s = socket(PF_PACKET, SOCK_RAW, htons(aoe_type)); if (s == -1) { perror("got bad socket"); return -1; } i = getindx(s, eth); sa.sll_family = AF_PACKET; sa.sll_protocol = htons(0x88a2); sa.sll_ifindex = i; n = bind(s, (struct sockaddr *)&sa, sizeof sa); if (n == -1) { perror("bind funky"); return -1; } return s; } int getea(int s, char *name, uchar *ea) { struct ifreq xx; int n; strcpy(xx.ifr_name, name); n = ioctl(s, SIOCGIFHWADDR, &xx); if (n == -1) { perror("Can't get hw addr"); return 0; } memmove(ea, xx.ifr_hwaddr.sa_data, 6); return 1; } aoetools-30/sos-linux0000755000175000017500000000114211044655705014625 0ustar ecashinecashin#! /bin/sh me="`basename $0`" outf="$HOME/sos-`hostname`-`date +%Y%m%d-%H%M%S`.txt" if test "`whoami`" != "root"; then echo "$me: please run $me as root" 1>&2 exit 1 fi echo "$me: output file is $outf" exec > $outf exec 2>&1 set -x uname -a grep . /etc/*release* /etc/*version* | sed 50q find /sys/module/aoe -name version | xargs cat cat /proc/mounts aoe-version aoe-stat cat /proc/mdstat pvs ifconfig -a free dmesg | tail -n 50 lspci set +x for i in `aoe-stat | awk '{print $3}' | sed 's!,! !g'`; do echo ethtool -S $i done | sort | uniq | sh -x # top -b -n 1 grep . /sys/block/etherd*/debug /dev/null aoetools-30/sos-linux.80000644000175000017500000000076411102351275014767 0ustar ecashinecashin.TH sos-linux 8 .SH NAME sos-linux \- create file containing AoE-related information .SH SYNOPSIS .nf .B sos-linux .fi .SH DESCRIPTION The .I sos-linux script creates a dated output file in the home directory of the user running it. .PP The filename is printed on the standard output. .PP The file contains information about the local system that is likely to be relevant to its use as an AoE initiator. .SH "SEE ALSO" .IR aoe-stat (8), .IR aoetools (8). .SH AUTHOR Ed L. Cashin (ecashin@coraid.com)