code: func (s *Server) ReadV3(p *Packet) (interface{}, error) {
  	req := new(RequestReadV3)
  	err := UnmarshalBinary(p.Payload, req)
  	if err != nil {
  		return nil, err
  	}
  
  	session, err := s.getSession(p)
  	if err != nil {
  		return nil, err
  	}
  
  	session.mu.Lock()
  	file, ok := session.files[req.Handle]
  	session.mu.Unlock()
  
  	if !ok {
  		return nil, &Status{Code: StatusInvalidHandle}
  	}
  
  	buf := make([]byte, req.RequiredSize)
  
  	// Use ReadFull as Read() of an archive io.Pipe may return much smaller chunks,
  	// such as when we've read a tar header.
  	n, err := io.ReadFull(file, buf)
  	if err != nil && n == 0 {
  		if err != io.EOF {
  			return nil, err
  		}
  	}
  
  	res := &ReplyReadV3{
  		ActualSize: uint32(n),
  		Payload:    buf[:n],
  	}
  
  	return res, nil
  }
docs: // ReadV3 handles OpReadV3 requests