Skip to content

Commit c743d5a

Browse files
committedMay 13, 2014
Import vblade-21 from aoetools.sourceforge.net
0 parents  commit c743d5a

21 files changed

+2862
-0
lines changed
 

‎COPYING

+340
Large diffs are not rendered by default.

‎HACKING

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
Contributions to the vblade are welcome.
2+
3+
In contributing, though, please stay true to the original simplicity
4+
of the software. Many open source projects suffer from the "creeping
5+
feature demon" phenomenon. If you think the vblade needs a great new
6+
feature, first seriously try to think of a way to accomplish your goal
7+
without adding to the vblade itself.
8+
9+
Patches should be clean (to the point and easy to read) and should do
10+
one thing. Send multiple patches if necessary. Patches should be
11+
generated with "diff -uprN" if possible, and should be designed to be
12+
applied with "patch -p1".
13+
14+
When possible, the best way to submit a patch is by sending it to the
15+
aoetools-discuss list. You can subscribe at the aoetools project web
16+
page on sourceforge.net.
17+
18+
When you send your patch, here are some things to cover:
19+
20+
* What version of the vblade did you use to generate the patch?
21+
(Hopefully it was the latest.)
22+
23+
* What was your motivation for creating the patch? That is, what
24+
problem does it solve?
25+
26+
* What testing did you perform to ensure that your patch did not
27+
introduce bugs and accomplished what you intended?
28+
29+
* If your changes affect the end-user experience, have you updated
30+
the vblade documentation?

‎NEWS

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
-*- change-log -*-
2+
2013-03-18 Ed Cashin <ecashin@coraid.com>
3+
add big-endian support from Daniel Mealha Cabrita <dancab@gmx.net>
4+
vblade-21
5+
6+
2009-08-14 Sam Hopkins <sah@coraid.com>
7+
bugfix: aoe command error did not set Error bit in flags
8+
add support for AoEr11
9+
set ident serial to shelf.slot:hostname
10+
vblade-20
11+
12+
2008-10-08 Ed Cashin <ecashin@coraid.com>
13+
add Chris Webb's bpf fix for FreeBSD
14+
add Ryan Thomas's fix to stop bufcnt being overridden
15+
vblade-19
16+
17+
2008-07-14 Ed Cashin <ecashin@coraid.com>
18+
add Chris Webb's block device options patch
19+
add Chris Webb's socket options patch for better jumbo handling
20+
remove obsolete contrib/o_direct.diff
21+
vblade-18
22+
23+
2008-06-09 Ed Cashin <ecashin@coraid.com>
24+
add Chris Webb's latest BPF patch to vblade, remove from contrib
25+
update contributed AIO patch for compatibility with current sources
26+
vblade-17
27+
28+
2008-05-07 Ed Cashin <ecashin@coraid.com>
29+
add Chris Webb's AIO patch to the contributions
30+
add Chris Webb's BPF patch to the contributions
31+
vblade-16
32+
33+
2008-02-20 Ed Cashin <ecashin@coraid.com>
34+
require the amount of data we use, not the amount ethernet requires
35+
make sure the packet length agrees with the config query length
36+
make sure the packet length agrees with the amount to write
37+
remove newline embedded in fw version field of ATA dev ID response
38+
vblade-15
39+
40+
2006-11-20 Sam Hopkins <sah@coraid.com>
41+
apply contrib jumbo patch to standard distribution
42+
add jumbo configuration app. note in README
43+
add jumbo README reference to manpage
44+
add mask feature; -m flag
45+
update manpage to describe -m flag
46+
vblade-14
47+
48+
2006-10-05 Sam Hopkins <sah@coraid.com>
49+
fix confcmd memcpy bug
50+
correct scnt return value in read/write ata response
51+
replace O_RDONLY fallback with explicit stat. root always wins.
52+
vblade-13
53+
54+
2006-10-04 Sam Hopkins <sah@coraid.com>
55+
fix confcmd buglets
56+
fix atacmd buglets
57+
add atacmd handling for bad argument errors
58+
add O_RDONLY open if O_RDWR fails
59+
add contrib patch directory
60+
add contrib/README
61+
add jumbo patch to contrib
62+
add o_direct patch to contrib
63+
vblade-12
64+
65+
2006-09-21 "Adam J. Richter" <adam@yggdrasil.com>
66+
add install target for makefile
67+
vblade-11
68+
69+
2005-12-06 Ed Cashin <ecashin@coraid.com>
70+
fix u64 configuration on FreeBSD
71+
release vblade-10
72+
73+
2005-12-06 Valeriy Glushkov <valery@rocketdivision.com>
74+
implemented config string support
75+
added handler for ATA Check power mode command
76+
77+
2005-11-15 Ed Cashin <ecashin@coraid.com>
78+
add compatibility with platforms lacking u64 (e.g., Slackware)
79+
release vblade-9
80+
81+
2005-11-10 Ed Cashin <ecashin@coraid.com>
82+
call atainit on program startup
83+
put VBLADE_VERSION in dat.h and use it in firmware version
84+
release vblade-7
85+
include Stacey's patch to use p{read,write} on FreeBSD
86+
include Stacey's patch to typedef ulong on FreeBSD
87+
fix makefile dependencies (e.g., rebuild on new aoe.c)
88+
fix config string length specification
89+
include Stacey's patch to avoid compile warnings on FreeBSD
90+
release vblade-8
91+
92+
2005-11-10 "Stacey D. Son" <sson@verio.net>
93+
include FreeBSD support
94+
95+
2005-10-03 Ed Cashin <ecashin@coraid.com>
96+
don't invoke vblade with dash from vbladed
97+
98+
2005-08-31 20:14:12 GMT Ed Cashin <ecashin@coraid.com>
99+
ATA identify: don't juggle bytes in shorts on big endian arch
100+
add manpage for vblade, vbladed
101+
release vblade-6
102+
103+
2005-03-17 15:24:30 GMT Ed Cashin <ecashin@coraid.com>
104+
follow up on vblade-2's off-by-one patch, making end of device usable
105+
release vblade-5
106+
107+
2005-03-15 22:03:17 GMT Ed Cashin <ecashin@coraid.com>
108+
don't rely on kernel headers for defining the aoe type 0x88a2
109+
release vblade-4
110+
111+
2005-03-15 17:27:01 GMT Ed Cashin <ecashin@coraid.com>
112+
docs: aoe-2.6-7 is the first driver to support multiple blades per mac
113+
release vblade-3
114+
115+
2005-03-11 18:30:26 GMT Ed Cashin <ecashin@coraid.com>
116+
put 64-bit configuration into config.h file
117+
don't use uninitialized variables
118+
broadcast config query on startup
119+
clarify desired patch format in HACKING
120+
add sah@coraid.com's vblade-1.ata.c.patch: fix off-by-one and ext LBA
121+
add docs, remove daemonizing code from vblade
122+
release vblade-2
123+
124+
2005-02-08 20:21:52 GMT Ed Cashin <ecashin@coraid.com>
125+
starting documentation
126+
add script that daemonizes vblade process, logging output
127+
make vblade sources -Wall clean, use daemon(3)
128+
release vblade-1

