Implement fs stat

10.97.12.10:10001       29P  208T   29P   1% /home/restechprod/eggs/mnt
This commit is contained in:
Francesco Mazzoli
2023-05-29 18:42:19 +00:00
parent d48b100ab1
commit 55074b16b4
13 changed files with 567 additions and 62 deletions

View File

@@ -331,6 +331,9 @@ std::ostream& operator<<(std::ostream& out, ShuckleMessageKind kind) {
case ShuckleMessageKind::CDC:
out << "CDC";
break;
case ShuckleMessageKind::INFO:
out << "INFO";
break;
case ShuckleMessageKind::REGISTER_BLOCK_SERVICES:
out << "REGISTER_BLOCK_SERVICES";
break;
@@ -2914,6 +2917,54 @@ std::ostream& operator<<(std::ostream& out, const CdcResp& x) {
return out;
}
void InfoReq::pack(BincodeBuf& buf) const {
}
void InfoReq::unpack(BincodeBuf& buf) {
}
void InfoReq::clear() {
}
bool InfoReq::operator==(const InfoReq& rhs) const {
return true;
}
std::ostream& operator<<(std::ostream& out, const InfoReq& x) {
out << "InfoReq(" << ")";
return out;
}
void InfoResp::pack(BincodeBuf& buf) const {
buf.packScalar<uint32_t>(numBlockServices);
buf.packScalar<uint32_t>(numFailureDomains);
buf.packScalar<uint64_t>(capacity);
buf.packScalar<uint64_t>(available);
buf.packScalar<uint64_t>(blocks);
}
void InfoResp::unpack(BincodeBuf& buf) {
numBlockServices = buf.unpackScalar<uint32_t>();
numFailureDomains = buf.unpackScalar<uint32_t>();
capacity = buf.unpackScalar<uint64_t>();
available = buf.unpackScalar<uint64_t>();
blocks = buf.unpackScalar<uint64_t>();
}
void InfoResp::clear() {
numBlockServices = uint32_t(0);
numFailureDomains = uint32_t(0);
capacity = uint64_t(0);
available = uint64_t(0);
blocks = uint64_t(0);
}
bool InfoResp::operator==(const InfoResp& rhs) const {
if ((uint32_t)this->numBlockServices != (uint32_t)rhs.numBlockServices) { return false; };
if ((uint32_t)this->numFailureDomains != (uint32_t)rhs.numFailureDomains) { return false; };
if ((uint64_t)this->capacity != (uint64_t)rhs.capacity) { return false; };
if ((uint64_t)this->available != (uint64_t)rhs.available) { return false; };
if ((uint64_t)this->blocks != (uint64_t)rhs.blocks) { return false; };
return true;
}
std::ostream& operator<<(std::ostream& out, const InfoResp& x) {
out << "InfoResp(" << "NumBlockServices=" << x.numBlockServices << ", " << "NumFailureDomains=" << x.numFailureDomains << ", " << "Capacity=" << x.capacity << ", " << "Available=" << x.available << ", " << "Blocks=" << x.blocks << ")";
return out;
}
void RegisterBlockServicesReq::pack(BincodeBuf& buf) const {
buf.packList<BlockServiceInfo>(blockServices);
}
@@ -5112,43 +5163,53 @@ CdcReq& ShuckleReqContainer::setCdc() {
x.clear();
return x;
}
const InfoReq& ShuckleReqContainer::getInfo() const {
ALWAYS_ASSERT(_kind == ShuckleMessageKind::INFO, "%s != %s", _kind, ShuckleMessageKind::INFO);
return std::get<2>(_data);
}
InfoReq& ShuckleReqContainer::setInfo() {
_kind = ShuckleMessageKind::INFO;
auto& x = std::get<2>(_data);
x.clear();
return x;
}
const RegisterBlockServicesReq& ShuckleReqContainer::getRegisterBlockServices() const {
ALWAYS_ASSERT(_kind == ShuckleMessageKind::REGISTER_BLOCK_SERVICES, "%s != %s", _kind, ShuckleMessageKind::REGISTER_BLOCK_SERVICES);
return std::get<2>(_data);
return std::get<3>(_data);
}
RegisterBlockServicesReq& ShuckleReqContainer::setRegisterBlockServices() {
_kind = ShuckleMessageKind::REGISTER_BLOCK_SERVICES;
auto& x = std::get<2>(_data);
auto& x = std::get<3>(_data);
x.clear();
return x;
}
const RegisterShardReq& ShuckleReqContainer::getRegisterShard() const {
ALWAYS_ASSERT(_kind == ShuckleMessageKind::REGISTER_SHARD, "%s != %s", _kind, ShuckleMessageKind::REGISTER_SHARD);
return std::get<3>(_data);
return std::get<4>(_data);
}
RegisterShardReq& ShuckleReqContainer::setRegisterShard() {
_kind = ShuckleMessageKind::REGISTER_SHARD;
auto& x = std::get<3>(_data);
auto& x = std::get<4>(_data);
x.clear();
return x;
}
const AllBlockServicesReq& ShuckleReqContainer::getAllBlockServices() const {
ALWAYS_ASSERT(_kind == ShuckleMessageKind::ALL_BLOCK_SERVICES, "%s != %s", _kind, ShuckleMessageKind::ALL_BLOCK_SERVICES);
return std::get<4>(_data);
return std::get<5>(_data);
}
AllBlockServicesReq& ShuckleReqContainer::setAllBlockServices() {
_kind = ShuckleMessageKind::ALL_BLOCK_SERVICES;
auto& x = std::get<4>(_data);
auto& x = std::get<5>(_data);
x.clear();
return x;
}
const RegisterCdcReq& ShuckleReqContainer::getRegisterCdc() const {
ALWAYS_ASSERT(_kind == ShuckleMessageKind::REGISTER_CDC, "%s != %s", _kind, ShuckleMessageKind::REGISTER_CDC);
return std::get<5>(_data);
return std::get<6>(_data);
}
RegisterCdcReq& ShuckleReqContainer::setRegisterCdc() {
_kind = ShuckleMessageKind::REGISTER_CDC;
auto& x = std::get<5>(_data);
auto& x = std::get<6>(_data);
x.clear();
return x;
}
@@ -5158,14 +5219,16 @@ size_t ShuckleReqContainer::packedSize() const {
return std::get<0>(_data).packedSize();
case ShuckleMessageKind::CDC:
return std::get<1>(_data).packedSize();
case ShuckleMessageKind::REGISTER_BLOCK_SERVICES:
case ShuckleMessageKind::INFO:
return std::get<2>(_data).packedSize();
case ShuckleMessageKind::REGISTER_SHARD:
case ShuckleMessageKind::REGISTER_BLOCK_SERVICES:
return std::get<3>(_data).packedSize();
case ShuckleMessageKind::ALL_BLOCK_SERVICES:
case ShuckleMessageKind::REGISTER_SHARD:
return std::get<4>(_data).packedSize();
case ShuckleMessageKind::REGISTER_CDC:
case ShuckleMessageKind::ALL_BLOCK_SERVICES:
return std::get<5>(_data).packedSize();
case ShuckleMessageKind::REGISTER_CDC:
return std::get<6>(_data).packedSize();
default:
throw EGGS_EXCEPTION("bad ShuckleMessageKind kind %s", _kind);
}
@@ -5179,18 +5242,21 @@ void ShuckleReqContainer::pack(BincodeBuf& buf) const {
case ShuckleMessageKind::CDC:
std::get<1>(_data).pack(buf);
break;
case ShuckleMessageKind::REGISTER_BLOCK_SERVICES:
case ShuckleMessageKind::INFO:
std::get<2>(_data).pack(buf);
break;
case ShuckleMessageKind::REGISTER_SHARD:
case ShuckleMessageKind::REGISTER_BLOCK_SERVICES:
std::get<3>(_data).pack(buf);
break;
case ShuckleMessageKind::ALL_BLOCK_SERVICES:
case ShuckleMessageKind::REGISTER_SHARD:
std::get<4>(_data).pack(buf);
break;
case ShuckleMessageKind::REGISTER_CDC:
case ShuckleMessageKind::ALL_BLOCK_SERVICES:
std::get<5>(_data).pack(buf);
break;
case ShuckleMessageKind::REGISTER_CDC:
std::get<6>(_data).pack(buf);
break;
default:
throw EGGS_EXCEPTION("bad ShuckleMessageKind kind %s", _kind);
}
@@ -5205,18 +5271,21 @@ void ShuckleReqContainer::unpack(BincodeBuf& buf, ShuckleMessageKind kind) {
case ShuckleMessageKind::CDC:
std::get<1>(_data).unpack(buf);
break;
case ShuckleMessageKind::REGISTER_BLOCK_SERVICES:
case ShuckleMessageKind::INFO:
std::get<2>(_data).unpack(buf);
break;
case ShuckleMessageKind::REGISTER_SHARD:
case ShuckleMessageKind::REGISTER_BLOCK_SERVICES:
std::get<3>(_data).unpack(buf);
break;
case ShuckleMessageKind::ALL_BLOCK_SERVICES:
case ShuckleMessageKind::REGISTER_SHARD:
std::get<4>(_data).unpack(buf);
break;
case ShuckleMessageKind::REGISTER_CDC:
case ShuckleMessageKind::ALL_BLOCK_SERVICES:
std::get<5>(_data).unpack(buf);
break;
case ShuckleMessageKind::REGISTER_CDC:
std::get<6>(_data).unpack(buf);
break;
default:
throw BINCODE_EXCEPTION("bad ShuckleMessageKind kind %s", kind);
}
@@ -5230,6 +5299,9 @@ std::ostream& operator<<(std::ostream& out, const ShuckleReqContainer& x) {
case ShuckleMessageKind::CDC:
out << x.getCdc();
break;
case ShuckleMessageKind::INFO:
out << x.getInfo();
break;
case ShuckleMessageKind::REGISTER_BLOCK_SERVICES:
out << x.getRegisterBlockServices();
break;
@@ -5268,43 +5340,53 @@ CdcResp& ShuckleRespContainer::setCdc() {
x.clear();
return x;
}
const InfoResp& ShuckleRespContainer::getInfo() const {
ALWAYS_ASSERT(_kind == ShuckleMessageKind::INFO, "%s != %s", _kind, ShuckleMessageKind::INFO);
return std::get<2>(_data);
}
InfoResp& ShuckleRespContainer::setInfo() {
_kind = ShuckleMessageKind::INFO;
auto& x = std::get<2>(_data);
x.clear();
return x;
}
const RegisterBlockServicesResp& ShuckleRespContainer::getRegisterBlockServices() const {
ALWAYS_ASSERT(_kind == ShuckleMessageKind::REGISTER_BLOCK_SERVICES, "%s != %s", _kind, ShuckleMessageKind::REGISTER_BLOCK_SERVICES);
return std::get<2>(_data);
return std::get<3>(_data);
}
RegisterBlockServicesResp& ShuckleRespContainer::setRegisterBlockServices() {
_kind = ShuckleMessageKind::REGISTER_BLOCK_SERVICES;
auto& x = std::get<2>(_data);
auto& x = std::get<3>(_data);
x.clear();
return x;
}
const RegisterShardResp& ShuckleRespContainer::getRegisterShard() const {
ALWAYS_ASSERT(_kind == ShuckleMessageKind::REGISTER_SHARD, "%s != %s", _kind, ShuckleMessageKind::REGISTER_SHARD);
return std::get<3>(_data);
return std::get<4>(_data);
}
RegisterShardResp& ShuckleRespContainer::setRegisterShard() {
_kind = ShuckleMessageKind::REGISTER_SHARD;
auto& x = std::get<3>(_data);
auto& x = std::get<4>(_data);
x.clear();
return x;
}
const AllBlockServicesResp& ShuckleRespContainer::getAllBlockServices() const {
ALWAYS_ASSERT(_kind == ShuckleMessageKind::ALL_BLOCK_SERVICES, "%s != %s", _kind, ShuckleMessageKind::ALL_BLOCK_SERVICES);
return std::get<4>(_data);
return std::get<5>(_data);
}
AllBlockServicesResp& ShuckleRespContainer::setAllBlockServices() {
_kind = ShuckleMessageKind::ALL_BLOCK_SERVICES;
auto& x = std::get<4>(_data);
auto& x = std::get<5>(_data);
x.clear();
return x;
}
const RegisterCdcResp& ShuckleRespContainer::getRegisterCdc() const {
ALWAYS_ASSERT(_kind == ShuckleMessageKind::REGISTER_CDC, "%s != %s", _kind, ShuckleMessageKind::REGISTER_CDC);
return std::get<5>(_data);
return std::get<6>(_data);
}
RegisterCdcResp& ShuckleRespContainer::setRegisterCdc() {
_kind = ShuckleMessageKind::REGISTER_CDC;
auto& x = std::get<5>(_data);
auto& x = std::get<6>(_data);
x.clear();
return x;
}
@@ -5314,14 +5396,16 @@ size_t ShuckleRespContainer::packedSize() const {
return std::get<0>(_data).packedSize();
case ShuckleMessageKind::CDC:
return std::get<1>(_data).packedSize();
case ShuckleMessageKind::REGISTER_BLOCK_SERVICES:
case ShuckleMessageKind::INFO:
return std::get<2>(_data).packedSize();
case ShuckleMessageKind::REGISTER_SHARD:
case ShuckleMessageKind::REGISTER_BLOCK_SERVICES:
return std::get<3>(_data).packedSize();
case ShuckleMessageKind::ALL_BLOCK_SERVICES:
case ShuckleMessageKind::REGISTER_SHARD:
return std::get<4>(_data).packedSize();
case ShuckleMessageKind::REGISTER_CDC:
case ShuckleMessageKind::ALL_BLOCK_SERVICES:
return std::get<5>(_data).packedSize();
case ShuckleMessageKind::REGISTER_CDC:
return std::get<6>(_data).packedSize();
default:
throw EGGS_EXCEPTION("bad ShuckleMessageKind kind %s", _kind);
}
@@ -5335,18 +5419,21 @@ void ShuckleRespContainer::pack(BincodeBuf& buf) const {
case ShuckleMessageKind::CDC:
std::get<1>(_data).pack(buf);
break;
case ShuckleMessageKind::REGISTER_BLOCK_SERVICES:
case ShuckleMessageKind::INFO:
std::get<2>(_data).pack(buf);
break;
case ShuckleMessageKind::REGISTER_SHARD:
case ShuckleMessageKind::REGISTER_BLOCK_SERVICES:
std::get<3>(_data).pack(buf);
break;
case ShuckleMessageKind::ALL_BLOCK_SERVICES:
case ShuckleMessageKind::REGISTER_SHARD:
std::get<4>(_data).pack(buf);
break;
case ShuckleMessageKind::REGISTER_CDC:
case ShuckleMessageKind::ALL_BLOCK_SERVICES:
std::get<5>(_data).pack(buf);
break;
case ShuckleMessageKind::REGISTER_CDC:
std::get<6>(_data).pack(buf);
break;
default:
throw EGGS_EXCEPTION("bad ShuckleMessageKind kind %s", _kind);
}
@@ -5361,18 +5448,21 @@ void ShuckleRespContainer::unpack(BincodeBuf& buf, ShuckleMessageKind kind) {
case ShuckleMessageKind::CDC:
std::get<1>(_data).unpack(buf);
break;
case ShuckleMessageKind::REGISTER_BLOCK_SERVICES:
case ShuckleMessageKind::INFO:
std::get<2>(_data).unpack(buf);
break;
case ShuckleMessageKind::REGISTER_SHARD:
case ShuckleMessageKind::REGISTER_BLOCK_SERVICES:
std::get<3>(_data).unpack(buf);
break;
case ShuckleMessageKind::ALL_BLOCK_SERVICES:
case ShuckleMessageKind::REGISTER_SHARD:
std::get<4>(_data).unpack(buf);
break;
case ShuckleMessageKind::REGISTER_CDC:
case ShuckleMessageKind::ALL_BLOCK_SERVICES:
std::get<5>(_data).unpack(buf);
break;
case ShuckleMessageKind::REGISTER_CDC:
std::get<6>(_data).unpack(buf);
break;
default:
throw BINCODE_EXCEPTION("bad ShuckleMessageKind kind %s", kind);
}
@@ -5386,6 +5476,9 @@ std::ostream& operator<<(std::ostream& out, const ShuckleRespContainer& x) {
case ShuckleMessageKind::CDC:
out << x.getCdc();
break;
case ShuckleMessageKind::INFO:
out << x.getInfo();
break;
case ShuckleMessageKind::REGISTER_BLOCK_SERVICES:
out << x.getRegisterBlockServices();
break;

View File

@@ -122,6 +122,7 @@ enum class ShuckleMessageKind : uint8_t {
ERROR = 0,
SHARDS = 3,
CDC = 7,
INFO = 8,
REGISTER_BLOCK_SERVICES = 2,
REGISTER_SHARD = 4,
ALL_BLOCK_SERVICES = 5,
@@ -2619,6 +2620,50 @@ struct CdcResp {
std::ostream& operator<<(std::ostream& out, const CdcResp& x);
struct InfoReq {
static constexpr uint16_t STATIC_SIZE = 0; //
InfoReq() { clear(); }
uint16_t packedSize() const {
uint16_t _size = 0;
return _size;
}
void pack(BincodeBuf& buf) const;
void unpack(BincodeBuf& buf);
void clear();
bool operator==(const InfoReq&rhs) const;
};
std::ostream& operator<<(std::ostream& out, const InfoReq& x);
struct InfoResp {
uint32_t numBlockServices;
uint32_t numFailureDomains;
uint64_t capacity;
uint64_t available;
uint64_t blocks;
static constexpr uint16_t STATIC_SIZE = 4 + 4 + 8 + 8 + 8; // numBlockServices + numFailureDomains + capacity + available + blocks
InfoResp() { clear(); }
uint16_t packedSize() const {
uint16_t _size = 0;
_size += 4; // numBlockServices
_size += 4; // numFailureDomains
_size += 8; // capacity
_size += 8; // available
_size += 8; // blocks
return _size;
}
void pack(BincodeBuf& buf) const;
void unpack(BincodeBuf& buf);
void clear();
bool operator==(const InfoResp&rhs) const;
};
std::ostream& operator<<(std::ostream& out, const InfoResp& x);
struct RegisterBlockServicesReq {
BincodeList<BlockServiceInfo> blockServices;
@@ -3198,13 +3243,15 @@ std::ostream& operator<<(std::ostream& out, const CDCRespContainer& x);
struct ShuckleReqContainer {
private:
ShuckleMessageKind _kind = (ShuckleMessageKind)0;
std::tuple<ShardsReq, CdcReq, RegisterBlockServicesReq, RegisterShardReq, AllBlockServicesReq, RegisterCdcReq> _data;
std::tuple<ShardsReq, CdcReq, InfoReq, RegisterBlockServicesReq, RegisterShardReq, AllBlockServicesReq, RegisterCdcReq> _data;
public:
ShuckleMessageKind kind() const { return _kind; }
const ShardsReq& getShards() const;
ShardsReq& setShards();
const CdcReq& getCdc() const;
CdcReq& setCdc();
const InfoReq& getInfo() const;
InfoReq& setInfo();
const RegisterBlockServicesReq& getRegisterBlockServices() const;
RegisterBlockServicesReq& setRegisterBlockServices();
const RegisterShardReq& getRegisterShard() const;
@@ -3226,13 +3273,15 @@ std::ostream& operator<<(std::ostream& out, const ShuckleReqContainer& x);
struct ShuckleRespContainer {
private:
ShuckleMessageKind _kind = (ShuckleMessageKind)0;
std::tuple<ShardsResp, CdcResp, RegisterBlockServicesResp, RegisterShardResp, AllBlockServicesResp, RegisterCdcResp> _data;
std::tuple<ShardsResp, CdcResp, InfoResp, RegisterBlockServicesResp, RegisterShardResp, AllBlockServicesResp, RegisterCdcResp> _data;
public:
ShuckleMessageKind kind() const { return _kind; }
const ShardsResp& getShards() const;
ShardsResp& setShards();
const CdcResp& getCdc() const;
CdcResp& setCdc();
const InfoResp& getInfo() const;
InfoResp& setInfo();
const RegisterBlockServicesResp& getRegisterBlockServices() const;
RegisterBlockServicesResp& setRegisterBlockServices();
const RegisterShardResp& getRegisterShard() const;

View File

@@ -15,7 +15,7 @@
const char* exe = NULL;
#define badUsage(...) do { \
fprintf(stderr, "Bad usage, expecting %s writefile|readfile <command arguments>\n", exe); \
fprintf(stderr, "Bad usage, expecting %s writefile|readfile|readlink <command arguments>\n", exe); \
__VA_OPT__(fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n");) \
exit(2); \
} while(0) \

View File

@@ -1495,6 +1495,11 @@ func main() {
reflect.TypeOf(msgs.CdcReq{}),
reflect.TypeOf(msgs.CdcResp{}),
},
{
0x08,
reflect.TypeOf(msgs.InfoReq{}),
reflect.TypeOf(msgs.InfoResp{}),
},
}
shuckleReqResps := append(kernelShuckleReqResps, []reqRespType{

View File

@@ -145,6 +145,25 @@ func handleRegisterCdcReq(log *lib.Logger, s *state, w io.Writer, req *msgs.Regi
return &msgs.RegisterCdcResp{}
}
func handleInfoReq(log *lib.Logger, s *state, w io.Writer, req *msgs.InfoReq) *msgs.InfoResp {
s.mutex.RLock()
defer s.mutex.RUnlock()
resp := msgs.InfoResp{}
failureDomains := make(map[[16]byte]struct{})
for _, bs := range s.blockServices {
resp.Capacity += bs.CapacityBytes
resp.NumBlockServices++
resp.Available += bs.AvailableBytes
resp.Blocks += bs.Blocks
failureDomains[bs.FailureDomain] = struct{}{}
}
resp.NumFailureDomains = uint32(len(failureDomains))
return &resp
}
func handleRequest(log *lib.Logger, s *state, conn *net.TCPConn) {
conn.SetLinger(0) // poor man error handling for now
defer conn.Close()
@@ -174,6 +193,8 @@ func handleRequest(log *lib.Logger, s *state, conn *net.TCPConn) {
resp = handleCdcReq(log, s, conn, whichReq)
case *msgs.RegisterCdcReq:
resp = handleRegisterCdcReq(log, s, conn, whichReq)
case *msgs.InfoReq:
resp = handleInfoReq(log, s, conn, whichReq)
default:
log.RaiseAlert(fmt.Errorf("bad req type %T", req))
}

View File

@@ -45,6 +45,8 @@ func ReadShuckleRequest(
req = &msgs.RegisterCdcReq{}
case msgs.CDC:
req = &msgs.CdcReq{}
case msgs.INFO:
req = &msgs.InfoReq{}
default:
return nil, fmt.Errorf("bad shuckle request kind %v", kind)
}
@@ -109,6 +111,8 @@ func ReadShuckleResponse(
resp = &msgs.RegisterCdcResp{}
case msgs.CDC:
resp = &msgs.CdcResp{}
case msgs.INFO:
resp = &msgs.InfoResp{}
default:
return nil, fmt.Errorf("bad shuckle response kind %v", kind)
}

View File

@@ -1384,6 +1384,16 @@ type CdcResp struct {
LastSeen EggsTime
}
type InfoReq struct{}
type InfoResp struct {
NumBlockServices uint32
NumFailureDomains uint32
Capacity uint64
Available uint64
Blocks uint64
}
// --------------------------------------------------------------------
// block service requests/responses

View File

@@ -542,6 +542,8 @@ func (k ShuckleMessageKind) String() string {
return "SHARDS"
case 7:
return "CDC"
case 8:
return "INFO"
case 2:
return "REGISTER_BLOCK_SERVICES"
case 4:
@@ -559,6 +561,7 @@ func (k ShuckleMessageKind) String() string {
const (
SHARDS ShuckleMessageKind = 0x3
CDC ShuckleMessageKind = 0x7
INFO ShuckleMessageKind = 0x8
REGISTER_BLOCK_SERVICES ShuckleMessageKind = 0x2
REGISTER_SHARD ShuckleMessageKind = 0x4
ALL_BLOCK_SERVICES ShuckleMessageKind = 0x5
@@ -571,6 +574,8 @@ func MkShuckleMessage(k string) (ShuckleRequest, ShuckleResponse) {
return &ShardsReq{}, &ShardsResp{}
case k == "CDC":
return &CdcReq{}, &CdcResp{}
case k == "INFO":
return &InfoReq{}, &InfoResp{}
case k == "REGISTER_BLOCK_SERVICES":
return &RegisterBlockServicesReq{}, &RegisterBlockServicesResp{}
case k == "REGISTER_SHARD":
@@ -3624,6 +3629,60 @@ func (v *CdcResp) Unpack(r io.Reader) error {
return nil
}
func (v *InfoReq) ShuckleRequestKind() ShuckleMessageKind {
return INFO
}
func (v *InfoReq) Pack(w io.Writer) error {
return nil
}
func (v *InfoReq) Unpack(r io.Reader) error {
return nil
}
func (v *InfoResp) ShuckleResponseKind() ShuckleMessageKind {
return INFO
}
func (v *InfoResp) Pack(w io.Writer) error {
if err := bincode.PackScalar(w, uint32(v.NumBlockServices)); err != nil {
return err
}
if err := bincode.PackScalar(w, uint32(v.NumFailureDomains)); err != nil {
return err
}
if err := bincode.PackScalar(w, uint64(v.Capacity)); err != nil {
return err
}
if err := bincode.PackScalar(w, uint64(v.Available)); err != nil {
return err
}
if err := bincode.PackScalar(w, uint64(v.Blocks)); err != nil {
return err
}
return nil
}
func (v *InfoResp) Unpack(r io.Reader) error {
if err := bincode.UnpackScalar(r, (*uint32)(&v.NumBlockServices)); err != nil {
return err
}
if err := bincode.UnpackScalar(r, (*uint32)(&v.NumFailureDomains)); err != nil {
return err
}
if err := bincode.UnpackScalar(r, (*uint64)(&v.Capacity)); err != nil {
return err
}
if err := bincode.UnpackScalar(r, (*uint64)(&v.Available)); err != nil {
return err
}
if err := bincode.UnpackScalar(r, (*uint64)(&v.Blocks)); err != nil {
return err
}
return nil
}
func (v *RegisterBlockServicesReq) ShuckleRequestKind() ShuckleMessageKind {
return REGISTER_BLOCK_SERVICES
}

View File

@@ -84,7 +84,8 @@
#define EGGSFS_SHUCKLE_SHARDS 0x3
#define EGGSFS_SHUCKLE_CDC 0x7
#define __print_eggsfs_shuckle_kind(k) __print_symbolic(k, { 3, "SHARDS" }, { 7, "CDC" })
#define EGGSFS_SHUCKLE_INFO 0x8
#define __print_eggsfs_shuckle_kind(k) __print_symbolic(k, { 3, "SHARDS" }, { 7, "CDC" }, { 8, "INFO" })
#define EGGSFS_BLOCKS_FETCH_BLOCK 0x2
#define EGGSFS_BLOCKS_WRITE_BLOCK 0x3
@@ -4821,6 +4822,173 @@ static inline void _eggsfs_cdc_resp_put_last_seen(struct eggsfs_bincode_put_ctx*
{ struct eggsfs_cdc_resp_last_seen* __dummy __attribute__((unused)) = &(prev); }\
struct eggsfs_cdc_resp_end* next __attribute__((unused)) = NULL
#define EGGSFS_INFO_REQ_SIZE 0
struct eggsfs_info_req_start;
#define eggsfs_info_req_get_start(ctx, start) struct eggsfs_info_req_start* start = NULL
struct eggsfs_info_req_end;
#define eggsfs_info_req_get_end(ctx, prev, next) \
{ struct eggsfs_info_req_start** __dummy __attribute__((unused)) = &(prev); }\
struct eggsfs_info_req_end* next = NULL
static inline void eggsfs_info_req_get_finish(struct eggsfs_bincode_get_ctx* ctx, struct eggsfs_info_req_end* end) {
if (unlikely(ctx->buf != ctx->end)) {
ctx->err = EGGSFS_ERR_MALFORMED_RESPONSE;
}
}
#define eggsfs_info_req_put_start(ctx, start) struct eggsfs_info_req_start* start = NULL
#define eggsfs_info_req_put_end(ctx, prev, next) \
{ struct eggsfs_info_req_start** __dummy __attribute__((unused)) = &(prev); }\
struct eggsfs_info_req_end* next __attribute__((unused)) = NULL
#define EGGSFS_INFO_RESP_SIZE 32
struct eggsfs_info_resp_start;
#define eggsfs_info_resp_get_start(ctx, start) struct eggsfs_info_resp_start* start = NULL
struct eggsfs_info_resp_num_block_services { u32 x; };
static inline void _eggsfs_info_resp_get_num_block_services(struct eggsfs_bincode_get_ctx* ctx, struct eggsfs_info_resp_start** prev, struct eggsfs_info_resp_num_block_services* next) {
if (likely(ctx->err == 0)) {
if (unlikely(ctx->end - ctx->buf < 4)) {
ctx->err = EGGSFS_ERR_MALFORMED_RESPONSE;
} else {
next->x = get_unaligned_le32(ctx->buf);
ctx->buf += 4;
}
}
}
#define eggsfs_info_resp_get_num_block_services(ctx, prev, next) \
struct eggsfs_info_resp_num_block_services next; \
_eggsfs_info_resp_get_num_block_services(ctx, &(prev), &(next))
struct eggsfs_info_resp_num_failure_domains { u32 x; };
static inline void _eggsfs_info_resp_get_num_failure_domains(struct eggsfs_bincode_get_ctx* ctx, struct eggsfs_info_resp_num_block_services* prev, struct eggsfs_info_resp_num_failure_domains* next) {
if (likely(ctx->err == 0)) {
if (unlikely(ctx->end - ctx->buf < 4)) {
ctx->err = EGGSFS_ERR_MALFORMED_RESPONSE;
} else {
next->x = get_unaligned_le32(ctx->buf);
ctx->buf += 4;
}
}
}
#define eggsfs_info_resp_get_num_failure_domains(ctx, prev, next) \
struct eggsfs_info_resp_num_failure_domains next; \
_eggsfs_info_resp_get_num_failure_domains(ctx, &(prev), &(next))
struct eggsfs_info_resp_capacity { u64 x; };
static inline void _eggsfs_info_resp_get_capacity(struct eggsfs_bincode_get_ctx* ctx, struct eggsfs_info_resp_num_failure_domains* prev, struct eggsfs_info_resp_capacity* next) {
if (likely(ctx->err == 0)) {
if (unlikely(ctx->end - ctx->buf < 8)) {
ctx->err = EGGSFS_ERR_MALFORMED_RESPONSE;
} else {
next->x = get_unaligned_le64(ctx->buf);
ctx->buf += 8;
}
}
}
#define eggsfs_info_resp_get_capacity(ctx, prev, next) \
struct eggsfs_info_resp_capacity next; \
_eggsfs_info_resp_get_capacity(ctx, &(prev), &(next))
struct eggsfs_info_resp_available { u64 x; };
static inline void _eggsfs_info_resp_get_available(struct eggsfs_bincode_get_ctx* ctx, struct eggsfs_info_resp_capacity* prev, struct eggsfs_info_resp_available* next) {
if (likely(ctx->err == 0)) {
if (unlikely(ctx->end - ctx->buf < 8)) {
ctx->err = EGGSFS_ERR_MALFORMED_RESPONSE;
} else {
next->x = get_unaligned_le64(ctx->buf);
ctx->buf += 8;
}
}
}
#define eggsfs_info_resp_get_available(ctx, prev, next) \
struct eggsfs_info_resp_available next; \
_eggsfs_info_resp_get_available(ctx, &(prev), &(next))
struct eggsfs_info_resp_blocks { u64 x; };
static inline void _eggsfs_info_resp_get_blocks(struct eggsfs_bincode_get_ctx* ctx, struct eggsfs_info_resp_available* prev, struct eggsfs_info_resp_blocks* next) {
if (likely(ctx->err == 0)) {
if (unlikely(ctx->end - ctx->buf < 8)) {
ctx->err = EGGSFS_ERR_MALFORMED_RESPONSE;
} else {
next->x = get_unaligned_le64(ctx->buf);
ctx->buf += 8;
}
}
}
#define eggsfs_info_resp_get_blocks(ctx, prev, next) \
struct eggsfs_info_resp_blocks next; \
_eggsfs_info_resp_get_blocks(ctx, &(prev), &(next))
struct eggsfs_info_resp_end;
#define eggsfs_info_resp_get_end(ctx, prev, next) \
{ struct eggsfs_info_resp_blocks* __dummy __attribute__((unused)) = &(prev); }\
struct eggsfs_info_resp_end* next = NULL
static inline void eggsfs_info_resp_get_finish(struct eggsfs_bincode_get_ctx* ctx, struct eggsfs_info_resp_end* end) {
if (unlikely(ctx->buf != ctx->end)) {
ctx->err = EGGSFS_ERR_MALFORMED_RESPONSE;
}
}
#define eggsfs_info_resp_put_start(ctx, start) struct eggsfs_info_resp_start* start = NULL
static inline void _eggsfs_info_resp_put_num_block_services(struct eggsfs_bincode_put_ctx* ctx, struct eggsfs_info_resp_start** prev, struct eggsfs_info_resp_num_block_services* next, u32 x) {
next = NULL;
BUG_ON(ctx->end - ctx->cursor < 4);
put_unaligned_le32(x, ctx->cursor);
ctx->cursor += 4;
}
#define eggsfs_info_resp_put_num_block_services(ctx, prev, next, x) \
struct eggsfs_info_resp_num_block_services next; \
_eggsfs_info_resp_put_num_block_services(ctx, &(prev), &(next), x)
static inline void _eggsfs_info_resp_put_num_failure_domains(struct eggsfs_bincode_put_ctx* ctx, struct eggsfs_info_resp_num_block_services* prev, struct eggsfs_info_resp_num_failure_domains* next, u32 x) {
next = NULL;
BUG_ON(ctx->end - ctx->cursor < 4);
put_unaligned_le32(x, ctx->cursor);
ctx->cursor += 4;
}
#define eggsfs_info_resp_put_num_failure_domains(ctx, prev, next, x) \
struct eggsfs_info_resp_num_failure_domains next; \
_eggsfs_info_resp_put_num_failure_domains(ctx, &(prev), &(next), x)
static inline void _eggsfs_info_resp_put_capacity(struct eggsfs_bincode_put_ctx* ctx, struct eggsfs_info_resp_num_failure_domains* prev, struct eggsfs_info_resp_capacity* next, u64 x) {
next = NULL;
BUG_ON(ctx->end - ctx->cursor < 8);
put_unaligned_le64(x, ctx->cursor);
ctx->cursor += 8;
}
#define eggsfs_info_resp_put_capacity(ctx, prev, next, x) \
struct eggsfs_info_resp_capacity next; \
_eggsfs_info_resp_put_capacity(ctx, &(prev), &(next), x)
static inline void _eggsfs_info_resp_put_available(struct eggsfs_bincode_put_ctx* ctx, struct eggsfs_info_resp_capacity* prev, struct eggsfs_info_resp_available* next, u64 x) {
next = NULL;
BUG_ON(ctx->end - ctx->cursor < 8);
put_unaligned_le64(x, ctx->cursor);
ctx->cursor += 8;
}
#define eggsfs_info_resp_put_available(ctx, prev, next, x) \
struct eggsfs_info_resp_available next; \
_eggsfs_info_resp_put_available(ctx, &(prev), &(next), x)
static inline void _eggsfs_info_resp_put_blocks(struct eggsfs_bincode_put_ctx* ctx, struct eggsfs_info_resp_available* prev, struct eggsfs_info_resp_blocks* next, u64 x) {
next = NULL;
BUG_ON(ctx->end - ctx->cursor < 8);
put_unaligned_le64(x, ctx->cursor);
ctx->cursor += 8;
}
#define eggsfs_info_resp_put_blocks(ctx, prev, next, x) \
struct eggsfs_info_resp_blocks next; \
_eggsfs_info_resp_put_blocks(ctx, &(prev), &(next), x)
#define eggsfs_info_resp_put_end(ctx, prev, next) \
{ struct eggsfs_info_resp_blocks* __dummy __attribute__((unused)) = &(prev); }\
struct eggsfs_info_resp_end* next __attribute__((unused)) = NULL
#define EGGSFS_FETCH_BLOCK_REQ_SIZE 16
struct eggsfs_fetch_block_req_start;
#define eggsfs_fetch_block_req_get_start(ctx, start) struct eggsfs_fetch_block_req_start* start = NULL

View File

@@ -28,29 +28,15 @@ int eggsfs_read_shuckle_resp_header(char* buf, u32* resp_len, u8* resp_kind) {
return 0;
}
int eggsfs_create_shuckle_socket(const char* shuckle_addr, struct socket** sock) {
int eggsfs_create_shuckle_socket(struct sockaddr_in* addr, struct socket** sock) {
int err;
const char* addr_end;
u16 port;
// parse device, which is the shuckle address in 0.0.0.0:0 form (ipv4, port)
struct sockaddr_in addr;
addr.sin_family = AF_INET;
if (in4_pton(shuckle_addr, -1, (u8*)&addr.sin_addr, ':', &addr_end) != 1) {
err = -EINVAL;
goto out_err;
}
err = kstrtou16(addr_end+1, 10, &port);
if (err < 0) { goto out_err; }
addr.sin_port = htons(port);
eggsfs_debug_print("parsed shuckle addr %pI4:%d", &addr.sin_addr, ntohs(addr.sin_port));
// create socket
err = sock_create_kern(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP, sock);
if (err < 0) { goto out_err; }
// connect
err = kernel_connect(*sock, (struct sockaddr*)&addr, sizeof(addr), 0);
err = kernel_connect(*sock, (struct sockaddr*)addr, sizeof(*addr), 0);
if (err < 0) { goto out_connect; }
eggsfs_debug_print("connected to shuckle");
@@ -62,3 +48,21 @@ out_err:
eggsfs_debug_print("failed err=%d", err);
return err;
}
int eggsfs_parse_shuckle_addr(const char* str, struct sockaddr_in* addr) {
int err;
const char* addr_end;
u16 port;
// parse device, which is the shuckle address in 0.0.0.0:0 form (ipv4, port)
addr->sin_family = AF_INET;
if (in4_pton(str, -1, (u8*)&addr->sin_addr, ':', &addr_end) != 1) {
return -EINVAL;
}
err = kstrtou16(addr_end+1, 10, &port);
if (err < 0) { return err; }
addr->sin_port = htons(port);
eggsfs_debug_print("parsed shuckle addr %pI4:%d", &addr->sin_addr, ntohs(addr->sin_port));
return 0;
}

View File

@@ -10,6 +10,8 @@ void eggsfs_write_shuckle_req_header(char* buf, u32 req_len, u8 req_kind);
#define EGGSFS_SHUCKLE_RESP_HEADER_SIZE (4 + 4 + 1) // protocol + len + kind
int eggsfs_read_shuckle_resp_header(char* buf, u32* resp_len, u8* resp_kind);
int eggsfs_create_shuckle_socket(const char* shuckle_addr, struct socket** sock);
int eggsfs_parse_shuckle_addr(const char* str, struct sockaddr_in* addr);
int eggsfs_create_shuckle_socket(struct sockaddr_in* addr, struct socket** sock);
#endif

View File

@@ -3,6 +3,7 @@
#include <linux/inet.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/statfs.h>
#include "log.h"
#include "inode.h"
@@ -27,11 +28,14 @@ static struct eggsfs_fs_info* eggsfs_init_fs_info(const char* dev_name) {
struct eggsfs_fs_info* info = kmalloc(sizeof(struct eggsfs_fs_info), GFP_KERNEL);
if (!info) { err = -ENOMEM; goto out; }
err = eggsfs_parse_shuckle_addr(dev_name, &info->shuckle_addr);
if (err) { goto out; }
err = eggsfs_init_shard_socket(&info->sock);
if (err) { goto out_info; }
struct socket* shuckle_sock;
err = eggsfs_create_shuckle_socket(dev_name, &shuckle_sock);
err = eggsfs_create_shuckle_socket(&info->shuckle_addr, &shuckle_sock);
if (err < 0) { goto out_info; }
struct kvec iov;
@@ -193,12 +197,96 @@ static void eggsfs_put_super(struct super_block* sb) {
sb->s_fs_info = NULL;
}
#define EGGSFS_SUPER_MAGIC 0x45474753 // EGGS
int eggsfs_statfs(struct dentry* dentry, struct kstatfs* stats) {
struct eggsfs_fs_info* info = (struct eggsfs_fs_info*)dentry->d_sb->s_fs_info;
struct socket* shuckle_sock;
int err = eggsfs_create_shuckle_socket(&info->shuckle_addr, &shuckle_sock);
if (err < 0) { return err; }
struct kvec iov;
struct msghdr msg = {NULL};
static_assert(EGGSFS_INFO_REQ_SIZE == 0);
char shuckle_req[EGGSFS_SHUCKLE_REQ_HEADER_SIZE];
eggsfs_write_shuckle_req_header(shuckle_req, 0, EGGSFS_SHUCKLE_INFO);
int written_so_far;
for (written_so_far = 0; written_so_far < sizeof(shuckle_req);) {
iov.iov_base = shuckle_req + written_so_far;
iov.iov_len = sizeof(shuckle_req) - written_so_far;
int written = kernel_sendmsg(shuckle_sock, &msg, &iov, 1, iov.iov_len);
if (written < 0) { err = written; goto out_sock; }
written_so_far += written;
}
char shuckle_resp_header[EGGSFS_SHUCKLE_RESP_HEADER_SIZE];
int read_so_far;
for (read_so_far = 0; read_so_far < sizeof(shuckle_resp_header);) {
iov.iov_base = shuckle_resp_header + read_so_far;
iov.iov_len = sizeof(shuckle_resp_header) - read_so_far;
int read = kernel_recvmsg(shuckle_sock, &msg, &iov, 1, iov.iov_len, 0);
if (read < 0) { err = read; goto out_sock; }
read_so_far += read;
}
u32 shuckle_resp_len;
u8 shuckle_resp_kind;
err = eggsfs_read_shuckle_resp_header(shuckle_resp_header, &shuckle_resp_len, &shuckle_resp_kind);
if (err < 0) { goto out_sock; }
if (shuckle_resp_len != EGGSFS_INFO_RESP_SIZE) {
eggsfs_debug_print("expected size of %d, got %d", EGGSFS_INFO_RESP_SIZE, shuckle_resp_len);
err = -EINVAL; goto out_sock;
}
char shuckle_resp[EGGSFS_INFO_RESP_SIZE];
for (read_so_far = 0; read_so_far < sizeof(shuckle_resp);) {
iov.iov_base = (char*)&shuckle_resp + read_so_far;
iov.iov_len = sizeof(shuckle_resp) - read_so_far;
int read = kernel_recvmsg(shuckle_sock, &msg, &iov, 1, iov.iov_len, 0);
if (read < 0) { err = read; goto out_sock; }
read_so_far += read;
}
struct eggsfs_bincode_get_ctx ctx = {
.buf = shuckle_resp,
.end = shuckle_resp + sizeof(shuckle_resp),
.err = 0,
};
eggsfs_info_resp_get_start(&ctx, start);
eggsfs_info_resp_get_num_block_services(&ctx, start, num_block_services);
eggsfs_info_resp_get_num_failure_domains(&ctx, num_block_services, num_failure_domains);
eggsfs_info_resp_get_capacity(&ctx, num_failure_domains, capacity);
eggsfs_info_resp_get_available(&ctx, capacity, available);
eggsfs_info_resp_get_blocks(&ctx, available, blocks);
eggsfs_info_resp_get_end(&ctx, blocks, end);
eggsfs_info_resp_get_finish(&ctx, end);
if (ctx.err != 0) { err = eggsfs_error_to_linux(ctx.err); goto out_sock; }
stats->f_type = EGGSFS_SUPER_MAGIC;
stats->f_bsize = PAGE_SIZE;
stats->f_frsize = PAGE_SIZE;
stats->f_blocks = capacity.x / PAGE_SIZE;
stats->f_bfree = available.x / PAGE_SIZE;
stats->f_bavail = available.x / PAGE_SIZE;
stats->f_files = -1;
stats->f_ffree = -1;
stats->f_namelen = EGGSFS_MAX_FILENAME;
sock_release(shuckle_sock);
return 0;
out_sock:
sock_release(shuckle_sock);
return err;
}
static const struct super_operations eggsfs_super_ops = {
.alloc_inode = eggsfs_inode_alloc,
.evict_inode = eggsfs_inode_evict,
.free_inode = eggsfs_inode_free,
.put_super = eggsfs_put_super,
.statfs = eggsfs_statfs,
};
static struct dentry* eggsfs_mount(struct file_system_type* fs_type, int flags, const char* dev_name, void* data) {

View File

@@ -6,6 +6,8 @@
#include "net.h"
struct eggsfs_fs_info {
struct sockaddr_in shuckle_addr;
struct eggsfs_shard_socket sock;
// NB: ->msg_iter is used by `kernel_sendmsg`, so when you want to use the `struct msghhdr`