func (s *BlockVolume) RestoreSnapshot(name string) (err error) {
	if s.volume.Type != VolumeType {
		panic("Wrong type")
	}
	if err = s.mds.Lock(s.srv.Lease()); err != nil {
		return err
	}
	defer s.mds.Unlock()
	snaps, err := s.mds.GetSnapshots()
	if err != nil {
		return err
	}
	var found Snapshot
	for _, x := range snaps {
		if x.Name == name {
			found = x
			break
		}
	}
	if found.Name != name {
		return torus.ErrNotExist
	}
	ref := torus.INodeRefFromBytes(found.INodeRef)
	return s.mds.SyncINode(ref)
}
func (b *blockEtcd) GetINode() (torus.INodeRef, error) {
	resp, err := b.Etcd.Client.Get(b.getContext(), etcd.MkKey("volumemeta", etcd.Uint64ToHex(uint64(b.vid)), "blockinode"))
	if err != nil {
		return torus.NewINodeRef(0, 0), err
	}
	if len(resp.Kvs) != 1 {
		return torus.NewINodeRef(0, 0), errors.New("unexpected metadata for volume")
	}
	return torus.INodeRefFromBytes(resp.Kvs[0].Value), nil
}
func (b *blockvolGC) PrepVolume(vol *models.Volume) error {
	if vol.Type != VolumeType {
		return nil
	}
	mds, err := createBlockMetadata(b.srv.MDS, vol.Name, torus.VolumeID(vol.Id))
	if err != nil {
		return err
	}
	curRef, err := mds.GetINode()
	if err != nil {
		return err
	}
	b.highwaters[curRef.Volume()] = 0
	if curRef.INode <= 1 {
		return nil
	}

	snaps, err := mds.GetSnapshots()
	if err != nil {
		return err
	}

	curINodes := make([]torus.INodeRef, 0, len(snaps)+1)
	curINodes = append(curINodes, curRef)
	for _, x := range snaps {
		curINodes = append(curINodes, torus.INodeRefFromBytes(x.INodeRef))
	}

	for _, x := range curINodes {
		inode, err := b.inodes.GetINode(b.getContext(), x)
		if err != nil {
			return err
		}
		set, err := blockset.UnmarshalFromProto(inode.Blocks, nil)
		if err != nil {
			return err
		}
		refs := set.GetAllBlockRefs()
		for _, ref := range refs {
			if ref.IsZero() {
				continue
			}
			if ref.INode > b.highwaters[ref.Volume()] {
				b.highwaters[ref.Volume()] = ref.INode
			}
			b.set[ref] = true
		}
	}
	b.curINodes = append(b.curINodes, curINodes...)
	return nil
}
func (s *BlockVolume) OpenSnapshot(name string) (*BlockFile, error) {
	if s.volume.Type != VolumeType {
		panic("wrong type")
	}
	snaps, err := s.mds.GetSnapshots()
	if err != nil {
		return nil, err
	}
	var found Snapshot
	for _, x := range snaps {
		if x.Name == name {
			found = x
			break
		}
	}
	if found.Name != name {
		return nil, torus.ErrNotExist
	}
	ref := torus.INodeRefFromBytes(found.INodeRef)
	inode, err := s.getOrCreateBlockINode(ref)
	if err != nil {
		return nil, err
	}
	bs, err := blockset.UnmarshalFromProto(inode.GetBlocks(), s.srv.Blocks)
	if err != nil {
		return nil, err
	}
	f, err := s.srv.CreateFile(s.volume, inode, bs)
	if err != nil {
		return nil, err
	}
	f.ReadOnly = true
	return &BlockFile{
		File: f,
		vol:  s,
	}, nil
}