‎README

+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
2+
INTRODUCTION
3+
------------
4+
5+
The vblade is the virtual EtherDrive (R) blade, a program that makes a
6+
seekable file available over an ethernet local area network (LAN) via
7+
the ATA over Ethernet (AoE) protocol.
8+
9+
The seekable file is typically a block device like /dev/md0 but even
10+
regular files will work. Sparse files can be especially convenient.
11+
When vblade exports the block storage over AoE it becomes a storage
12+
target. Another host on the same LAN can access the storage if it has
13+
a compatible aoe kernel driver.
14+
15+
BUILDING
16+
--------
17+
18+
The following command should build the vblade program on a Linux-based
19+
system:
20+
21+
make
22+
23+
For FreeBSD systems, include an extra parameter like so:
24+
25+
make PLATFORM=freebsd
26+
27+
EXAMPLES
28+
--------
29+
30+
There is a "vbladed" script that daemonizes the program and sends its
31+
output to the logger program. Make sure you have logger installed if
32+
you would like to run vblade as a daemon with the vbladed script.
33+
34+
ecashin@kokone vblade$ echo 'I have logger' | logger
35+
ecashin@kokone vblade$ tail -3 /var/log/messages
36+
Feb 8 14:52:49 kokone -- MARK --
37+
Feb 8 15:12:49 kokone -- MARK --
38+
Feb 8 15:19:56 kokone logger: I have logger
39+
40+
Here is a short example showing how to export a block device with a
41+
vblade. (This is a loop device backed by a sparse file, but you could
42+
use any seekable file instead of /dev/loop7.)
43+
44+
ecashin@kokone vblade$ make
45+
cc -Wall -c -o aoe.o aoe.c
46+
cc -Wall -c -o linux.o linux.c
47+
cc -Wall -c -o ata.o ata.c
48+
cc -o vblade aoe.o linux.o ata.o
49+
ecashin@kokone vblade$ su
50+
Password:
51+
root@kokone vblade# modprobe loop
52+
root@kokone vblade# dd if=/dev/zero bs=1k count=1 seek=`expr 1024 \* 4096` of=bd
53+
-file
54+
1+0 records in
55+
1+0 records out
56+
1024 bytes transferred in 0.009901 seconds (103423 bytes/sec)
57+
root@kokone vblade# losetup /dev/loop7 bd-file
58+
root@kokone vblade# ./vblade 9 0 eth0 /dev/loop7
59+
ioctl returned 0
60+
4294968320 bytes
61+
pid 16967: e9.0, 8388610 sectors
62+
63+
Here's how you can use the Linux aoe driver to access the storage from
64+
another host on the LAN.
65+
66+
ecashin@kokone ecashin$ ssh makki
67+
Last login: Mon Feb 7 10:25:04 2005
68+
ecashin@makki ~$ su
69+
Password:
70+
root@makki ecashin# modprobe aoe
71+
root@makki ecashin# aoe-stat
72+
e9.0 eth1 up
73+
root@makki ecashin# mkfs -t ext3 /dev/etherd/e9.0
74+
mke2fs 1.35 (28-Feb-2004)
75+
...
76+
Creating journal (8192 blocks): done
77+
Writing superblocks and filesystem accounting information: done
78+
79+
This filesystem will be automatically checked every 24 mounts or
80+
180 days, whichever comes first. Use tune2fs -c or -i to override.
81+
root@makki ecashin# mkdir /mnt/e9.0
82+
root@makki ecashin# mount /dev/etherd/e9.0 /mnt/e9.0
83+
root@makki ecashin# echo hooray > /mnt/e9.0/test.txt
84+
root@makki ecashin# cat /mnt/e9.0/test.txt
85+
hooray
86+
87+
Remember: be as careful with these devices as you would with /dev/hda!
88+
89+
Jumbo Frame Compatibility
90+
-------------------------
91+
92+
Vblade can use jumbo frames provided your initiator is jumbo frame
93+
capable. There is one small configuration gotcha to consider
94+
to avoid having the vblade kernel frequently drop frames.
95+
96+
Vblade uses a raw socket to perform AoE. The linux kernel will
97+
only buffer a certain amount of data for a raw socket. For 2.6
98+
kernels, this value is managed through /proc:
99+
100+
root@nai aoe# grep . /proc/sys/net/core/rmem_*
101+
/proc/sys/net/core/rmem_default:128000
102+
/proc/sys/net/core/rmem_max:128000
103+
104+
rmem_max is the max amount a user process may expand the receive
105+
buffer to -- through setsockopt(...) -- and rmem_default is, as you
106+
might expect, the default.
107+
108+
The gotcha is that this amount to buffer does not relate
109+
to the amount of user data buffered, but the amount of
110+
real data buffered. As an example, the Intel GbE controller
111+
must be given 16KB frames to use an MTU over 8KB.
112+
For each received frame, the kernel must be able to buffer
113+
16KB, even if the aoe frame is only 60 bytes in length.
114+
115+
The linux aoe initiator will use 16 outstanding frames when
116+
used with vblade. A good default for ensuring frames are
117+
not dropped is to allocate 16KB for 17 frames:
118+
119+
for f in /proc/sys/net/core/rmem_*; do echo $((17 * 16 * 1024)) >$f; done
120+
121+
Be sure to start vblade after changing the buffering defaults
122+
as the buffer value is set when the socket is opened.
123+
124+
AoE Initiator Compatibility
125+
---------------------------
126+
127+
The Linux aoe driver for the 2.6 kernel is compatible if you use
128+
aoe-2.6-7 or newer. You can use older aoe drivers but you will only
129+
be able to see one vblade per MAC address.
130+
131+
Contrib Patches
132+
---------------
133+
134+
see contrib/README
135+
136+
Kvblade
137+
-------
138+
139+
While vblade runs as a userland process (like "ls" or "vi"), there
140+
is another program that runs inside the kernel. It is called
141+
kvblade. It is alpha software.

