#include #include #include "snap.h" int shelf; enum{ Rbsize = 8192, }; typedef struct{ int fd; uchar buf[Rbsize]; long blen; uvlong boff; }Afd; Afd atab[3] = {{.fd =-1,}, {.fd = -1,}, {.fd = -1,},}; static int tailio(Afd *t, long (*io)(int, void*, long, vlong), void *buf, ulong l, uvlong byte) { int r; ulong rem; rem = byte&(Rbsize-1); if(l+rem > Rbsize) l = Rbsize-rem; if(t->boff == byte) r = t->blen; else{ r = pread(t->fd, t->buf, Rbsize, byte-rem); if(r < 0){ t->boff = -1; return -1; } t->boff = byte-rem; t->blen = r; } if(l+rem >= r) l = r-rem; else if(io == pwrite) return -1; if(io == pwrite){ memmove(t->buf+rem, buf, l); r = io(t->fd, t->buf, r, byte-rem); if(r != t->blen) return -1; }else memmove(buf, t->buf+rem, l); return l; } static int byteio(Afd *t, long (*d)(int, void*, long, vlong), char *buf, ulong l, uvlong byte) { int r; ulong l0; l0 = l; loop: if(l == 0) return l0-l; if((r = tailio(t, d, buf, l, byte)) < 0) return -1; byte += r; buf += r; l -= r; if(byte%Rbsize) return l0-l; while(l >= Rbsize){ if((r = d(t->fd, buf, Rbsize, byte)) < 0) return -1; byte += r; buf += r; l -= r; if(r < Rbsize) return l0-l; } goto loop; } Afd* afd(int fd) { int i; for(i = 0; i < nelem(atab); i++) if(atab[i].fd == fd) return atab+i; return 0; } long aoepread(int fd, void *buf, long n, vlong offset) { return byteio(afd(fd), pread, buf, n, offset); } long aoepwrite(int fd, void *buf, long n, vlong offset) { return byteio(afd(fd), pwrite, buf, n, offset); } void aoeclose(int fd) { Afd *a; a = afd(fd); if(a == 0) sysfatal("bad aoefd %d", fd); close(fd); a->fd = -1; } int aoeopen(int slot) { char buf[64]; Afd *a; for(a = atab; a < atab+nelem(atab); a++) if(a->fd == -1) goto found; sysfatal("too many open aoe devices"); found: #ifdef LINUX snprint(buf, sizeof buf, "/dev/etherd/e%d.%d", shelf, slot); #else snprint(buf, sizeof buf, "/dev/aoe/%d.%d/data", shelf, slot); #endif a->fd = open(buf, OREAD); a->boff = -1; if(a->fd == -1) sysfatal("aoeopen[%s]: %r", buf); return a->fd; }