‎aoe.c

+519
Large diffs are not rendered by default.

‎ata.c

+185
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
// ata.c: ATA simulator for vblade
2+
#include "config.h"
3+
#include <string.h>
4+
#include <stdio.h>
5+
#include <sys/types.h>
6+
#include "dat.h"
7+
#include "fns.h"
8+
9+
enum {
10+
// err bits
11+
UNC = 1<<6,
12+
MC = 1<<5,
13+
IDNF = 1<<4,
14+
MCR = 1<<3,
15+
ABRT = 1<<2,
16+
NM = 1<<1,
17+
18+
// status bits
19+
BSY = 1<<7,
20+
DRDY = 1<<6,
21+
DF = 1<<5,
22+
DRQ = 1<<3,
23+
ERR = 1<<0,
24+
};
25+
26+
static ushort ident[256];
27+
28+
static void
29+
setfld(ushort *a, int idx, int len, char *str) // set field in ident
30+
{
31+
uchar *p;
32+
33+
p = (uchar *)(a+idx);
34+
while (len > 0) {
35+
if (*str == 0)
36+
p[1] = ' ';
37+
else
38+
p[1] = *str++;
39+
if (*str == 0)
40+
p[0] = ' ';
41+
else
42+
p[0] = *str++;
43+
p += 2;
44+
len -= 2;
45+
}
46+
}
47+
48+
static void
49+
setlba28(ushort *ident, vlong lba)
50+
{
51+
uchar *cp;
52+
53+
cp = (uchar *) &ident[60];
54+
*cp++ = lba;
55+
*cp++ = lba >>= 8;
56+
*cp++ = lba >>= 8;
57+
*cp++ = (lba >>= 8) & 0xf;
58+
}
59+
60+
static void
61+
setlba48(ushort *ident, vlong lba)
62+
{
63+
uchar *cp;
64+
65+
cp = (uchar *) &ident[100];
66+
*cp++ = lba;
67+
*cp++ = lba >>= 8;
68+
*cp++ = lba >>= 8;
69+
*cp++ = lba >>= 8;
70+
*cp++ = lba >>= 8;
71+
*cp++ = lba >>= 8;
72+
}
73+
74+
static void
75+
setushort(ushort *a, int i, ushort n)
76+
{
77+
uchar *p;
78+
79+
p = (uchar *)(a+i);
80+
*p++ = n & 0xff;
81+
*p++ = n >> 8;
82+
}
83+
84+
void
85+
atainit(void)
86+
{
87+
char buf[64];
88+
89+
setushort(ident, 47, 0x8000);
90+
setushort(ident, 49, 0x0200);
91+
setushort(ident, 50, 0x4000);
92+
setushort(ident, 83, 0x5400);
93+
setushort(ident, 84, 0x4000);
94+
setushort(ident, 86, 0x1400);
95+
setushort(ident, 87, 0x4000);
96+
setushort(ident, 93, 0x400b);
97+
setfld(ident, 27, 40, "Coraid EtherDrive vblade");
98+
sprintf(buf, "V%d", VBLADE_VERSION);
99+
setfld(ident, 23, 8, buf);
100+
setfld(ident, 10, 20, serial);
101+
}
102+
103+
104+
/* The ATA spec is weird in that you specify the device size as number
105+
* of sectors and then address the sectors with an offset. That means
106+
* with LBA 28 you shouldn't see an LBA of all ones. Still, we don't
107+
* check for that.
108+
*/
109+
int
110+
atacmd(Ataregs *p, uchar *dp, int ndp, int payload) // do the ata cmd
111+
{
112+
vlong lba;
113+
ushort *ip;
114+
int n;
115+
enum { MAXLBA28SIZE = 0x0fffffff };
116+
extern int maxscnt;
117+
118+
p->status = 0;
119+
switch (p->cmd) {
120+
default:
121+
p->status = DRDY | ERR;
122+
p->err = ABRT;
123+
return 0;
124+
case 0xe7: // flush cache
125+
return 0;
126+
case 0xec: // identify device
127+
if (p->sectors != 1 || ndp < 512)
128+
return -1;
129+
memmove(dp, ident, 512);
130+
ip = (ushort *)dp;
131+
if (size & ~MAXLBA28SIZE)
132+
setlba28(ip, MAXLBA28SIZE);
133+
else
134+
setlba28(ip, size);
135+
setlba48(ip, size);
136+
p->err = 0;
137+
p->status = DRDY;
138+
p->sectors = 0;
139+
return 0;
140+
case 0xe5: // check power mode
141+
p->err = 0;
142+
p->sectors = 0xff; // the device is active or idle
143+
p->status = DRDY;
144+
return 0;
145+
case 0x20: // read sectors
146+
case 0x30: // write sectors
147+
lba = p->lba & MAXLBA28SIZE;
148+
break;
149+
case 0x24: // read sectors ext
150+
case 0x34: // write sectors ext
151+
lba = p->lba & 0x0000ffffffffffffLL; // full 48
152+
break;
153+
}
154+
155+
// we ought not be here unless we are a read/write
156+
157+
if (p->sectors > maxscnt || p->sectors*512 > ndp)
158+
return -1;
159+
160+
if (lba + p->sectors > size) {
161+
p->err = IDNF;
162+
p->status = DRDY | ERR;
163+
p->lba = lba;
164+
return 0;
165+
}
166+
if (p->cmd == 0x20 || p->cmd == 0x24)
167+
n = getsec(bfd, dp, lba, p->sectors);
168+
else {
169+
// packet should be big enough to contain the data
170+
if (payload < 512 * p->sectors)
171+
return -1;
172+
n = putsec(bfd, dp, lba, p->sectors);
173+
}
174+
n /= 512;
175+
if (n != p->sectors) {
176+
p->err = ABRT;
177+
p->status = ERR;
178+
} else
179+
p->err = 0;
180+
p->status |= DRDY;
181+
p->lba += n;
182+
p->sectors -= n;
183+
return 0;
184+
}
185+

‎bpf.c

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
// bpf.c: bpf packet filter for linux/freebsd
2+
3+
#include "config.h"
4+
#include <stdio.h>
5+
#include <stdlib.h>
6+
#include <string.h>
7+
#include <sys/types.h>
8+
#include "dat.h"
9+
#include "fns.h"
10+
11+
struct bpf_insn {
12+
ushort code;
13+
uchar jt;
14+
uchar jf;
15+
u_int32_t k;
16+
};
17+
18+
struct bpf_program {
19+
uint bf_len;
20+
struct bpf_insn *bf_insns;
21+
};
22+
23+
/* instruction classes */
24+
#define BPF_CLASS(code) ((code) & 0x07)
25+
#define BPF_LD 0x00
26+
#define BPF_LDX 0x01
27+
#define BPF_ST 0x02
28+
#define BPF_STX 0x03
29+
#define BPF_ALU 0x04
30+
#define BPF_JMP 0x05
31+
#define BPF_RET 0x06
32+
#define BPF_MISC 0x07
33+
34+
/* ld/ldx fields */
35+
#define BPF_SIZE(code) ((code) & 0x18)
36+
#define BPF_W 0x00
37+
#define BPF_H 0x08
38+
#define BPF_B 0x10
39+
#define BPF_MODE(code) ((code) & 0xe0)
40+
#define BPF_IMM 0x00
41+
#define BPF_ABS 0x20
42+
#define BPF_IND 0x40
43+
#define BPF_MEM 0x60
44+
#define BPF_LEN 0x80
45+
#define BPF_MSH 0xa0
46+
47+
/* alu/jmp fields */
48+
#define BPF_OP(code) ((code) & 0xf0)
49+
#define BPF_ADD 0x00
50+
#define BPF_SUB 0x10
51+
#define BPF_MUL 0x20
52+
#define BPF_DIV 0x30
53+
#define BPF_OR 0x40
54+
#define BPF_AND 0x50
55+
#define BPF_LSH 0x60
56+
#define BPF_RSH 0x70
57+
#define BPF_NEG 0x80
58+
#define BPF_JA 0x00
59+
#define BPF_JEQ 0x10
60+
#define BPF_JGT 0x20
61+
#define BPF_JGE 0x30
62+
#define BPF_JSET 0x40
63+
#define BPF_SRC(code) ((code) & 0x08)
64+
#define BPF_K 0x00
65+
#define BPF_X 0x08
66+
67+
/* ret - BPF_K and BPF_X also apply */
68+
#define BPF_RVAL(code) ((code) & 0x18)
69+
#define BPF_A 0x10
70+
71+
/* misc */
72+
#define BPF_MISCOP(code) ((code) & 0xf8)
73+
#define BPF_TAX 0x00
74+
#define BPF_TXA 0x80
75+
76+
/* macros for insn array initializers */
77+
#define BPF_STMT(code, k) { (ushort)(code), 0, 0, k }
78+
#define BPF_JUMP(code, k, jt, jf) { (ushort)(code), jt, jf, k }
79+
80+
void *
81+
create_bpf_program(int shelf, int slot)
82+
{
83+
struct bpf_program *bpf_program;
84+
struct bpf_insn insns[] = {
85+
/* Load the type into register */
86+
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12),
87+
/* Does it match AoE Type (0x88a2)? No, goto INVALID */
88+
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x88a2, 0, 12),
89+
/* Load the flags into register */
90+
BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 14),
91+
/* Check to see if the Resp flag is set */
92+
BPF_STMT(BPF_ALU+BPF_AND+BPF_K, Resp),
93+
/* Yes, goto INVALID */
94+
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 9),
95+
/* Load the shelf number into register */
96+
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 16),
97+
/* Does it match shelf number? No, goto CHECKBROADCAST */
98+
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, shelf, 0, 2),
99+
/* Load the slot number into register */
100+
BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 18),
101+
/* Does it match shelf number? Yes, goto VALID */
102+
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, slot, 4, 0),
103+
/* CHECKBROADCAST: is (shelf, slot) == (0xffff, 0xff)? */
104+
/* Load the shelf number into register */
105+
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 16),
106+
/* Is it 0xffff? No, goto INVALID */
107+
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0xffff, 0, 3),
108+
/* Load the slot number into register */
109+
BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 18),
110+
/* Is it 0xff? No, goto INVALID */
111+
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0xff, 0, 1),
112+
/* VALID: return -1 (allow the packet to be read) */
113+
BPF_STMT(BPF_RET+BPF_K, -1),
114+
/* INVALID: return 0 (ignore the packet) */
115+
BPF_STMT(BPF_RET+BPF_K, 0),
116+
};
117+
if ((bpf_program = malloc(sizeof(struct bpf_program))) == NULL
118+
|| (bpf_program->bf_insns = malloc(sizeof(insns))) == NULL) {
119+
perror("malloc");
120+
exit(1);
121+
}
122+
bpf_program->bf_len = sizeof(insns)/sizeof(struct bpf_insn);
123+
memcpy(bpf_program->bf_insns, insns, sizeof(insns));
124+
return (void *)bpf_program;
125+
}
126+
127+
void
128+
free_bpf_program(void *bpf_program)
129+
{
130+
free(((struct bpf_program *) bpf_program)->bf_insns);
131+
free(bpf_program);
132+
}

‎config.h

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#define _FILE_OFFSET_BITS 64
2+
typedef unsigned long long u64;

‎config/config.h.in

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#define _FILE_OFFSET_BITS 64
2+
//u64 typedef unsigned long long u64;

‎config/u64.c

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#include <stdio.h>
2+
3+
int main(void)
4+
{
5+
u64 n;
6+
printf("%d\n", (int) n+2);
7+
return 0;
8+
}

‎contrib/README

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
The patches in the contrib directory enable features
3+
that either don't work completely, aren't well tested, or
4+
are of limited general use. They can be applied by
5+
using patch in the vblade source directory as follows:
6+
7+
forfeit:~/vblade-12 # patch -p1 <contrib/jumbo.diff
8+
patching file aoe.c
9+
patching file fns.h
10+
patching file freebsd.c
11+
patching file linux.c
12+
forfeit:~/vblade-12 #

‎contrib/vblade-17-aio.2.README

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
This proof-of-concept patch modifies vblade to access the underlying block
2+
device using POSIX asynchronous IO (AIO) rather than using normal blocking
3+
read() and write(). AIO allows vblade to receive and queue several several ATA
4+
read/write commands at once, returning the response to the client
5+
asynchronously as each IO operation completes. It should be most beneficial
6+
for devices which experience very non-sequential IO. An AIO-enabled vblade is
7+
also a good starting point if you want to generalise vblade to export multiple
8+
devices without the complexity and overhead of a multithreaded approach.
9+
10+
The patch implements AIO support for both Linux and FreeBSD, but I have not
11+
tested the FreeBSD support and would therefore be especially interested to
12+
hear success/failure reports for compiling and running AIO vblade on FreeBSD.
13+
A SIGIO handler which writes a single byte to a pipe is used to notify the
14+
main poll() loop that AIO operations have completed and are ready to return to
15+
the client. Running oprofile on a box with a heavily loaded loopback
16+
vblade-aio suggests that it spends an inordinate amount of time in the signal
17+
handler. Some method of poll()ing directly on the AIO events at the same time
18+
as the socket fd could cut this overhead out completely.
19+
20+
More generally, experimenting on Linux with standard O_DIRECT vblade and
21+
O_DIRECT vblade-aio on a loopback interface with MTU 9000 suggests that the
22+
performance difference on a single RAID1-backed block device is fairly small:
23+
swamped by the performance of the network and the underlying block device.
24+
However, the POSIX AIO in glibc librt is emulated in userspace threads rather
25+
than using the kernel AIO api. A kernel-backed POSIX AIO implementation should
26+
perform better, especially for multiple access to a single block device.
27+
28+
I would be delighted to hear any feedback and experiences from people running
29+
vblade together with this patch.
30+
31+
Chris Webb <chris@arachsys.com>, 2008-04-21.

‎contrib/vblade-17-aio.2.diff

+538
Large diffs are not rendered by default.

‎dat.h

+174
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
/* dat.h: include file for vblade AoE target */
2+
3+
#define nil ((void *)0)
4+
/*
5+
* tunable variables
6+
*/
7+
8+
enum {
9+
VBLADE_VERSION = 21,
10+
11+
// Firmware version
12+
FWV = 0x4000 + VBLADE_VERSION,
13+
};
14+
15+
#undef major
16+
#undef minor
17+
#undef makedev
18+
19+
#define major(x) ((x) >> 24 & 0xFF)
20+
#define minor(x) ((x) & 0xffffff)
21+
#define makedev(x, y) ((x) << 24 | (y))
22+
23+
typedef unsigned char uchar;
24+
//typedef unsigned short ushort;
25+
#ifdef __FreeBSD__
26+
typedef unsigned long ulong;
27+
#else
28+
//typedef unsigned long ulong;
29+
#endif
30+
typedef long long vlong;
31+
32+
typedef struct Aoehdr Aoehdr;
33+
typedef struct Ata Ata;
34+
typedef struct Conf Conf;
35+
typedef struct Ataregs Ataregs;
36+
typedef struct Mdir Mdir;
37+
typedef struct Aoemask Aoemask;
38+
typedef struct Aoesrr Aoesrr;
39+
40+
struct Ataregs
41+
{
42+
vlong lba;
43+
uchar cmd;
44+
uchar status;
45+
uchar err;
46+
uchar feature;
47+
uchar sectors;
48+
};
49+
50+
struct Aoehdr
51+
{
52+
uchar dst[6];
53+
uchar src[6];
54+
ushort type;
55+
uchar flags;
56+
uchar error;
57+
ushort maj;
58+
uchar min;
59+
uchar cmd;
60+
uchar tag[4];
61+
};
62+
63+
struct Ata
64+
{
65+
Aoehdr h;
66+
uchar aflag;
67+
uchar err;
68+
uchar sectors;
69+
uchar cmd;
70+
uchar lba[6];
71+
uchar resvd[2];
72+
};
73+
74+
struct Conf
75+
{
76+
Aoehdr h;
77+
ushort bufcnt;
78+
ushort firmware;
79+
uchar scnt;
80+
uchar vercmd;
81+
ushort len;
82+
uchar data[1024];
83+
};
84+
85+
// mask directive
86+
struct Mdir {
87+
uchar res;
88+
uchar cmd;
89+
uchar mac[6];
90+
};
91+
92+
struct Aoemask {
93+
Aoehdr h;
94+
uchar res;
95+
uchar cmd;
96+
uchar merror;
97+
uchar nmacs;
98+
// struct Mdir m[0];
99+
};
100+
101+
struct Aoesrr {
102+
Aoehdr h;
103+
uchar rcmd;
104+
uchar nmacs;
105+
// uchar mac[6][nmacs];
106+
};
107+
108+
enum {
109+
AoEver = 1,
110+
111+
ATAcmd = 0, // command codes
112+
Config,
113+
Mask,
114+
Resrel,
115+
116+
Resp = (1<<3), // flags
117+
Error = (1<<2),
118+
119+
BadCmd = 1,
120+
BadArg,
121+
DevUnavailable,
122+
ConfigErr,
123+
BadVersion,
124+
Res,
125+
126+
Write = (1<<0),
127+
Async = (1<<1),
128+
Device = (1<<4),
129+
Extend = (1<<6),
130+
131+
Qread = 0,
132+
Qtest,
133+
Qprefix,
134+
Qset,
135+
Qfset,
136+
137+
Nretries = 3,
138+
Nconfig = 1024,
139+
140+
Bufcount = 16,
141+
142+
/* mask commands */
143+
Mread= 0,
144+
Medit,
145+
146+
/* mask directives */
147+
MDnop= 0,
148+
MDadd,
149+
MDdel,
150+
151+
/* mask errors */
152+
MEunspec= 1,
153+
MEbaddir,
154+
MEfull,
155+
156+
/* header sizes, including aoe hdr */
157+
Naoehdr= 24,
158+
Natahdr= Naoehdr + 12,
159+
Ncfghdr= Naoehdr + 8,
160+
Nmaskhdr= Naoehdr + 4,
161+
Nsrrhdr= Naoehdr + 2,
162+
163+
Nserial= 20,
164+
};
165+
166+
int shelf, slot;
167+
ulong aoetag;
168+
uchar mac[6];
169+
int bfd; // block file descriptor
170+
int sfd; // socket file descriptor
171+
vlong size; // size of vblade
172+
char *progname;
173+
char serial[Nserial+1];
174+

‎fns.h

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// fns.h: function prototypes
2+
3+
// aoe.c
4+
5+
void aoe(void);
6+
void aoeinit(void);
7+
void aoequery(void);
8+
void aoeconfig(void);
9+
void aoead(int);
10+
void aoeflush(int, int);
11+
void aoetick(void);
12+
void aoerequest(int, int, vlong, int, uchar *, int);
13+
int maskok(uchar *);
14+
int rrok(uchar *);
15+
16+
// ata.c
17+
18+
void atainit(void);
19+
int atacmd(Ataregs *, uchar *, int, int);
20+
21+
// bpf.c
22+
23+
void * create_bpf_program(int, int);
24+
void free_bpf_program(void *);
25+
26+
// os specific
27+
28+
int dial(char *, int);
29+
int getea(int, char *, uchar *);
30+
int putsec(int, uchar *, vlong, int);
31+
int getsec(int, uchar *, vlong, int);
32+
int putpkt(int, uchar *, int);
33+
int getpkt(int, uchar *, int);
34+
vlong getsize(int);
35+
int getmtu(int, char *);

‎freebsd.c

+289
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
/*
2+
* Copyright (c) 2005, Stacey Son <sson (at) verio (dot) net>
3+
* All rights reserved.
4+
*/
5+
6+
// freebsd.c: low level access routines for FreeBSD
7+
#include "config.h"
8+
#include <sys/types.h>
9+
#include <sys/socket.h>
10+
#include <stdio.h>
11+
#include <string.h>
12+
#include <stdlib.h>
13+
#include <unistd.h>
14+
#include <sys/time.h>
15+
16+
#include <netinet/in.h>
17+
#include <net/ethernet.h>
18+
#include <net/bpf.h>
19+
#include <net/if.h>
20+
#include <net/if_arp.h>
21+
#include <net/if_dl.h>
22+
#include <net/route.h>
23+
24+
#include <sys/ioctl.h>
25+
#include <sys/types.h>
26+
#include <net/if.h>
27+
#include <sys/stat.h>
28+
#include <sys/disklabel.h>
29+
#include <sys/select.h>
30+
#include <sys/sysctl.h>
31+
32+
#include <fcntl.h>
33+
#include <errno.h>
34+
35+
#include "dat.h"
36+
#include "fns.h"
37+
38+
#define BPF_DEV "/dev/bpf0"
39+
40+
/* Packet buffer for getpkt() */
41+
static uchar *pktbuf = NULL;
42+
static int pktbufsz = 0;
43+
44+
int
45+
dial(char *eth, int bufcnt)
46+
{
47+
char m;
48+
int fd = -1;
49+
struct bpf_version bv;
50+
u_int v;
51+
unsigned bufsize, linktype;
52+
char device[sizeof BPF_DEV];
53+
struct ifreq ifr;
54+
55+
struct bpf_program *bpf_program = create_bpf_program(shelf, slot);
56+
57+
strncpy(device, BPF_DEV, sizeof BPF_DEV);
58+
59+
/* find a bpf device we can use, check /dev/bpf[0-9] */
60+
for (m = '0'; m <= '9'; m++) {
61+
device[sizeof(BPF_DEV)-2] = m;
62+
63+
if ((fd = open(device, O_RDWR)) > 0)
64+
break;
65+
}
66+
67+
if (fd < 0) {
68+
perror("open");
69+
return -1;
70+
}
71+
72+
if (ioctl(fd, BIOCVERSION, &bv) < 0) {
73+
perror("BIOCVERSION");
74+
goto bad;
75+
}
76+
77+
if (bv.bv_major != BPF_MAJOR_VERSION ||
78+
bv.bv_minor < BPF_MINOR_VERSION) {
79+
fprintf(stderr,
80+
"kernel bpf filter out of date\n");
81+
goto bad;
82+
}
83+
84+
/*
85+
* Try finding a good size for the buffer; 65536 may be too
86+
* big, so keep cutting it in half until we find a size
87+
* that works, or run out of sizes to try.
88+
*
89+
*/
90+
for (v = 65536; v != 0; v >>= 1) {
91+
(void) ioctl(fd, BIOCSBLEN, (caddr_t)&v);
92+
93+
(void)strncpy(ifr.ifr_name, eth,
94+
sizeof(ifr.ifr_name));
95+
if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) >= 0)
96+
break; /* that size worked; we're done */
97+
98+
if (errno != ENOBUFS) {
99+
fprintf(stderr, "BIOCSETIF: %s: %s\n",
100+
eth, strerror(errno));
101+
goto bad;
102+
}
103+
}
104+
if (v == 0) {
105+
fprintf(stderr,
106+
"BIOCSBLEN: %s: No buffer size worked\n", eth);
107+
goto bad;
108+
}
109+
110+
/* Allocate memory for the packet buffer */
111+
pktbufsz = v;
112+
if ((pktbuf = malloc(pktbufsz)) == NULL) {
113+
perror("malloc");
114+
goto bad;
115+
}
116+
117+
/* Don't wait for buffer to be full or timeout */
118+
v = 1;
119+
if (ioctl(fd, BIOCIMMEDIATE, &v) < 0) {
120+
perror("BIOCIMMEDIATE");
121+
goto bad;
122+
}
123+
124+
/* Only read incoming packets */
125+
v = 0;
126+
if (ioctl(fd, BIOCSSEESENT, &v) < 0) {
127+
perror("BIOCSSEESENT");
128+
goto bad;
129+
}
130+
131+
/* Don't complete ethernet hdr */
132+
v = 1;
133+
if (ioctl(fd, BIOCSHDRCMPLT, &v) < 0) {
134+
perror("BIOCSHDRCMPLT");
135+
goto bad;
136+
}
137+
138+
/* Get the data link layer type. */
139+
if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) {
140+
perror("BIOCGDLT");
141+
goto bad;
142+
}
143+
linktype = v;
144+
145+
/* Get the filter buf size */
146+
if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) {
147+
perror("BIOCGBLEN");
148+
goto bad;
149+
}
150+
bufsize = v;
151+
152+
if (ioctl(fd, BIOCSETF, (caddr_t)bpf_program) < 0) {
153+
perror("BIOSETF");
154+
goto bad;
155+
}
156+
157+
free_bpf_program(bpf_program);
158+
return(fd);
159+
160+
bad:
161+
free_bpf_program(bpf_program);
162+
close(fd);
163+
return(-1);
164+
}
165+
166+
int
167+
getea(int s, char *eth, uchar *ea)
168+
{
169+
int mib[6];
170+
size_t len;
171+
char *buf, *next, *end;
172+
struct if_msghdr *ifm;
173+
struct sockaddr_dl *sdl;
174+
175+
176+
mib[0] = CTL_NET; mib[1] = AF_ROUTE;
177+
mib[2] = 0; mib[3] = AF_LINK;
178+
mib[4] = NET_RT_IFLIST; mib[5] = 0;
179+
180+
if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
181+
return (-1);
182+
}
183+
184+
if (!(buf = (char *) malloc(len))) {
185+
return (-1);
186+
}
187+
188+
if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
189+
free(buf);
190+
return (-1);
191+
}
192+
end = buf + len;
193+
194+
for (next = buf; next < end; next += ifm->ifm_msglen) {
195+
ifm = (struct if_msghdr *)next;
196+
if (ifm->ifm_type == RTM_IFINFO) {
197+
sdl = (struct sockaddr_dl *)(ifm + 1);
198+
if (strncmp(&sdl->sdl_data[0], eth,
199+
sdl->sdl_nlen) == 0) {
200+
memcpy(ea, LLADDR(sdl), ETHER_ADDR_LEN);
201+
break;
202+
}
203+
204+
}
205+
206+
}
207+
208+
free(buf);
209+
return(0);
210+
}
211+
212+
213+
int
214+
getsec(int fd, uchar *place, vlong lba, int nsec)
215+
{
216+
return pread(fd, place, nsec * 512, lba * 512);
217+
}
218+
219+
int
220+
putsec(int fd, uchar *place, vlong lba, int nsec)
221+
{
222+
return pwrite(fd, place, nsec * 512, lba * 512);
223+
}
224+
225+
static int pktn = 0;
226+
static uchar *pktbp = NULL;
227+
228+
int
229+
getpkt(int fd, uchar *buf, int sz)
230+
{
231+
register struct bpf_hdr *bh;
232+
register int pktlen, retlen;
233+
234+
if (pktn <= 0) {
235+
if ((pktn = read(fd, pktbuf, pktbufsz)) < 0) {
236+
perror("read");
237+
exit(1);
238+
}
239+
pktbp = pktbuf;
240+
}
241+
242+
bh = (struct bpf_hdr *) pktbp;
243+
retlen = (int) bh->bh_caplen;
244+
/* This memcpy() is currently needed */
245+
memcpy(buf, (void *)(pktbp + bh->bh_hdrlen),
246+
retlen > sz ? sz : retlen);
247+
pktlen = bh->bh_hdrlen + bh->bh_caplen;
248+
249+
pktbp = pktbp + BPF_WORDALIGN(pktlen);
250+
pktn -= (int) BPF_WORDALIGN(pktlen);
251+
252+
return retlen;
253+
}
254+
255+
int
256+
putpkt(int fd, uchar *buf, int sz)
257+
{
258+
return write(fd, buf, sz);
259+
}
260+
261+
int
262+
getmtu(int fd, char *name)
263+
{
264+
return 1500;
265+
}
266+
267+
vlong
268+
getsize(int fd)
269+
{
270+
vlong size;
271+
struct stat s;
272+
int n;
273+
struct disklabel lab;
274+
275+
// Try getting disklabel from block dev
276+
if ((n = ioctl(fd, DIOCGDINFO, lab)) != -1) {
277+
size = lab.d_secsize * lab.d_secperunit;
278+
} else {
279+
// must not be a block special dev
280+
if (fstat(fd, &s) == -1) {
281+
perror("getsize");
282+
exit(1);
283+
}
284+
size = s.st_size;
285+
}
286+
printf("ioctl returned %d\n", n);
287+
printf("%lld bytes\n", size);
288+
return size;
289+
}

‎linux.c

+160
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
// linux.c: low level access routines for Linux
2+
#define _GNU_SOURCE
3+
#include "config.h"
4+
#include <sys/socket.h>
5+
#include <stdio.h>
6+
#include <string.h>
7+
#include <stdlib.h>
8+
#include <unistd.h>
9+
#include <sys/time.h>
10+
#include <features.h> /* for the glibc version number */
11+
#if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1
12+
#include <netpacket/packet.h>
13+
#include <net/ethernet.h> /* the L2 protocols */
14+
#else
15+
#include <asm/types.h>
16+
#include <linux/if_packet.h>
17+
#include <linux/if_ether.h> /* The L2 protocols */
18+
#endif
19+
20+
#include <fcntl.h>
21+
#include <sys/ioctl.h>
22+
#include <sys/types.h>
23+
#include <net/if.h>
24+
#include <netinet/in.h>
25+
#include <linux/fs.h>
26+
#include <sys/stat.h>
27+
28+
#include "dat.h"
29+
#include "fns.h"
30+
31+
int getindx(int, char *);
32+
int getea(int, char *, uchar *);
33+
34+
35+
36+
int
37+
dial(char *eth, int bufcnt) // get us a raw connection to an interface
38+
{
39+
int i, n, s;
40+
struct sockaddr_ll sa;
41+
enum { aoe_type = 0x88a2 };
42+
43+
memset(&sa, 0, sizeof sa);
44+
s = socket(PF_PACKET, SOCK_RAW, htons(aoe_type));
45+
if (s == -1) {
46+
perror("got bad socket");
47+
return -1;
48+
}
49+
i = getindx(s, eth);
50+
sa.sll_family = AF_PACKET;
51+
sa.sll_protocol = htons(0x88a2);
52+
sa.sll_ifindex = i;
53+
n = bind(s, (struct sockaddr *)&sa, sizeof sa);
54+
if (n == -1) {
55+
perror("bind funky");
56+
return -1;
57+
}
58+
59+
struct bpf_program {
60+
ulong bf_len;
61+
void *bf_insns;
62+
} *bpf_program = create_bpf_program(shelf, slot);
63+
setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, bpf_program, sizeof(*bpf_program));
64+
free_bpf_program(bpf_program);
65+
66+
n = bufcnt * getmtu(s, eth);
67+
if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n)) < 0)
68+
perror("setsockopt SOL_SOCKET, SO_SNDBUF");
69+
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) < 0)
70+
perror("setsockopt SOL_SOCKET, SO_RCVBUF");
71+
72+
return s;
73+
}
74+
75+
int
76+
getindx(int s, char *name) // return the index of device 'name'
77+
{
78+
struct ifreq xx;
79+
int n;
80+
81+
strcpy(xx.ifr_name, name);
82+
n = ioctl(s, SIOCGIFINDEX, &xx);
83+
if (n == -1)
84+
return -1;
85+
return xx.ifr_ifindex;
86+
}
87+
88+
int
89+
getea(int s, char *name, uchar *ea)
90+
{
91+
struct ifreq xx;
92+
int n;
93+
94+
strcpy(xx.ifr_name, name);
95+
n = ioctl(s, SIOCGIFHWADDR, &xx);
96+
if (n == -1) {
97+
perror("Can't get hw addr");
98+
return 0;
99+
}
100+
memmove(ea, xx.ifr_hwaddr.sa_data, 6);
101+
return 1;
102+
}
103+
104+
int
105+
getmtu(int s, char *name)
106+
{
107+
struct ifreq xx;
108+
int n;
109+
110+
strcpy(xx.ifr_name, name);
111+
n = ioctl(s, SIOCGIFMTU, &xx);
112+
if (n == -1) {
113+
perror("Can't get mtu");
114+
return 1500;
115+
}
116+
return xx.ifr_mtu;
117+
}
118+
119+
int
120+
getsec(int fd, uchar *place, vlong lba, int nsec)
121+
{
122+
return pread(fd, place, nsec * 512, lba * 512);
123+
}
124+
125+
int
126+
putsec(int fd, uchar *place, vlong lba, int nsec)
127+
{
128+
return pwrite(fd, place, nsec * 512, lba * 512);
129+
}
130+
131+
int
132+
getpkt(int fd, uchar *buf, int sz)
133+
{
134+
return read(fd, buf, sz);
135+
}
136+
137+
int
138+
putpkt(int fd, uchar *buf, int sz)
139+
{
140+
return write(fd, buf, sz);
141+
}
142+
143+
vlong
144+
getsize(int fd)
145+
{
146+
vlong size;
147+
struct stat s;
148+
int n;
149+
150+
n = ioctl(fd, BLKGETSIZE64, &size);
151+
if (n == -1) { // must not be a block special
152+
n = fstat(fd, &s);
153+
if (n == -1) {
154+
perror("getsize");
155+
exit(1);
156+
}
157+
size = s.st_size;
158+
}
159+
return size;
160+
}

‎linux.h

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// linux.h: header for linux.c
2+
3+
typedef unsigned char uchar;
4+
typedef long long vlong;
5+
6+
int dial(char *);
7+
int getindx(int, char *);
8+
int getea(int, char *, uchar *);
9+
int getsec(int, uchar *, vlong, int);
10+
int putsec(int, uchar *, vlong, int);
11+
vlong getsize(int);

‎makefile

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# makefile for vblade
2+
3+
# see README for others
4+
PLATFORM=linux
5+
6+
prefix = /usr
7+
sbindir = ${prefix}/sbin
8+
sharedir = ${prefix}/share
9+
mandir = ${sharedir}/man
10+
11+
O=aoe.o bpf.o ${PLATFORM}.o ata.o
12+
CFLAGS += -Wall -g -O2
13+
CC = gcc
14+
15+
vblade: $O
16+
${CC} -o vblade $O
17+
18+
aoe.o : aoe.c config.h dat.h fns.h makefile
19+
${CC} ${CFLAGS} -c $<
20+
21+
${PLATFORM}.o : ${PLATFORM}.c config.h dat.h fns.h makefile
22+
${CC} ${CFLAGS} -c $<
23+
24+
ata.o : ata.c config.h dat.h fns.h makefile
25+
${CC} ${CFLAGS} -c $<
26+
27+
bpf.o : bpf.c
28+
${CC} ${CFLAGS} -c $<
29+
30+
config.h : config/config.h.in makefile
31+
@if ${CC} ${CFLAGS} config/u64.c > /dev/null 2>&1; then \
32+
sh -xc "cp config/config.h.in config.h"; \
33+
else \
34+
sh -xc "sed 's!^//u64 !!' config/config.h.in > config.h"; \
35+
fi
36+
37+
clean :
38+
rm -f $O vblade
39+
40+
install : vblade vbladed
41+
install vblade ${sbindir}/
42+
install vbladed ${sbindir}/
43+
install vblade.8 ${mandir}/man8/

‎vblade.8

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
.TH vblade 8
2+
.SH NAME
3+
vblade, vbladed \- export data via ATA over Ethernet
4+
.SH SYNOPSIS
5+
.nf
6+
.B vblade [ -m mac[,mac...] ] shelf slot netif filename
7+
.fi
8+
.SH DESCRIPTION
9+
The
10+
.I vblade
11+
command starts a process that uses raw sockets to perform ATA over
12+
Ethernet, acting like a virtual EtherDrive (R) blade.
13+
.PP
14+
The
15+
.I vbladed
16+
script can be used to daemonize the vblade process,
17+
detaching it from your terminal and sending its output to the system
18+
logs.
19+
.SS Arguments
20+
.TP
21+
\fBshelf\fP
22+
This should be the shelf address (major AoE address) of the AoE device
23+
to create.
24+
.TP
25+
\fBslot\fP
26+
This should be the slot address (minor AoE address) of the AoE device
27+
to create.
28+
.TP
29+
\fBnetif\fP
30+
The name of the ethernet network interface to use for AoE
31+
communications.
32+
.TP
33+
\fBfilename\fP
34+
The name of the regular file or block device to export.
35+
.SS Options
36+
.TP
37+
\fB-b\fP
38+
The -b flag takes an argument, the advertised buffer count, specifying
39+
the maximum number of outstanding messages the server can queue for
40+
processing.
41+
.TP
42+
\fB-d\fP
43+
The -d flag selects O_DIRECT mode for accessing the underlying block
44+
device.
45+
.TP
46+
\fB-s\fP
47+
The -s flag selects O_SYNC mode for accessing the underlying block
48+
device, so all writes are committed to disk before returning to the
49+
client.
50+
.TP
51+
\fB-r\fP
52+
The -r flag restricts the export of the device to be read-only.
53+
.TP
54+
\fB-m\fP
55+
The -m flag takes an argument, a comma separated list of MAC addresses
56+
permitted access to the vblade. A MAC address can be specified in upper
57+
or lower case, with or without colons.
58+
.SH EXAMPLE
59+
In this example, the root user on a host named
60+
.I nai
61+
exports a file named "3TB" to the LAN on eth0 using AoE shelf address 11
62+
and slot address 1. The process runs in the foreground. Using
63+
.I vbladed
64+
would have resulted in the process running as a daemon in the
65+
background.
66+
.IP
67+
.EX
68+
.nf
69+
nai:~# vblade 11 1 eth0 /data/3TB
70+
.fi
71+
.EE
72+
.SH BUGS
73+
Users of Jumbo frames should read the README file distributed with
74+
vblade to learn about a workaround for kernel buffering limitations.
75+
.SH AUTHOR
76+
Brantley Coile (brantley@coraid.com)

‎vbladed

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#! /bin/sh
2+
# run a vblade daemon using a logger process
3+
# output is directed to syslogd
4+
#
5+
6+
sh -c "`dirname $0`/vblade $* < /dev/null 2>&1 | logger -t vbladed" &

0 commit comments

Comments
 (0)
Please sign in to comment.