mirror of
https://github.com/pgsty/minio.git
synced 2026-07-21 13:10:22 +03:00
Migrate this project to minio micro services code
This commit is contained in:
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Minio Client (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// NOTE - Rename() not guaranteed to be atomic on all filesystems which are not fully POSIX compatible
|
||||
|
||||
// Package atomic provides atomic file write semantics by leveraging Rename's() atomicity.
|
||||
package atomic
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// File container provided for atomic file writes
|
||||
type File struct {
|
||||
*os.File
|
||||
file string
|
||||
}
|
||||
|
||||
// Close the file replacing, returns an error if any
|
||||
func (f *File) Close() error {
|
||||
// close the embedded fd
|
||||
if err := f.File.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
// atomic rename to final destination
|
||||
if err := os.Rename(f.Name(), f.file); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CloseAndPurge removes the temp file, closes the transaction and returns an error if any
|
||||
func (f *File) CloseAndPurge() error {
|
||||
// close the embedded fd
|
||||
if err := f.File.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.Remove(f.Name()); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FileCreate creates a new file at filePath for atomic writes, it also creates parent directories if they don't exist
|
||||
func FileCreate(filePath string) (*File, error) {
|
||||
// if parent directories do not exist, ioutil.TempFile doesn't create them
|
||||
// handle such a case with os.MkdirAll()
|
||||
if err := os.MkdirAll(filepath.Dir(filePath), 0700); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f, err := ioutil.TempFile(filepath.Dir(filePath), filepath.Base(filePath))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := os.Chmod(f.Name(), 0600); err != nil {
|
||||
if err := os.Remove(f.Name()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &File{File: f, file: filePath}, nil
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Minio Client (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package atomic
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
. "gopkg.in/check.v1"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) { TestingT(t) }
|
||||
|
||||
type MySuite struct {
|
||||
root string
|
||||
}
|
||||
|
||||
var _ = Suite(&MySuite{})
|
||||
|
||||
func (s *MySuite) SetUpSuite(c *C) {
|
||||
root, err := ioutil.TempDir("/tmp", "atomic-")
|
||||
c.Assert(err, IsNil)
|
||||
s.root = root
|
||||
}
|
||||
|
||||
func (s *MySuite) TearDownSuite(c *C) {
|
||||
os.RemoveAll(s.root)
|
||||
}
|
||||
|
||||
func (s *MySuite) TestAtomic(c *C) {
|
||||
f, err := FileCreate(filepath.Join(s.root, "testfile"))
|
||||
c.Assert(err, IsNil)
|
||||
_, err = os.Stat(filepath.Join(s.root, "testfile"))
|
||||
c.Assert(err, Not(IsNil))
|
||||
err = f.Close()
|
||||
c.Assert(err, IsNil)
|
||||
_, err = os.Stat(filepath.Join(s.root, "testfile"))
|
||||
c.Assert(err, IsNil)
|
||||
}
|
||||
|
||||
func (s *MySuite) TestAtomicPurge(c *C) {
|
||||
f, err := FileCreate(filepath.Join(s.root, "purgefile"))
|
||||
c.Assert(err, IsNil)
|
||||
_, err = os.Stat(filepath.Join(s.root, "purgefile"))
|
||||
c.Assert(err, Not(IsNil))
|
||||
err = f.CloseAndPurge()
|
||||
c.Assert(err, IsNil)
|
||||
err = f.Close()
|
||||
c.Assert(err, Not(IsNil))
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cpu
|
||||
|
||||
// cpuid, cpuidex
|
||||
func cpuid(op uint32) (eax, ebx, ecx, edx uint32)
|
||||
func cpuidex(op, op2 uint32) (eax, ebx, ecx, edx uint32)
|
||||
|
||||
// HasSSE41 - CPUID instruction verification wrapper for SSE41 extensions
|
||||
func HasSSE41() bool {
|
||||
_, _, c, _ := cpuid(1)
|
||||
return ((c & (1 << 19)) != 0)
|
||||
}
|
||||
|
||||
// HasAVX - CPUID instruction verification wrapper for AVX extensions
|
||||
func HasAVX() bool {
|
||||
_, _, c, _ := cpuid(1)
|
||||
return ((c & (1 << 28)) != 0)
|
||||
}
|
||||
|
||||
// HasAVX2 - CPUID instruction verification wrapper for AVX2 extensions
|
||||
func HasAVX2() bool {
|
||||
_, b, _, _ := cpuidex(7, 0)
|
||||
return ((b & (1 << 5)) != 0)
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file.
|
||||
//
|
||||
// See https://github.com/klauspost/cpuid/blob/master/LICENSE
|
||||
//
|
||||
// Using this inside Minio with modifications
|
||||
//
|
||||
|
||||
// func cpuid(op uint32) (eax, ebx, ecx, edx uint32)
|
||||
TEXT ·cpuid(SB),7,$0
|
||||
MOVL op+0(FP),AX
|
||||
CPUID
|
||||
MOVL AX,eax+8(FP)
|
||||
MOVL BX,ebx+12(FP)
|
||||
MOVL CX,ecx+16(FP)
|
||||
MOVL DX,edx+20(FP)
|
||||
RET
|
||||
|
||||
// func cpuidex(op, op2 uint32) (eax, ebx, ecx, edx uint32)
|
||||
TEXT ·cpuidex(SB),7,$0
|
||||
MOVL op+0(FP),AX
|
||||
MOVL op2+4(FP),CX
|
||||
CPUID
|
||||
MOVL AX,eax+8(FP)
|
||||
MOVL BX,ebx+12(FP)
|
||||
MOVL CX,ecx+16(FP)
|
||||
MOVL DX,edx+20(FP)
|
||||
RET
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cpu_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/minio/minio/pkg/cpu"
|
||||
. "gopkg.in/check.v1"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) { TestingT(t) }
|
||||
|
||||
type MySuite struct{}
|
||||
|
||||
var _ = Suite(&MySuite{})
|
||||
|
||||
func hasCPUFeatureFromOS(feature string) (bool, error) {
|
||||
if runtime.GOOS == "linux" {
|
||||
command := exec.Command("/bin/cat", "/proc/cpuinfo")
|
||||
output, err := command.Output()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if strings.Contains(string(output), feature) {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
return false, errors.New("Not Implemented on this platform")
|
||||
}
|
||||
|
||||
func (s *MySuite) TestHasSSE41(c *C) {
|
||||
if runtime.GOOS == "linux" {
|
||||
var flag = cpu.HasSSE41()
|
||||
osCheck, err := hasCPUFeatureFromOS("sse4_1")
|
||||
c.Assert(err, IsNil)
|
||||
c.Check(flag, Equals, osCheck)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *MySuite) TestHasAVX(c *C) {
|
||||
if runtime.GOOS == "linux" {
|
||||
var flag = cpu.HasAVX()
|
||||
osFlag, err := hasCPUFeatureFromOS("avx")
|
||||
c.Assert(err, IsNil)
|
||||
c.Check(osFlag, Equals, flag)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *MySuite) TestHasAVX2(c *C) {
|
||||
if runtime.GOOS == "linux" {
|
||||
var flag = cpu.HasAVX2()
|
||||
osFlag, err := hasCPUFeatureFromOS("avx2")
|
||||
c.Assert(err, IsNil)
|
||||
c.Check(osFlag, Equals, flag)
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
// Package cpu provides wrapper around assembly functions for checking processor
|
||||
// instruction capabilities for SSE4.1, AVX, AVX2 support
|
||||
//
|
||||
// Example
|
||||
//
|
||||
// ``cpu.HasSSE41()`` returns true for SSE4.1 instruction support, false otherwise
|
||||
//
|
||||
// ``cpu.HasAVX()`` returns true for AVX instruction support, false otherwise
|
||||
//
|
||||
// ``cpu.HasAVX2()`` returns true for AVX2 instruction support, false otherwise
|
||||
package cpu
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2014 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package md5
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Sum - low memory footprint io.Reader based md5sum helper
|
||||
func Sum(reader io.Reader) ([]byte, error) {
|
||||
hash := md5.New()
|
||||
var err error
|
||||
var length int
|
||||
for err == nil {
|
||||
byteBuffer := make([]byte, 1024*1024)
|
||||
length, err = reader.Read(byteBuffer)
|
||||
// While hash.Write() wouldn't mind a Nil byteBuffer
|
||||
// It is necessary for us to verify this and break
|
||||
if length == 0 {
|
||||
break
|
||||
}
|
||||
byteBuffer = byteBuffer[0:length]
|
||||
hash.Write(byteBuffer)
|
||||
}
|
||||
if err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
return hash.Sum(nil), nil
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package md5_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/minio/minio/pkg/crypto/md5"
|
||||
. "gopkg.in/check.v1"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) { TestingT(t) }
|
||||
|
||||
type MySuite struct{}
|
||||
|
||||
var _ = Suite(&MySuite{})
|
||||
|
||||
func (s *MySuite) TestMd5sum(c *C) {
|
||||
testString := []byte("Test string")
|
||||
expectedHash, _ := hex.DecodeString("0fd3dbec9730101bff92acc820befc34")
|
||||
hash, err := md5.Sum(bytes.NewBuffer(testString))
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(bytes.Equal(expectedHash, hash), Equals, true)
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
*.syso
|
||||
@@ -1,202 +0,0 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -1,167 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file of
|
||||
// Golang project:
|
||||
// https://github.com/golang/go/blob/master/LICENSE
|
||||
|
||||
// Using this part of Minio codebase under the license
|
||||
// Apache License Version 2.0 with modifications
|
||||
|
||||
// Package sha1 implements the SHA1 hash algorithm as defined in RFC 3174.
|
||||
package sha1
|
||||
|
||||
import (
|
||||
"hash"
|
||||
"io"
|
||||
|
||||
"github.com/minio/minio/pkg/cpu"
|
||||
)
|
||||
|
||||
// The size of a SHA1 checksum in bytes.
|
||||
const Size = 20
|
||||
|
||||
// The blocksize of SHA1 in bytes.
|
||||
const BlockSize = 64
|
||||
|
||||
const (
|
||||
chunk = 64
|
||||
init0 = 0x67452301
|
||||
init1 = 0xEFCDAB89
|
||||
init2 = 0x98BADCFE
|
||||
init3 = 0x10325476
|
||||
init4 = 0xC3D2E1F0
|
||||
)
|
||||
|
||||
// digest represents the partial evaluation of a checksum.
|
||||
type digest struct {
|
||||
h [5]uint32
|
||||
x [chunk]byte
|
||||
nx int
|
||||
len uint64
|
||||
}
|
||||
|
||||
// Reset digest
|
||||
func (d *digest) Reset() {
|
||||
d.h[0] = init0
|
||||
d.h[1] = init1
|
||||
d.h[2] = init2
|
||||
d.h[3] = init3
|
||||
d.h[4] = init4
|
||||
d.nx = 0
|
||||
d.len = 0
|
||||
}
|
||||
|
||||
// New returns a new hash.Hash computing the SHA1 checksum.
|
||||
func New() hash.Hash {
|
||||
d := new(digest)
|
||||
d.Reset()
|
||||
return d
|
||||
}
|
||||
|
||||
func block(dig *digest, p []byte) {
|
||||
switch true {
|
||||
case cpu.HasSSE41() == true:
|
||||
blockSSE3(dig, p)
|
||||
default:
|
||||
blockGeneric(dig, p)
|
||||
}
|
||||
}
|
||||
|
||||
// Return output size
|
||||
func (d *digest) Size() int { return Size }
|
||||
|
||||
// Return checksum blocksize
|
||||
func (d *digest) BlockSize() int { return BlockSize }
|
||||
|
||||
// Write to digest
|
||||
func (d *digest) Write(p []byte) (nn int, err error) {
|
||||
nn = len(p)
|
||||
d.len += uint64(nn)
|
||||
if d.nx > 0 {
|
||||
n := copy(d.x[d.nx:], p)
|
||||
d.nx += n
|
||||
if d.nx == chunk {
|
||||
block(d, d.x[:])
|
||||
d.nx = 0
|
||||
}
|
||||
p = p[n:]
|
||||
}
|
||||
if len(p) >= chunk {
|
||||
n := len(p) &^ (chunk - 1)
|
||||
block(d, p[:n])
|
||||
p = p[n:]
|
||||
}
|
||||
if len(p) > 0 {
|
||||
d.nx = copy(d.x[:], p)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Return checksum bytes
|
||||
func (d *digest) Sum(in []byte) []byte {
|
||||
// Make a copy of d0 so that caller can keep writing and summing.
|
||||
d0 := *d
|
||||
hash := d0.checkSum()
|
||||
return append(in, hash[:]...)
|
||||
}
|
||||
|
||||
// Intermediate checksum function
|
||||
func (d *digest) checkSum() [Size]byte {
|
||||
len := d.len
|
||||
// Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
|
||||
var tmp [64]byte
|
||||
tmp[0] = 0x80
|
||||
if len%64 < 56 {
|
||||
d.Write(tmp[0 : 56-len%64])
|
||||
} else {
|
||||
d.Write(tmp[0 : 64+56-len%64])
|
||||
}
|
||||
|
||||
// Length in bits.
|
||||
len <<= 3
|
||||
for i := uint(0); i < 8; i++ {
|
||||
tmp[i] = byte(len >> (56 - 8*i))
|
||||
}
|
||||
d.Write(tmp[0:8])
|
||||
|
||||
if d.nx != 0 {
|
||||
panic("d.nx != 0")
|
||||
}
|
||||
|
||||
var digest [Size]byte
|
||||
for i, s := range d.h {
|
||||
digest[i*4] = byte(s >> 24)
|
||||
digest[i*4+1] = byte(s >> 16)
|
||||
digest[i*4+2] = byte(s >> 8)
|
||||
digest[i*4+3] = byte(s)
|
||||
}
|
||||
|
||||
return digest
|
||||
}
|
||||
|
||||
/// Convenience functions
|
||||
|
||||
// Sum1 - single caller sha1 helper
|
||||
func Sum1(data []byte) [Size]byte {
|
||||
var d digest
|
||||
d.Reset()
|
||||
d.Write(data)
|
||||
return d.checkSum()
|
||||
}
|
||||
|
||||
// Sum - io.Reader based streaming sha1 helper
|
||||
func Sum(reader io.Reader) ([]byte, error) {
|
||||
h := New()
|
||||
var err error
|
||||
for err == nil {
|
||||
length := 0
|
||||
byteBuffer := make([]byte, 1024*1024)
|
||||
length, err = reader.Read(byteBuffer)
|
||||
byteBuffer = byteBuffer[0:length]
|
||||
h.Write(byteBuffer)
|
||||
}
|
||||
if err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
return h.Sum(nil), nil
|
||||
}
|
||||
@@ -1,967 +0,0 @@
|
||||
/*
|
||||
* Implement fast SHA-1 with AVX2 instructions. (x86_64)
|
||||
*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2014 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* Contact Information:
|
||||
* Ilya Albrekht <ilya.albrekht@intel.com>
|
||||
* Maxim Locktyukhin <maxim.locktyukhin@intel.com>
|
||||
* Ronen Zohar <ronen.zohar@intel.com>
|
||||
* Chandramouli Narayanan <mouli@linux.intel.com>
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2014 Intel Corporation.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* SHA-1 implementation with Intel(R) AVX2 instruction set extensions.
|
||||
*
|
||||
*This implementation is based on the previous SSSE3 release:
|
||||
* https://software.intel.com/en-us/articles/improving-the-performance-of-the-secure-hash-algorithm-1
|
||||
*
|
||||
*Updates 20-byte SHA-1 record in 'hash' for even number of
|
||||
*'num_blocks' consecutive 64-byte blocks
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Using this part of Minio codebase under the license
|
||||
* Apache License Version 2.0 with modifications
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAS_AVX2
|
||||
#ifndef ENTRY
|
||||
#define ENTRY(name) \
|
||||
.globl name ; \
|
||||
.align 4,0x90 ; \
|
||||
name:
|
||||
#endif
|
||||
|
||||
#ifndef END
|
||||
#define END(name) \
|
||||
.size name, .-name
|
||||
#endif
|
||||
|
||||
#ifndef ENDPROC
|
||||
#define ENDPROC(name) \
|
||||
.type name, @function ; \
|
||||
END(name)
|
||||
#endif
|
||||
|
||||
#define NUM_INVALID 100
|
||||
|
||||
#define TYPE_R32 0
|
||||
#define TYPE_R64 1
|
||||
#define TYPE_XMM 2
|
||||
#define TYPE_INVALID 100
|
||||
|
||||
.macro R32_NUM opd r32
|
||||
\opd = NUM_INVALID
|
||||
.ifc \r32,%eax
|
||||
\opd = 0
|
||||
.endif
|
||||
.ifc \r32,%ecx
|
||||
\opd = 1
|
||||
.endif
|
||||
.ifc \r32,%edx
|
||||
\opd = 2
|
||||
.endif
|
||||
.ifc \r32,%ebx
|
||||
\opd = 3
|
||||
.endif
|
||||
.ifc \r32,%esp
|
||||
\opd = 4
|
||||
.endif
|
||||
.ifc \r32,%ebp
|
||||
\opd = 5
|
||||
.endif
|
||||
.ifc \r32,%esi
|
||||
\opd = 6
|
||||
.endif
|
||||
.ifc \r32,%edi
|
||||
\opd = 7
|
||||
.endif
|
||||
#ifdef X86_64
|
||||
.ifc \r32,%r8d
|
||||
\opd = 8
|
||||
.endif
|
||||
.ifc \r32,%r9d
|
||||
\opd = 9
|
||||
.endif
|
||||
.ifc \r32,%r10d
|
||||
\opd = 10
|
||||
.endif
|
||||
.ifc \r32,%r11d
|
||||
\opd = 11
|
||||
.endif
|
||||
.ifc \r32,%r12d
|
||||
\opd = 12
|
||||
.endif
|
||||
.ifc \r32,%r13d
|
||||
\opd = 13
|
||||
.endif
|
||||
.ifc \r32,%r14d
|
||||
\opd = 14
|
||||
.endif
|
||||
.ifc \r32,%r15d
|
||||
\opd = 15
|
||||
.endif
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro R64_NUM opd r64
|
||||
\opd = NUM_INVALID
|
||||
#ifdef X86_64
|
||||
.ifc \r64,%rax
|
||||
\opd = 0
|
||||
.endif
|
||||
.ifc \r64,%rcx
|
||||
\opd = 1
|
||||
.endif
|
||||
.ifc \r64,%rdx
|
||||
\opd = 2
|
||||
.endif
|
||||
.ifc \r64,%rbx
|
||||
\opd = 3
|
||||
.endif
|
||||
.ifc \r64,%rsp
|
||||
\opd = 4
|
||||
.endif
|
||||
.ifc \r64,%rbp
|
||||
\opd = 5
|
||||
.endif
|
||||
.ifc \r64,%rsi
|
||||
\opd = 6
|
||||
.endif
|
||||
.ifc \r64,%rdi
|
||||
\opd = 7
|
||||
.endif
|
||||
.ifc \r64,%r8
|
||||
\opd = 8
|
||||
.endif
|
||||
.ifc \r64,%r9
|
||||
\opd = 9
|
||||
.endif
|
||||
.ifc \r64,%r10
|
||||
\opd = 10
|
||||
.endif
|
||||
.ifc \r64,%r11
|
||||
\opd = 11
|
||||
.endif
|
||||
.ifc \r64,%r12
|
||||
\opd = 12
|
||||
.endif
|
||||
.ifc \r64,%r13
|
||||
\opd = 13
|
||||
.endif
|
||||
.ifc \r64,%r14
|
||||
\opd = 14
|
||||
.endif
|
||||
.ifc \r64,%r15
|
||||
\opd = 15
|
||||
.endif
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro XMM_NUM opd xmm
|
||||
\opd = NUM_INVALID
|
||||
.ifc \xmm,%xmm0
|
||||
\opd = 0
|
||||
.endif
|
||||
.ifc \xmm,%xmm1
|
||||
\opd = 1
|
||||
.endif
|
||||
.ifc \xmm,%xmm2
|
||||
\opd = 2
|
||||
.endif
|
||||
.ifc \xmm,%xmm3
|
||||
\opd = 3
|
||||
.endif
|
||||
.ifc \xmm,%xmm4
|
||||
\opd = 4
|
||||
.endif
|
||||
.ifc \xmm,%xmm5
|
||||
\opd = 5
|
||||
.endif
|
||||
.ifc \xmm,%xmm6
|
||||
\opd = 6
|
||||
.endif
|
||||
.ifc \xmm,%xmm7
|
||||
\opd = 7
|
||||
.endif
|
||||
.ifc \xmm,%xmm8
|
||||
\opd = 8
|
||||
.endif
|
||||
.ifc \xmm,%xmm9
|
||||
\opd = 9
|
||||
.endif
|
||||
.ifc \xmm,%xmm10
|
||||
\opd = 10
|
||||
.endif
|
||||
.ifc \xmm,%xmm11
|
||||
\opd = 11
|
||||
.endif
|
||||
.ifc \xmm,%xmm12
|
||||
\opd = 12
|
||||
.endif
|
||||
.ifc \xmm,%xmm13
|
||||
\opd = 13
|
||||
.endif
|
||||
.ifc \xmm,%xmm14
|
||||
\opd = 14
|
||||
.endif
|
||||
.ifc \xmm,%xmm15
|
||||
\opd = 15
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro TYPE type reg
|
||||
R32_NUM reg_type_r32 \reg
|
||||
R64_NUM reg_type_r64 \reg
|
||||
XMM_NUM reg_type_xmm \reg
|
||||
.if reg_type_r64 <> NUM_INVALID
|
||||
\type = TYPE_R64
|
||||
.elseif reg_type_r32 <> NUM_INVALID
|
||||
\type = TYPE_R32
|
||||
.elseif reg_type_xmm <> NUM_INVALID
|
||||
\type = TYPE_XMM
|
||||
.else
|
||||
\type = TYPE_INVALID
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro PFX_OPD_SIZE
|
||||
.byte 0x66
|
||||
.endm
|
||||
|
||||
.macro PFX_REX opd1 opd2 W=0
|
||||
.if ((\opd1 | \opd2) & 8) || \W
|
||||
.byte 0x40 | ((\opd1 & 8) >> 3) | ((\opd2 & 8) >> 1) | (\W << 3)
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro MODRM mod opd1 opd2
|
||||
.byte \mod | (\opd1 & 7) | ((\opd2 & 7) << 3)
|
||||
.endm
|
||||
|
||||
.macro PSHUFB_XMM xmm1 xmm2
|
||||
XMM_NUM pshufb_opd1 \xmm1
|
||||
XMM_NUM pshufb_opd2 \xmm2
|
||||
PFX_OPD_SIZE
|
||||
PFX_REX pshufb_opd1 pshufb_opd2
|
||||
.byte 0x0f, 0x38, 0x00
|
||||
MODRM 0xc0 pshufb_opd1 pshufb_opd2
|
||||
.endm
|
||||
|
||||
.macro PCLMULQDQ imm8 xmm1 xmm2
|
||||
XMM_NUM clmul_opd1 \xmm1
|
||||
XMM_NUM clmul_opd2 \xmm2
|
||||
PFX_OPD_SIZE
|
||||
PFX_REX clmul_opd1 clmul_opd2
|
||||
.byte 0x0f, 0x3a, 0x44
|
||||
MODRM 0xc0 clmul_opd1 clmul_opd2
|
||||
.byte \imm8
|
||||
.endm
|
||||
|
||||
.macro PEXTRD imm8 xmm gpr
|
||||
R32_NUM extrd_opd1 \gpr
|
||||
XMM_NUM extrd_opd2 \xmm
|
||||
PFX_OPD_SIZE
|
||||
PFX_REX extrd_opd1 extrd_opd2
|
||||
.byte 0x0f, 0x3a, 0x16
|
||||
MODRM 0xc0 extrd_opd1 extrd_opd2
|
||||
.byte \imm8
|
||||
.endm
|
||||
|
||||
.macro MOVQ_R64_XMM opd1 opd2
|
||||
TYPE movq_r64_xmm_opd1_type \opd1
|
||||
.if movq_r64_xmm_opd1_type == TYPE_XMM
|
||||
XMM_NUM movq_r64_xmm_opd1 \opd1
|
||||
R64_NUM movq_r64_xmm_opd2 \opd2
|
||||
.else
|
||||
R64_NUM movq_r64_xmm_opd1 \opd1
|
||||
XMM_NUM movq_r64_xmm_opd2 \opd2
|
||||
.endif
|
||||
PFX_OPD_SIZE
|
||||
PFX_REX movq_r64_xmm_opd1 movq_r64_xmm_opd2 1
|
||||
.if movq_r64_xmm_opd1_type == TYPE_XMM
|
||||
.byte 0x0f, 0x7e
|
||||
.else
|
||||
.byte 0x0f, 0x6e
|
||||
.endif
|
||||
MODRM 0xc0 movq_r64_xmm_opd1 movq_r64_xmm_opd2
|
||||
.endm
|
||||
|
||||
#define CTX %rdi /* arg1 */
|
||||
#define BUF %rsi /* arg2 */
|
||||
#define CNT %rdx /* arg3 */
|
||||
|
||||
#define REG_A %ecx
|
||||
#define REG_B %esi
|
||||
#define REG_C %edi
|
||||
#define REG_D %eax
|
||||
#define REG_E %edx
|
||||
#define REG_TB %ebx
|
||||
#define REG_TA %r12d
|
||||
#define REG_RA %rcx
|
||||
#define REG_RB %rsi
|
||||
#define REG_RC %rdi
|
||||
#define REG_RD %rax
|
||||
#define REG_RE %rdx
|
||||
#define REG_RTA %r12
|
||||
#define REG_RTB %rbx
|
||||
#define REG_T1 %ebp
|
||||
#define xmm_mov vmovups
|
||||
#define avx2_zeroupper vzeroupper
|
||||
#define RND_F1 1
|
||||
#define RND_F2 2
|
||||
#define RND_F3 3
|
||||
|
||||
.macro REGALLOC
|
||||
.set A, REG_A
|
||||
.set B, REG_B
|
||||
.set C, REG_C
|
||||
.set D, REG_D
|
||||
.set E, REG_E
|
||||
.set TB, REG_TB
|
||||
.set TA, REG_TA
|
||||
|
||||
.set RA, REG_RA
|
||||
.set RB, REG_RB
|
||||
.set RC, REG_RC
|
||||
.set RD, REG_RD
|
||||
.set RE, REG_RE
|
||||
|
||||
.set RTA, REG_RTA
|
||||
.set RTB, REG_RTB
|
||||
|
||||
.set T1, REG_T1
|
||||
.endm
|
||||
|
||||
#define K_BASE %r8
|
||||
#define HASH_PTR %r9
|
||||
#define BUFFER_PTR %r10
|
||||
#define BUFFER_PTR2 %r13
|
||||
#define BUFFER_END %r11
|
||||
|
||||
#define PRECALC_BUF %r14
|
||||
#define WK_BUF %r15
|
||||
|
||||
#define W_TMP %xmm0
|
||||
#define WY_TMP %ymm0
|
||||
#define WY_TMP2 %ymm9
|
||||
|
||||
# AVX2 variables
|
||||
#define WY0 %ymm3
|
||||
#define WY4 %ymm5
|
||||
#define WY08 %ymm7
|
||||
#define WY12 %ymm8
|
||||
#define WY16 %ymm12
|
||||
#define WY20 %ymm13
|
||||
#define WY24 %ymm14
|
||||
#define WY28 %ymm15
|
||||
|
||||
#define YMM_SHUFB_BSWAP %ymm10
|
||||
|
||||
/*
|
||||
* Keep 2 iterations precalculated at a time:
|
||||
* - 80 DWORDs per iteration * 2
|
||||
*/
|
||||
#define W_SIZE (80*2*2 +16)
|
||||
|
||||
#define WK(t) ((((t) % 80) / 4)*32 + ( (t) % 4)*4 + ((t)/80)*16 )(WK_BUF)
|
||||
#define PRECALC_WK(t) ((t)*2*2)(PRECALC_BUF)
|
||||
|
||||
|
||||
.macro UPDATE_HASH hash, val
|
||||
add \hash, \val
|
||||
mov \val, \hash
|
||||
.endm
|
||||
|
||||
.macro PRECALC_RESET_WY
|
||||
.set WY_00, WY0
|
||||
.set WY_04, WY4
|
||||
.set WY_08, WY08
|
||||
.set WY_12, WY12
|
||||
.set WY_16, WY16
|
||||
.set WY_20, WY20
|
||||
.set WY_24, WY24
|
||||
.set WY_28, WY28
|
||||
.set WY_32, WY_00
|
||||
.endm
|
||||
|
||||
.macro PRECALC_ROTATE_WY
|
||||
/* Rotate macros */
|
||||
.set WY_32, WY_28
|
||||
.set WY_28, WY_24
|
||||
.set WY_24, WY_20
|
||||
.set WY_20, WY_16
|
||||
.set WY_16, WY_12
|
||||
.set WY_12, WY_08
|
||||
.set WY_08, WY_04
|
||||
.set WY_04, WY_00
|
||||
.set WY_00, WY_32
|
||||
|
||||
/* Define register aliases */
|
||||
.set WY, WY_00
|
||||
.set WY_minus_04, WY_04
|
||||
.set WY_minus_08, WY_08
|
||||
.set WY_minus_12, WY_12
|
||||
.set WY_minus_16, WY_16
|
||||
.set WY_minus_20, WY_20
|
||||
.set WY_minus_24, WY_24
|
||||
.set WY_minus_28, WY_28
|
||||
.set WY_minus_32, WY
|
||||
.endm
|
||||
|
||||
.macro PRECALC_00_15
|
||||
.if (i == 0) # Initialize and rotate registers
|
||||
PRECALC_RESET_WY
|
||||
PRECALC_ROTATE_WY
|
||||
.endif
|
||||
|
||||
/* message scheduling pre-compute for rounds 0-15 */
|
||||
.if ((i & 7) == 0)
|
||||
/*
|
||||
* blended AVX2 and ALU instruction scheduling
|
||||
* 1 vector iteration per 8 rounds
|
||||
*/
|
||||
vmovdqu ((i * 2) + PRECALC_OFFSET)(BUFFER_PTR), W_TMP
|
||||
.elseif ((i & 7) == 1)
|
||||
vinsertf128 $1, (((i-1) * 2)+PRECALC_OFFSET)(BUFFER_PTR2),\
|
||||
WY_TMP, WY_TMP
|
||||
.elseif ((i & 7) == 2)
|
||||
vpshufb YMM_SHUFB_BSWAP, WY_TMP, WY
|
||||
.elseif ((i & 7) == 4)
|
||||
vpaddd K_XMM(K_BASE), WY, WY_TMP
|
||||
.elseif ((i & 7) == 7)
|
||||
vmovdqu WY_TMP, PRECALC_WK(i&~7)
|
||||
|
||||
PRECALC_ROTATE_WY
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro PRECALC_16_31
|
||||
/*
|
||||
* message scheduling pre-compute for rounds 16-31
|
||||
* calculating last 32 w[i] values in 8 XMM registers
|
||||
* pre-calculate K+w[i] values and store to mem
|
||||
* for later load by ALU add instruction
|
||||
*
|
||||
* "brute force" vectorization for rounds 16-31 only
|
||||
* due to w[i]->w[i-3] dependency
|
||||
*/
|
||||
.if ((i & 7) == 0)
|
||||
/*
|
||||
* blended AVX2 and ALU instruction scheduling
|
||||
* 1 vector iteration per 8 rounds
|
||||
*/
|
||||
/* w[i-14] */
|
||||
vpalignr $8, WY_minus_16, WY_minus_12, WY
|
||||
vpsrldq $4, WY_minus_04, WY_TMP /* w[i-3] */
|
||||
.elseif ((i & 7) == 1)
|
||||
vpxor WY_minus_08, WY, WY
|
||||
vpxor WY_minus_16, WY_TMP, WY_TMP
|
||||
.elseif ((i & 7) == 2)
|
||||
vpxor WY_TMP, WY, WY
|
||||
vpslldq $12, WY, WY_TMP2
|
||||
.elseif ((i & 7) == 3)
|
||||
vpslld $1, WY, WY_TMP
|
||||
vpsrld $31, WY, WY
|
||||
.elseif ((i & 7) == 4)
|
||||
vpor WY, WY_TMP, WY_TMP
|
||||
vpslld $2, WY_TMP2, WY
|
||||
.elseif ((i & 7) == 5)
|
||||
vpsrld $30, WY_TMP2, WY_TMP2
|
||||
vpxor WY, WY_TMP, WY_TMP
|
||||
.elseif ((i & 7) == 7)
|
||||
vpxor WY_TMP2, WY_TMP, WY
|
||||
vpaddd K_XMM(K_BASE), WY, WY_TMP
|
||||
vmovdqu WY_TMP, PRECALC_WK(i&~7)
|
||||
|
||||
PRECALC_ROTATE_WY
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro PRECALC_32_79
|
||||
/*
|
||||
* in SHA-1 specification:
|
||||
* w[i] = (w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]) rol 1
|
||||
* instead we do equal:
|
||||
* w[i] = (w[i-6] ^ w[i-16] ^ w[i-28] ^ w[i-32]) rol 2
|
||||
* allows more efficient vectorization
|
||||
* since w[i]=>w[i-3] dependency is broken
|
||||
*/
|
||||
|
||||
.if ((i & 7) == 0)
|
||||
/*
|
||||
* blended AVX2 and ALU instruction scheduling
|
||||
* 1 vector iteration per 8 rounds
|
||||
*/
|
||||
vpalignr $8, WY_minus_08, WY_minus_04, WY_TMP
|
||||
.elseif ((i & 7) == 1)
|
||||
/* W is W_minus_32 before xor */
|
||||
vpxor WY_minus_28, WY, WY
|
||||
.elseif ((i & 7) == 2)
|
||||
vpxor WY_minus_16, WY_TMP, WY_TMP
|
||||
.elseif ((i & 7) == 3)
|
||||
vpxor WY_TMP, WY, WY
|
||||
.elseif ((i & 7) == 4)
|
||||
vpslld $2, WY, WY_TMP
|
||||
.elseif ((i & 7) == 5)
|
||||
vpsrld $30, WY, WY
|
||||
vpor WY, WY_TMP, WY
|
||||
.elseif ((i & 7) == 7)
|
||||
vpaddd K_XMM(K_BASE), WY, WY_TMP
|
||||
vmovdqu WY_TMP, PRECALC_WK(i&~7)
|
||||
|
||||
PRECALC_ROTATE_WY
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro PRECALC r, s
|
||||
.set i, \r
|
||||
|
||||
.if (i < 40)
|
||||
.set K_XMM, 32*0
|
||||
.elseif (i < 80)
|
||||
.set K_XMM, 32*1
|
||||
.elseif (i < 120)
|
||||
.set K_XMM, 32*2
|
||||
.else
|
||||
.set K_XMM, 32*3
|
||||
.endif
|
||||
|
||||
.if (i<32)
|
||||
PRECALC_00_15 \s
|
||||
.elseif (i<64)
|
||||
PRECALC_16_31 \s
|
||||
.elseif (i < 160)
|
||||
PRECALC_32_79 \s
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro ROTATE_STATE
|
||||
.set T_REG, E
|
||||
.set E, D
|
||||
.set D, C
|
||||
.set C, B
|
||||
.set B, TB
|
||||
.set TB, A
|
||||
.set A, T_REG
|
||||
|
||||
.set T_REG, RE
|
||||
.set RE, RD
|
||||
.set RD, RC
|
||||
.set RC, RB
|
||||
.set RB, RTB
|
||||
.set RTB, RA
|
||||
.set RA, T_REG
|
||||
.endm
|
||||
|
||||
/* Macro relies on saved ROUND_Fx */
|
||||
|
||||
.macro RND_FUN f, r
|
||||
.if (\f == RND_F1)
|
||||
ROUND_F1 \r
|
||||
.elseif (\f == RND_F2)
|
||||
ROUND_F2 \r
|
||||
.elseif (\f == RND_F3)
|
||||
ROUND_F3 \r
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro RR r
|
||||
.set round_id, (\r % 80)
|
||||
|
||||
.if (round_id == 0) /* Precalculate F for first round */
|
||||
.set ROUND_FUNC, RND_F1
|
||||
mov B, TB
|
||||
|
||||
rorx $(32-30), B, B /* b>>>2 */
|
||||
andn D, TB, T1
|
||||
and C, TB
|
||||
xor T1, TB
|
||||
.endif
|
||||
|
||||
RND_FUN ROUND_FUNC, \r
|
||||
ROTATE_STATE
|
||||
|
||||
.if (round_id == 18)
|
||||
.set ROUND_FUNC, RND_F2
|
||||
.elseif (round_id == 38)
|
||||
.set ROUND_FUNC, RND_F3
|
||||
.elseif (round_id == 58)
|
||||
.set ROUND_FUNC, RND_F2
|
||||
.endif
|
||||
|
||||
.set round_id, ( (\r+1) % 80)
|
||||
|
||||
RND_FUN ROUND_FUNC, (\r+1)
|
||||
ROTATE_STATE
|
||||
.endm
|
||||
|
||||
.macro ROUND_F1 r
|
||||
add WK(\r), E
|
||||
|
||||
andn C, A, T1 /* ~b&d */
|
||||
lea (RE,RTB), E /* Add F from the previous round */
|
||||
|
||||
rorx $(32-5), A, TA /* T2 = A >>> 5 */
|
||||
rorx $(32-30),A, TB /* b>>>2 for next round */
|
||||
|
||||
PRECALC (\r) /* msg scheduling for next 2 blocks */
|
||||
|
||||
/*
|
||||
* Calculate F for the next round
|
||||
* (b & c) ^ andn[b, d]
|
||||
*/
|
||||
and B, A /* b&c */
|
||||
xor T1, A /* F1 = (b&c) ^ (~b&d) */
|
||||
|
||||
lea (RE,RTA), E /* E += A >>> 5 */
|
||||
.endm
|
||||
|
||||
.macro ROUND_F2 r
|
||||
add WK(\r), E
|
||||
lea (RE,RTB), E /* Add F from the previous round */
|
||||
|
||||
/* Calculate F for the next round */
|
||||
rorx $(32-5), A, TA /* T2 = A >>> 5 */
|
||||
.if ((round_id) < 79)
|
||||
rorx $(32-30), A, TB /* b>>>2 for next round */
|
||||
.endif
|
||||
PRECALC (\r) /* msg scheduling for next 2 blocks */
|
||||
|
||||
.if ((round_id) < 79)
|
||||
xor B, A
|
||||
.endif
|
||||
|
||||
add TA, E /* E += A >>> 5 */
|
||||
|
||||
.if ((round_id) < 79)
|
||||
xor C, A
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro ROUND_F3 r
|
||||
add WK(\r), E
|
||||
PRECALC (\r) /* msg scheduling for next 2 blocks */
|
||||
|
||||
lea (RE,RTB), E /* Add F from the previous round */
|
||||
|
||||
mov B, T1
|
||||
or A, T1
|
||||
|
||||
rorx $(32-5), A, TA /* T2 = A >>> 5 */
|
||||
rorx $(32-30), A, TB /* b>>>2 for next round */
|
||||
|
||||
/* Calculate F for the next round
|
||||
* (b and c) or (d and (b or c))
|
||||
*/
|
||||
and C, T1
|
||||
and B, A
|
||||
or T1, A
|
||||
|
||||
add TA, E /* E += A >>> 5 */
|
||||
|
||||
.endm
|
||||
|
||||
/*
|
||||
* macro implements 80 rounds of SHA-1, for multiple blocks with s/w pipelining
|
||||
*/
|
||||
.macro SHA1_PIPELINED_MAIN_BODY
|
||||
|
||||
REGALLOC
|
||||
|
||||
mov (HASH_PTR), A
|
||||
mov 4(HASH_PTR), B
|
||||
mov 8(HASH_PTR), C
|
||||
mov 12(HASH_PTR), D
|
||||
mov 16(HASH_PTR), E
|
||||
|
||||
mov %rsp, PRECALC_BUF
|
||||
lea (2*4*80+32)(%rsp), WK_BUF
|
||||
|
||||
# Precalc WK for first 2 blocks
|
||||
PRECALC_OFFSET = 0
|
||||
.set i, 0
|
||||
.rept 160
|
||||
PRECALC i
|
||||
.set i, i + 1
|
||||
.endr
|
||||
PRECALC_OFFSET = 128
|
||||
xchg WK_BUF, PRECALC_BUF
|
||||
|
||||
.align 32
|
||||
_loop:
|
||||
/*
|
||||
* code loops through more than one block
|
||||
* we use K_BASE value as a signal of a last block,
|
||||
* it is set below by: cmovae BUFFER_PTR, K_BASE
|
||||
*/
|
||||
cmp K_BASE, BUFFER_PTR
|
||||
jne _begin
|
||||
.align 32
|
||||
jmp _end
|
||||
.align 32
|
||||
_begin:
|
||||
|
||||
/*
|
||||
* Do first block
|
||||
* rounds: 0,2,4,6,8
|
||||
*/
|
||||
.set j, 0
|
||||
.rept 5
|
||||
RR j
|
||||
.set j, j+2
|
||||
.endr
|
||||
|
||||
jmp _loop0
|
||||
_loop0:
|
||||
|
||||
/*
|
||||
* rounds:
|
||||
* 10,12,14,16,18
|
||||
* 20,22,24,26,28
|
||||
* 30,32,34,36,38
|
||||
* 40,42,44,46,48
|
||||
* 50,52,54,56,58
|
||||
*/
|
||||
.rept 25
|
||||
RR j
|
||||
.set j, j+2
|
||||
.endr
|
||||
|
||||
add $(2*64), BUFFER_PTR /* move to next odd-64-byte block */
|
||||
cmp BUFFER_END, BUFFER_PTR /* is current block the last one? */
|
||||
cmovae K_BASE, BUFFER_PTR /* signal the last iteration smartly */
|
||||
|
||||
/*
|
||||
* rounds
|
||||
* 60,62,64,66,68
|
||||
* 70,72,74,76,78
|
||||
*/
|
||||
.rept 10
|
||||
RR j
|
||||
.set j, j+2
|
||||
.endr
|
||||
|
||||
UPDATE_HASH (HASH_PTR), A
|
||||
UPDATE_HASH 4(HASH_PTR), TB
|
||||
UPDATE_HASH 8(HASH_PTR), C
|
||||
UPDATE_HASH 12(HASH_PTR), D
|
||||
UPDATE_HASH 16(HASH_PTR), E
|
||||
|
||||
cmp K_BASE, BUFFER_PTR /* is current block the last one? */
|
||||
je _loop
|
||||
|
||||
mov TB, B
|
||||
|
||||
/* Process second block */
|
||||
/*
|
||||
* rounds
|
||||
* 0+80, 2+80, 4+80, 6+80, 8+80
|
||||
* 10+80,12+80,14+80,16+80,18+80
|
||||
*/
|
||||
|
||||
.set j, 0
|
||||
.rept 10
|
||||
RR j+80
|
||||
.set j, j+2
|
||||
.endr
|
||||
|
||||
jmp _loop1
|
||||
_loop1:
|
||||
/*
|
||||
* rounds
|
||||
* 20+80,22+80,24+80,26+80,28+80
|
||||
* 30+80,32+80,34+80,36+80,38+80
|
||||
*/
|
||||
.rept 10
|
||||
RR j+80
|
||||
.set j, j+2
|
||||
.endr
|
||||
|
||||
jmp _loop2
|
||||
_loop2:
|
||||
|
||||
/*
|
||||
* rounds
|
||||
* 40+80,42+80,44+80,46+80,48+80
|
||||
* 50+80,52+80,54+80,56+80,58+80
|
||||
*/
|
||||
.rept 10
|
||||
RR j+80
|
||||
.set j, j+2
|
||||
.endr
|
||||
|
||||
add $(2*64), BUFFER_PTR2 /* move to next even-64-byte block */
|
||||
|
||||
cmp BUFFER_END, BUFFER_PTR2 /* is current block the last one */
|
||||
cmovae K_BASE, BUFFER_PTR /* signal the last iteration smartly */
|
||||
|
||||
jmp _loop3
|
||||
_loop3:
|
||||
|
||||
/*
|
||||
* rounds
|
||||
* 60+80,62+80,64+80,66+80,68+80
|
||||
* 70+80,72+80,74+80,76+80,78+80
|
||||
*/
|
||||
.rept 10
|
||||
RR j+80
|
||||
.set j, j+2
|
||||
.endr
|
||||
|
||||
UPDATE_HASH (HASH_PTR), A
|
||||
UPDATE_HASH 4(HASH_PTR), TB
|
||||
UPDATE_HASH 8(HASH_PTR), C
|
||||
UPDATE_HASH 12(HASH_PTR), D
|
||||
UPDATE_HASH 16(HASH_PTR), E
|
||||
|
||||
/* Reset state for AVX2 reg permutation */
|
||||
mov A, TA
|
||||
mov TB, A
|
||||
mov C, TB
|
||||
mov E, C
|
||||
mov D, B
|
||||
mov TA, D
|
||||
|
||||
REGALLOC
|
||||
|
||||
xchg WK_BUF, PRECALC_BUF
|
||||
|
||||
jmp _loop
|
||||
|
||||
.align 32
|
||||
_end:
|
||||
|
||||
.endm
|
||||
|
||||
.section .rodata
|
||||
|
||||
#define K1 0x5a827999
|
||||
#define K2 0x6ed9eba1
|
||||
#define K3 0x8f1bbcdc
|
||||
#define K4 0xca62c1d6
|
||||
|
||||
.align 128
|
||||
K_XMM_AR:
|
||||
.long K1, K1, K1, K1
|
||||
.long K1, K1, K1, K1
|
||||
.long K2, K2, K2, K2
|
||||
.long K2, K2, K2, K2
|
||||
.long K3, K3, K3, K3
|
||||
.long K3, K3, K3, K3
|
||||
.long K4, K4, K4, K4
|
||||
.long K4, K4, K4, K4
|
||||
|
||||
BSWAP_SHUFB_CTL:
|
||||
.long 0x00010203
|
||||
.long 0x04050607
|
||||
.long 0x08090a0b
|
||||
.long 0x0c0d0e0f
|
||||
.long 0x00010203
|
||||
.long 0x04050607
|
||||
.long 0x08090a0b
|
||||
.long 0x0c0d0e0f
|
||||
|
||||
# void sha1_transform(int32_t *hash, const char* input, size_t num_blocks) ;
|
||||
.text
|
||||
ENTRY(sha1_transform)
|
||||
|
||||
push %rbx
|
||||
push %rbp
|
||||
push %r12
|
||||
push %r13
|
||||
push %r14
|
||||
push %r15
|
||||
|
||||
RESERVE_STACK = (W_SIZE*4 + 8+24)
|
||||
|
||||
/* Align stack */
|
||||
mov %rsp, %rbx
|
||||
and $~(0x20-1), %rsp
|
||||
push %rbx
|
||||
sub $RESERVE_STACK, %rsp
|
||||
|
||||
avx2_zeroupper
|
||||
|
||||
lea K_XMM_AR(%rip), K_BASE
|
||||
|
||||
mov CTX, HASH_PTR
|
||||
mov BUF, BUFFER_PTR
|
||||
lea 64(BUF), BUFFER_PTR2
|
||||
|
||||
shl $6, CNT /* mul by 64 */
|
||||
add BUF, CNT
|
||||
add $64, CNT
|
||||
mov CNT, BUFFER_END
|
||||
|
||||
cmp BUFFER_END, BUFFER_PTR2
|
||||
cmovae K_BASE, BUFFER_PTR2
|
||||
|
||||
xmm_mov BSWAP_SHUFB_CTL(%rip), YMM_SHUFB_BSWAP
|
||||
|
||||
SHA1_PIPELINED_MAIN_BODY
|
||||
|
||||
avx2_zeroupper
|
||||
|
||||
add $RESERVE_STACK, %rsp
|
||||
pop %rsp
|
||||
|
||||
pop %r15
|
||||
pop %r14
|
||||
pop %r13
|
||||
pop %r12
|
||||
pop %rbp
|
||||
pop %rbx
|
||||
|
||||
ret
|
||||
|
||||
ENDPROC(sha1_transform)
|
||||
#endif
|
||||
@@ -1,169 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file of
|
||||
// Golang project:
|
||||
// https://github.com/golang/go/blob/master/LICENSE
|
||||
|
||||
// Using this part of Minio codebase under the license
|
||||
// Apache License Version 2.0 with modifications
|
||||
|
||||
// Package sha1 implements the SHA1 hash algorithm as defined in RFC 3174.
|
||||
package sha1
|
||||
|
||||
import (
|
||||
"hash"
|
||||
"io"
|
||||
|
||||
"github.com/minio/minio/pkg/cpu"
|
||||
)
|
||||
|
||||
// The size of a SHA1 checksum in bytes.
|
||||
const Size = 20
|
||||
|
||||
// The blocksize of SHA1 in bytes.
|
||||
const BlockSize = 64
|
||||
|
||||
const (
|
||||
chunk = 64
|
||||
init0 = 0x67452301
|
||||
init1 = 0xEFCDAB89
|
||||
init2 = 0x98BADCFE
|
||||
init3 = 0x10325476
|
||||
init4 = 0xC3D2E1F0
|
||||
)
|
||||
|
||||
// digest represents the partial evaluation of a checksum.
|
||||
type digest struct {
|
||||
h [5]uint32
|
||||
x [chunk]byte
|
||||
nx int
|
||||
len uint64
|
||||
}
|
||||
|
||||
// Reset digest
|
||||
func (d *digest) Reset() {
|
||||
d.h[0] = init0
|
||||
d.h[1] = init1
|
||||
d.h[2] = init2
|
||||
d.h[3] = init3
|
||||
d.h[4] = init4
|
||||
d.nx = 0
|
||||
d.len = 0
|
||||
}
|
||||
|
||||
// New returns a new hash.Hash computing the SHA1 checksum.
|
||||
func New() hash.Hash {
|
||||
d := new(digest)
|
||||
d.Reset()
|
||||
return d
|
||||
}
|
||||
|
||||
func block(dig *digest, p []byte) {
|
||||
switch true {
|
||||
case cpu.HasAVX2() == true:
|
||||
blockAVX2(dig, p)
|
||||
case cpu.HasSSE41() == true:
|
||||
blockSSE3(dig, p)
|
||||
default:
|
||||
blockGeneric(dig, p)
|
||||
}
|
||||
}
|
||||
|
||||
// Return output size
|
||||
func (d *digest) Size() int { return Size }
|
||||
|
||||
// Return checksum blocksize
|
||||
func (d *digest) BlockSize() int { return BlockSize }
|
||||
|
||||
// Write to digest
|
||||
func (d *digest) Write(p []byte) (nn int, err error) {
|
||||
nn = len(p)
|
||||
d.len += uint64(nn)
|
||||
if d.nx > 0 {
|
||||
n := copy(d.x[d.nx:], p)
|
||||
d.nx += n
|
||||
if d.nx == chunk {
|
||||
block(d, d.x[:])
|
||||
d.nx = 0
|
||||
}
|
||||
p = p[n:]
|
||||
}
|
||||
if len(p) >= chunk {
|
||||
n := len(p) &^ (chunk - 1)
|
||||
block(d, p[:n])
|
||||
p = p[n:]
|
||||
}
|
||||
if len(p) > 0 {
|
||||
d.nx = copy(d.x[:], p)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Return checksum bytes
|
||||
func (d *digest) Sum(in []byte) []byte {
|
||||
// Make a copy of d0 so that caller can keep writing and summing.
|
||||
d0 := *d
|
||||
hash := d0.checkSum()
|
||||
return append(in, hash[:]...)
|
||||
}
|
||||
|
||||
// Intermediate checksum function
|
||||
func (d *digest) checkSum() [Size]byte {
|
||||
len := d.len
|
||||
// Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
|
||||
var tmp [64]byte
|
||||
tmp[0] = 0x80
|
||||
if len%64 < 56 {
|
||||
d.Write(tmp[0 : 56-len%64])
|
||||
} else {
|
||||
d.Write(tmp[0 : 64+56-len%64])
|
||||
}
|
||||
|
||||
// Length in bits.
|
||||
len <<= 3
|
||||
for i := uint(0); i < 8; i++ {
|
||||
tmp[i] = byte(len >> (56 - 8*i))
|
||||
}
|
||||
d.Write(tmp[0:8])
|
||||
|
||||
if d.nx != 0 {
|
||||
panic("d.nx != 0")
|
||||
}
|
||||
|
||||
var digest [Size]byte
|
||||
for i, s := range d.h {
|
||||
digest[i*4] = byte(s >> 24)
|
||||
digest[i*4+1] = byte(s >> 16)
|
||||
digest[i*4+2] = byte(s >> 8)
|
||||
digest[i*4+3] = byte(s)
|
||||
}
|
||||
|
||||
return digest
|
||||
}
|
||||
|
||||
/// Convenience functions
|
||||
|
||||
// Sum1 - single caller sha1 helper
|
||||
func Sum1(data []byte) [Size]byte {
|
||||
var d digest
|
||||
d.Reset()
|
||||
d.Write(data)
|
||||
return d.checkSum()
|
||||
}
|
||||
|
||||
// Sum - io.Reader based streaming sha1 helper
|
||||
func Sum(reader io.Reader) ([]byte, error) {
|
||||
h := New()
|
||||
var err error
|
||||
for err == nil {
|
||||
length := 0
|
||||
byteBuffer := make([]byte, 1024*1024)
|
||||
length, err = reader.Read(byteBuffer)
|
||||
byteBuffer = byteBuffer[0:length]
|
||||
h.Write(byteBuffer)
|
||||
}
|
||||
if err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
return h.Sum(nil), nil
|
||||
}
|
||||
@@ -1,579 +0,0 @@
|
||||
;---------------------
|
||||
; https://software.intel.com/en-us/articles/improving-the-performance-of-the-secure-hash-algorithm-1
|
||||
;
|
||||
; License information:
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; This implementation notably advances the performance of SHA-1 algorithm compared to existing
|
||||
; implementations. We are encouraging all projects utilizing SHA-1 to integrate this new fast
|
||||
; implementation and are ready to help if issues or concerns arise (you are welcome to leave
|
||||
; a comment or write an email to the authors). It is provided 'as is' and free for either
|
||||
; commercial or non-commercial use.
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;
|
||||
; This code implements two interfaces of SHA-1 update function: 1) working on a single
|
||||
; 64-byte block and 2) working on a buffer of multiple 64-bit blocks. Multiple blocks
|
||||
; version of code is software pipelined and faster overall, it is a default. Assemble
|
||||
; with -DINTEL_SHA1_SINGLEBLOCK to select single 64-byte block function interface.
|
||||
;
|
||||
; C++ prototypes of implemented functions are below:
|
||||
;
|
||||
; #ifndef INTEL_SHA1_SINGLEBLOCK
|
||||
; // Updates 20-byte SHA-1 record in 'hash' for 'num_blocks' consequtive 64-byte blocks
|
||||
; extern "C" void sha1_update_intel(int *hash, const char* input, size_t num_blocks );
|
||||
; #else
|
||||
; // Updates 20-byte SHA-1 record in 'hash' for one 64-byte block pointed by 'input'
|
||||
; extern "C" void sha1_update_intel(int *hash, const char* input);
|
||||
; #endif
|
||||
;
|
||||
; Function name 'sha1_update_intel' can be changed in the source or via macro:
|
||||
; -DINTEL_SHA1_UPDATE_FUNCNAME=my_sha1_update_func_name
|
||||
;
|
||||
; It implements both UNIX(default) and Windows ABIs, use -DWIN_ABI on Windows
|
||||
;
|
||||
; Code checks CPU for SSSE3 support via CPUID feature flag (CPUID.1.ECX.SSSE3[bit 9]==1),
|
||||
; and performs dispatch. Since in most cases the functionality on non-SSSE3 supporting CPUs
|
||||
; is also required, the default (e.g. one being replaced) function can be provided for
|
||||
; dispatch on such CPUs, the name of old function can be changed in the source or via macro:
|
||||
; -DINTEL_SHA1_UPDATE_DEFAULT_DISPATCH=default_sha1_update_function_name
|
||||
;
|
||||
; Authors: Maxim Locktyukhin and Ronen Zohar at Intel.com
|
||||
;
|
||||
|
||||
%ifndef INTEL_SHA1_UPDATE_DEFAULT_DISPATCH
|
||||
;; can be replaced with a default SHA-1 update function name
|
||||
%define INTEL_SHA1_UPDATE_DEFAULT_DISPATCH sha1_intel_non_ssse3_cpu_stub_
|
||||
%else
|
||||
extern INTEL_SHA1_UPDATE_DEFAULT_DISPATCH
|
||||
%endif
|
||||
|
||||
;; provide alternative SHA-1 update function's name here
|
||||
%ifndef INTEL_SHA1_UPDATE_FUNCNAME
|
||||
%define INTEL_SHA1_UPDATE_FUNCNAME sha1_update_intel
|
||||
%endif
|
||||
|
||||
global INTEL_SHA1_UPDATE_FUNCNAME
|
||||
|
||||
|
||||
%ifndef INTEL_SHA1_SINGLEBLOCK
|
||||
%assign multiblock 1
|
||||
%else
|
||||
%assign multiblock 0
|
||||
%endif
|
||||
|
||||
|
||||
bits 64
|
||||
default rel
|
||||
|
||||
%ifdef WIN_ABI
|
||||
%xdefine arg1 rcx
|
||||
%xdefine arg2 rdx
|
||||
%xdefine arg3 r8
|
||||
%else
|
||||
%xdefine arg1 rdi
|
||||
%xdefine arg2 rsi
|
||||
%xdefine arg3 rdx
|
||||
%endif
|
||||
|
||||
%xdefine ctx arg1
|
||||
%xdefine buf arg2
|
||||
%xdefine cnt arg3
|
||||
|
||||
%macro REGALLOC 0
|
||||
%xdefine A ecx
|
||||
%xdefine B esi
|
||||
%xdefine C edi
|
||||
%xdefine D ebp
|
||||
%xdefine E edx
|
||||
|
||||
%xdefine T1 eax
|
||||
%xdefine T2 ebx
|
||||
%endmacro
|
||||
|
||||
%xdefine K_BASE r8
|
||||
%xdefine HASH_PTR r9
|
||||
%xdefine BUFFER_PTR r10
|
||||
%xdefine BUFFER_END r11
|
||||
|
||||
%xdefine W_TMP xmm0
|
||||
%xdefine W_TMP2 xmm9
|
||||
|
||||
%xdefine W0 xmm1
|
||||
%xdefine W4 xmm2
|
||||
%xdefine W8 xmm3
|
||||
%xdefine W12 xmm4
|
||||
%xdefine W16 xmm5
|
||||
%xdefine W20 xmm6
|
||||
%xdefine W24 xmm7
|
||||
%xdefine W28 xmm8
|
||||
|
||||
%xdefine XMM_SHUFB_BSWAP xmm10
|
||||
|
||||
;; we keep window of 64 w[i]+K pre-calculated values in a circular buffer
|
||||
%xdefine WK(t) (rsp + (t & 15)*4)
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
;
|
||||
; macro implements SHA-1 function's body for single or several 64-byte blocks
|
||||
; first param: function's name
|
||||
; second param: =0 - function implements single 64-byte block hash
|
||||
; =1 - function implements multiple64-byte blocks hash
|
||||
; 3rd function's argument is a number, greater 0, of 64-byte blocks to calc hash for
|
||||
;
|
||||
%macro SHA1_VECTOR_ASM 2
|
||||
align 4096
|
||||
%1:
|
||||
push rbx
|
||||
push rbp
|
||||
|
||||
%ifdef WIN_ABI
|
||||
push rdi
|
||||
push rsi
|
||||
|
||||
%xdefine stack_size (16*4 + 16*5 + 8)
|
||||
%else
|
||||
%xdefine stack_size (16*4 + 8)
|
||||
%endif
|
||||
|
||||
sub rsp, stack_size
|
||||
|
||||
%ifdef WIN_ABI
|
||||
%xdefine xmm_save_base (rsp + 16*4)
|
||||
|
||||
xmm_mov [xmm_save_base + 0*16], xmm6
|
||||
xmm_mov [xmm_save_base + 1*16], xmm7
|
||||
xmm_mov [xmm_save_base + 2*16], xmm8
|
||||
xmm_mov [xmm_save_base + 3*16], xmm9
|
||||
xmm_mov [xmm_save_base + 4*16], xmm10
|
||||
%endif
|
||||
|
||||
mov HASH_PTR, ctx
|
||||
mov BUFFER_PTR, buf
|
||||
|
||||
%if (%2 == 1)
|
||||
shl cnt, 6 ;; mul by 64
|
||||
add cnt, buf
|
||||
mov BUFFER_END, cnt
|
||||
%endif
|
||||
|
||||
lea K_BASE, [K_XMM_AR]
|
||||
xmm_mov XMM_SHUFB_BSWAP, [bswap_shufb_ctl]
|
||||
|
||||
SHA1_PIPELINED_MAIN_BODY %2
|
||||
|
||||
%ifdef WIN_ABI
|
||||
xmm_mov xmm6, [xmm_save_base + 0*16]
|
||||
xmm_mov xmm7, [xmm_save_base + 1*16]
|
||||
xmm_mov xmm8, [xmm_save_base + 2*16]
|
||||
xmm_mov xmm9, [xmm_save_base + 3*16]
|
||||
xmm_mov xmm10,[xmm_save_base + 4*16]
|
||||
%endif
|
||||
|
||||
add rsp, stack_size
|
||||
|
||||
%ifdef WIN_ABI
|
||||
pop rsi
|
||||
pop rdi
|
||||
%endif
|
||||
|
||||
pop rbp
|
||||
pop rbx
|
||||
|
||||
ret
|
||||
%endmacro
|
||||
|
||||
;--------------------------------------------
|
||||
; macro implements 80 rounds of SHA-1, for one 64-byte block or multiple blocks with s/w pipelining
|
||||
; macro param: =0 - process single 64-byte block
|
||||
; =1 - multiple blocks
|
||||
;
|
||||
%macro SHA1_PIPELINED_MAIN_BODY 1
|
||||
|
||||
REGALLOC
|
||||
|
||||
mov A, [HASH_PTR ]
|
||||
mov B, [HASH_PTR+ 4]
|
||||
mov C, [HASH_PTR+ 8]
|
||||
mov D, [HASH_PTR+12]
|
||||
|
||||
mov E, [HASH_PTR+16]
|
||||
|
||||
%assign i 0
|
||||
%rep W_PRECALC_AHEAD
|
||||
W_PRECALC i
|
||||
%assign i i+1
|
||||
%endrep
|
||||
|
||||
%xdefine F F1
|
||||
|
||||
%if (%1 == 1) ;; code loops through more than one block
|
||||
%%_loop:
|
||||
cmp BUFFER_PTR, K_BASE ;; we use K_BASE value as a signal of a last block,
|
||||
jne %%_begin ;; it is set below by: cmovae BUFFER_PTR, K_BASE
|
||||
jmp %%_end
|
||||
|
||||
align 32
|
||||
%%_begin:
|
||||
%endif
|
||||
RR A,B,C,D,E,0
|
||||
RR D,E,A,B,C,2
|
||||
RR B,C,D,E,A,4
|
||||
RR E,A,B,C,D,6
|
||||
RR C,D,E,A,B,8
|
||||
|
||||
RR A,B,C,D,E,10
|
||||
RR D,E,A,B,C,12
|
||||
RR B,C,D,E,A,14
|
||||
RR E,A,B,C,D,16
|
||||
RR C,D,E,A,B,18
|
||||
|
||||
%xdefine F F2
|
||||
|
||||
RR A,B,C,D,E,20
|
||||
RR D,E,A,B,C,22
|
||||
RR B,C,D,E,A,24
|
||||
RR E,A,B,C,D,26
|
||||
RR C,D,E,A,B,28
|
||||
|
||||
RR A,B,C,D,E,30
|
||||
RR D,E,A,B,C,32
|
||||
RR B,C,D,E,A,34
|
||||
RR E,A,B,C,D,36
|
||||
RR C,D,E,A,B,38
|
||||
|
||||
%xdefine F F3
|
||||
|
||||
RR A,B,C,D,E,40
|
||||
RR D,E,A,B,C,42
|
||||
RR B,C,D,E,A,44
|
||||
RR E,A,B,C,D,46
|
||||
RR C,D,E,A,B,48
|
||||
|
||||
RR A,B,C,D,E,50
|
||||
RR D,E,A,B,C,52
|
||||
RR B,C,D,E,A,54
|
||||
RR E,A,B,C,D,56
|
||||
RR C,D,E,A,B,58
|
||||
|
||||
%xdefine F F4
|
||||
|
||||
%if (%1 == 1) ;; if code loops through more than one block
|
||||
add BUFFER_PTR, 64 ;; move to next 64-byte block
|
||||
cmp BUFFER_PTR, BUFFER_END ;; check if current block is the last one
|
||||
cmovae BUFFER_PTR, K_BASE ;; smart way to signal the last iteration
|
||||
%else
|
||||
%xdefine W_NO_TAIL_PRECALC 1 ;; no software pipelining for single block interface
|
||||
%endif
|
||||
|
||||
RR A,B,C,D,E,60
|
||||
RR D,E,A,B,C,62
|
||||
RR B,C,D,E,A,64
|
||||
RR E,A,B,C,D,66
|
||||
RR C,D,E,A,B,68
|
||||
|
||||
RR A,B,C,D,E,70
|
||||
RR D,E,A,B,C,72
|
||||
RR B,C,D,E,A,74
|
||||
RR E,A,B,C,D,76
|
||||
RR C,D,E,A,B,78
|
||||
|
||||
UPDATE_HASH [HASH_PTR ],A
|
||||
UPDATE_HASH [HASH_PTR+ 4],B
|
||||
UPDATE_HASH [HASH_PTR+ 8],C
|
||||
UPDATE_HASH [HASH_PTR+12],D
|
||||
UPDATE_HASH [HASH_PTR+16],E
|
||||
|
||||
%if (%1 == 1)
|
||||
jmp %%_loop
|
||||
|
||||
align 32
|
||||
%%_end:
|
||||
%endif
|
||||
|
||||
|
||||
%xdefine W_NO_TAIL_PRECALC 0
|
||||
%xdefine F %error
|
||||
|
||||
%endmacro
|
||||
|
||||
|
||||
%macro F1 3
|
||||
mov T1,%2
|
||||
xor T1,%3
|
||||
and T1,%1
|
||||
xor T1,%3
|
||||
%endmacro
|
||||
|
||||
%macro F2 3
|
||||
mov T1,%3
|
||||
xor T1,%2
|
||||
xor T1,%1
|
||||
%endmacro
|
||||
|
||||
%macro F3 3
|
||||
mov T1,%2
|
||||
mov T2,%1
|
||||
or T1,%1
|
||||
and T2,%2
|
||||
and T1,%3
|
||||
or T1,T2
|
||||
%endmacro
|
||||
|
||||
%define F4 F2
|
||||
|
||||
%macro UPDATE_HASH 2
|
||||
add %2, %1
|
||||
mov %1, %2
|
||||
%endmacro
|
||||
|
||||
|
||||
%macro W_PRECALC 1
|
||||
%xdefine i (%1)
|
||||
|
||||
%if (i < 20)
|
||||
%xdefine K_XMM 0
|
||||
%elif (i < 40)
|
||||
%xdefine K_XMM 16
|
||||
%elif (i < 60)
|
||||
%xdefine K_XMM 32
|
||||
%else
|
||||
%xdefine K_XMM 48
|
||||
%endif
|
||||
|
||||
%if (i<16 || (i>=80 && i<(80 + W_PRECALC_AHEAD)))
|
||||
|
||||
%if (W_NO_TAIL_PRECALC == 0)
|
||||
|
||||
%xdefine i ((%1) % 80) ;; pre-compute for the next iteration
|
||||
|
||||
%if (i == 0)
|
||||
W_PRECALC_RESET
|
||||
%endif
|
||||
|
||||
|
||||
W_PRECALC_00_15
|
||||
%endif
|
||||
|
||||
%elif (i < 32)
|
||||
W_PRECALC_16_31
|
||||
%elif (i < 80) ;; rounds 32-79
|
||||
W_PRECALC_32_79
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro W_PRECALC_RESET 0
|
||||
%xdefine W W0
|
||||
%xdefine W_minus_04 W4
|
||||
%xdefine W_minus_08 W8
|
||||
%xdefine W_minus_12 W12
|
||||
%xdefine W_minus_16 W16
|
||||
%xdefine W_minus_20 W20
|
||||
%xdefine W_minus_24 W24
|
||||
%xdefine W_minus_28 W28
|
||||
%xdefine W_minus_32 W
|
||||
%endmacro
|
||||
|
||||
%macro W_PRECALC_ROTATE 0
|
||||
%xdefine W_minus_32 W_minus_28
|
||||
%xdefine W_minus_28 W_minus_24
|
||||
%xdefine W_minus_24 W_minus_20
|
||||
%xdefine W_minus_20 W_minus_16
|
||||
%xdefine W_minus_16 W_minus_12
|
||||
%xdefine W_minus_12 W_minus_08
|
||||
%xdefine W_minus_08 W_minus_04
|
||||
%xdefine W_minus_04 W
|
||||
%xdefine W W_minus_32
|
||||
%endmacro
|
||||
|
||||
%xdefine W_PRECALC_AHEAD 16
|
||||
%xdefine W_NO_TAIL_PRECALC 0
|
||||
|
||||
|
||||
%xdefine xmm_mov movdqa
|
||||
|
||||
%macro W_PRECALC_00_15 0
|
||||
;; message scheduling pre-compute for rounds 0-15
|
||||
%if ((i & 3) == 0) ;; blended SSE and ALU instruction scheduling, 1 vector iteration per 4 rounds
|
||||
movdqu W_TMP, [BUFFER_PTR + (i * 4)]
|
||||
%elif ((i & 3) == 1)
|
||||
pshufb W_TMP, XMM_SHUFB_BSWAP
|
||||
movdqa W, W_TMP
|
||||
%elif ((i & 3) == 2)
|
||||
paddd W_TMP, [K_BASE]
|
||||
%elif ((i & 3) == 3)
|
||||
movdqa [WK(i&~3)], W_TMP
|
||||
|
||||
W_PRECALC_ROTATE
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro W_PRECALC_16_31 0
|
||||
;; message scheduling pre-compute for rounds 16-31
|
||||
;; calculating last 32 w[i] values in 8 XMM registers
|
||||
;; pre-calculate K+w[i] values and store to mem, for later load by ALU add instruction
|
||||
;;
|
||||
;; "brute force" vectorization for rounds 16-31 only due to w[i]->w[i-3] dependency
|
||||
;;
|
||||
%if ((i & 3) == 0) ;; blended SSE and ALU instruction scheduling, 1 vector iteration per 4 rounds
|
||||
movdqa W, W_minus_12
|
||||
palignr W, W_minus_16, 8 ;; w[i-14]
|
||||
movdqa W_TMP, W_minus_04
|
||||
psrldq W_TMP, 4 ;; w[i-3]
|
||||
pxor W, W_minus_08
|
||||
%elif ((i & 3) == 1)
|
||||
pxor W_TMP, W_minus_16
|
||||
pxor W, W_TMP
|
||||
movdqa W_TMP2, W
|
||||
movdqa W_TMP, W
|
||||
pslldq W_TMP2, 12
|
||||
%elif ((i & 3) == 2)
|
||||
psrld W, 31
|
||||
pslld W_TMP, 1
|
||||
por W_TMP, W
|
||||
movdqa W, W_TMP2
|
||||
psrld W_TMP2, 30
|
||||
pslld W, 2
|
||||
%elif ((i & 3) == 3)
|
||||
pxor W_TMP, W
|
||||
pxor W_TMP, W_TMP2
|
||||
movdqa W, W_TMP
|
||||
paddd W_TMP, [K_BASE + K_XMM]
|
||||
movdqa [WK(i&~3)],W_TMP
|
||||
|
||||
W_PRECALC_ROTATE
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro W_PRECALC_32_79 0
|
||||
;; in SHA-1 specification: w[i] = (w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]) rol 1
|
||||
;; instead we do equal: w[i] = (w[i-6] ^ w[i-16] ^ w[i-28] ^ w[i-32]) rol 2
|
||||
;; allows more efficient vectorization since w[i]=>w[i-3] dependency is broken
|
||||
;;
|
||||
%if ((i & 3) == 0) ;; blended SSE and ALU instruction scheduling, 1 vector iteration per 4 rounds
|
||||
movdqa W_TMP, W_minus_04
|
||||
pxor W, W_minus_28 ;; W is W_minus_32 before xor
|
||||
palignr W_TMP, W_minus_08, 8
|
||||
%elif ((i & 3) == 1)
|
||||
pxor W, W_minus_16
|
||||
pxor W, W_TMP
|
||||
movdqa W_TMP, W
|
||||
%elif ((i & 3) == 2)
|
||||
psrld W, 30
|
||||
pslld W_TMP, 2
|
||||
por W_TMP, W
|
||||
%elif ((i & 3) == 3)
|
||||
movdqa W, W_TMP
|
||||
paddd W_TMP, [K_BASE + K_XMM]
|
||||
movdqa [WK(i&~3)],W_TMP
|
||||
|
||||
W_PRECALC_ROTATE
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro RR 6 ;; RR does two rounds of SHA-1 back to back with W pre-calculation
|
||||
|
||||
;; TEMP = A
|
||||
;; A = F( i, B, C, D ) + E + ROTATE_LEFT( A, 5 ) + W[i] + K(i)
|
||||
;; C = ROTATE_LEFT( B, 30 )
|
||||
;; D = C
|
||||
;; E = D
|
||||
;; B = TEMP
|
||||
|
||||
W_PRECALC (%6 + W_PRECALC_AHEAD)
|
||||
F %2, %3, %4 ;; F returns result in T1
|
||||
add %5, [WK(%6)]
|
||||
rol %2, 30
|
||||
mov T2, %1
|
||||
add %4, [WK(%6 + 1)]
|
||||
rol T2, 5
|
||||
add %5, T1
|
||||
|
||||
W_PRECALC (%6 + W_PRECALC_AHEAD + 1)
|
||||
add T2, %5
|
||||
mov %5, T2
|
||||
rol T2, 5
|
||||
add %4, T2
|
||||
F %1, %2, %3 ;; F returns result in T1
|
||||
add %4, T1
|
||||
rol %1, 30
|
||||
|
||||
;; write: %1, %2
|
||||
;; rotate: %1<=%4, %2<=%5, %3<=%1, %4<=%2, %5<=%3
|
||||
%endmacro
|
||||
|
||||
|
||||
|
||||
;;----------------------
|
||||
section .data align=128
|
||||
|
||||
%xdefine K1 0x5a827999
|
||||
%xdefine K2 0x6ed9eba1
|
||||
%xdefine K3 0x8f1bbcdc
|
||||
%xdefine K4 0xca62c1d6
|
||||
|
||||
align 128
|
||||
K_XMM_AR:
|
||||
DD K1, K1, K1, K1
|
||||
DD K2, K2, K2, K2
|
||||
DD K3, K3, K3, K3
|
||||
DD K4, K4, K4, K4
|
||||
|
||||
align 16
|
||||
bswap_shufb_ctl:
|
||||
DD 00010203h
|
||||
DD 04050607h
|
||||
DD 08090a0bh
|
||||
DD 0c0d0e0fh
|
||||
|
||||
;; dispatch pointer, points to the init routine for the first invocation
|
||||
sha1_update_intel_dispatched:
|
||||
DQ sha1_update_intel_init_
|
||||
|
||||
;;----------------------
|
||||
section .text align=4096
|
||||
|
||||
SHA1_VECTOR_ASM sha1_update_intel_ssse3_, multiblock
|
||||
|
||||
align 32
|
||||
sha1_update_intel_init_: ;; we get here with the first time invocation
|
||||
call sha1_update_intel_dispacth_init_
|
||||
INTEL_SHA1_UPDATE_FUNCNAME: ;; we get here after init
|
||||
jmp qword [sha1_update_intel_dispatched]
|
||||
|
||||
;; CPUID feature flag based dispatch
|
||||
sha1_update_intel_dispacth_init_:
|
||||
push rax
|
||||
push rbx
|
||||
push rcx
|
||||
push rdx
|
||||
push rsi
|
||||
|
||||
lea rsi, [INTEL_SHA1_UPDATE_DEFAULT_DISPATCH]
|
||||
|
||||
mov eax, 1
|
||||
cpuid
|
||||
|
||||
test ecx, 0200h ;; SSSE3 support, CPUID.1.ECX[bit 9]
|
||||
jz _done
|
||||
|
||||
lea rsi, [sha1_update_intel_ssse3_]
|
||||
|
||||
_done:
|
||||
mov [sha1_update_intel_dispatched], rsi
|
||||
|
||||
pop rsi
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop rbx
|
||||
pop rax
|
||||
ret
|
||||
|
||||
;;----------------------
|
||||
;; in the case a default SHA-1 update function implementation was not provided
|
||||
;; and code was invoked on a non-SSSE3 supporting CPU, dispatch handles this
|
||||
;; failure in a safest way - jumps to the stub function with UD2 instruction below
|
||||
sha1_intel_non_ssse3_cpu_stub_:
|
||||
ud2 ;; in the case no default SHA-1 was provided non-SSSE3 CPUs safely fail here
|
||||
ret
|
||||
|
||||
; END
|
||||
;----------------------
|
||||
@@ -1,138 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file of
|
||||
// Golang project:
|
||||
// https://github.com/golang/go/blob/master/LICENSE
|
||||
|
||||
// Using this part of Minio codebase under the license
|
||||
// Apache License Version 2.0 with modifications
|
||||
|
||||
// SHA1 hash algorithm. See RFC 3174.
|
||||
|
||||
package sha1
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type sha1Test struct {
|
||||
out string
|
||||
in string
|
||||
}
|
||||
|
||||
var golden = []sha1Test{
|
||||
{"da39a3ee5e6b4b0d3255bfef95601890afd80709", ""},
|
||||
{"86f7e437faa5a7fce15d1ddcb9eaeaea377667b8", "a"},
|
||||
{"da23614e02469a0d7c7bd1bdab5c9c474b1904dc", "ab"},
|
||||
{"a9993e364706816aba3e25717850c26c9cd0d89d", "abc"},
|
||||
{"81fe8bfe87576c3ecb22426f8e57847382917acf", "abcd"},
|
||||
{"03de6c570bfe24bfc328ccd7ca46b76eadaf4334", "abcde"},
|
||||
{"1f8ac10f23c5b5bc1167bda84b833e5c057a77d2", "abcdef"},
|
||||
{"2fb5e13419fc89246865e7a324f476ec624e8740", "abcdefg"},
|
||||
{"425af12a0743502b322e93a015bcf868e324d56a", "abcdefgh"},
|
||||
{"c63b19f1e4c8b5f76b25c49b8b87f57d8e4872a1", "abcdefghi"},
|
||||
{"d68c19a0a345b7eab78d5e11e991c026ec60db63", "abcdefghij"},
|
||||
{"ebf81ddcbe5bf13aaabdc4d65354fdf2044f38a7", "Discard medicine more than two years old."},
|
||||
{"e5dea09392dd886ca63531aaa00571dc07554bb6", "He who has a shady past knows that nice guys finish last."},
|
||||
{"45988f7234467b94e3e9494434c96ee3609d8f8f", "I wouldn't marry him with a ten foot pole."},
|
||||
{"55dee037eb7460d5a692d1ce11330b260e40c988", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"},
|
||||
{"b7bc5fb91080c7de6b582ea281f8a396d7c0aee8", "The days of the digital watch are numbered. -Tom Stoppard"},
|
||||
{"c3aed9358f7c77f523afe86135f06b95b3999797", "Nepal premier won't resign."},
|
||||
{"6e29d302bf6e3a5e4305ff318d983197d6906bb9", "For every action there is an equal and opposite government program."},
|
||||
{"597f6a540010f94c15d71806a99a2c8710e747bd", "His money is twice tainted: 'taint yours and 'taint mine."},
|
||||
{"6859733b2590a8a091cecf50086febc5ceef1e80", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"},
|
||||
{"514b2630ec089b8aee18795fc0cf1f4860cdacad", "It's a tiny change to the code and not completely disgusting. - Bob Manchek"},
|
||||
{"c5ca0d4a7b6676fc7aa72caa41cc3d5df567ed69", "size: a.out: bad magic"},
|
||||
{"74c51fa9a04eadc8c1bbeaa7fc442f834b90a00a", "The major problem is with sendmail. -Mark Horton"},
|
||||
{"0b4c4ce5f52c3ad2821852a8dc00217fa18b8b66", "Give me a rock, paper and scissors and I will move the world. CCFestoon"},
|
||||
{"3ae7937dd790315beb0f48330e8642237c61550a", "If the enemy is within range, then so are you."},
|
||||
{"410a2b296df92b9a47412b13281df8f830a9f44b", "It's well we cannot hear the screams/That we create in others' dreams."},
|
||||
{"841e7c85ca1adcddbdd0187f1289acb5c642f7f5", "You remind me of a TV show, but that's all right: I watch it anyway."},
|
||||
{"163173b825d03b952601376b25212df66763e1db", "C is as portable as Stonehedge!!"},
|
||||
{"32b0377f2687eb88e22106f133c586ab314d5279", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"},
|
||||
{"0885aaf99b569542fd165fa44e322718f4a984e0", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule"},
|
||||
{"6627d6904d71420b0bf3886ab629623538689f45", "How can you write a big system without C++? -Paul Glick"},
|
||||
}
|
||||
|
||||
func TestGolden(t *testing.T) {
|
||||
for i := 0; i < len(golden); i++ {
|
||||
g := golden[i]
|
||||
s := fmt.Sprintf("%x", Sum1([]byte(g.in)))
|
||||
if s != g.out {
|
||||
t.Fatalf("Sum function: sha1(%s) = %s want %s", g.in, s, g.out)
|
||||
}
|
||||
c := New()
|
||||
for j := 0; j < 3; j++ {
|
||||
if j < 2 {
|
||||
io.WriteString(c, g.in)
|
||||
} else {
|
||||
io.WriteString(c, g.in[0:len(g.in)/2])
|
||||
c.Sum(nil)
|
||||
io.WriteString(c, g.in[len(g.in)/2:])
|
||||
}
|
||||
s := fmt.Sprintf("%x", c.Sum(nil))
|
||||
if s != g.out {
|
||||
t.Fatalf("sha1[%d](%s) = %s want %s", j, g.in, s, g.out)
|
||||
}
|
||||
c.Reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSize(t *testing.T) {
|
||||
c := New()
|
||||
if got := c.Size(); got != Size {
|
||||
t.Errorf("Size = %d; want %d", got, Size)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockSize(t *testing.T) {
|
||||
c := New()
|
||||
if got := c.BlockSize(); got != BlockSize {
|
||||
t.Errorf("BlockSize = %d; want %d", got, BlockSize)
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that blockGeneric (pure Go) and block (in assembly for amd64, 386, arm) match.
|
||||
func TestBlockGeneric(t *testing.T) {
|
||||
gen, asm := New().(*digest), New().(*digest)
|
||||
buf := make([]byte, BlockSize*20) // arbitrary factor
|
||||
rand.Read(buf)
|
||||
blockGeneric(gen, buf)
|
||||
block(asm, buf)
|
||||
if *gen != *asm {
|
||||
t.Error("block and blockGeneric resulted in different states")
|
||||
}
|
||||
}
|
||||
|
||||
var bench = New()
|
||||
var buf = make([]byte, 1024*1024)
|
||||
|
||||
func benchmarkSize(b *testing.B, size int) {
|
||||
b.SetBytes(int64(size))
|
||||
sum := make([]byte, bench.Size())
|
||||
for i := 0; i < b.N; i++ {
|
||||
bench.Reset()
|
||||
bench.Write(buf[:size])
|
||||
bench.Sum(sum[:0])
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkHash8Bytes(b *testing.B) {
|
||||
benchmarkSize(b, 8)
|
||||
}
|
||||
|
||||
func BenchmarkHash1K(b *testing.B) {
|
||||
benchmarkSize(b, 1024)
|
||||
}
|
||||
|
||||
func BenchmarkHash8K(b *testing.B) {
|
||||
benchmarkSize(b, 8192)
|
||||
}
|
||||
|
||||
func BenchmarkHash1M(b *testing.B) {
|
||||
benchmarkSize(b, 1024*1024)
|
||||
}
|
||||
@@ -1,167 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file of
|
||||
// Golang project:
|
||||
// https://github.com/golang/go/blob/master/LICENSE
|
||||
|
||||
// Using this part of Minio codebase under the license
|
||||
// Apache License Version 2.0 with modifications
|
||||
|
||||
// Package sha1 implements the SHA1 hash algorithm as defined in RFC 3174.
|
||||
package sha1
|
||||
|
||||
import (
|
||||
"hash"
|
||||
"io"
|
||||
|
||||
"github.com/minio/minio/pkg/cpu"
|
||||
)
|
||||
|
||||
// The size of a SHA1 checksum in bytes.
|
||||
const Size = 20
|
||||
|
||||
// The blocksize of SHA1 in bytes.
|
||||
const BlockSize = 64
|
||||
|
||||
const (
|
||||
chunk = 64
|
||||
init0 = 0x67452301
|
||||
init1 = 0xEFCDAB89
|
||||
init2 = 0x98BADCFE
|
||||
init3 = 0x10325476
|
||||
init4 = 0xC3D2E1F0
|
||||
)
|
||||
|
||||
// digest represents the partial evaluation of a checksum.
|
||||
type digest struct {
|
||||
h [5]uint32
|
||||
x [chunk]byte
|
||||
nx int
|
||||
len uint64
|
||||
}
|
||||
|
||||
// Reset digest
|
||||
func (d *digest) Reset() {
|
||||
d.h[0] = init0
|
||||
d.h[1] = init1
|
||||
d.h[2] = init2
|
||||
d.h[3] = init3
|
||||
d.h[4] = init4
|
||||
d.nx = 0
|
||||
d.len = 0
|
||||
}
|
||||
|
||||
// New returns a new hash.Hash computing the SHA1 checksum.
|
||||
func New() hash.Hash {
|
||||
d := new(digest)
|
||||
d.Reset()
|
||||
return d
|
||||
}
|
||||
|
||||
func block(dig *digest, p []byte) {
|
||||
switch true {
|
||||
case cpu.HasSSE41() == true:
|
||||
blockSSE3(dig, p)
|
||||
default:
|
||||
blockGeneric(dig, p)
|
||||
}
|
||||
}
|
||||
|
||||
// Return output size
|
||||
func (d *digest) Size() int { return Size }
|
||||
|
||||
// Return checksum blocksize
|
||||
func (d *digest) BlockSize() int { return BlockSize }
|
||||
|
||||
// Write to digest
|
||||
func (d *digest) Write(p []byte) (nn int, err error) {
|
||||
nn = len(p)
|
||||
d.len += uint64(nn)
|
||||
if d.nx > 0 {
|
||||
n := copy(d.x[d.nx:], p)
|
||||
d.nx += n
|
||||
if d.nx == chunk {
|
||||
block(d, d.x[:])
|
||||
d.nx = 0
|
||||
}
|
||||
p = p[n:]
|
||||
}
|
||||
if len(p) >= chunk {
|
||||
n := len(p) &^ (chunk - 1)
|
||||
block(d, p[:n])
|
||||
p = p[n:]
|
||||
}
|
||||
if len(p) > 0 {
|
||||
d.nx = copy(d.x[:], p)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Return checksum bytes
|
||||
func (d *digest) Sum(in []byte) []byte {
|
||||
// Make a copy of d0 so that caller can keep writing and summing.
|
||||
d0 := *d
|
||||
hash := d0.checkSum()
|
||||
return append(in, hash[:]...)
|
||||
}
|
||||
|
||||
// Intermediate checksum function
|
||||
func (d *digest) checkSum() [Size]byte {
|
||||
len := d.len
|
||||
// Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
|
||||
var tmp [64]byte
|
||||
tmp[0] = 0x80
|
||||
if len%64 < 56 {
|
||||
d.Write(tmp[0 : 56-len%64])
|
||||
} else {
|
||||
d.Write(tmp[0 : 64+56-len%64])
|
||||
}
|
||||
|
||||
// Length in bits.
|
||||
len <<= 3
|
||||
for i := uint(0); i < 8; i++ {
|
||||
tmp[i] = byte(len >> (56 - 8*i))
|
||||
}
|
||||
d.Write(tmp[0:8])
|
||||
|
||||
if d.nx != 0 {
|
||||
panic("d.nx != 0")
|
||||
}
|
||||
|
||||
var digest [Size]byte
|
||||
for i, s := range d.h {
|
||||
digest[i*4] = byte(s >> 24)
|
||||
digest[i*4+1] = byte(s >> 16)
|
||||
digest[i*4+2] = byte(s >> 8)
|
||||
digest[i*4+3] = byte(s)
|
||||
}
|
||||
|
||||
return digest
|
||||
}
|
||||
|
||||
/// Convenience functions
|
||||
|
||||
// Sum1 - single caller sha1 helper
|
||||
func Sum1(data []byte) [Size]byte {
|
||||
var d digest
|
||||
d.Reset()
|
||||
d.Write(data)
|
||||
return d.checkSum()
|
||||
}
|
||||
|
||||
// Sum - io.Reader based streaming sha1 helper
|
||||
func Sum(reader io.Reader) ([]byte, error) {
|
||||
h := New()
|
||||
var err error
|
||||
for err == nil {
|
||||
length := 0
|
||||
byteBuffer := make([]byte, 1024*1024)
|
||||
length, err = reader.Read(byteBuffer)
|
||||
byteBuffer = byteBuffer[0:length]
|
||||
h.Write(byteBuffer)
|
||||
}
|
||||
if err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
return h.Sum(nil), nil
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
// !build amd64
|
||||
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2014 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sha1
|
||||
|
||||
//go:generate yasm -f macho64 -DINTEL_SHA1_UPDATE_FUNCNAME=_sha1_update_intel sha1_sse3_amd64.asm -o sha1_sse3_amd64.syso
|
||||
@@ -1,21 +0,0 @@
|
||||
// !build amd64
|
||||
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2014 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sha1
|
||||
|
||||
//go:generate yasm -f elf64 sha1_sse3_amd64.asm -o sha1_sse3_amd64.syso
|
||||
@@ -1,21 +0,0 @@
|
||||
// !build amd64
|
||||
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2014 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sha1
|
||||
|
||||
//go:generate yasm -f win64 -DWIN_ABI=1 sha1_sse3_amd64.asm -o sha1_sse3_amd64.syso
|
||||
@@ -1,29 +0,0 @@
|
||||
// +build amd64
|
||||
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2014 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sha1
|
||||
|
||||
// #include <stdint.h>
|
||||
// #include <stdlib.h>
|
||||
// void sha1_update_intel(int32_t *hash, const char* input, size_t num_blocks);
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
func blockSSE3(dig *digest, p []byte) {
|
||||
C.sha1_update_intel((*C.int32_t)(unsafe.Pointer(&dig.h[0])), (*C.char)(unsafe.Pointer(&p[0])), (C.size_t)(len(p)/chunk))
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
// +build amd64
|
||||
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file of
|
||||
// Golang project:
|
||||
// https://github.com/golang/go/blob/master/LICENSE
|
||||
|
||||
// Using this part of Minio codebase under the license
|
||||
// Apache License Version 2.0 with modifications
|
||||
|
||||
package sha1
|
||||
|
||||
const (
|
||||
_K0 = 0x5A827999
|
||||
_K1 = 0x6ED9EBA1
|
||||
_K2 = 0x8F1BBCDC
|
||||
_K3 = 0xCA62C1D6
|
||||
)
|
||||
|
||||
// blockGeneric is a portable, pure Go version of the SHA1 block step.
|
||||
// It's used by sha1block_generic.go and tests.
|
||||
func blockGeneric(dig *digest, p []byte) {
|
||||
var w [16]uint32
|
||||
|
||||
h0, h1, h2, h3, h4 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4]
|
||||
for len(p) >= chunk {
|
||||
// Can interlace the computation of w with the
|
||||
// rounds below if needed for speed.
|
||||
for i := 0; i < 16; i++ {
|
||||
j := i * 4
|
||||
w[i] = uint32(p[j])<<24 | uint32(p[j+1])<<16 | uint32(p[j+2])<<8 | uint32(p[j+3])
|
||||
}
|
||||
|
||||
a, b, c, d, e := h0, h1, h2, h3, h4
|
||||
|
||||
// Each of the four 20-iteration rounds
|
||||
// differs only in the computation of f and
|
||||
// the choice of K (_K0, _K1, etc).
|
||||
i := 0
|
||||
for ; i < 16; i++ {
|
||||
f := b&c | (^b)&d
|
||||
a5 := a<<5 | a>>(32-5)
|
||||
b30 := b<<30 | b>>(32-30)
|
||||
t := a5 + f + e + w[i&0xf] + _K0
|
||||
a, b, c, d, e = t, a, b30, c, d
|
||||
}
|
||||
for ; i < 20; i++ {
|
||||
tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf]
|
||||
w[i&0xf] = tmp<<1 | tmp>>(32-1)
|
||||
|
||||
f := b&c | (^b)&d
|
||||
a5 := a<<5 | a>>(32-5)
|
||||
b30 := b<<30 | b>>(32-30)
|
||||
t := a5 + f + e + w[i&0xf] + _K0
|
||||
a, b, c, d, e = t, a, b30, c, d
|
||||
}
|
||||
for ; i < 40; i++ {
|
||||
tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf]
|
||||
w[i&0xf] = tmp<<1 | tmp>>(32-1)
|
||||
f := b ^ c ^ d
|
||||
a5 := a<<5 | a>>(32-5)
|
||||
b30 := b<<30 | b>>(32-30)
|
||||
t := a5 + f + e + w[i&0xf] + _K1
|
||||
a, b, c, d, e = t, a, b30, c, d
|
||||
}
|
||||
for ; i < 60; i++ {
|
||||
tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf]
|
||||
w[i&0xf] = tmp<<1 | tmp>>(32-1)
|
||||
f := ((b | c) & d) | (b & c)
|
||||
|
||||
a5 := a<<5 | a>>(32-5)
|
||||
b30 := b<<30 | b>>(32-30)
|
||||
t := a5 + f + e + w[i&0xf] + _K2
|
||||
a, b, c, d, e = t, a, b30, c, d
|
||||
}
|
||||
for ; i < 80; i++ {
|
||||
tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf]
|
||||
w[i&0xf] = tmp<<1 | tmp>>(32-1)
|
||||
f := b ^ c ^ d
|
||||
a5 := a<<5 | a>>(32-5)
|
||||
b30 := b<<30 | b>>(32-30)
|
||||
t := a5 + f + e + w[i&0xf] + _K3
|
||||
a, b, c, d, e = t, a, b30, c, d
|
||||
}
|
||||
|
||||
h0 += a
|
||||
h1 += b
|
||||
h2 += c
|
||||
h3 += d
|
||||
h4 += e
|
||||
|
||||
p = p[chunk:]
|
||||
}
|
||||
dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4] = h0, h1, h2, h3, h4
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
// +build amd64
|
||||
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2014 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sha1
|
||||
|
||||
// #cgo CFLAGS: -DHAS_AVX2
|
||||
// #include <stdint.h>
|
||||
// #include <stdlib.h>
|
||||
// void sha1_transform(int32_t *hash, const char* input, size_t num_blocks);
|
||||
// void sha1_update_intel(int32_t *hash, const char* input, size_t num_blocks);
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
func blockAVX2(dig *digest, p []byte) {
|
||||
C.sha1_transform((*C.int32_t)(unsafe.Pointer(&dig.h[0])), (*C.char)(unsafe.Pointer(&p[0])), (C.size_t)(len(p)/chunk))
|
||||
}
|
||||
|
||||
func blockSSE3(dig *digest, p []byte) {
|
||||
C.sha1_update_intel((*C.int32_t)(unsafe.Pointer(&dig.h[0])), (*C.char)(unsafe.Pointer(&p[0])), (C.size_t)(len(p)/chunk))
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
// +build amd64
|
||||
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2014 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sha1
|
||||
|
||||
// #include <stdint.h>
|
||||
// #include <stdlib.h>
|
||||
// void sha1_update_intel(int32_t *hash, const char* input, size_t num_blocks);
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
func blockSSE3(dig *digest, p []byte) {
|
||||
C.sha1_update_intel((*C.int32_t)(unsafe.Pointer(&dig.h[0])), (*C.char)(unsafe.Pointer(&p[0])), (C.size_t)(len(p)/chunk))
|
||||
}
|
||||
@@ -1,202 +0,0 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -1,759 +0,0 @@
|
||||
########################################################################
|
||||
# Implement fast SHA-256 with AVX1 instructions. (x86_64)
|
||||
#
|
||||
# Copyright (C) 2013 Intel Corporation.
|
||||
#
|
||||
# Authors:
|
||||
# James Guilford <james.guilford@intel.com>
|
||||
# Kirk Yap <kirk.s.yap@intel.com>
|
||||
# Tim Chen <tim.c.chen@linux.intel.com>
|
||||
#
|
||||
# This software is available to you under a choice of one of two
|
||||
# licenses. You may choose to be licensed under the terms of the GNU
|
||||
# General Public License (GPL) Version 2, available from the file
|
||||
# COPYING in the main directory of this source tree, or the
|
||||
# OpenIB.org BSD license below:
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or
|
||||
# without modification, are permitted provided that the following
|
||||
# conditions are met:
|
||||
#
|
||||
# - Redistributions of source code must retain the above
|
||||
# copyright notice, this list of conditions and the following
|
||||
# disclaimer.
|
||||
#
|
||||
# - Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following
|
||||
# disclaimer in the documentation and/or other materials
|
||||
# provided with the distribution.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
########################################################################
|
||||
#
|
||||
# This code is described in an Intel White-Paper:
|
||||
# "Fast SHA-256 Implementations on Intel Architecture Processors"
|
||||
#
|
||||
# To find it, surf to http://www.intel.com/p/en_US/embedded
|
||||
# and search for that title.
|
||||
#
|
||||
########################################################################
|
||||
# This code schedules 1 block at a time, with 4 lanes per block
|
||||
########################################################################
|
||||
# Using this part of Minio codebase under the license
|
||||
# Apache License Version 2.0 with modifications
|
||||
##
|
||||
|
||||
#ifdef HAS_AVX
|
||||
#ifndef ENTRY
|
||||
#define ENTRY(name) \
|
||||
.globl name ; \
|
||||
.align 4,0x90 ; \
|
||||
name:
|
||||
#endif
|
||||
|
||||
#ifndef END
|
||||
#define END(name) \
|
||||
.size name, .-name
|
||||
#endif
|
||||
|
||||
#ifndef ENDPROC
|
||||
#define ENDPROC(name) \
|
||||
.type name, @function ; \
|
||||
END(name)
|
||||
#endif
|
||||
|
||||
#define NUM_INVALID 100
|
||||
|
||||
#define TYPE_R32 0
|
||||
#define TYPE_R64 1
|
||||
#define TYPE_XMM 2
|
||||
#define TYPE_INVALID 100
|
||||
|
||||
.macro R32_NUM opd r32
|
||||
\opd = NUM_INVALID
|
||||
.ifc \r32,%eax
|
||||
\opd = 0
|
||||
.endif
|
||||
.ifc \r32,%ecx
|
||||
\opd = 1
|
||||
.endif
|
||||
.ifc \r32,%edx
|
||||
\opd = 2
|
||||
.endif
|
||||
.ifc \r32,%ebx
|
||||
\opd = 3
|
||||
.endif
|
||||
.ifc \r32,%esp
|
||||
\opd = 4
|
||||
.endif
|
||||
.ifc \r32,%ebp
|
||||
\opd = 5
|
||||
.endif
|
||||
.ifc \r32,%esi
|
||||
\opd = 6
|
||||
.endif
|
||||
.ifc \r32,%edi
|
||||
\opd = 7
|
||||
.endif
|
||||
#ifdef X86_64
|
||||
.ifc \r32,%r8d
|
||||
\opd = 8
|
||||
.endif
|
||||
.ifc \r32,%r9d
|
||||
\opd = 9
|
||||
.endif
|
||||
.ifc \r32,%r10d
|
||||
\opd = 10
|
||||
.endif
|
||||
.ifc \r32,%r11d
|
||||
\opd = 11
|
||||
.endif
|
||||
.ifc \r32,%r12d
|
||||
\opd = 12
|
||||
.endif
|
||||
.ifc \r32,%r13d
|
||||
\opd = 13
|
||||
.endif
|
||||
.ifc \r32,%r14d
|
||||
\opd = 14
|
||||
.endif
|
||||
.ifc \r32,%r15d
|
||||
\opd = 15
|
||||
.endif
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro R64_NUM opd r64
|
||||
\opd = NUM_INVALID
|
||||
#ifdef X86_64
|
||||
.ifc \r64,%rax
|
||||
\opd = 0
|
||||
.endif
|
||||
.ifc \r64,%rcx
|
||||
\opd = 1
|
||||
.endif
|
||||
.ifc \r64,%rdx
|
||||
\opd = 2
|
||||
.endif
|
||||
.ifc \r64,%rbx
|
||||
\opd = 3
|
||||
.endif
|
||||
.ifc \r64,%rsp
|
||||
\opd = 4
|
||||
.endif
|
||||
.ifc \r64,%rbp
|
||||
\opd = 5
|
||||
.endif
|
||||
.ifc \r64,%rsi
|
||||
\opd = 6
|
||||
.endif
|
||||
.ifc \r64,%rdi
|
||||
\opd = 7
|
||||
.endif
|
||||
.ifc \r64,%r8
|
||||
\opd = 8
|
||||
.endif
|
||||
.ifc \r64,%r9
|
||||
\opd = 9
|
||||
.endif
|
||||
.ifc \r64,%r10
|
||||
\opd = 10
|
||||
.endif
|
||||
.ifc \r64,%r11
|
||||
\opd = 11
|
||||
.endif
|
||||
.ifc \r64,%r12
|
||||
\opd = 12
|
||||
.endif
|
||||
.ifc \r64,%r13
|
||||
\opd = 13
|
||||
.endif
|
||||
.ifc \r64,%r14
|
||||
\opd = 14
|
||||
.endif
|
||||
.ifc \r64,%r15
|
||||
\opd = 15
|
||||
.endif
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro XMM_NUM opd xmm
|
||||
\opd = NUM_INVALID
|
||||
.ifc \xmm,%xmm0
|
||||
\opd = 0
|
||||
.endif
|
||||
.ifc \xmm,%xmm1
|
||||
\opd = 1
|
||||
.endif
|
||||
.ifc \xmm,%xmm2
|
||||
\opd = 2
|
||||
.endif
|
||||
.ifc \xmm,%xmm3
|
||||
\opd = 3
|
||||
.endif
|
||||
.ifc \xmm,%xmm4
|
||||
\opd = 4
|
||||
.endif
|
||||
.ifc \xmm,%xmm5
|
||||
\opd = 5
|
||||
.endif
|
||||
.ifc \xmm,%xmm6
|
||||
\opd = 6
|
||||
.endif
|
||||
.ifc \xmm,%xmm7
|
||||
\opd = 7
|
||||
.endif
|
||||
.ifc \xmm,%xmm8
|
||||
\opd = 8
|
||||
.endif
|
||||
.ifc \xmm,%xmm9
|
||||
\opd = 9
|
||||
.endif
|
||||
.ifc \xmm,%xmm10
|
||||
\opd = 10
|
||||
.endif
|
||||
.ifc \xmm,%xmm11
|
||||
\opd = 11
|
||||
.endif
|
||||
.ifc \xmm,%xmm12
|
||||
\opd = 12
|
||||
.endif
|
||||
.ifc \xmm,%xmm13
|
||||
\opd = 13
|
||||
.endif
|
||||
.ifc \xmm,%xmm14
|
||||
\opd = 14
|
||||
.endif
|
||||
.ifc \xmm,%xmm15
|
||||
\opd = 15
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro TYPE type reg
|
||||
R32_NUM reg_type_r32 \reg
|
||||
R64_NUM reg_type_r64 \reg
|
||||
XMM_NUM reg_type_xmm \reg
|
||||
.if reg_type_r64 <> NUM_INVALID
|
||||
\type = TYPE_R64
|
||||
.elseif reg_type_r32 <> NUM_INVALID
|
||||
\type = TYPE_R32
|
||||
.elseif reg_type_xmm <> NUM_INVALID
|
||||
\type = TYPE_XMM
|
||||
.else
|
||||
\type = TYPE_INVALID
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro PFX_OPD_SIZE
|
||||
.byte 0x66
|
||||
.endm
|
||||
|
||||
.macro PFX_REX opd1 opd2 W=0
|
||||
.if ((\opd1 | \opd2) & 8) || \W
|
||||
.byte 0x40 | ((\opd1 & 8) >> 3) | ((\opd2 & 8) >> 1) | (\W << 3)
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro MODRM mod opd1 opd2
|
||||
.byte \mod | (\opd1 & 7) | ((\opd2 & 7) << 3)
|
||||
.endm
|
||||
|
||||
.macro PSHUFB_XMM xmm1 xmm2
|
||||
XMM_NUM pshufb_opd1 \xmm1
|
||||
XMM_NUM pshufb_opd2 \xmm2
|
||||
PFX_OPD_SIZE
|
||||
PFX_REX pshufb_opd1 pshufb_opd2
|
||||
.byte 0x0f, 0x38, 0x00
|
||||
MODRM 0xc0 pshufb_opd1 pshufb_opd2
|
||||
.endm
|
||||
|
||||
.macro PCLMULQDQ imm8 xmm1 xmm2
|
||||
XMM_NUM clmul_opd1 \xmm1
|
||||
XMM_NUM clmul_opd2 \xmm2
|
||||
PFX_OPD_SIZE
|
||||
PFX_REX clmul_opd1 clmul_opd2
|
||||
.byte 0x0f, 0x3a, 0x44
|
||||
MODRM 0xc0 clmul_opd1 clmul_opd2
|
||||
.byte \imm8
|
||||
.endm
|
||||
|
||||
.macro PEXTRD imm8 xmm gpr
|
||||
R32_NUM extrd_opd1 \gpr
|
||||
XMM_NUM extrd_opd2 \xmm
|
||||
PFX_OPD_SIZE
|
||||
PFX_REX extrd_opd1 extrd_opd2
|
||||
.byte 0x0f, 0x3a, 0x16
|
||||
MODRM 0xc0 extrd_opd1 extrd_opd2
|
||||
.byte \imm8
|
||||
.endm
|
||||
|
||||
.macro MOVQ_R64_XMM opd1 opd2
|
||||
TYPE movq_r64_xmm_opd1_type \opd1
|
||||
.if movq_r64_xmm_opd1_type == TYPE_XMM
|
||||
XMM_NUM movq_r64_xmm_opd1 \opd1
|
||||
R64_NUM movq_r64_xmm_opd2 \opd2
|
||||
.else
|
||||
R64_NUM movq_r64_xmm_opd1 \opd1
|
||||
XMM_NUM movq_r64_xmm_opd2 \opd2
|
||||
.endif
|
||||
PFX_OPD_SIZE
|
||||
PFX_REX movq_r64_xmm_opd1 movq_r64_xmm_opd2 1
|
||||
.if movq_r64_xmm_opd1_type == TYPE_XMM
|
||||
.byte 0x0f, 0x7e
|
||||
.else
|
||||
.byte 0x0f, 0x6e
|
||||
.endif
|
||||
MODRM 0xc0 movq_r64_xmm_opd1 movq_r64_xmm_opd2
|
||||
.endm
|
||||
|
||||
## assume buffers not aligned
|
||||
#define VMOVDQ vmovdqu
|
||||
|
||||
################################ Define Macros
|
||||
|
||||
# addm [mem], reg
|
||||
# Add reg to mem using reg-mem add and store
|
||||
.macro addm p1 p2
|
||||
add \p1, \p2
|
||||
mov \p2, \p1
|
||||
.endm
|
||||
|
||||
|
||||
.macro MY_ROR p1 p2
|
||||
shld $(32-(\p1)), \p2, \p2
|
||||
.endm
|
||||
|
||||
################################
|
||||
|
||||
# COPY_XMM_AND_BSWAP xmm, [mem], byte_flip_mask
|
||||
# Load xmm with mem and byte swap each dword
|
||||
.macro COPY_XMM_AND_BSWAP p1 p2 p3
|
||||
VMOVDQ \p2, \p1
|
||||
vpshufb \p3, \p1, \p1
|
||||
.endm
|
||||
|
||||
################################
|
||||
|
||||
X0 = %xmm4
|
||||
X1 = %xmm5
|
||||
X2 = %xmm6
|
||||
X3 = %xmm7
|
||||
|
||||
XTMP0 = %xmm0
|
||||
XTMP1 = %xmm1
|
||||
XTMP2 = %xmm2
|
||||
XTMP3 = %xmm3
|
||||
XTMP4 = %xmm8
|
||||
XFER = %xmm9
|
||||
XTMP5 = %xmm11
|
||||
|
||||
SHUF_00BA = %xmm10 # shuffle xBxA -> 00BA
|
||||
SHUF_DC00 = %xmm12 # shuffle xDxC -> DC00
|
||||
BYTE_FLIP_MASK = %xmm13
|
||||
|
||||
NUM_BLKS = %rdx # 3rd arg
|
||||
CTX = %rsi # 2nd arg
|
||||
INP = %rdi # 1st arg
|
||||
|
||||
SRND = %rdi # clobbers INP
|
||||
c = %ecx
|
||||
d = %r8d
|
||||
e = %edx
|
||||
TBL = %rbp
|
||||
a = %eax
|
||||
b = %ebx
|
||||
|
||||
f = %r9d
|
||||
g = %r10d
|
||||
h = %r11d
|
||||
|
||||
y0 = %r13d
|
||||
y1 = %r14d
|
||||
y2 = %r15d
|
||||
|
||||
|
||||
_INP_END_SIZE = 8
|
||||
_INP_SIZE = 8
|
||||
_XFER_SIZE = 16
|
||||
_XMM_SAVE_SIZE = 0
|
||||
|
||||
_INP_END = 0
|
||||
_INP = _INP_END + _INP_END_SIZE
|
||||
_XFER = _INP + _INP_SIZE
|
||||
_XMM_SAVE = _XFER + _XFER_SIZE
|
||||
STACK_SIZE = _XMM_SAVE + _XMM_SAVE_SIZE
|
||||
|
||||
# rotate_Xs
|
||||
# Rotate values of symbols X0...X3
|
||||
.macro rotate_Xs
|
||||
X_ = X0
|
||||
X0 = X1
|
||||
X1 = X2
|
||||
X2 = X3
|
||||
X3 = X_
|
||||
.endm
|
||||
|
||||
# ROTATE_ARGS
|
||||
# Rotate values of symbols a...h
|
||||
.macro ROTATE_ARGS
|
||||
TMP_ = h
|
||||
h = g
|
||||
g = f
|
||||
f = e
|
||||
e = d
|
||||
d = c
|
||||
c = b
|
||||
b = a
|
||||
a = TMP_
|
||||
.endm
|
||||
|
||||
.macro FOUR_ROUNDS_AND_SCHED
|
||||
## compute s0 four at a time and s1 two at a time
|
||||
## compute W[-16] + W[-7] 4 at a time
|
||||
|
||||
mov e, y0 # y0 = e
|
||||
MY_ROR (25-11), y0 # y0 = e >> (25-11)
|
||||
mov a, y1 # y1 = a
|
||||
vpalignr $4, X2, X3, XTMP0 # XTMP0 = W[-7]
|
||||
MY_ROR (22-13), y1 # y1 = a >> (22-13)
|
||||
xor e, y0 # y0 = e ^ (e >> (25-11))
|
||||
mov f, y2 # y2 = f
|
||||
MY_ROR (11-6), y0 # y0 = (e >> (11-6)) ^ (e >> (25-6))
|
||||
xor a, y1 # y1 = a ^ (a >> (22-13)
|
||||
xor g, y2 # y2 = f^g
|
||||
vpaddd X0, XTMP0, XTMP0 # XTMP0 = W[-7] + W[-16]
|
||||
xor e, y0 # y0 = e ^ (e >> (11-6)) ^ (e >> (25-6))
|
||||
and e, y2 # y2 = (f^g)&e
|
||||
MY_ROR (13-2), y1 # y1 = (a >> (13-2)) ^ (a >> (22-2))
|
||||
## compute s0
|
||||
vpalignr $4, X0, X1, XTMP1 # XTMP1 = W[-15]
|
||||
xor a, y1 # y1 = a ^ (a >> (13-2)) ^ (a >> (22-2))
|
||||
MY_ROR 6, y0 # y0 = S1 = (e>>6) & (e>>11) ^ (e>>25)
|
||||
xor g, y2 # y2 = CH = ((f^g)&e)^g
|
||||
MY_ROR 2, y1 # y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22)
|
||||
add y0, y2 # y2 = S1 + CH
|
||||
add _XFER(%rsp), y2 # y2 = k + w + S1 + CH
|
||||
mov a, y0 # y0 = a
|
||||
add y2, h # h = h + S1 + CH + k + w
|
||||
mov a, y2 # y2 = a
|
||||
vpsrld $7, XTMP1, XTMP2
|
||||
or c, y0 # y0 = a|c
|
||||
add h, d # d = d + h + S1 + CH + k + w
|
||||
and c, y2 # y2 = a&c
|
||||
vpslld $(32-7), XTMP1, XTMP3
|
||||
and b, y0 # y0 = (a|c)&b
|
||||
add y1, h # h = h + S1 + CH + k + w + S0
|
||||
vpor XTMP2, XTMP3, XTMP3 # XTMP1 = W[-15] MY_ROR 7
|
||||
or y2, y0 # y0 = MAJ = (a|c)&b)|(a&c)
|
||||
add y0, h # h = h + S1 + CH + k + w + S0 + MAJ
|
||||
ROTATE_ARGS
|
||||
mov e, y0 # y0 = e
|
||||
mov a, y1 # y1 = a
|
||||
MY_ROR (25-11), y0 # y0 = e >> (25-11)
|
||||
xor e, y0 # y0 = e ^ (e >> (25-11))
|
||||
mov f, y2 # y2 = f
|
||||
MY_ROR (22-13), y1 # y1 = a >> (22-13)
|
||||
vpsrld $18, XTMP1, XTMP2 #
|
||||
xor a, y1 # y1 = a ^ (a >> (22-13)
|
||||
MY_ROR (11-6), y0 # y0 = (e >> (11-6)) ^ (e >> (25-6))
|
||||
xor g, y2 # y2 = f^g
|
||||
vpsrld $3, XTMP1, XTMP4 # XTMP4 = W[-15] >> 3
|
||||
MY_ROR (13-2), y1 # y1 = (a >> (13-2)) ^ (a >> (22-2))
|
||||
xor e, y0 # y0 = e ^ (e >> (11-6)) ^ (e >> (25-6))
|
||||
and e, y2 # y2 = (f^g)&e
|
||||
MY_ROR 6, y0 # y0 = S1 = (e>>6) & (e>>11) ^ (e>>25)
|
||||
vpslld $(32-18), XTMP1, XTMP1
|
||||
xor a, y1 # y1 = a ^ (a >> (13-2)) ^ (a >> (22-2))
|
||||
xor g, y2 # y2 = CH = ((f^g)&e)^g
|
||||
vpxor XTMP1, XTMP3, XTMP3 #
|
||||
add y0, y2 # y2 = S1 + CH
|
||||
add (1*4 + _XFER)(%rsp), y2 # y2 = k + w + S1 + CH
|
||||
MY_ROR 2, y1 # y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22)
|
||||
vpxor XTMP2, XTMP3, XTMP3 # XTMP1 = W[-15] MY_ROR 7 ^ W[-15] MY_ROR
|
||||
mov a, y0 # y0 = a
|
||||
add y2, h # h = h + S1 + CH + k + w
|
||||
mov a, y2 # y2 = a
|
||||
vpxor XTMP4, XTMP3, XTMP1 # XTMP1 = s0
|
||||
or c, y0 # y0 = a|c
|
||||
add h, d # d = d + h + S1 + CH + k + w
|
||||
and c, y2 # y2 = a&c
|
||||
## compute low s1
|
||||
vpshufd $0b11111010, X3, XTMP2 # XTMP2 = W[-2] {BBAA}
|
||||
and b, y0 # y0 = (a|c)&b
|
||||
add y1, h # h = h + S1 + CH + k + w + S0
|
||||
vpaddd XTMP1, XTMP0, XTMP0 # XTMP0 = W[-16] + W[-7] + s0
|
||||
or y2, y0 # y0 = MAJ = (a|c)&b)|(a&c)
|
||||
add y0, h # h = h + S1 + CH + k + w + S0 + MAJ
|
||||
ROTATE_ARGS
|
||||
mov e, y0 # y0 = e
|
||||
mov a, y1 # y1 = a
|
||||
MY_ROR (25-11), y0 # y0 = e >> (25-11)
|
||||
xor e, y0 # y0 = e ^ (e >> (25-11))
|
||||
MY_ROR (22-13), y1 # y1 = a >> (22-13)
|
||||
mov f, y2 # y2 = f
|
||||
xor a, y1 # y1 = a ^ (a >> (22-13)
|
||||
MY_ROR (11-6), y0 # y0 = (e >> (11-6)) ^ (e >> (25-6))
|
||||
vpsrld $10, XTMP2, XTMP4 # XTMP4 = W[-2] >> 10 {BBAA}
|
||||
xor g, y2 # y2 = f^g
|
||||
vpsrlq $19, XTMP2, XTMP3 # XTMP3 = W[-2] MY_ROR 19 {xBxA}
|
||||
xor e, y0 # y0 = e ^ (e >> (11-6)) ^ (e >> (25-6))
|
||||
and e, y2 # y2 = (f^g)&e
|
||||
vpsrlq $17, XTMP2, XTMP2 # XTMP2 = W[-2] MY_ROR 17 {xBxA}
|
||||
MY_ROR (13-2), y1 # y1 = (a >> (13-2)) ^ (a >> (22-2))
|
||||
xor a, y1 # y1 = a ^ (a >> (13-2)) ^ (a >> (22-2))
|
||||
xor g, y2 # y2 = CH = ((f^g)&e)^g
|
||||
MY_ROR 6, y0 # y0 = S1 = (e>>6) & (e>>11) ^ (e>>25)
|
||||
vpxor XTMP3, XTMP2, XTMP2 #
|
||||
add y0, y2 # y2 = S1 + CH
|
||||
MY_ROR 2, y1 # y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22)
|
||||
add (2*4 + _XFER)(%rsp), y2 # y2 = k + w + S1 + CH
|
||||
vpxor XTMP2, XTMP4, XTMP4 # XTMP4 = s1 {xBxA}
|
||||
mov a, y0 # y0 = a
|
||||
add y2, h # h = h + S1 + CH + k + w
|
||||
mov a, y2 # y2 = a
|
||||
vpshufb SHUF_00BA, XTMP4, XTMP4 # XTMP4 = s1 {00BA}
|
||||
or c, y0 # y0 = a|c
|
||||
add h, d # d = d + h + S1 + CH + k + w
|
||||
and c, y2 # y2 = a&c
|
||||
vpaddd XTMP4, XTMP0, XTMP0 # XTMP0 = {..., ..., W[1], W[0]}
|
||||
and b, y0 # y0 = (a|c)&b
|
||||
add y1, h # h = h + S1 + CH + k + w + S0
|
||||
## compute high s1
|
||||
vpshufd $0b01010000, XTMP0, XTMP2 # XTMP2 = W[-2] {DDCC}
|
||||
or y2, y0 # y0 = MAJ = (a|c)&b)|(a&c)
|
||||
add y0, h # h = h + S1 + CH + k + w + S0 + MAJ
|
||||
ROTATE_ARGS
|
||||
mov e, y0 # y0 = e
|
||||
MY_ROR (25-11), y0 # y0 = e >> (25-11)
|
||||
mov a, y1 # y1 = a
|
||||
MY_ROR (22-13), y1 # y1 = a >> (22-13)
|
||||
xor e, y0 # y0 = e ^ (e >> (25-11))
|
||||
mov f, y2 # y2 = f
|
||||
MY_ROR (11-6), y0 # y0 = (e >> (11-6)) ^ (e >> (25-6))
|
||||
vpsrld $10, XTMP2, XTMP5 # XTMP5 = W[-2] >> 10 {DDCC}
|
||||
xor a, y1 # y1 = a ^ (a >> (22-13)
|
||||
xor g, y2 # y2 = f^g
|
||||
vpsrlq $19, XTMP2, XTMP3 # XTMP3 = W[-2] MY_ROR 19 {xDxC}
|
||||
xor e, y0 # y0 = e ^ (e >> (11-6)) ^ (e >> (25-6))
|
||||
and e, y2 # y2 = (f^g)&e
|
||||
MY_ROR (13-2), y1 # y1 = (a >> (13-2)) ^ (a >> (22-2))
|
||||
vpsrlq $17, XTMP2, XTMP2 # XTMP2 = W[-2] MY_ROR 17 {xDxC}
|
||||
xor a, y1 # y1 = a ^ (a >> (13-2)) ^ (a >> (22-2))
|
||||
MY_ROR 6, y0 # y0 = S1 = (e>>6) & (e>>11) ^ (e>>25)
|
||||
xor g, y2 # y2 = CH = ((f^g)&e)^g
|
||||
vpxor XTMP3, XTMP2, XTMP2
|
||||
MY_ROR 2, y1 # y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22)
|
||||
add y0, y2 # y2 = S1 + CH
|
||||
add (3*4 + _XFER)(%rsp), y2 # y2 = k + w + S1 + CH
|
||||
vpxor XTMP2, XTMP5, XTMP5 # XTMP5 = s1 {xDxC}
|
||||
mov a, y0 # y0 = a
|
||||
add y2, h # h = h + S1 + CH + k + w
|
||||
mov a, y2 # y2 = a
|
||||
vpshufb SHUF_DC00, XTMP5, XTMP5 # XTMP5 = s1 {DC00}
|
||||
or c, y0 # y0 = a|c
|
||||
add h, d # d = d + h + S1 + CH + k + w
|
||||
and c, y2 # y2 = a&c
|
||||
vpaddd XTMP0, XTMP5, X0 # X0 = {W[3], W[2], W[1], W[0]}
|
||||
and b, y0 # y0 = (a|c)&b
|
||||
add y1, h # h = h + S1 + CH + k + w + S0
|
||||
or y2, y0 # y0 = MAJ = (a|c)&b)|(a&c)
|
||||
add y0, h # h = h + S1 + CH + k + w + S0 + MAJ
|
||||
ROTATE_ARGS
|
||||
rotate_Xs
|
||||
.endm
|
||||
|
||||
## input is [rsp + _XFER + %1 * 4]
|
||||
.macro DO_ROUND round
|
||||
mov e, y0 # y0 = e
|
||||
MY_ROR (25-11), y0 # y0 = e >> (25-11)
|
||||
mov a, y1 # y1 = a
|
||||
xor e, y0 # y0 = e ^ (e >> (25-11))
|
||||
MY_ROR (22-13), y1 # y1 = a >> (22-13)
|
||||
mov f, y2 # y2 = f
|
||||
xor a, y1 # y1 = a ^ (a >> (22-13)
|
||||
MY_ROR (11-6), y0 # y0 = (e >> (11-6)) ^ (e >> (25-6))
|
||||
xor g, y2 # y2 = f^g
|
||||
xor e, y0 # y0 = e ^ (e >> (11-6)) ^ (e >> (25-6))
|
||||
MY_ROR (13-2), y1 # y1 = (a >> (13-2)) ^ (a >> (22-2))
|
||||
and e, y2 # y2 = (f^g)&e
|
||||
xor a, y1 # y1 = a ^ (a >> (13-2)) ^ (a >> (22-2))
|
||||
MY_ROR 6, y0 # y0 = S1 = (e>>6) & (e>>11) ^ (e>>25)
|
||||
xor g, y2 # y2 = CH = ((f^g)&e)^g
|
||||
add y0, y2 # y2 = S1 + CH
|
||||
MY_ROR 2, y1 # y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22)
|
||||
offset = \round * 4 + _XFER #
|
||||
add offset(%rsp), y2 # y2 = k + w + S1 + CH
|
||||
mov a, y0 # y0 = a
|
||||
add y2, h # h = h + S1 + CH + k + w
|
||||
mov a, y2 # y2 = a
|
||||
or c, y0 # y0 = a|c
|
||||
add h, d # d = d + h + S1 + CH + k + w
|
||||
and c, y2 # y2 = a&c
|
||||
and b, y0 # y0 = (a|c)&b
|
||||
add y1, h # h = h + S1 + CH + k + w + S0
|
||||
or y2, y0 # y0 = MAJ = (a|c)&b)|(a&c)
|
||||
add y0, h # h = h + S1 + CH + k + w + S0 + MAJ
|
||||
ROTATE_ARGS
|
||||
.endm
|
||||
|
||||
########################################################################
|
||||
## void sha256_transform_avx(void *input_data, UINT32 digest[8], UINT64 num_blks)
|
||||
## arg 1 : pointer to input data
|
||||
## arg 2 : pointer to digest
|
||||
## arg 3 : Num blocks
|
||||
########################################################################
|
||||
.text
|
||||
ENTRY(sha256_transform_avx)
|
||||
.align 32
|
||||
pushq %rbx
|
||||
pushq %rbp
|
||||
pushq %r13
|
||||
pushq %r14
|
||||
pushq %r15
|
||||
pushq %r12
|
||||
|
||||
mov %rsp, %r12
|
||||
subq $STACK_SIZE, %rsp # allocate stack space
|
||||
and $~15, %rsp # align stack pointer
|
||||
|
||||
shl $6, NUM_BLKS # convert to bytes
|
||||
jz done_hash
|
||||
add INP, NUM_BLKS # pointer to end of data
|
||||
mov NUM_BLKS, _INP_END(%rsp)
|
||||
|
||||
## load initial digest
|
||||
mov 4*0(CTX), a
|
||||
mov 4*1(CTX), b
|
||||
mov 4*2(CTX), c
|
||||
mov 4*3(CTX), d
|
||||
mov 4*4(CTX), e
|
||||
mov 4*5(CTX), f
|
||||
mov 4*6(CTX), g
|
||||
mov 4*7(CTX), h
|
||||
|
||||
vmovdqa PSHUFFLE_BYTE_FLIP_MASK(%rip), BYTE_FLIP_MASK
|
||||
vmovdqa _SHUF_00BA(%rip), SHUF_00BA
|
||||
vmovdqa _SHUF_DC00(%rip), SHUF_DC00
|
||||
loop0:
|
||||
lea K256(%rip), TBL
|
||||
|
||||
## byte swap first 16 dwords
|
||||
COPY_XMM_AND_BSWAP X0, 0*16(INP), BYTE_FLIP_MASK
|
||||
COPY_XMM_AND_BSWAP X1, 1*16(INP), BYTE_FLIP_MASK
|
||||
COPY_XMM_AND_BSWAP X2, 2*16(INP), BYTE_FLIP_MASK
|
||||
COPY_XMM_AND_BSWAP X3, 3*16(INP), BYTE_FLIP_MASK
|
||||
|
||||
mov INP, _INP(%rsp)
|
||||
|
||||
## schedule 48 input dwords, by doing 3 rounds of 16 each
|
||||
mov $3, SRND
|
||||
.align 16
|
||||
loop1:
|
||||
vpaddd (TBL), X0, XFER
|
||||
vmovdqa XFER, _XFER(%rsp)
|
||||
FOUR_ROUNDS_AND_SCHED
|
||||
|
||||
vpaddd 1*16(TBL), X0, XFER
|
||||
vmovdqa XFER, _XFER(%rsp)
|
||||
FOUR_ROUNDS_AND_SCHED
|
||||
|
||||
vpaddd 2*16(TBL), X0, XFER
|
||||
vmovdqa XFER, _XFER(%rsp)
|
||||
FOUR_ROUNDS_AND_SCHED
|
||||
|
||||
vpaddd 3*16(TBL), X0, XFER
|
||||
vmovdqa XFER, _XFER(%rsp)
|
||||
add $4*16, TBL
|
||||
FOUR_ROUNDS_AND_SCHED
|
||||
|
||||
sub $1, SRND
|
||||
jne loop1
|
||||
|
||||
mov $2, SRND
|
||||
loop2:
|
||||
vpaddd (TBL), X0, XFER
|
||||
vmovdqa XFER, _XFER(%rsp)
|
||||
DO_ROUND 0
|
||||
DO_ROUND 1
|
||||
DO_ROUND 2
|
||||
DO_ROUND 3
|
||||
|
||||
vpaddd 1*16(TBL), X1, XFER
|
||||
vmovdqa XFER, _XFER(%rsp)
|
||||
add $2*16, TBL
|
||||
DO_ROUND 0
|
||||
DO_ROUND 1
|
||||
DO_ROUND 2
|
||||
DO_ROUND 3
|
||||
|
||||
vmovdqa X2, X0
|
||||
vmovdqa X3, X1
|
||||
|
||||
sub $1, SRND
|
||||
jne loop2
|
||||
|
||||
addm (4*0)(CTX),a
|
||||
addm (4*1)(CTX),b
|
||||
addm (4*2)(CTX),c
|
||||
addm (4*3)(CTX),d
|
||||
addm (4*4)(CTX),e
|
||||
addm (4*5)(CTX),f
|
||||
addm (4*6)(CTX),g
|
||||
addm (4*7)(CTX),h
|
||||
|
||||
mov _INP(%rsp), INP
|
||||
add $64, INP
|
||||
cmp _INP_END(%rsp), INP
|
||||
jne loop0
|
||||
|
||||
done_hash:
|
||||
|
||||
mov %r12, %rsp
|
||||
|
||||
popq %r12
|
||||
popq %r15
|
||||
popq %r14
|
||||
popq %r13
|
||||
popq %rbp
|
||||
popq %rbx
|
||||
ret
|
||||
ENDPROC(sha256_transform_avx)
|
||||
|
||||
.data
|
||||
.align 64
|
||||
K256:
|
||||
.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
|
||||
.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
|
||||
.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
|
||||
.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
|
||||
.long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
|
||||
.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
|
||||
.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
|
||||
.long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
|
||||
.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
|
||||
.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
|
||||
.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
|
||||
.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
|
||||
.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
|
||||
.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
|
||||
.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
|
||||
.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
|
||||
|
||||
PSHUFFLE_BYTE_FLIP_MASK:
|
||||
.octa 0x0c0d0e0f08090a0b0405060700010203
|
||||
|
||||
# shuffle xBxA -> 00BA
|
||||
_SHUF_00BA:
|
||||
.octa 0xFFFFFFFFFFFFFFFF0b0a090803020100
|
||||
|
||||
# shuffle xDxC -> DC00
|
||||
_SHUF_DC00:
|
||||
.octa 0x0b0a090803020100FFFFFFFFFFFFFFFF
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,772 +0,0 @@
|
||||
########################################################################
|
||||
# Implement fast SHA-256 with SSSE3 instructions. (x86_64)
|
||||
#
|
||||
# Copyright (C) 2013 Intel Corporation.
|
||||
#
|
||||
# Authors:
|
||||
# James Guilford <james.guilford@intel.com>
|
||||
# Kirk Yap <kirk.s.yap@intel.com>
|
||||
# Tim Chen <tim.c.chen@linux.intel.com>
|
||||
#
|
||||
# This software is available to you under a choice of one of two
|
||||
# licenses. You may choose to be licensed under the terms of the GNU
|
||||
# General Public License (GPL) Version 2, available from the file
|
||||
# COPYING in the main directory of this source tree, or the
|
||||
# OpenIB.org BSD license below:
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or
|
||||
# without modification, are permitted provided that the following
|
||||
# conditions are met:
|
||||
#
|
||||
# - Redistributions of source code must retain the above
|
||||
# copyright notice, this list of conditions and the following
|
||||
# disclaimer.
|
||||
#
|
||||
# - Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following
|
||||
# disclaimer in the documentation and/or other materials
|
||||
# provided with the distribution.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
########################################################################
|
||||
#
|
||||
# This code is described in an Intel White-Paper:
|
||||
# "Fast SHA-256 Implementations on Intel Architecture Processors"
|
||||
#
|
||||
# To find it, surf to http://www.intel.com/p/en_US/embedded
|
||||
# and search for that title.
|
||||
#
|
||||
########################################################################
|
||||
#
|
||||
# Using this part of Minio codebase under the license
|
||||
# Apache License Version 2.0 with modifications
|
||||
##
|
||||
|
||||
#ifdef HAS_SSE41
|
||||
#ifndef ENTRY
|
||||
#define ENTRY(name) \
|
||||
.globl name ; \
|
||||
.align 4,0x90 ; \
|
||||
name:
|
||||
#endif
|
||||
|
||||
#ifndef END
|
||||
#define END(name) \
|
||||
.size name, .-name
|
||||
#endif
|
||||
|
||||
#ifndef ENDPROC
|
||||
#define ENDPROC(name) \
|
||||
.type name, @function ; \
|
||||
END(name)
|
||||
#endif
|
||||
|
||||
#define NUM_INVALID 100
|
||||
|
||||
#define TYPE_R32 0
|
||||
#define TYPE_R64 1
|
||||
#define TYPE_XMM 2
|
||||
#define TYPE_INVALID 100
|
||||
|
||||
.macro R32_NUM opd r32
|
||||
\opd = NUM_INVALID
|
||||
.ifc \r32,%eax
|
||||
\opd = 0
|
||||
.endif
|
||||
.ifc \r32,%ecx
|
||||
\opd = 1
|
||||
.endif
|
||||
.ifc \r32,%edx
|
||||
\opd = 2
|
||||
.endif
|
||||
.ifc \r32,%ebx
|
||||
\opd = 3
|
||||
.endif
|
||||
.ifc \r32,%esp
|
||||
\opd = 4
|
||||
.endif
|
||||
.ifc \r32,%ebp
|
||||
\opd = 5
|
||||
.endif
|
||||
.ifc \r32,%esi
|
||||
\opd = 6
|
||||
.endif
|
||||
.ifc \r32,%edi
|
||||
\opd = 7
|
||||
.endif
|
||||
#ifdef X86_64
|
||||
.ifc \r32,%r8d
|
||||
\opd = 8
|
||||
.endif
|
||||
.ifc \r32,%r9d
|
||||
\opd = 9
|
||||
.endif
|
||||
.ifc \r32,%r10d
|
||||
\opd = 10
|
||||
.endif
|
||||
.ifc \r32,%r11d
|
||||
\opd = 11
|
||||
.endif
|
||||
.ifc \r32,%r12d
|
||||
\opd = 12
|
||||
.endif
|
||||
.ifc \r32,%r13d
|
||||
\opd = 13
|
||||
.endif
|
||||
.ifc \r32,%r14d
|
||||
\opd = 14
|
||||
.endif
|
||||
.ifc \r32,%r15d
|
||||
\opd = 15
|
||||
.endif
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro R64_NUM opd r64
|
||||
\opd = NUM_INVALID
|
||||
#ifdef X86_64
|
||||
.ifc \r64,%rax
|
||||
\opd = 0
|
||||
.endif
|
||||
.ifc \r64,%rcx
|
||||
\opd = 1
|
||||
.endif
|
||||
.ifc \r64,%rdx
|
||||
\opd = 2
|
||||
.endif
|
||||
.ifc \r64,%rbx
|
||||
\opd = 3
|
||||
.endif
|
||||
.ifc \r64,%rsp
|
||||
\opd = 4
|
||||
.endif
|
||||
.ifc \r64,%rbp
|
||||
\opd = 5
|
||||
.endif
|
||||
.ifc \r64,%rsi
|
||||
\opd = 6
|
||||
.endif
|
||||
.ifc \r64,%rdi
|
||||
\opd = 7
|
||||
.endif
|
||||
.ifc \r64,%r8
|
||||
\opd = 8
|
||||
.endif
|
||||
.ifc \r64,%r9
|
||||
\opd = 9
|
||||
.endif
|
||||
.ifc \r64,%r10
|
||||
\opd = 10
|
||||
.endif
|
||||
.ifc \r64,%r11
|
||||
\opd = 11
|
||||
.endif
|
||||
.ifc \r64,%r12
|
||||
\opd = 12
|
||||
.endif
|
||||
.ifc \r64,%r13
|
||||
\opd = 13
|
||||
.endif
|
||||
.ifc \r64,%r14
|
||||
\opd = 14
|
||||
.endif
|
||||
.ifc \r64,%r15
|
||||
\opd = 15
|
||||
.endif
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro XMM_NUM opd xmm
|
||||
\opd = NUM_INVALID
|
||||
.ifc \xmm,%xmm0
|
||||
\opd = 0
|
||||
.endif
|
||||
.ifc \xmm,%xmm1
|
||||
\opd = 1
|
||||
.endif
|
||||
.ifc \xmm,%xmm2
|
||||
\opd = 2
|
||||
.endif
|
||||
.ifc \xmm,%xmm3
|
||||
\opd = 3
|
||||
.endif
|
||||
.ifc \xmm,%xmm4
|
||||
\opd = 4
|
||||
.endif
|
||||
.ifc \xmm,%xmm5
|
||||
\opd = 5
|
||||
.endif
|
||||
.ifc \xmm,%xmm6
|
||||
\opd = 6
|
||||
.endif
|
||||
.ifc \xmm,%xmm7
|
||||
\opd = 7
|
||||
.endif
|
||||
.ifc \xmm,%xmm8
|
||||
\opd = 8
|
||||
.endif
|
||||
.ifc \xmm,%xmm9
|
||||
\opd = 9
|
||||
.endif
|
||||
.ifc \xmm,%xmm10
|
||||
\opd = 10
|
||||
.endif
|
||||
.ifc \xmm,%xmm11
|
||||
\opd = 11
|
||||
.endif
|
||||
.ifc \xmm,%xmm12
|
||||
\opd = 12
|
||||
.endif
|
||||
.ifc \xmm,%xmm13
|
||||
\opd = 13
|
||||
.endif
|
||||
.ifc \xmm,%xmm14
|
||||
\opd = 14
|
||||
.endif
|
||||
.ifc \xmm,%xmm15
|
||||
\opd = 15
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro TYPE type reg
|
||||
R32_NUM reg_type_r32 \reg
|
||||
R64_NUM reg_type_r64 \reg
|
||||
XMM_NUM reg_type_xmm \reg
|
||||
.if reg_type_r64 <> NUM_INVALID
|
||||
\type = TYPE_R64
|
||||
.elseif reg_type_r32 <> NUM_INVALID
|
||||
\type = TYPE_R32
|
||||
.elseif reg_type_xmm <> NUM_INVALID
|
||||
\type = TYPE_XMM
|
||||
.else
|
||||
\type = TYPE_INVALID
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro PFX_OPD_SIZE
|
||||
.byte 0x66
|
||||
.endm
|
||||
|
||||
.macro PFX_REX opd1 opd2 W=0
|
||||
.if ((\opd1 | \opd2) & 8) || \W
|
||||
.byte 0x40 | ((\opd1 & 8) >> 3) | ((\opd2 & 8) >> 1) | (\W << 3)
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro MODRM mod opd1 opd2
|
||||
.byte \mod | (\opd1 & 7) | ((\opd2 & 7) << 3)
|
||||
.endm
|
||||
|
||||
.macro PSHUFB_XMM xmm1 xmm2
|
||||
XMM_NUM pshufb_opd1 \xmm1
|
||||
XMM_NUM pshufb_opd2 \xmm2
|
||||
PFX_OPD_SIZE
|
||||
PFX_REX pshufb_opd1 pshufb_opd2
|
||||
.byte 0x0f, 0x38, 0x00
|
||||
MODRM 0xc0 pshufb_opd1 pshufb_opd2
|
||||
.endm
|
||||
|
||||
.macro PCLMULQDQ imm8 xmm1 xmm2
|
||||
XMM_NUM clmul_opd1 \xmm1
|
||||
XMM_NUM clmul_opd2 \xmm2
|
||||
PFX_OPD_SIZE
|
||||
PFX_REX clmul_opd1 clmul_opd2
|
||||
.byte 0x0f, 0x3a, 0x44
|
||||
MODRM 0xc0 clmul_opd1 clmul_opd2
|
||||
.byte \imm8
|
||||
.endm
|
||||
|
||||
.macro PEXTRD imm8 xmm gpr
|
||||
R32_NUM extrd_opd1 \gpr
|
||||
XMM_NUM extrd_opd2 \xmm
|
||||
PFX_OPD_SIZE
|
||||
PFX_REX extrd_opd1 extrd_opd2
|
||||
.byte 0x0f, 0x3a, 0x16
|
||||
MODRM 0xc0 extrd_opd1 extrd_opd2
|
||||
.byte \imm8
|
||||
.endm
|
||||
|
||||
.macro MOVQ_R64_XMM opd1 opd2
|
||||
TYPE movq_r64_xmm_opd1_type \opd1
|
||||
.if movq_r64_xmm_opd1_type == TYPE_XMM
|
||||
XMM_NUM movq_r64_xmm_opd1 \opd1
|
||||
R64_NUM movq_r64_xmm_opd2 \opd2
|
||||
.else
|
||||
R64_NUM movq_r64_xmm_opd1 \opd1
|
||||
XMM_NUM movq_r64_xmm_opd2 \opd2
|
||||
.endif
|
||||
PFX_OPD_SIZE
|
||||
PFX_REX movq_r64_xmm_opd1 movq_r64_xmm_opd2 1
|
||||
.if movq_r64_xmm_opd1_type == TYPE_XMM
|
||||
.byte 0x0f, 0x7e
|
||||
.else
|
||||
.byte 0x0f, 0x6e
|
||||
.endif
|
||||
MODRM 0xc0 movq_r64_xmm_opd1 movq_r64_xmm_opd2
|
||||
.endm
|
||||
|
||||
## assume buffers not aligned
|
||||
#define MOVDQ movdqu
|
||||
|
||||
################################ Define Macros
|
||||
|
||||
# addm [mem], reg
|
||||
# Add reg to mem using reg-mem add and store
|
||||
.macro addm p1 p2
|
||||
add \p1, \p2
|
||||
mov \p2, \p1
|
||||
.endm
|
||||
|
||||
################################
|
||||
|
||||
# COPY_XMM_AND_BSWAP xmm, [mem], byte_flip_mask
|
||||
# Load xmm with mem and byte swap each dword
|
||||
.macro COPY_XMM_AND_BSWAP p1 p2 p3
|
||||
MOVDQ \p2, \p1
|
||||
pshufb \p3, \p1
|
||||
.endm
|
||||
|
||||
################################
|
||||
|
||||
X0 = %xmm4
|
||||
X1 = %xmm5
|
||||
X2 = %xmm6
|
||||
X3 = %xmm7
|
||||
|
||||
XTMP0 = %xmm0
|
||||
XTMP1 = %xmm1
|
||||
XTMP2 = %xmm2
|
||||
XTMP3 = %xmm3
|
||||
XTMP4 = %xmm8
|
||||
XFER = %xmm9
|
||||
|
||||
SHUF_00BA = %xmm10 # shuffle xBxA -> 00BA
|
||||
SHUF_DC00 = %xmm11 # shuffle xDxC -> DC00
|
||||
BYTE_FLIP_MASK = %xmm12
|
||||
|
||||
NUM_BLKS = %rdx # 3rd arg
|
||||
CTX = %rsi # 2nd arg
|
||||
INP = %rdi # 1st arg
|
||||
|
||||
SRND = %rdi # clobbers INP
|
||||
c = %ecx
|
||||
d = %r8d
|
||||
e = %edx
|
||||
TBL = %rbp
|
||||
a = %eax
|
||||
b = %ebx
|
||||
|
||||
f = %r9d
|
||||
g = %r10d
|
||||
h = %r11d
|
||||
|
||||
y0 = %r13d
|
||||
y1 = %r14d
|
||||
y2 = %r15d
|
||||
|
||||
|
||||
|
||||
_INP_END_SIZE = 8
|
||||
_INP_SIZE = 8
|
||||
_XFER_SIZE = 16
|
||||
_XMM_SAVE_SIZE = 0
|
||||
|
||||
_INP_END = 0
|
||||
_INP = _INP_END + _INP_END_SIZE
|
||||
_XFER = _INP + _INP_SIZE
|
||||
_XMM_SAVE = _XFER + _XFER_SIZE
|
||||
STACK_SIZE = _XMM_SAVE + _XMM_SAVE_SIZE
|
||||
|
||||
# rotate_Xs
|
||||
# Rotate values of symbols X0...X3
|
||||
.macro rotate_Xs
|
||||
X_ = X0
|
||||
X0 = X1
|
||||
X1 = X2
|
||||
X2 = X3
|
||||
X3 = X_
|
||||
.endm
|
||||
|
||||
# ROTATE_ARGS
|
||||
# Rotate values of symbols a...h
|
||||
.macro ROTATE_ARGS
|
||||
TMP_ = h
|
||||
h = g
|
||||
g = f
|
||||
f = e
|
||||
e = d
|
||||
d = c
|
||||
c = b
|
||||
b = a
|
||||
a = TMP_
|
||||
.endm
|
||||
|
||||
.macro FOUR_ROUNDS_AND_SCHED
|
||||
## compute s0 four at a time and s1 two at a time
|
||||
## compute W[-16] + W[-7] 4 at a time
|
||||
movdqa X3, XTMP0
|
||||
mov e, y0 # y0 = e
|
||||
ror $(25-11), y0 # y0 = e >> (25-11)
|
||||
mov a, y1 # y1 = a
|
||||
palignr $4, X2, XTMP0 # XTMP0 = W[-7]
|
||||
ror $(22-13), y1 # y1 = a >> (22-13)
|
||||
xor e, y0 # y0 = e ^ (e >> (25-11))
|
||||
mov f, y2 # y2 = f
|
||||
ror $(11-6), y0 # y0 = (e >> (11-6)) ^ (e >> (25-6))
|
||||
movdqa X1, XTMP1
|
||||
xor a, y1 # y1 = a ^ (a >> (22-13)
|
||||
xor g, y2 # y2 = f^g
|
||||
paddd X0, XTMP0 # XTMP0 = W[-7] + W[-16]
|
||||
xor e, y0 # y0 = e ^ (e >> (11-6)) ^ (e >> (25-6))
|
||||
and e, y2 # y2 = (f^g)&e
|
||||
ror $(13-2), y1 # y1 = (a >> (13-2)) ^ (a >> (22-2))
|
||||
## compute s0
|
||||
palignr $4, X0, XTMP1 # XTMP1 = W[-15]
|
||||
xor a, y1 # y1 = a ^ (a >> (13-2)) ^ (a >> (22-2))
|
||||
ror $6, y0 # y0 = S1 = (e>>6) & (e>>11) ^ (e>>25)
|
||||
xor g, y2 # y2 = CH = ((f^g)&e)^g
|
||||
movdqa XTMP1, XTMP2 # XTMP2 = W[-15]
|
||||
ror $2, y1 # y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22)
|
||||
add y0, y2 # y2 = S1 + CH
|
||||
add _XFER(%rsp) , y2 # y2 = k + w + S1 + CH
|
||||
movdqa XTMP1, XTMP3 # XTMP3 = W[-15]
|
||||
mov a, y0 # y0 = a
|
||||
add y2, h # h = h + S1 + CH + k + w
|
||||
mov a, y2 # y2 = a
|
||||
pslld $(32-7), XTMP1 #
|
||||
or c, y0 # y0 = a|c
|
||||
add h, d # d = d + h + S1 + CH + k + w
|
||||
and c, y2 # y2 = a&c
|
||||
psrld $7, XTMP2 #
|
||||
and b, y0 # y0 = (a|c)&b
|
||||
add y1, h # h = h + S1 + CH + k + w + S0
|
||||
por XTMP2, XTMP1 # XTMP1 = W[-15] ror 7
|
||||
or y2, y0 # y0 = MAJ = (a|c)&b)|(a&c)
|
||||
add y0, h # h = h + S1 + CH + k + w + S0 + MAJ
|
||||
#
|
||||
ROTATE_ARGS #
|
||||
movdqa XTMP3, XTMP2 # XTMP2 = W[-15]
|
||||
mov e, y0 # y0 = e
|
||||
mov a, y1 # y1 = a
|
||||
movdqa XTMP3, XTMP4 # XTMP4 = W[-15]
|
||||
ror $(25-11), y0 # y0 = e >> (25-11)
|
||||
xor e, y0 # y0 = e ^ (e >> (25-11))
|
||||
mov f, y2 # y2 = f
|
||||
ror $(22-13), y1 # y1 = a >> (22-13)
|
||||
pslld $(32-18), XTMP3 #
|
||||
xor a, y1 # y1 = a ^ (a >> (22-13)
|
||||
ror $(11-6), y0 # y0 = (e >> (11-6)) ^ (e >> (25-6))
|
||||
xor g, y2 # y2 = f^g
|
||||
psrld $18, XTMP2 #
|
||||
ror $(13-2), y1 # y1 = (a >> (13-2)) ^ (a >> (22-2))
|
||||
xor e, y0 # y0 = e ^ (e >> (11-6)) ^ (e >> (25-6))
|
||||
and e, y2 # y2 = (f^g)&e
|
||||
ror $6, y0 # y0 = S1 = (e>>6) & (e>>11) ^ (e>>25)
|
||||
pxor XTMP3, XTMP1
|
||||
xor a, y1 # y1 = a ^ (a >> (13-2)) ^ (a >> (22-2))
|
||||
xor g, y2 # y2 = CH = ((f^g)&e)^g
|
||||
psrld $3, XTMP4 # XTMP4 = W[-15] >> 3
|
||||
add y0, y2 # y2 = S1 + CH
|
||||
add (1*4 + _XFER)(%rsp), y2 # y2 = k + w + S1 + CH
|
||||
ror $2, y1 # y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22)
|
||||
pxor XTMP2, XTMP1 # XTMP1 = W[-15] ror 7 ^ W[-15] ror 18
|
||||
mov a, y0 # y0 = a
|
||||
add y2, h # h = h + S1 + CH + k + w
|
||||
mov a, y2 # y2 = a
|
||||
pxor XTMP4, XTMP1 # XTMP1 = s0
|
||||
or c, y0 # y0 = a|c
|
||||
add h, d # d = d + h + S1 + CH + k + w
|
||||
and c, y2 # y2 = a&c
|
||||
## compute low s1
|
||||
pshufd $0b11111010, X3, XTMP2 # XTMP2 = W[-2] {BBAA}
|
||||
and b, y0 # y0 = (a|c)&b
|
||||
add y1, h # h = h + S1 + CH + k + w + S0
|
||||
paddd XTMP1, XTMP0 # XTMP0 = W[-16] + W[-7] + s0
|
||||
or y2, y0 # y0 = MAJ = (a|c)&b)|(a&c)
|
||||
add y0, h # h = h + S1 + CH + k + w + S0 + MAJ
|
||||
|
||||
ROTATE_ARGS
|
||||
movdqa XTMP2, XTMP3 # XTMP3 = W[-2] {BBAA}
|
||||
mov e, y0 # y0 = e
|
||||
mov a, y1 # y1 = a
|
||||
ror $(25-11), y0 # y0 = e >> (25-11)
|
||||
movdqa XTMP2, XTMP4 # XTMP4 = W[-2] {BBAA}
|
||||
xor e, y0 # y0 = e ^ (e >> (25-11))
|
||||
ror $(22-13), y1 # y1 = a >> (22-13)
|
||||
mov f, y2 # y2 = f
|
||||
xor a, y1 # y1 = a ^ (a >> (22-13)
|
||||
ror $(11-6), y0 # y0 = (e >> (11-6)) ^ (e >> (25-6))
|
||||
psrlq $17, XTMP2 # XTMP2 = W[-2] ror 17 {xBxA}
|
||||
xor g, y2 # y2 = f^g
|
||||
psrlq $19, XTMP3 # XTMP3 = W[-2] ror 19 {xBxA}
|
||||
xor e, y0 # y0 = e ^ (e >> (11-6)) ^ (e >> (25-6))
|
||||
and e, y2 # y2 = (f^g)&e
|
||||
psrld $10, XTMP4 # XTMP4 = W[-2] >> 10 {BBAA}
|
||||
ror $(13-2), y1 # y1 = (a >> (13-2)) ^ (a >> (22-2))
|
||||
xor a, y1 # y1 = a ^ (a >> (13-2)) ^ (a >> (22-2))
|
||||
xor g, y2 # y2 = CH = ((f^g)&e)^g
|
||||
ror $6, y0 # y0 = S1 = (e>>6) & (e>>11) ^ (e>>25)
|
||||
pxor XTMP3, XTMP2
|
||||
add y0, y2 # y2 = S1 + CH
|
||||
ror $2, y1 # y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22)
|
||||
add (2*4 + _XFER)(%rsp), y2 # y2 = k + w + S1 + CH
|
||||
pxor XTMP2, XTMP4 # XTMP4 = s1 {xBxA}
|
||||
mov a, y0 # y0 = a
|
||||
add y2, h # h = h + S1 + CH + k + w
|
||||
mov a, y2 # y2 = a
|
||||
pshufb SHUF_00BA, XTMP4 # XTMP4 = s1 {00BA}
|
||||
or c, y0 # y0 = a|c
|
||||
add h, d # d = d + h + S1 + CH + k + w
|
||||
and c, y2 # y2 = a&c
|
||||
paddd XTMP4, XTMP0 # XTMP0 = {..., ..., W[1], W[0]}
|
||||
and b, y0 # y0 = (a|c)&b
|
||||
add y1, h # h = h + S1 + CH + k + w + S0
|
||||
## compute high s1
|
||||
pshufd $0b01010000, XTMP0, XTMP2 # XTMP2 = W[-2] {BBAA}
|
||||
or y2, y0 # y0 = MAJ = (a|c)&b)|(a&c)
|
||||
add y0, h # h = h + S1 + CH + k + w + S0 + MAJ
|
||||
#
|
||||
ROTATE_ARGS #
|
||||
movdqa XTMP2, XTMP3 # XTMP3 = W[-2] {DDCC}
|
||||
mov e, y0 # y0 = e
|
||||
ror $(25-11), y0 # y0 = e >> (25-11)
|
||||
mov a, y1 # y1 = a
|
||||
movdqa XTMP2, X0 # X0 = W[-2] {DDCC}
|
||||
ror $(22-13), y1 # y1 = a >> (22-13)
|
||||
xor e, y0 # y0 = e ^ (e >> (25-11))
|
||||
mov f, y2 # y2 = f
|
||||
ror $(11-6), y0 # y0 = (e >> (11-6)) ^ (e >> (25-6))
|
||||
psrlq $17, XTMP2 # XTMP2 = W[-2] ror 17 {xDxC}
|
||||
xor a, y1 # y1 = a ^ (a >> (22-13)
|
||||
xor g, y2 # y2 = f^g
|
||||
psrlq $19, XTMP3 # XTMP3 = W[-2] ror 19 {xDxC}
|
||||
xor e, y0 # y0 = e ^ (e >> (11-6)) ^ (e >> (25
|
||||
and e, y2 # y2 = (f^g)&e
|
||||
ror $(13-2), y1 # y1 = (a >> (13-2)) ^ (a >> (22-2))
|
||||
psrld $10, X0 # X0 = W[-2] >> 10 {DDCC}
|
||||
xor a, y1 # y1 = a ^ (a >> (13-2)) ^ (a >> (22
|
||||
ror $6, y0 # y0 = S1 = (e>>6) & (e>>11) ^ (e>>2
|
||||
xor g, y2 # y2 = CH = ((f^g)&e)^g
|
||||
pxor XTMP3, XTMP2 #
|
||||
ror $2, y1 # y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>2
|
||||
add y0, y2 # y2 = S1 + CH
|
||||
add (3*4 + _XFER)(%rsp), y2 # y2 = k + w + S1 + CH
|
||||
pxor XTMP2, X0 # X0 = s1 {xDxC}
|
||||
mov a, y0 # y0 = a
|
||||
add y2, h # h = h + S1 + CH + k + w
|
||||
mov a, y2 # y2 = a
|
||||
pshufb SHUF_DC00, X0 # X0 = s1 {DC00}
|
||||
or c, y0 # y0 = a|c
|
||||
add h, d # d = d + h + S1 + CH + k + w
|
||||
and c, y2 # y2 = a&c
|
||||
paddd XTMP0, X0 # X0 = {W[3], W[2], W[1], W[0]}
|
||||
and b, y0 # y0 = (a|c)&b
|
||||
add y1, h # h = h + S1 + CH + k + w + S0
|
||||
or y2, y0 # y0 = MAJ = (a|c)&b)|(a&c)
|
||||
add y0, h # h = h + S1 + CH + k + w + S0 + MAJ
|
||||
|
||||
ROTATE_ARGS
|
||||
rotate_Xs
|
||||
.endm
|
||||
|
||||
## input is [rsp + _XFER + %1 * 4]
|
||||
.macro DO_ROUND round
|
||||
mov e, y0 # y0 = e
|
||||
ror $(25-11), y0 # y0 = e >> (25-11)
|
||||
mov a, y1 # y1 = a
|
||||
xor e, y0 # y0 = e ^ (e >> (25-11))
|
||||
ror $(22-13), y1 # y1 = a >> (22-13)
|
||||
mov f, y2 # y2 = f
|
||||
xor a, y1 # y1 = a ^ (a >> (22-13)
|
||||
ror $(11-6), y0 # y0 = (e >> (11-6)) ^ (e >> (25-6))
|
||||
xor g, y2 # y2 = f^g
|
||||
xor e, y0 # y0 = e ^ (e >> (11-6)) ^ (e >> (25-6))
|
||||
ror $(13-2), y1 # y1 = (a >> (13-2)) ^ (a >> (22-2))
|
||||
and e, y2 # y2 = (f^g)&e
|
||||
xor a, y1 # y1 = a ^ (a >> (13-2)) ^ (a >> (22-2))
|
||||
ror $6, y0 # y0 = S1 = (e>>6) & (e>>11) ^ (e>>25)
|
||||
xor g, y2 # y2 = CH = ((f^g)&e)^g
|
||||
add y0, y2 # y2 = S1 + CH
|
||||
ror $2, y1 # y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22)
|
||||
offset = \round * 4 + _XFER
|
||||
add offset(%rsp), y2 # y2 = k + w + S1 + CH
|
||||
mov a, y0 # y0 = a
|
||||
add y2, h # h = h + S1 + CH + k + w
|
||||
mov a, y2 # y2 = a
|
||||
or c, y0 # y0 = a|c
|
||||
add h, d # d = d + h + S1 + CH + k + w
|
||||
and c, y2 # y2 = a&c
|
||||
and b, y0 # y0 = (a|c)&b
|
||||
add y1, h # h = h + S1 + CH + k + w + S0
|
||||
or y2, y0 # y0 = MAJ = (a|c)&b)|(a&c)
|
||||
add y0, h # h = h + S1 + CH + k + w + S0 + MAJ
|
||||
ROTATE_ARGS
|
||||
.endm
|
||||
|
||||
########################################################################
|
||||
## void sha256_transform_ssse3(void *input_data, UINT32 digest[8], UINT64 num_blks)
|
||||
## arg 1 : pointer to input data
|
||||
## arg 2 : pointer to digest
|
||||
## arg 3 : Num blocks
|
||||
########################################################################
|
||||
.text
|
||||
ENTRY(sha256_transform_ssse3)
|
||||
.align 32
|
||||
pushq %rbx
|
||||
pushq %rbp
|
||||
pushq %r13
|
||||
pushq %r14
|
||||
pushq %r15
|
||||
pushq %r12
|
||||
|
||||
mov %rsp, %r12
|
||||
subq $STACK_SIZE, %rsp
|
||||
and $~15, %rsp
|
||||
|
||||
shl $6, NUM_BLKS # convert to bytes
|
||||
jz done_hash
|
||||
add INP, NUM_BLKS
|
||||
mov NUM_BLKS, _INP_END(%rsp) # pointer to end of data
|
||||
|
||||
## load initial digest
|
||||
mov 4*0(CTX), a
|
||||
mov 4*1(CTX), b
|
||||
mov 4*2(CTX), c
|
||||
mov 4*3(CTX), d
|
||||
mov 4*4(CTX), e
|
||||
mov 4*5(CTX), f
|
||||
mov 4*6(CTX), g
|
||||
mov 4*7(CTX), h
|
||||
|
||||
movdqa PSHUFFLE_BYTE_FLIP_MASK(%rip), BYTE_FLIP_MASK
|
||||
movdqa _SHUF_00BA(%rip), SHUF_00BA
|
||||
movdqa _SHUF_DC00(%rip), SHUF_DC00
|
||||
|
||||
loop0:
|
||||
lea K256(%rip), TBL
|
||||
|
||||
## byte swap first 16 dwords
|
||||
COPY_XMM_AND_BSWAP X0, 0*16(INP), BYTE_FLIP_MASK
|
||||
COPY_XMM_AND_BSWAP X1, 1*16(INP), BYTE_FLIP_MASK
|
||||
COPY_XMM_AND_BSWAP X2, 2*16(INP), BYTE_FLIP_MASK
|
||||
COPY_XMM_AND_BSWAP X3, 3*16(INP), BYTE_FLIP_MASK
|
||||
|
||||
mov INP, _INP(%rsp)
|
||||
|
||||
## schedule 48 input dwords, by doing 3 rounds of 16 each
|
||||
mov $3, SRND
|
||||
.align 16
|
||||
loop1:
|
||||
movdqa (TBL), XFER
|
||||
paddd X0, XFER
|
||||
movdqa XFER, _XFER(%rsp)
|
||||
FOUR_ROUNDS_AND_SCHED
|
||||
|
||||
movdqa 1*16(TBL), XFER
|
||||
paddd X0, XFER
|
||||
movdqa XFER, _XFER(%rsp)
|
||||
FOUR_ROUNDS_AND_SCHED
|
||||
|
||||
movdqa 2*16(TBL), XFER
|
||||
paddd X0, XFER
|
||||
movdqa XFER, _XFER(%rsp)
|
||||
FOUR_ROUNDS_AND_SCHED
|
||||
|
||||
movdqa 3*16(TBL), XFER
|
||||
paddd X0, XFER
|
||||
movdqa XFER, _XFER(%rsp)
|
||||
add $4*16, TBL
|
||||
FOUR_ROUNDS_AND_SCHED
|
||||
|
||||
sub $1, SRND
|
||||
jne loop1
|
||||
|
||||
mov $2, SRND
|
||||
loop2:
|
||||
paddd (TBL), X0
|
||||
movdqa X0, _XFER(%rsp)
|
||||
DO_ROUND 0
|
||||
DO_ROUND 1
|
||||
DO_ROUND 2
|
||||
DO_ROUND 3
|
||||
paddd 1*16(TBL), X1
|
||||
movdqa X1, _XFER(%rsp)
|
||||
add $2*16, TBL
|
||||
DO_ROUND 0
|
||||
DO_ROUND 1
|
||||
DO_ROUND 2
|
||||
DO_ROUND 3
|
||||
|
||||
movdqa X2, X0
|
||||
movdqa X3, X1
|
||||
|
||||
sub $1, SRND
|
||||
jne loop2
|
||||
|
||||
addm (4*0)(CTX),a
|
||||
addm (4*1)(CTX),b
|
||||
addm (4*2)(CTX),c
|
||||
addm (4*3)(CTX),d
|
||||
addm (4*4)(CTX),e
|
||||
addm (4*5)(CTX),f
|
||||
addm (4*6)(CTX),g
|
||||
addm (4*7)(CTX),h
|
||||
|
||||
mov _INP(%rsp), INP
|
||||
add $64, INP
|
||||
cmp _INP_END(%rsp), INP
|
||||
jne loop0
|
||||
|
||||
done_hash:
|
||||
|
||||
mov %r12, %rsp
|
||||
|
||||
popq %r12
|
||||
popq %r15
|
||||
popq %r14
|
||||
popq %r13
|
||||
popq %rbp
|
||||
popq %rbx
|
||||
|
||||
ret
|
||||
ENDPROC(sha256_transform_ssse3)
|
||||
|
||||
.data
|
||||
.align 64
|
||||
K256:
|
||||
.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
|
||||
.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
|
||||
.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
|
||||
.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
|
||||
.long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
|
||||
.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
|
||||
.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
|
||||
.long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
|
||||
.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
|
||||
.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
|
||||
.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
|
||||
.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
|
||||
.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
|
||||
.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
|
||||
.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
|
||||
.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
|
||||
|
||||
PSHUFFLE_BYTE_FLIP_MASK:
|
||||
.octa 0x0c0d0e0f08090a0b0405060700010203
|
||||
|
||||
# shuffle xBxA -> 00BA
|
||||
_SHUF_00BA:
|
||||
.octa 0xFFFFFFFFFFFFFFFF0b0a090803020100
|
||||
|
||||
# shuffle xDxC -> DC00
|
||||
_SHUF_DC00:
|
||||
.octa 0x0b0a090803020100FFFFFFFFFFFFFFFF
|
||||
#endif
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2014 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sha256
|
||||
|
||||
import (
|
||||
"hash"
|
||||
"io"
|
||||
|
||||
"crypto/sha256"
|
||||
)
|
||||
|
||||
// Sum256 - single caller sha256 helper
|
||||
func Sum256(data []byte) []byte {
|
||||
d := sha256.New()
|
||||
d.Write(data)
|
||||
return d.Sum(nil)
|
||||
}
|
||||
|
||||
// Sum - io.Reader based streaming sha256 helper
|
||||
func Sum(reader io.Reader) ([]byte, error) {
|
||||
d := sha256.New()
|
||||
var err error
|
||||
for err == nil {
|
||||
length := 0
|
||||
byteBuffer := make([]byte, 1024*1024)
|
||||
length, err = reader.Read(byteBuffer)
|
||||
byteBuffer = byteBuffer[0:length]
|
||||
d.Write(byteBuffer)
|
||||
}
|
||||
if err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
return d.Sum(nil), nil
|
||||
}
|
||||
|
||||
// New returns a new hash.Hash computing SHA256.
|
||||
func New() hash.Hash {
|
||||
return sha256.New()
|
||||
}
|
||||
@@ -1,179 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file of
|
||||
// Golang project:
|
||||
// https://github.com/golang/go/blob/master/LICENSE
|
||||
|
||||
// Using this part of Minio codebase under the license
|
||||
// Apache License Version 2.0 with modifications
|
||||
|
||||
// Package sha256 provides SHA256SSE3, SHA256AVX, SHA256AVX2
|
||||
package sha256
|
||||
|
||||
import (
|
||||
"hash"
|
||||
"io"
|
||||
|
||||
"github.com/minio/minio/pkg/cpu"
|
||||
)
|
||||
|
||||
// The size of a SHA256 checksum in bytes.
|
||||
const Size = 32
|
||||
|
||||
// The blocksize of SHA256 in bytes.
|
||||
const BlockSize = 64
|
||||
|
||||
const (
|
||||
chunk = 64
|
||||
init0 = 0x6A09E667
|
||||
init1 = 0xBB67AE85
|
||||
init2 = 0x3C6EF372
|
||||
init3 = 0xA54FF53A
|
||||
init4 = 0x510E527F
|
||||
init5 = 0x9B05688C
|
||||
init6 = 0x1F83D9AB
|
||||
init7 = 0x5BE0CD19
|
||||
)
|
||||
|
||||
// digest represents the partial evaluation of a checksum.
|
||||
type digest struct {
|
||||
h [8]uint32
|
||||
x [chunk]byte
|
||||
nx int
|
||||
len uint64
|
||||
}
|
||||
|
||||
// Reset digest back to default
|
||||
func (d *digest) Reset() {
|
||||
d.h[0] = init0
|
||||
d.h[1] = init1
|
||||
d.h[2] = init2
|
||||
d.h[3] = init3
|
||||
d.h[4] = init4
|
||||
d.h[5] = init5
|
||||
d.h[6] = init6
|
||||
d.h[7] = init7
|
||||
d.nx = 0
|
||||
d.len = 0
|
||||
}
|
||||
|
||||
func block(dig *digest, p []byte) {
|
||||
switch true {
|
||||
case cpu.HasAVX2() == true:
|
||||
blockAVX2(dig, p)
|
||||
case cpu.HasAVX() == true:
|
||||
blockAVX(dig, p)
|
||||
case cpu.HasSSE41() == true:
|
||||
blockSSE(dig, p)
|
||||
default:
|
||||
blockGeneric(dig, p)
|
||||
}
|
||||
}
|
||||
|
||||
// New returns a new hash.Hash computing the SHA256 checksum.
|
||||
func New() hash.Hash {
|
||||
d := new(digest)
|
||||
d.Reset()
|
||||
return d
|
||||
}
|
||||
|
||||
// Return size of checksum
|
||||
func (d *digest) Size() int { return Size }
|
||||
|
||||
// Return blocksize of checksum
|
||||
func (d *digest) BlockSize() int { return BlockSize }
|
||||
|
||||
// Write to digest
|
||||
func (d *digest) Write(p []byte) (nn int, err error) {
|
||||
nn = len(p)
|
||||
d.len += uint64(nn)
|
||||
if d.nx > 0 {
|
||||
n := copy(d.x[d.nx:], p)
|
||||
d.nx += n
|
||||
if d.nx == chunk {
|
||||
block(d, d.x[:])
|
||||
d.nx = 0
|
||||
}
|
||||
p = p[n:]
|
||||
}
|
||||
if len(p) >= chunk {
|
||||
n := len(p) &^ (chunk - 1)
|
||||
block(d, p[:n])
|
||||
p = p[n:]
|
||||
}
|
||||
if len(p) > 0 {
|
||||
d.nx = copy(d.x[:], p)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Return sha256 sum in bytes
|
||||
func (d *digest) Sum(in []byte) []byte {
|
||||
// Make a copy of d0 so that caller can keep writing and summing.
|
||||
d0 := *d
|
||||
hash := d0.checkSum()
|
||||
return append(in, hash[:]...)
|
||||
}
|
||||
|
||||
// Intermediate checksum function
|
||||
func (d *digest) checkSum() [Size]byte {
|
||||
len := d.len
|
||||
// Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
|
||||
var tmp [64]byte
|
||||
tmp[0] = 0x80
|
||||
if len%64 < 56 {
|
||||
d.Write(tmp[0 : 56-len%64])
|
||||
} else {
|
||||
d.Write(tmp[0 : 64+56-len%64])
|
||||
}
|
||||
|
||||
// Length in bits.
|
||||
len <<= 3
|
||||
for i := uint(0); i < 8; i++ {
|
||||
tmp[i] = byte(len >> (56 - 8*i))
|
||||
}
|
||||
d.Write(tmp[0:8])
|
||||
|
||||
if d.nx != 0 {
|
||||
panic("d.nx != 0")
|
||||
}
|
||||
|
||||
h := d.h[:]
|
||||
|
||||
var digest [Size]byte
|
||||
for i, s := range h {
|
||||
digest[i*4] = byte(s >> 24)
|
||||
digest[i*4+1] = byte(s >> 16)
|
||||
digest[i*4+2] = byte(s >> 8)
|
||||
digest[i*4+3] = byte(s)
|
||||
}
|
||||
|
||||
return digest
|
||||
}
|
||||
|
||||
/// Convenience functions
|
||||
|
||||
// Sum256 - single caller sha256 helper
|
||||
func Sum256(data []byte) []byte {
|
||||
var d digest
|
||||
d.Reset()
|
||||
d.Write(data)
|
||||
return d.Sum(nil)
|
||||
}
|
||||
|
||||
// Sum - io.Reader based streaming sha256 helper
|
||||
func Sum(reader io.Reader) ([]byte, error) {
|
||||
h := New()
|
||||
var err error
|
||||
for err == nil {
|
||||
length := 0
|
||||
byteBuffer := make([]byte, 1024*1024)
|
||||
length, err = reader.Read(byteBuffer)
|
||||
byteBuffer = byteBuffer[0:length]
|
||||
h.Write(byteBuffer)
|
||||
}
|
||||
if err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
return h.Sum(nil), nil
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file of
|
||||
// Golang project:
|
||||
// https://github.com/golang/go/blob/master/LICENSE
|
||||
|
||||
// Using this part of Minio codebase under the license
|
||||
// Apache License Version 2.0 with modifications
|
||||
|
||||
// SHA256 hash algorithm. See FIPS 180-2.
|
||||
|
||||
package sha256
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type sha256Test struct {
|
||||
out string
|
||||
in string
|
||||
}
|
||||
|
||||
var golden = []sha256Test{
|
||||
{"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", ""},
|
||||
{"ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb", "a"},
|
||||
{"fb8e20fc2e4c3f248c60c39bd652f3c1347298bb977b8b4d5903b85055620603", "ab"},
|
||||
{"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", "abc"},
|
||||
{"88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589", "abcd"},
|
||||
{"36bbe50ed96841d10443bcb670d6554f0a34b761be67ec9c4a8ad2c0c44ca42c", "abcde"},
|
||||
{"bef57ec7f53a6d40beb640a780a639c83bc29ac8a9816f1fc6c5c6dcd93c4721", "abcdef"},
|
||||
{"7d1a54127b222502f5b79b5fb0803061152a44f92b37e23c6527baf665d4da9a", "abcdefg"},
|
||||
{"9c56cc51b374c3ba189210d5b6d4bf57790d351c96c47c02190ecf1e430635ab", "abcdefgh"},
|
||||
{"19cc02f26df43cc571bc9ed7b0c4d29224a3ec229529221725ef76d021c8326f", "abcdefghi"},
|
||||
{"72399361da6a7754fec986dca5b7cbaf1c810a28ded4abaf56b2106d06cb78b0", "abcdefghij"},
|
||||
{"a144061c271f152da4d151034508fed1c138b8c976339de229c3bb6d4bbb4fce", "Discard medicine more than two years old."},
|
||||
{"6dae5caa713a10ad04b46028bf6dad68837c581616a1589a265a11288d4bb5c4", "He who has a shady past knows that nice guys finish last."},
|
||||
{"ae7a702a9509039ddbf29f0765e70d0001177914b86459284dab8b348c2dce3f", "I wouldn't marry him with a ten foot pole."},
|
||||
{"6748450b01c568586715291dfa3ee018da07d36bb7ea6f180c1af6270215c64f", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"},
|
||||
{"14b82014ad2b11f661b5ae6a99b75105c2ffac278cd071cd6c05832793635774", "The days of the digital watch are numbered. -Tom Stoppard"},
|
||||
{"7102cfd76e2e324889eece5d6c41921b1e142a4ac5a2692be78803097f6a48d8", "Nepal premier won't resign."},
|
||||
{"23b1018cd81db1d67983c5f7417c44da9deb582459e378d7a068552ea649dc9f", "For every action there is an equal and opposite government program."},
|
||||
{"8001f190dfb527261c4cfcab70c98e8097a7a1922129bc4096950e57c7999a5a", "His money is twice tainted: 'taint yours and 'taint mine."},
|
||||
{"8c87deb65505c3993eb24b7a150c4155e82eee6960cf0c3a8114ff736d69cad5", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"},
|
||||
{"bfb0a67a19cdec3646498b2e0f751bddc41bba4b7f30081b0b932aad214d16d7", "It's a tiny change to the code and not completely disgusting. - Bob Manchek"},
|
||||
{"7f9a0b9bf56332e19f5a0ec1ad9c1425a153da1c624868fda44561d6b74daf36", "size: a.out: bad magic"},
|
||||
{"b13f81b8aad9e3666879af19886140904f7f429ef083286195982a7588858cfc", "The major problem is with sendmail. -Mark Horton"},
|
||||
{"b26c38d61519e894480c70c8374ea35aa0ad05b2ae3d6674eec5f52a69305ed4", "Give me a rock, paper and scissors and I will move the world. CCFestoon"},
|
||||
{"049d5e26d4f10222cd841a119e38bd8d2e0d1129728688449575d4ff42b842c1", "If the enemy is within range, then so are you."},
|
||||
{"0e116838e3cc1c1a14cd045397e29b4d087aa11b0853fc69ec82e90330d60949", "It's well we cannot hear the screams/That we create in others' dreams."},
|
||||
{"4f7d8eb5bcf11de2a56b971021a444aa4eafd6ecd0f307b5109e4e776cd0fe46", "You remind me of a TV show, but that's all right: I watch it anyway."},
|
||||
{"61c0cc4c4bd8406d5120b3fb4ebc31ce87667c162f29468b3c779675a85aebce", "C is as portable as Stonehedge!!"},
|
||||
{"1fb2eb3688093c4a3f80cd87a5547e2ce940a4f923243a79a2a1e242220693ac", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"},
|
||||
{"395585ce30617b62c80b93e8208ce866d4edc811a177fdb4b82d3911d8696423", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule"},
|
||||
{"4f9b189a13d030838269dce846b16a1ce9ce81fe63e65de2f636863336a98fe6", "How can you write a big system without C++? -Paul Glick"},
|
||||
}
|
||||
|
||||
func TestGolden(t *testing.T) {
|
||||
for i := 0; i < len(golden); i++ {
|
||||
g := golden[i]
|
||||
s := fmt.Sprintf("%x", Sum256([]byte(g.in)))
|
||||
if s != g.out {
|
||||
t.Fatalf("Sum256 function: sha256(%s) = %s want %s", g.in, s, g.out)
|
||||
}
|
||||
c := New()
|
||||
for j := 0; j < 3; j++ {
|
||||
if j < 2 {
|
||||
io.WriteString(c, g.in)
|
||||
} else {
|
||||
io.WriteString(c, g.in[0:len(g.in)/2])
|
||||
c.Sum(nil)
|
||||
io.WriteString(c, g.in[len(g.in)/2:])
|
||||
}
|
||||
s := fmt.Sprintf("%x", c.Sum(nil))
|
||||
if s != g.out {
|
||||
t.Fatalf("sha256[%d](%s) = %s want %s", j, g.in, s, g.out)
|
||||
}
|
||||
c.Reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSize(t *testing.T) {
|
||||
c := New()
|
||||
if got := c.Size(); got != Size {
|
||||
t.Errorf("Size = %d; want %d", got, Size)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockSize(t *testing.T) {
|
||||
c := New()
|
||||
if got := c.BlockSize(); got != BlockSize {
|
||||
t.Errorf("BlockSize = %d want %d", got, BlockSize)
|
||||
}
|
||||
}
|
||||
|
||||
var bench = New()
|
||||
var buf = make([]byte, 1024*1024)
|
||||
|
||||
func benchmarkSize(b *testing.B, size int) {
|
||||
b.SetBytes(int64(size))
|
||||
sum := make([]byte, bench.Size())
|
||||
for i := 0; i < b.N; i++ {
|
||||
bench.Reset()
|
||||
bench.Write(buf[:size])
|
||||
bench.Sum(sum[:0])
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkHash8Bytes(b *testing.B) {
|
||||
benchmarkSize(b, 8)
|
||||
}
|
||||
|
||||
func BenchmarkHash1K(b *testing.B) {
|
||||
benchmarkSize(b, 1024)
|
||||
}
|
||||
|
||||
func BenchmarkHash8K(b *testing.B) {
|
||||
benchmarkSize(b, 8192)
|
||||
}
|
||||
|
||||
func BenchmarkHash1M(b *testing.B) {
|
||||
benchmarkSize(b, 1024*1024)
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2014 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sha256
|
||||
|
||||
import (
|
||||
"hash"
|
||||
"io"
|
||||
|
||||
"crypto/sha256"
|
||||
)
|
||||
|
||||
// Sum256 - single caller sha256 helper
|
||||
func Sum256(data []byte) []byte {
|
||||
d := sha256.New()
|
||||
d.Write(data)
|
||||
return d.Sum(nil)
|
||||
}
|
||||
|
||||
// Sum - io.Reader based streaming sha256 helper
|
||||
func Sum(reader io.Reader) ([]byte, error) {
|
||||
d := sha256.New()
|
||||
var err error
|
||||
for err == nil {
|
||||
length := 0
|
||||
byteBuffer := make([]byte, 1024*1024)
|
||||
length, err = reader.Read(byteBuffer)
|
||||
byteBuffer = byteBuffer[0:length]
|
||||
d.Write(byteBuffer)
|
||||
}
|
||||
if err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
return d.Sum(nil), nil
|
||||
}
|
||||
|
||||
// New returns a new hash.Hash computing SHA256.
|
||||
func New() hash.Hash {
|
||||
return sha256.New()
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
// +build amd64
|
||||
|
||||
//
|
||||
// Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Software block transform are provided by The Go Authors:
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file of
|
||||
// Golang project:
|
||||
// https://github.com/golang/go/blob/master/LICENSE
|
||||
|
||||
package sha256
|
||||
|
||||
// #cgo CFLAGS: -DHAS_SSE41 -DHAS_AVX -DHAS_AVX2
|
||||
// #include <stdint.h>
|
||||
// void sha256_transform_ssse3 (const char *input_data, uint32_t *digest, unsigned long num_blks);
|
||||
// void sha256_transform_avx (const char *input_data, uint32_t *digest, unsigned long num_blks);
|
||||
// void sha256_transform_rorx (const char *input_data, uint32_t *digest, unsigned long num_blks);
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
func blockSSE(dig *digest, p []byte) {
|
||||
C.sha256_transform_ssse3((*C.char)(unsafe.Pointer(&p[0])), (*C.uint32_t)(unsafe.Pointer(&dig.h[0])), (C.ulong)(len(p)/64))
|
||||
}
|
||||
|
||||
func blockAVX(dig *digest, p []byte) {
|
||||
C.sha256_transform_avx((*C.char)(unsafe.Pointer(&p[0])), (*C.uint32_t)(unsafe.Pointer(&dig.h[0])), (C.ulong)(len(p)/64))
|
||||
}
|
||||
|
||||
func blockAVX2(dig *digest, p []byte) {
|
||||
C.sha256_transform_rorx((*C.char)(unsafe.Pointer(&p[0])), (*C.uint32_t)(unsafe.Pointer(&dig.h[0])), (C.ulong)(len(p)/64))
|
||||
}
|
||||
|
||||
func blockGeneric(dig *digest, p []byte) {
|
||||
var w [64]uint32
|
||||
h0, h1, h2, h3, h4, h5, h6, h7 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7]
|
||||
for len(p) >= chunk {
|
||||
// Can interlace the computation of w with the
|
||||
// rounds below if needed for speed.
|
||||
for i := 0; i < 16; i++ {
|
||||
j := i * 4
|
||||
w[i] = uint32(p[j])<<24 | uint32(p[j+1])<<16 | uint32(p[j+2])<<8 | uint32(p[j+3])
|
||||
}
|
||||
for i := 16; i < 64; i++ {
|
||||
v1 := w[i-2]
|
||||
t1 := (v1>>17 | v1<<(32-17)) ^ (v1>>19 | v1<<(32-19)) ^ (v1 >> 10)
|
||||
v2 := w[i-15]
|
||||
t2 := (v2>>7 | v2<<(32-7)) ^ (v2>>18 | v2<<(32-18)) ^ (v2 >> 3)
|
||||
w[i] = t1 + w[i-7] + t2 + w[i-16]
|
||||
}
|
||||
|
||||
a, b, c, d, e, f, g, h := h0, h1, h2, h3, h4, h5, h6, h7
|
||||
|
||||
for i := 0; i < 64; i++ {
|
||||
t1 := h + ((e>>6 | e<<(32-6)) ^ (e>>11 | e<<(32-11)) ^ (e>>25 | e<<(32-25))) + ((e & f) ^ (^e & g)) + _K[i] + w[i]
|
||||
|
||||
t2 := ((a>>2 | a<<(32-2)) ^ (a>>13 | a<<(32-13)) ^ (a>>22 | a<<(32-22))) + ((a & b) ^ (a & c) ^ (b & c))
|
||||
|
||||
h = g
|
||||
g = f
|
||||
f = e
|
||||
e = d + t1
|
||||
d = c
|
||||
c = b
|
||||
b = a
|
||||
a = t1 + t2
|
||||
}
|
||||
|
||||
h0 += a
|
||||
h1 += b
|
||||
h2 += c
|
||||
h3 += d
|
||||
h4 += e
|
||||
h5 += f
|
||||
h6 += g
|
||||
h7 += h
|
||||
|
||||
p = p[chunk:]
|
||||
}
|
||||
|
||||
dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] = h0, h1, h2, h3, h4, h5, h6, h7
|
||||
}
|
||||
|
||||
var _K = []uint32{
|
||||
0x428a2f98,
|
||||
0x71374491,
|
||||
0xb5c0fbcf,
|
||||
0xe9b5dba5,
|
||||
0x3956c25b,
|
||||
0x59f111f1,
|
||||
0x923f82a4,
|
||||
0xab1c5ed5,
|
||||
0xd807aa98,
|
||||
0x12835b01,
|
||||
0x243185be,
|
||||
0x550c7dc3,
|
||||
0x72be5d74,
|
||||
0x80deb1fe,
|
||||
0x9bdc06a7,
|
||||
0xc19bf174,
|
||||
0xe49b69c1,
|
||||
0xefbe4786,
|
||||
0x0fc19dc6,
|
||||
0x240ca1cc,
|
||||
0x2de92c6f,
|
||||
0x4a7484aa,
|
||||
0x5cb0a9dc,
|
||||
0x76f988da,
|
||||
0x983e5152,
|
||||
0xa831c66d,
|
||||
0xb00327c8,
|
||||
0xbf597fc7,
|
||||
0xc6e00bf3,
|
||||
0xd5a79147,
|
||||
0x06ca6351,
|
||||
0x14292967,
|
||||
0x27b70a85,
|
||||
0x2e1b2138,
|
||||
0x4d2c6dfc,
|
||||
0x53380d13,
|
||||
0x650a7354,
|
||||
0x766a0abb,
|
||||
0x81c2c92e,
|
||||
0x92722c85,
|
||||
0xa2bfe8a1,
|
||||
0xa81a664b,
|
||||
0xc24b8b70,
|
||||
0xc76c51a3,
|
||||
0xd192e819,
|
||||
0xd6990624,
|
||||
0xf40e3585,
|
||||
0x106aa070,
|
||||
0x19a4c116,
|
||||
0x1e376c08,
|
||||
0x2748774c,
|
||||
0x34b0bcb5,
|
||||
0x391c0cb3,
|
||||
0x4ed8aa4a,
|
||||
0x5b9cca4f,
|
||||
0x682e6ff3,
|
||||
0x748f82ee,
|
||||
0x78a5636f,
|
||||
0x84c87814,
|
||||
0x8cc70208,
|
||||
0x90befffa,
|
||||
0xa4506ceb,
|
||||
0xbef9a3f7,
|
||||
0xc67178f2,
|
||||
}
|
||||
@@ -1,202 +0,0 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -1,686 +0,0 @@
|
||||
########################################################################
|
||||
# Implement fast SHA-512 with AVX instructions. (x86_64)
|
||||
#
|
||||
# Copyright (C) 2013 Intel Corporation.
|
||||
#
|
||||
# Authors:
|
||||
# James Guilford <james.guilford@intel.com>
|
||||
# Kirk Yap <kirk.s.yap@intel.com>
|
||||
# David Cote <david.m.cote@intel.com>
|
||||
# Tim Chen <tim.c.chen@linux.intel.com>
|
||||
#
|
||||
# This software is available to you under a choice of one of two
|
||||
# licenses. You may choose to be licensed under the terms of the GNU
|
||||
# General Public License (GPL) Version 2, available from the file
|
||||
# COPYING in the main directory of this source tree, or the
|
||||
# OpenIB.org BSD license below:
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or
|
||||
# without modification, are permitted provided that the following
|
||||
# conditions are met:
|
||||
#
|
||||
# - Redistributions of source code must retain the above
|
||||
# copyright notice, this list of conditions and the following
|
||||
# disclaimer.
|
||||
#
|
||||
# - Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following
|
||||
# disclaimer in the documentation and/or other materials
|
||||
# provided with the distribution.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
########################################################################
|
||||
#
|
||||
# This code is described in an Intel White-Paper:
|
||||
# "Fast SHA-512 Implementations on Intel Architecture Processors"
|
||||
#
|
||||
# To find it, surf to http://www.intel.com/p/en_US/embedded
|
||||
# and search for that title.
|
||||
#
|
||||
########################################################################
|
||||
# Using this part of Minio codebase under the license
|
||||
# Apache License Version 2.0 with modifications
|
||||
##
|
||||
|
||||
#ifdef HAS_AVX
|
||||
#ifndef ENTRY
|
||||
#define ENTRY(name) \
|
||||
.globl name ; \
|
||||
.align 4,0x90 ; \
|
||||
name:
|
||||
#endif
|
||||
|
||||
#ifndef END
|
||||
#define END(name) \
|
||||
.size name, .-name
|
||||
#endif
|
||||
|
||||
#ifndef ENDPROC
|
||||
#define ENDPROC(name) \
|
||||
.type name, @function ; \
|
||||
END(name)
|
||||
#endif
|
||||
|
||||
#define NUM_INVALID 100
|
||||
|
||||
#define TYPE_R32 0
|
||||
#define TYPE_R64 1
|
||||
#define TYPE_XMM 2
|
||||
#define TYPE_INVALID 100
|
||||
|
||||
.macro R32_NUM opd r32
|
||||
\opd = NUM_INVALID
|
||||
.ifc \r32,%eax
|
||||
\opd = 0
|
||||
.endif
|
||||
.ifc \r32,%ecx
|
||||
\opd = 1
|
||||
.endif
|
||||
.ifc \r32,%edx
|
||||
\opd = 2
|
||||
.endif
|
||||
.ifc \r32,%ebx
|
||||
\opd = 3
|
||||
.endif
|
||||
.ifc \r32,%esp
|
||||
\opd = 4
|
||||
.endif
|
||||
.ifc \r32,%ebp
|
||||
\opd = 5
|
||||
.endif
|
||||
.ifc \r32,%esi
|
||||
\opd = 6
|
||||
.endif
|
||||
.ifc \r32,%edi
|
||||
\opd = 7
|
||||
.endif
|
||||
#ifdef X86_64
|
||||
.ifc \r32,%r8d
|
||||
\opd = 8
|
||||
.endif
|
||||
.ifc \r32,%r9d
|
||||
\opd = 9
|
||||
.endif
|
||||
.ifc \r32,%r10d
|
||||
\opd = 10
|
||||
.endif
|
||||
.ifc \r32,%r11d
|
||||
\opd = 11
|
||||
.endif
|
||||
.ifc \r32,%r12d
|
||||
\opd = 12
|
||||
.endif
|
||||
.ifc \r32,%r13d
|
||||
\opd = 13
|
||||
.endif
|
||||
.ifc \r32,%r14d
|
||||
\opd = 14
|
||||
.endif
|
||||
.ifc \r32,%r15d
|
||||
\opd = 15
|
||||
.endif
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro R64_NUM opd r64
|
||||
\opd = NUM_INVALID
|
||||
#ifdef X86_64
|
||||
.ifc \r64,%rax
|
||||
\opd = 0
|
||||
.endif
|
||||
.ifc \r64,%rcx
|
||||
\opd = 1
|
||||
.endif
|
||||
.ifc \r64,%rdx
|
||||
\opd = 2
|
||||
.endif
|
||||
.ifc \r64,%rbx
|
||||
\opd = 3
|
||||
.endif
|
||||
.ifc \r64,%rsp
|
||||
\opd = 4
|
||||
.endif
|
||||
.ifc \r64,%rbp
|
||||
\opd = 5
|
||||
.endif
|
||||
.ifc \r64,%rsi
|
||||
\opd = 6
|
||||
.endif
|
||||
.ifc \r64,%rdi
|
||||
\opd = 7
|
||||
.endif
|
||||
.ifc \r64,%r8
|
||||
\opd = 8
|
||||
.endif
|
||||
.ifc \r64,%r9
|
||||
\opd = 9
|
||||
.endif
|
||||
.ifc \r64,%r10
|
||||
\opd = 10
|
||||
.endif
|
||||
.ifc \r64,%r11
|
||||
\opd = 11
|
||||
.endif
|
||||
.ifc \r64,%r12
|
||||
\opd = 12
|
||||
.endif
|
||||
.ifc \r64,%r13
|
||||
\opd = 13
|
||||
.endif
|
||||
.ifc \r64,%r14
|
||||
\opd = 14
|
||||
.endif
|
||||
.ifc \r64,%r15
|
||||
\opd = 15
|
||||
.endif
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro XMM_NUM opd xmm
|
||||
\opd = NUM_INVALID
|
||||
.ifc \xmm,%xmm0
|
||||
\opd = 0
|
||||
.endif
|
||||
.ifc \xmm,%xmm1
|
||||
\opd = 1
|
||||
.endif
|
||||
.ifc \xmm,%xmm2
|
||||
\opd = 2
|
||||
.endif
|
||||
.ifc \xmm,%xmm3
|
||||
\opd = 3
|
||||
.endif
|
||||
.ifc \xmm,%xmm4
|
||||
\opd = 4
|
||||
.endif
|
||||
.ifc \xmm,%xmm5
|
||||
\opd = 5
|
||||
.endif
|
||||
.ifc \xmm,%xmm6
|
||||
\opd = 6
|
||||
.endif
|
||||
.ifc \xmm,%xmm7
|
||||
\opd = 7
|
||||
.endif
|
||||
.ifc \xmm,%xmm8
|
||||
\opd = 8
|
||||
.endif
|
||||
.ifc \xmm,%xmm9
|
||||
\opd = 9
|
||||
.endif
|
||||
.ifc \xmm,%xmm10
|
||||
\opd = 10
|
||||
.endif
|
||||
.ifc \xmm,%xmm11
|
||||
\opd = 11
|
||||
.endif
|
||||
.ifc \xmm,%xmm12
|
||||
\opd = 12
|
||||
.endif
|
||||
.ifc \xmm,%xmm13
|
||||
\opd = 13
|
||||
.endif
|
||||
.ifc \xmm,%xmm14
|
||||
\opd = 14
|
||||
.endif
|
||||
.ifc \xmm,%xmm15
|
||||
\opd = 15
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro TYPE type reg
|
||||
R32_NUM reg_type_r32 \reg
|
||||
R64_NUM reg_type_r64 \reg
|
||||
XMM_NUM reg_type_xmm \reg
|
||||
.if reg_type_r64 <> NUM_INVALID
|
||||
\type = TYPE_R64
|
||||
.elseif reg_type_r32 <> NUM_INVALID
|
||||
\type = TYPE_R32
|
||||
.elseif reg_type_xmm <> NUM_INVALID
|
||||
\type = TYPE_XMM
|
||||
.else
|
||||
\type = TYPE_INVALID
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro PFX_OPD_SIZE
|
||||
.byte 0x66
|
||||
.endm
|
||||
|
||||
.macro PFX_REX opd1 opd2 W=0
|
||||
.if ((\opd1 | \opd2) & 8) || \W
|
||||
.byte 0x40 | ((\opd1 & 8) >> 3) | ((\opd2 & 8) >> 1) | (\W << 3)
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro MODRM mod opd1 opd2
|
||||
.byte \mod | (\opd1 & 7) | ((\opd2 & 7) << 3)
|
||||
.endm
|
||||
|
||||
.macro PSHUFB_XMM xmm1 xmm2
|
||||
XMM_NUM pshufb_opd1 \xmm1
|
||||
XMM_NUM pshufb_opd2 \xmm2
|
||||
PFX_OPD_SIZE
|
||||
PFX_REX pshufb_opd1 pshufb_opd2
|
||||
.byte 0x0f, 0x38, 0x00
|
||||
MODRM 0xc0 pshufb_opd1 pshufb_opd2
|
||||
.endm
|
||||
|
||||
.macro PCLMULQDQ imm8 xmm1 xmm2
|
||||
XMM_NUM clmul_opd1 \xmm1
|
||||
XMM_NUM clmul_opd2 \xmm2
|
||||
PFX_OPD_SIZE
|
||||
PFX_REX clmul_opd1 clmul_opd2
|
||||
.byte 0x0f, 0x3a, 0x44
|
||||
MODRM 0xc0 clmul_opd1 clmul_opd2
|
||||
.byte \imm8
|
||||
.endm
|
||||
|
||||
.macro PEXTRD imm8 xmm gpr
|
||||
R32_NUM extrd_opd1 \gpr
|
||||
XMM_NUM extrd_opd2 \xmm
|
||||
PFX_OPD_SIZE
|
||||
PFX_REX extrd_opd1 extrd_opd2
|
||||
.byte 0x0f, 0x3a, 0x16
|
||||
MODRM 0xc0 extrd_opd1 extrd_opd2
|
||||
.byte \imm8
|
||||
.endm
|
||||
|
||||
.macro MOVQ_R64_XMM opd1 opd2
|
||||
TYPE movq_r64_xmm_opd1_type \opd1
|
||||
.if movq_r64_xmm_opd1_type == TYPE_XMM
|
||||
XMM_NUM movq_r64_xmm_opd1 \opd1
|
||||
R64_NUM movq_r64_xmm_opd2 \opd2
|
||||
.else
|
||||
R64_NUM movq_r64_xmm_opd1 \opd1
|
||||
XMM_NUM movq_r64_xmm_opd2 \opd2
|
||||
.endif
|
||||
PFX_OPD_SIZE
|
||||
PFX_REX movq_r64_xmm_opd1 movq_r64_xmm_opd2 1
|
||||
.if movq_r64_xmm_opd1_type == TYPE_XMM
|
||||
.byte 0x0f, 0x7e
|
||||
.else
|
||||
.byte 0x0f, 0x6e
|
||||
.endif
|
||||
MODRM 0xc0 movq_r64_xmm_opd1 movq_r64_xmm_opd2
|
||||
.endm
|
||||
|
||||
.text
|
||||
|
||||
# Virtual Registers
|
||||
# ARG1
|
||||
msg = %rdi
|
||||
# ARG2
|
||||
digest = %rsi
|
||||
# ARG3
|
||||
msglen = %rdx
|
||||
T1 = %rcx
|
||||
T2 = %r8
|
||||
a_64 = %r9
|
||||
b_64 = %r10
|
||||
c_64 = %r11
|
||||
d_64 = %r12
|
||||
e_64 = %r13
|
||||
f_64 = %r14
|
||||
g_64 = %r15
|
||||
h_64 = %rbx
|
||||
tmp0 = %rax
|
||||
|
||||
# Local variables (stack frame)
|
||||
|
||||
# Message Schedule
|
||||
W_SIZE = 80*8
|
||||
# W[t] + K[t] | W[t+1] + K[t+1]
|
||||
WK_SIZE = 2*8
|
||||
RSPSAVE_SIZE = 1*8
|
||||
GPRSAVE_SIZE = 5*8
|
||||
|
||||
frame_W = 0
|
||||
frame_WK = frame_W + W_SIZE
|
||||
frame_RSPSAVE = frame_WK + WK_SIZE
|
||||
frame_GPRSAVE = frame_RSPSAVE + RSPSAVE_SIZE
|
||||
frame_size = frame_GPRSAVE + GPRSAVE_SIZE
|
||||
|
||||
# Useful QWORD "arrays" for simpler memory references
|
||||
# MSG, DIGEST, K_t, W_t are arrays
|
||||
# WK_2(t) points to 1 of 2 qwords at frame.WK depdending on t being odd/even
|
||||
|
||||
# Input message (arg1)
|
||||
#define MSG(i) 8*i(msg)
|
||||
|
||||
# Output Digest (arg2)
|
||||
#define DIGEST(i) 8*i(digest)
|
||||
|
||||
# SHA Constants (static mem)
|
||||
#define K_t(i) 8*i+K512(%rip)
|
||||
|
||||
# Message Schedule (stack frame)
|
||||
#define W_t(i) 8*i+frame_W(%rsp)
|
||||
|
||||
# W[t]+K[t] (stack frame)
|
||||
#define WK_2(i) 8*((i%2))+frame_WK(%rsp)
|
||||
|
||||
.macro RotateState
|
||||
# Rotate symbols a..h right
|
||||
TMP = h_64
|
||||
h_64 = g_64
|
||||
g_64 = f_64
|
||||
f_64 = e_64
|
||||
e_64 = d_64
|
||||
d_64 = c_64
|
||||
c_64 = b_64
|
||||
b_64 = a_64
|
||||
a_64 = TMP
|
||||
.endm
|
||||
|
||||
.macro RORQ p1 p2
|
||||
# shld is faster than ror on Sandybridge
|
||||
shld $(64-\p2), \p1, \p1
|
||||
.endm
|
||||
|
||||
.macro SHA512_Round rnd
|
||||
# Compute Round %%t
|
||||
mov f_64, T1 # T1 = f
|
||||
mov e_64, tmp0 # tmp = e
|
||||
xor g_64, T1 # T1 = f ^ g
|
||||
RORQ tmp0, 23 # 41 # tmp = e ror 23
|
||||
and e_64, T1 # T1 = (f ^ g) & e
|
||||
xor e_64, tmp0 # tmp = (e ror 23) ^ e
|
||||
xor g_64, T1 # T1 = ((f ^ g) & e) ^ g = CH(e,f,g)
|
||||
idx = \rnd
|
||||
add WK_2(idx), T1 # W[t] + K[t] from message scheduler
|
||||
RORQ tmp0, 4 # 18 # tmp = ((e ror 23) ^ e) ror 4
|
||||
xor e_64, tmp0 # tmp = (((e ror 23) ^ e) ror 4) ^ e
|
||||
mov a_64, T2 # T2 = a
|
||||
add h_64, T1 # T1 = CH(e,f,g) + W[t] + K[t] + h
|
||||
RORQ tmp0, 14 # 14 # tmp = ((((e ror23)^e)ror4)^e)ror14 = S1(e)
|
||||
add tmp0, T1 # T1 = CH(e,f,g) + W[t] + K[t] + S1(e)
|
||||
mov a_64, tmp0 # tmp = a
|
||||
xor c_64, T2 # T2 = a ^ c
|
||||
and c_64, tmp0 # tmp = a & c
|
||||
and b_64, T2 # T2 = (a ^ c) & b
|
||||
xor tmp0, T2 # T2 = ((a ^ c) & b) ^ (a & c) = Maj(a,b,c)
|
||||
mov a_64, tmp0 # tmp = a
|
||||
RORQ tmp0, 5 # 39 # tmp = a ror 5
|
||||
xor a_64, tmp0 # tmp = (a ror 5) ^ a
|
||||
add T1, d_64 # e(next_state) = d + T1
|
||||
RORQ tmp0, 6 # 34 # tmp = ((a ror 5) ^ a) ror 6
|
||||
xor a_64, tmp0 # tmp = (((a ror 5) ^ a) ror 6) ^ a
|
||||
lea (T1, T2), h_64 # a(next_state) = T1 + Maj(a,b,c)
|
||||
RORQ tmp0, 28 # 28 # tmp = ((((a ror5)^a)ror6)^a)ror28 = S0(a)
|
||||
add tmp0, h_64 # a(next_state) = T1 + Maj(a,b,c) S0(a)
|
||||
RotateState
|
||||
.endm
|
||||
|
||||
.macro SHA512_2Sched_2Round_avx rnd
|
||||
# Compute rounds t-2 and t-1
|
||||
# Compute message schedule QWORDS t and t+1
|
||||
|
||||
# Two rounds are computed based on the values for K[t-2]+W[t-2] and
|
||||
# K[t-1]+W[t-1] which were previously stored at WK_2 by the message
|
||||
# scheduler.
|
||||
# The two new schedule QWORDS are stored at [W_t(t)] and [W_t(t+1)].
|
||||
# They are then added to their respective SHA512 constants at
|
||||
# [K_t(t)] and [K_t(t+1)] and stored at dqword [WK_2(t)]
|
||||
# For brievity, the comments following vectored instructions only refer to
|
||||
# the first of a pair of QWORDS.
|
||||
# Eg. XMM4=W[t-2] really means XMM4={W[t-2]|W[t-1]}
|
||||
# The computation of the message schedule and the rounds are tightly
|
||||
# stitched to take advantage of instruction-level parallelism.
|
||||
|
||||
idx = \rnd - 2
|
||||
vmovdqa W_t(idx), %xmm4 # XMM4 = W[t-2]
|
||||
idx = \rnd - 15
|
||||
vmovdqu W_t(idx), %xmm5 # XMM5 = W[t-15]
|
||||
mov f_64, T1
|
||||
vpsrlq $61, %xmm4, %xmm0 # XMM0 = W[t-2]>>61
|
||||
mov e_64, tmp0
|
||||
vpsrlq $1, %xmm5, %xmm6 # XMM6 = W[t-15]>>1
|
||||
xor g_64, T1
|
||||
RORQ tmp0, 23 # 41
|
||||
vpsrlq $19, %xmm4, %xmm1 # XMM1 = W[t-2]>>19
|
||||
and e_64, T1
|
||||
xor e_64, tmp0
|
||||
vpxor %xmm1, %xmm0, %xmm0 # XMM0 = W[t-2]>>61 ^ W[t-2]>>19
|
||||
xor g_64, T1
|
||||
idx = \rnd
|
||||
add WK_2(idx), T1#
|
||||
vpsrlq $8, %xmm5, %xmm7 # XMM7 = W[t-15]>>8
|
||||
RORQ tmp0, 4 # 18
|
||||
vpsrlq $6, %xmm4, %xmm2 # XMM2 = W[t-2]>>6
|
||||
xor e_64, tmp0
|
||||
mov a_64, T2
|
||||
add h_64, T1
|
||||
vpxor %xmm7, %xmm6, %xmm6 # XMM6 = W[t-15]>>1 ^ W[t-15]>>8
|
||||
RORQ tmp0, 14 # 14
|
||||
add tmp0, T1
|
||||
vpsrlq $7, %xmm5, %xmm8 # XMM8 = W[t-15]>>7
|
||||
mov a_64, tmp0
|
||||
xor c_64, T2
|
||||
vpsllq $(64-61), %xmm4, %xmm3 # XMM3 = W[t-2]<<3
|
||||
and c_64, tmp0
|
||||
and b_64, T2
|
||||
vpxor %xmm3, %xmm2, %xmm2 # XMM2 = W[t-2]>>6 ^ W[t-2]<<3
|
||||
xor tmp0, T2
|
||||
mov a_64, tmp0
|
||||
vpsllq $(64-1), %xmm5, %xmm9 # XMM9 = W[t-15]<<63
|
||||
RORQ tmp0, 5 # 39
|
||||
vpxor %xmm9, %xmm8, %xmm8 # XMM8 = W[t-15]>>7 ^ W[t-15]<<63
|
||||
xor a_64, tmp0
|
||||
add T1, d_64
|
||||
RORQ tmp0, 6 # 34
|
||||
xor a_64, tmp0
|
||||
vpxor %xmm8, %xmm6, %xmm6 # XMM6 = W[t-15]>>1 ^ W[t-15]>>8 ^
|
||||
# W[t-15]>>7 ^ W[t-15]<<63
|
||||
lea (T1, T2), h_64
|
||||
RORQ tmp0, 28 # 28
|
||||
vpsllq $(64-19), %xmm4, %xmm4 # XMM4 = W[t-2]<<25
|
||||
add tmp0, h_64
|
||||
RotateState
|
||||
vpxor %xmm4, %xmm0, %xmm0 # XMM0 = W[t-2]>>61 ^ W[t-2]>>19 ^
|
||||
# W[t-2]<<25
|
||||
mov f_64, T1
|
||||
vpxor %xmm2, %xmm0, %xmm0 # XMM0 = s1(W[t-2])
|
||||
mov e_64, tmp0
|
||||
xor g_64, T1
|
||||
idx = \rnd - 16
|
||||
vpaddq W_t(idx), %xmm0, %xmm0 # XMM0 = s1(W[t-2]) + W[t-16]
|
||||
idx = \rnd - 7
|
||||
vmovdqu W_t(idx), %xmm1 # XMM1 = W[t-7]
|
||||
RORQ tmp0, 23 # 41
|
||||
and e_64, T1
|
||||
xor e_64, tmp0
|
||||
xor g_64, T1
|
||||
vpsllq $(64-8), %xmm5, %xmm5 # XMM5 = W[t-15]<<56
|
||||
idx = \rnd + 1
|
||||
add WK_2(idx), T1
|
||||
vpxor %xmm5, %xmm6, %xmm6 # XMM6 = s0(W[t-15])
|
||||
RORQ tmp0, 4 # 18
|
||||
vpaddq %xmm6, %xmm0, %xmm0 # XMM0 = s1(W[t-2]) + W[t-16] + s0(W[t-15])
|
||||
xor e_64, tmp0
|
||||
vpaddq %xmm1, %xmm0, %xmm0 # XMM0 = W[t] = s1(W[t-2]) + W[t-7] +
|
||||
# s0(W[t-15]) + W[t-16]
|
||||
mov a_64, T2
|
||||
add h_64, T1
|
||||
RORQ tmp0, 14 # 14
|
||||
add tmp0, T1
|
||||
idx = \rnd
|
||||
vmovdqa %xmm0, W_t(idx) # Store W[t]
|
||||
vpaddq K_t(idx), %xmm0, %xmm0 # Compute W[t]+K[t]
|
||||
vmovdqa %xmm0, WK_2(idx) # Store W[t]+K[t] for next rounds
|
||||
mov a_64, tmp0
|
||||
xor c_64, T2
|
||||
and c_64, tmp0
|
||||
and b_64, T2
|
||||
xor tmp0, T2
|
||||
mov a_64, tmp0
|
||||
RORQ tmp0, 5 # 39
|
||||
xor a_64, tmp0
|
||||
add T1, d_64
|
||||
RORQ tmp0, 6 # 34
|
||||
xor a_64, tmp0
|
||||
lea (T1, T2), h_64
|
||||
RORQ tmp0, 28 # 28
|
||||
add tmp0, h_64
|
||||
RotateState
|
||||
.endm
|
||||
|
||||
########################################################################
|
||||
# void sha512_transform_avx(const void* M, void* D, u64 L)
|
||||
# Purpose: Updates the SHA512 digest stored at D with the message stored in M.
|
||||
# The size of the message pointed to by M must be an integer multiple of SHA512
|
||||
# message blocks.
|
||||
# L is the message length in SHA512 blocks
|
||||
########################################################################
|
||||
ENTRY(sha512_transform_avx)
|
||||
cmp $0, msglen
|
||||
je nowork
|
||||
|
||||
# Allocate Stack Space
|
||||
mov %rsp, %rax
|
||||
sub $frame_size, %rsp
|
||||
and $~(0x20 - 1), %rsp
|
||||
mov %rax, frame_RSPSAVE(%rsp)
|
||||
|
||||
# Save GPRs
|
||||
mov %rbx, frame_GPRSAVE(%rsp)
|
||||
mov %r12, frame_GPRSAVE +8*1(%rsp)
|
||||
mov %r13, frame_GPRSAVE +8*2(%rsp)
|
||||
mov %r14, frame_GPRSAVE +8*3(%rsp)
|
||||
mov %r15, frame_GPRSAVE +8*4(%rsp)
|
||||
|
||||
updateblock:
|
||||
|
||||
# Load state variables
|
||||
mov DIGEST(0), a_64
|
||||
mov DIGEST(1), b_64
|
||||
mov DIGEST(2), c_64
|
||||
mov DIGEST(3), d_64
|
||||
mov DIGEST(4), e_64
|
||||
mov DIGEST(5), f_64
|
||||
mov DIGEST(6), g_64
|
||||
mov DIGEST(7), h_64
|
||||
|
||||
t = 0
|
||||
.rept 80/2 + 1
|
||||
# (80 rounds) / (2 rounds/iteration) + (1 iteration)
|
||||
# +1 iteration because the scheduler leads hashing by 1 iteration
|
||||
.if t < 2
|
||||
# BSWAP 2 QWORDS
|
||||
vmovdqa XMM_QWORD_BSWAP(%rip), %xmm1
|
||||
vmovdqu MSG(t), %xmm0
|
||||
vpshufb %xmm1, %xmm0, %xmm0 # BSWAP
|
||||
vmovdqa %xmm0, W_t(t) # Store Scheduled Pair
|
||||
vpaddq K_t(t), %xmm0, %xmm0 # Compute W[t]+K[t]
|
||||
vmovdqa %xmm0, WK_2(t) # Store into WK for rounds
|
||||
.elseif t < 16
|
||||
# BSWAP 2 QWORDS# Compute 2 Rounds
|
||||
vmovdqu MSG(t), %xmm0
|
||||
vpshufb %xmm1, %xmm0, %xmm0 # BSWAP
|
||||
SHA512_Round t-2 # Round t-2
|
||||
vmovdqa %xmm0, W_t(t) # Store Scheduled Pair
|
||||
vpaddq K_t(t), %xmm0, %xmm0 # Compute W[t]+K[t]
|
||||
SHA512_Round t-1 # Round t-1
|
||||
vmovdqa %xmm0, WK_2(t)# Store W[t]+K[t] into WK
|
||||
.elseif t < 79
|
||||
# Schedule 2 QWORDS# Compute 2 Rounds
|
||||
SHA512_2Sched_2Round_avx t
|
||||
.else
|
||||
# Compute 2 Rounds
|
||||
SHA512_Round t-2
|
||||
SHA512_Round t-1
|
||||
.endif
|
||||
t = t+2
|
||||
.endr
|
||||
|
||||
# Update digest
|
||||
add a_64, DIGEST(0)
|
||||
add b_64, DIGEST(1)
|
||||
add c_64, DIGEST(2)
|
||||
add d_64, DIGEST(3)
|
||||
add e_64, DIGEST(4)
|
||||
add f_64, DIGEST(5)
|
||||
add g_64, DIGEST(6)
|
||||
add h_64, DIGEST(7)
|
||||
|
||||
# Advance to next message block
|
||||
add $16*8, msg
|
||||
dec msglen
|
||||
jnz updateblock
|
||||
|
||||
# Restore GPRs
|
||||
mov frame_GPRSAVE(%rsp), %rbx
|
||||
mov frame_GPRSAVE +8*1(%rsp), %r12
|
||||
mov frame_GPRSAVE +8*2(%rsp), %r13
|
||||
mov frame_GPRSAVE +8*3(%rsp), %r14
|
||||
mov frame_GPRSAVE +8*4(%rsp), %r15
|
||||
|
||||
# Restore Stack Pointer
|
||||
mov frame_RSPSAVE(%rsp), %rsp
|
||||
|
||||
nowork:
|
||||
ret
|
||||
ENDPROC(sha512_transform_avx)
|
||||
|
||||
########################################################################
|
||||
### Binary Data
|
||||
|
||||
.data
|
||||
|
||||
.align 16
|
||||
|
||||
# Mask for byte-swapping a couple of qwords in an XMM register using (v)pshufb.
|
||||
XMM_QWORD_BSWAP:
|
||||
.octa 0x08090a0b0c0d0e0f0001020304050607
|
||||
|
||||
# K[t] used in SHA512 hashing
|
||||
K512:
|
||||
.quad 0x428a2f98d728ae22,0x7137449123ef65cd
|
||||
.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc
|
||||
.quad 0x3956c25bf348b538,0x59f111f1b605d019
|
||||
.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118
|
||||
.quad 0xd807aa98a3030242,0x12835b0145706fbe
|
||||
.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2
|
||||
.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1
|
||||
.quad 0x9bdc06a725c71235,0xc19bf174cf692694
|
||||
.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3
|
||||
.quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65
|
||||
.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483
|
||||
.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5
|
||||
.quad 0x983e5152ee66dfab,0xa831c66d2db43210
|
||||
.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4
|
||||
.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725
|
||||
.quad 0x06ca6351e003826f,0x142929670a0e6e70
|
||||
.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926
|
||||
.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df
|
||||
.quad 0x650a73548baf63de,0x766a0abb3c77b2a8
|
||||
.quad 0x81c2c92e47edaee6,0x92722c851482353b
|
||||
.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001
|
||||
.quad 0xc24b8b70d0f89791,0xc76c51a30654be30
|
||||
.quad 0xd192e819d6ef5218,0xd69906245565a910
|
||||
.quad 0xf40e35855771202a,0x106aa07032bbd1b8
|
||||
.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53
|
||||
.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8
|
||||
.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb
|
||||
.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3
|
||||
.quad 0x748f82ee5defb2fc,0x78a5636f43172f60
|
||||
.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec
|
||||
.quad 0x90befffa23631e28,0xa4506cebde82bde9
|
||||
.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b
|
||||
.quad 0xca273eceea26619c,0xd186b8c721c0c207
|
||||
.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178
|
||||
.quad 0x06f067aa72176fba,0x0a637dc5a2c898a6
|
||||
.quad 0x113f9804bef90dae,0x1b710b35131c471b
|
||||
.quad 0x28db77f523047d84,0x32caab7b40c72493
|
||||
.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c
|
||||
.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a
|
||||
.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,686 +0,0 @@
|
||||
########################################################################
|
||||
# Implement fast SHA-512 with SSSE3 instructions. (x86_64)
|
||||
#
|
||||
# Copyright (C) 2013 Intel Corporation.
|
||||
#
|
||||
# Authors:
|
||||
# James Guilford <james.guilford@intel.com>
|
||||
# Kirk Yap <kirk.s.yap@intel.com>
|
||||
# David Cote <david.m.cote@intel.com>
|
||||
# Tim Chen <tim.c.chen@linux.intel.com>
|
||||
#
|
||||
# This software is available to you under a choice of one of two
|
||||
# licenses. You may choose to be licensed under the terms of the GNU
|
||||
# General Public License (GPL) Version 2, available from the file
|
||||
# COPYING in the main directory of this source tree, or the
|
||||
# OpenIB.org BSD license below:
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or
|
||||
# without modification, are permitted provided that the following
|
||||
# conditions are met:
|
||||
#
|
||||
# - Redistributions of source code must retain the above
|
||||
# copyright notice, this list of conditions and the following
|
||||
# disclaimer.
|
||||
#
|
||||
# - Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following
|
||||
# disclaimer in the documentation and/or other materials
|
||||
# provided with the distribution.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
########################################################################
|
||||
#
|
||||
# This code is described in an Intel White-Paper:
|
||||
# "Fast SHA-512 Implementations on Intel Architecture Processors"
|
||||
#
|
||||
# To find it, surf to http://www.intel.com/p/en_US/embedded
|
||||
# and search for that title.
|
||||
#
|
||||
########################################################################
|
||||
# Using this part of Minio codebase under the license
|
||||
# Apache License Version 2.0 with modifications
|
||||
##
|
||||
|
||||
#ifdef HAS_SSE41
|
||||
#ifndef ENTRY
|
||||
#define ENTRY(name) \
|
||||
.globl name ; \
|
||||
.align 4,0x90 ; \
|
||||
name:
|
||||
#endif
|
||||
|
||||
#ifndef END
|
||||
#define END(name) \
|
||||
.size name, .-name
|
||||
#endif
|
||||
|
||||
#ifndef ENDPROC
|
||||
#define ENDPROC(name) \
|
||||
.type name, @function ; \
|
||||
END(name)
|
||||
#endif
|
||||
|
||||
#define NUM_INVALID 100
|
||||
|
||||
#define TYPE_R32 0
|
||||
#define TYPE_R64 1
|
||||
#define TYPE_XMM 2
|
||||
#define TYPE_INVALID 100
|
||||
|
||||
.macro R32_NUM opd r32
|
||||
\opd = NUM_INVALID
|
||||
.ifc \r32,%eax
|
||||
\opd = 0
|
||||
.endif
|
||||
.ifc \r32,%ecx
|
||||
\opd = 1
|
||||
.endif
|
||||
.ifc \r32,%edx
|
||||
\opd = 2
|
||||
.endif
|
||||
.ifc \r32,%ebx
|
||||
\opd = 3
|
||||
.endif
|
||||
.ifc \r32,%esp
|
||||
\opd = 4
|
||||
.endif
|
||||
.ifc \r32,%ebp
|
||||
\opd = 5
|
||||
.endif
|
||||
.ifc \r32,%esi
|
||||
\opd = 6
|
||||
.endif
|
||||
.ifc \r32,%edi
|
||||
\opd = 7
|
||||
.endif
|
||||
#ifdef X86_64
|
||||
.ifc \r32,%r8d
|
||||
\opd = 8
|
||||
.endif
|
||||
.ifc \r32,%r9d
|
||||
\opd = 9
|
||||
.endif
|
||||
.ifc \r32,%r10d
|
||||
\opd = 10
|
||||
.endif
|
||||
.ifc \r32,%r11d
|
||||
\opd = 11
|
||||
.endif
|
||||
.ifc \r32,%r12d
|
||||
\opd = 12
|
||||
.endif
|
||||
.ifc \r32,%r13d
|
||||
\opd = 13
|
||||
.endif
|
||||
.ifc \r32,%r14d
|
||||
\opd = 14
|
||||
.endif
|
||||
.ifc \r32,%r15d
|
||||
\opd = 15
|
||||
.endif
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro R64_NUM opd r64
|
||||
\opd = NUM_INVALID
|
||||
#ifdef X86_64
|
||||
.ifc \r64,%rax
|
||||
\opd = 0
|
||||
.endif
|
||||
.ifc \r64,%rcx
|
||||
\opd = 1
|
||||
.endif
|
||||
.ifc \r64,%rdx
|
||||
\opd = 2
|
||||
.endif
|
||||
.ifc \r64,%rbx
|
||||
\opd = 3
|
||||
.endif
|
||||
.ifc \r64,%rsp
|
||||
\opd = 4
|
||||
.endif
|
||||
.ifc \r64,%rbp
|
||||
\opd = 5
|
||||
.endif
|
||||
.ifc \r64,%rsi
|
||||
\opd = 6
|
||||
.endif
|
||||
.ifc \r64,%rdi
|
||||
\opd = 7
|
||||
.endif
|
||||
.ifc \r64,%r8
|
||||
\opd = 8
|
||||
.endif
|
||||
.ifc \r64,%r9
|
||||
\opd = 9
|
||||
.endif
|
||||
.ifc \r64,%r10
|
||||
\opd = 10
|
||||
.endif
|
||||
.ifc \r64,%r11
|
||||
\opd = 11
|
||||
.endif
|
||||
.ifc \r64,%r12
|
||||
\opd = 12
|
||||
.endif
|
||||
.ifc \r64,%r13
|
||||
\opd = 13
|
||||
.endif
|
||||
.ifc \r64,%r14
|
||||
\opd = 14
|
||||
.endif
|
||||
.ifc \r64,%r15
|
||||
\opd = 15
|
||||
.endif
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro XMM_NUM opd xmm
|
||||
\opd = NUM_INVALID
|
||||
.ifc \xmm,%xmm0
|
||||
\opd = 0
|
||||
.endif
|
||||
.ifc \xmm,%xmm1
|
||||
\opd = 1
|
||||
.endif
|
||||
.ifc \xmm,%xmm2
|
||||
\opd = 2
|
||||
.endif
|
||||
.ifc \xmm,%xmm3
|
||||
\opd = 3
|
||||
.endif
|
||||
.ifc \xmm,%xmm4
|
||||
\opd = 4
|
||||
.endif
|
||||
.ifc \xmm,%xmm5
|
||||
\opd = 5
|
||||
.endif
|
||||
.ifc \xmm,%xmm6
|
||||
\opd = 6
|
||||
.endif
|
||||
.ifc \xmm,%xmm7
|
||||
\opd = 7
|
||||
.endif
|
||||
.ifc \xmm,%xmm8
|
||||
\opd = 8
|
||||
.endif
|
||||
.ifc \xmm,%xmm9
|
||||
\opd = 9
|
||||
.endif
|
||||
.ifc \xmm,%xmm10
|
||||
\opd = 10
|
||||
.endif
|
||||
.ifc \xmm,%xmm11
|
||||
\opd = 11
|
||||
.endif
|
||||
.ifc \xmm,%xmm12
|
||||
\opd = 12
|
||||
.endif
|
||||
.ifc \xmm,%xmm13
|
||||
\opd = 13
|
||||
.endif
|
||||
.ifc \xmm,%xmm14
|
||||
\opd = 14
|
||||
.endif
|
||||
.ifc \xmm,%xmm15
|
||||
\opd = 15
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro TYPE type reg
|
||||
R32_NUM reg_type_r32 \reg
|
||||
R64_NUM reg_type_r64 \reg
|
||||
XMM_NUM reg_type_xmm \reg
|
||||
.if reg_type_r64 <> NUM_INVALID
|
||||
\type = TYPE_R64
|
||||
.elseif reg_type_r32 <> NUM_INVALID
|
||||
\type = TYPE_R32
|
||||
.elseif reg_type_xmm <> NUM_INVALID
|
||||
\type = TYPE_XMM
|
||||
.else
|
||||
\type = TYPE_INVALID
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro PFX_OPD_SIZE
|
||||
.byte 0x66
|
||||
.endm
|
||||
|
||||
.macro PFX_REX opd1 opd2 W=0
|
||||
.if ((\opd1 | \opd2) & 8) || \W
|
||||
.byte 0x40 | ((\opd1 & 8) >> 3) | ((\opd2 & 8) >> 1) | (\W << 3)
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro MODRM mod opd1 opd2
|
||||
.byte \mod | (\opd1 & 7) | ((\opd2 & 7) << 3)
|
||||
.endm
|
||||
|
||||
.macro PSHUFB_XMM xmm1 xmm2
|
||||
XMM_NUM pshufb_opd1 \xmm1
|
||||
XMM_NUM pshufb_opd2 \xmm2
|
||||
PFX_OPD_SIZE
|
||||
PFX_REX pshufb_opd1 pshufb_opd2
|
||||
.byte 0x0f, 0x38, 0x00
|
||||
MODRM 0xc0 pshufb_opd1 pshufb_opd2
|
||||
.endm
|
||||
|
||||
.macro PCLMULQDQ imm8 xmm1 xmm2
|
||||
XMM_NUM clmul_opd1 \xmm1
|
||||
XMM_NUM clmul_opd2 \xmm2
|
||||
PFX_OPD_SIZE
|
||||
PFX_REX clmul_opd1 clmul_opd2
|
||||
.byte 0x0f, 0x3a, 0x44
|
||||
MODRM 0xc0 clmul_opd1 clmul_opd2
|
||||
.byte \imm8
|
||||
.endm
|
||||
|
||||
.macro PEXTRD imm8 xmm gpr
|
||||
R32_NUM extrd_opd1 \gpr
|
||||
XMM_NUM extrd_opd2 \xmm
|
||||
PFX_OPD_SIZE
|
||||
PFX_REX extrd_opd1 extrd_opd2
|
||||
.byte 0x0f, 0x3a, 0x16
|
||||
MODRM 0xc0 extrd_opd1 extrd_opd2
|
||||
.byte \imm8
|
||||
.endm
|
||||
|
||||
.macro MOVQ_R64_XMM opd1 opd2
|
||||
TYPE movq_r64_xmm_opd1_type \opd1
|
||||
.if movq_r64_xmm_opd1_type == TYPE_XMM
|
||||
XMM_NUM movq_r64_xmm_opd1 \opd1
|
||||
R64_NUM movq_r64_xmm_opd2 \opd2
|
||||
.else
|
||||
R64_NUM movq_r64_xmm_opd1 \opd1
|
||||
XMM_NUM movq_r64_xmm_opd2 \opd2
|
||||
.endif
|
||||
PFX_OPD_SIZE
|
||||
PFX_REX movq_r64_xmm_opd1 movq_r64_xmm_opd2 1
|
||||
.if movq_r64_xmm_opd1_type == TYPE_XMM
|
||||
.byte 0x0f, 0x7e
|
||||
.else
|
||||
.byte 0x0f, 0x6e
|
||||
.endif
|
||||
MODRM 0xc0 movq_r64_xmm_opd1 movq_r64_xmm_opd2
|
||||
.endm
|
||||
|
||||
.text
|
||||
|
||||
# Virtual Registers
|
||||
# ARG1
|
||||
msg = %rdi
|
||||
# ARG2
|
||||
digest = %rsi
|
||||
# ARG3
|
||||
msglen = %rdx
|
||||
T1 = %rcx
|
||||
T2 = %r8
|
||||
a_64 = %r9
|
||||
b_64 = %r10
|
||||
c_64 = %r11
|
||||
d_64 = %r12
|
||||
e_64 = %r13
|
||||
f_64 = %r14
|
||||
g_64 = %r15
|
||||
h_64 = %rbx
|
||||
tmp0 = %rax
|
||||
|
||||
# Local variables (stack frame)
|
||||
|
||||
W_SIZE = 80*8
|
||||
WK_SIZE = 2*8
|
||||
RSPSAVE_SIZE = 1*8
|
||||
GPRSAVE_SIZE = 5*8
|
||||
|
||||
frame_W = 0
|
||||
frame_WK = frame_W + W_SIZE
|
||||
frame_RSPSAVE = frame_WK + WK_SIZE
|
||||
frame_GPRSAVE = frame_RSPSAVE + RSPSAVE_SIZE
|
||||
frame_size = frame_GPRSAVE + GPRSAVE_SIZE
|
||||
|
||||
# Useful QWORD "arrays" for simpler memory references
|
||||
# MSG, DIGEST, K_t, W_t are arrays
|
||||
# WK_2(t) points to 1 of 2 qwords at frame.WK depdending on t being odd/even
|
||||
|
||||
# Input message (arg1)
|
||||
#define MSG(i) 8*i(msg)
|
||||
|
||||
# Output Digest (arg2)
|
||||
#define DIGEST(i) 8*i(digest)
|
||||
|
||||
# SHA Constants (static mem)
|
||||
#define K_t(i) 8*i+K512(%rip)
|
||||
|
||||
# Message Schedule (stack frame)
|
||||
#define W_t(i) 8*i+frame_W(%rsp)
|
||||
|
||||
# W[t]+K[t] (stack frame)
|
||||
#define WK_2(i) 8*((i%2))+frame_WK(%rsp)
|
||||
|
||||
.macro RotateState
|
||||
# Rotate symbols a..h right
|
||||
TMP = h_64
|
||||
h_64 = g_64
|
||||
g_64 = f_64
|
||||
f_64 = e_64
|
||||
e_64 = d_64
|
||||
d_64 = c_64
|
||||
c_64 = b_64
|
||||
b_64 = a_64
|
||||
a_64 = TMP
|
||||
.endm
|
||||
|
||||
.macro SHA512_Round rnd
|
||||
|
||||
# Compute Round %%t
|
||||
mov f_64, T1 # T1 = f
|
||||
mov e_64, tmp0 # tmp = e
|
||||
xor g_64, T1 # T1 = f ^ g
|
||||
ror $23, tmp0 # 41 # tmp = e ror 23
|
||||
and e_64, T1 # T1 = (f ^ g) & e
|
||||
xor e_64, tmp0 # tmp = (e ror 23) ^ e
|
||||
xor g_64, T1 # T1 = ((f ^ g) & e) ^ g = CH(e,f,g)
|
||||
idx = \rnd
|
||||
add WK_2(idx), T1 # W[t] + K[t] from message scheduler
|
||||
ror $4, tmp0 # 18 # tmp = ((e ror 23) ^ e) ror 4
|
||||
xor e_64, tmp0 # tmp = (((e ror 23) ^ e) ror 4) ^ e
|
||||
mov a_64, T2 # T2 = a
|
||||
add h_64, T1 # T1 = CH(e,f,g) + W[t] + K[t] + h
|
||||
ror $14, tmp0 # 14 # tmp = ((((e ror23)^e)ror4)^e)ror14 = S1(e)
|
||||
add tmp0, T1 # T1 = CH(e,f,g) + W[t] + K[t] + S1(e)
|
||||
mov a_64, tmp0 # tmp = a
|
||||
xor c_64, T2 # T2 = a ^ c
|
||||
and c_64, tmp0 # tmp = a & c
|
||||
and b_64, T2 # T2 = (a ^ c) & b
|
||||
xor tmp0, T2 # T2 = ((a ^ c) & b) ^ (a & c) = Maj(a,b,c)
|
||||
mov a_64, tmp0 # tmp = a
|
||||
ror $5, tmp0 # 39 # tmp = a ror 5
|
||||
xor a_64, tmp0 # tmp = (a ror 5) ^ a
|
||||
add T1, d_64 # e(next_state) = d + T1
|
||||
ror $6, tmp0 # 34 # tmp = ((a ror 5) ^ a) ror 6
|
||||
xor a_64, tmp0 # tmp = (((a ror 5) ^ a) ror 6) ^ a
|
||||
lea (T1, T2), h_64 # a(next_state) = T1 + Maj(a,b,c)
|
||||
ror $28, tmp0 # 28 # tmp = ((((a ror5)^a)ror6)^a)ror28 = S0(a)
|
||||
add tmp0, h_64 # a(next_state) = T1 + Maj(a,b,c) S0(a)
|
||||
RotateState
|
||||
.endm
|
||||
|
||||
.macro SHA512_2Sched_2Round_sse rnd
|
||||
|
||||
# Compute rounds t-2 and t-1
|
||||
# Compute message schedule QWORDS t and t+1
|
||||
|
||||
# Two rounds are computed based on the values for K[t-2]+W[t-2] and
|
||||
# K[t-1]+W[t-1] which were previously stored at WK_2 by the message
|
||||
# scheduler.
|
||||
# The two new schedule QWORDS are stored at [W_t(%%t)] and [W_t(%%t+1)].
|
||||
# They are then added to their respective SHA512 constants at
|
||||
# [K_t(%%t)] and [K_t(%%t+1)] and stored at dqword [WK_2(%%t)]
|
||||
# For brievity, the comments following vectored instructions only refer to
|
||||
# the first of a pair of QWORDS.
|
||||
# Eg. XMM2=W[t-2] really means XMM2={W[t-2]|W[t-1]}
|
||||
# The computation of the message schedule and the rounds are tightly
|
||||
# stitched to take advantage of instruction-level parallelism.
|
||||
# For clarity, integer instructions (for the rounds calculation) are indented
|
||||
# by one tab. Vectored instructions (for the message scheduler) are indented
|
||||
# by two tabs.
|
||||
|
||||
mov f_64, T1
|
||||
idx = \rnd -2
|
||||
movdqa W_t(idx), %xmm2 # XMM2 = W[t-2]
|
||||
xor g_64, T1
|
||||
and e_64, T1
|
||||
movdqa %xmm2, %xmm0 # XMM0 = W[t-2]
|
||||
xor g_64, T1
|
||||
idx = \rnd
|
||||
add WK_2(idx), T1
|
||||
idx = \rnd - 15
|
||||
movdqu W_t(idx), %xmm5 # XMM5 = W[t-15]
|
||||
mov e_64, tmp0
|
||||
ror $23, tmp0 # 41
|
||||
movdqa %xmm5, %xmm3 # XMM3 = W[t-15]
|
||||
xor e_64, tmp0
|
||||
ror $4, tmp0 # 18
|
||||
psrlq $61-19, %xmm0 # XMM0 = W[t-2] >> 42
|
||||
xor e_64, tmp0
|
||||
ror $14, tmp0 # 14
|
||||
psrlq $(8-7), %xmm3 # XMM3 = W[t-15] >> 1
|
||||
add tmp0, T1
|
||||
add h_64, T1
|
||||
pxor %xmm2, %xmm0 # XMM0 = (W[t-2] >> 42) ^ W[t-2]
|
||||
mov a_64, T2
|
||||
xor c_64, T2
|
||||
pxor %xmm5, %xmm3 # XMM3 = (W[t-15] >> 1) ^ W[t-15]
|
||||
and b_64, T2
|
||||
mov a_64, tmp0
|
||||
psrlq $(19-6), %xmm0 # XMM0 = ((W[t-2]>>42)^W[t-2])>>13
|
||||
and c_64, tmp0
|
||||
xor tmp0, T2
|
||||
psrlq $(7-1), %xmm3 # XMM3 = ((W[t-15]>>1)^W[t-15])>>6
|
||||
mov a_64, tmp0
|
||||
ror $5, tmp0 # 39
|
||||
pxor %xmm2, %xmm0 # XMM0 = (((W[t-2]>>42)^W[t-2])>>13)^W[t-2]
|
||||
xor a_64, tmp0
|
||||
ror $6, tmp0 # 34
|
||||
pxor %xmm5, %xmm3 # XMM3 = (((W[t-15]>>1)^W[t-15])>>6)^W[t-15]
|
||||
xor a_64, tmp0
|
||||
ror $28, tmp0 # 28
|
||||
psrlq $6, %xmm0 # XMM0 = ((((W[t-2]>>42)^W[t-2])>>13)^W[t-2])>>6
|
||||
add tmp0, T2
|
||||
add T1, d_64
|
||||
psrlq $1, %xmm3 # XMM3 = (((W[t-15]>>1)^W[t-15])>>6)^W[t-15]>>1
|
||||
lea (T1, T2), h_64
|
||||
RotateState
|
||||
movdqa %xmm2, %xmm1 # XMM1 = W[t-2]
|
||||
mov f_64, T1
|
||||
xor g_64, T1
|
||||
movdqa %xmm5, %xmm4 # XMM4 = W[t-15]
|
||||
and e_64, T1
|
||||
xor g_64, T1
|
||||
psllq $(64-19)-(64-61) , %xmm1 # XMM1 = W[t-2] << 42
|
||||
idx = \rnd + 1
|
||||
add WK_2(idx), T1
|
||||
mov e_64, tmp0
|
||||
psllq $(64-1)-(64-8), %xmm4 # XMM4 = W[t-15] << 7
|
||||
ror $23, tmp0 # 41
|
||||
xor e_64, tmp0
|
||||
pxor %xmm2, %xmm1 # XMM1 = (W[t-2] << 42)^W[t-2]
|
||||
ror $4, tmp0 # 18
|
||||
xor e_64, tmp0
|
||||
pxor %xmm5, %xmm4 # XMM4 = (W[t-15]<<7)^W[t-15]
|
||||
ror $14, tmp0 # 14
|
||||
add tmp0, T1
|
||||
psllq $(64-61), %xmm1 # XMM1 = ((W[t-2] << 42)^W[t-2])<<3
|
||||
add h_64, T1
|
||||
mov a_64, T2
|
||||
psllq $(64-8), %xmm4 # XMM4 = ((W[t-15]<<7)^W[t-15])<<56
|
||||
xor c_64, T2
|
||||
and b_64, T2
|
||||
pxor %xmm1, %xmm0 # XMM0 = s1(W[t-2])
|
||||
mov a_64, tmp0
|
||||
and c_64, tmp0
|
||||
idx = \rnd - 7
|
||||
movdqu W_t(idx), %xmm1 # XMM1 = W[t-7]
|
||||
xor tmp0, T2
|
||||
pxor %xmm4, %xmm3 # XMM3 = s0(W[t-15])
|
||||
mov a_64, tmp0
|
||||
paddq %xmm3, %xmm0 # XMM0 = s1(W[t-2]) + s0(W[t-15])
|
||||
ror $5, tmp0 # 39
|
||||
idx =\rnd-16
|
||||
paddq W_t(idx), %xmm0 # XMM0 = s1(W[t-2]) + s0(W[t-15]) + W[t-16]
|
||||
xor a_64, tmp0
|
||||
paddq %xmm1, %xmm0 # XMM0 = s1(W[t-2]) + W[t-7] + s0(W[t-15]) + W[t-16]
|
||||
ror $6, tmp0 # 34
|
||||
movdqa %xmm0, W_t(\rnd) # Store scheduled qwords
|
||||
xor a_64, tmp0
|
||||
paddq K_t(\rnd), %xmm0 # Compute W[t]+K[t]
|
||||
ror $28, tmp0 # 28
|
||||
idx = \rnd
|
||||
movdqa %xmm0, WK_2(idx) # Store W[t]+K[t] for next rounds
|
||||
add tmp0, T2
|
||||
add T1, d_64
|
||||
lea (T1, T2), h_64
|
||||
RotateState
|
||||
.endm
|
||||
|
||||
########################################################################
|
||||
# void sha512_transform_ssse3(const void* M, void* D, u64 L)#
|
||||
# Purpose: Updates the SHA512 digest stored at D with the message stored in M.
|
||||
# The size of the message pointed to by M must be an integer multiple of SHA512
|
||||
# message blocks.
|
||||
# L is the message length in SHA512 blocks.
|
||||
########################################################################
|
||||
ENTRY(sha512_transform_ssse3)
|
||||
|
||||
cmp $0, msglen
|
||||
je nowork
|
||||
|
||||
# Allocate Stack Space
|
||||
mov %rsp, %rax
|
||||
sub $frame_size, %rsp
|
||||
and $~(0x20 - 1), %rsp
|
||||
mov %rax, frame_RSPSAVE(%rsp)
|
||||
|
||||
# Save GPRs
|
||||
mov %rbx, frame_GPRSAVE(%rsp)
|
||||
mov %r12, frame_GPRSAVE +8*1(%rsp)
|
||||
mov %r13, frame_GPRSAVE +8*2(%rsp)
|
||||
mov %r14, frame_GPRSAVE +8*3(%rsp)
|
||||
mov %r15, frame_GPRSAVE +8*4(%rsp)
|
||||
|
||||
updateblock:
|
||||
|
||||
# Load state variables
|
||||
mov DIGEST(0), a_64
|
||||
mov DIGEST(1), b_64
|
||||
mov DIGEST(2), c_64
|
||||
mov DIGEST(3), d_64
|
||||
mov DIGEST(4), e_64
|
||||
mov DIGEST(5), f_64
|
||||
mov DIGEST(6), g_64
|
||||
mov DIGEST(7), h_64
|
||||
|
||||
t = 0
|
||||
.rept 80/2 + 1
|
||||
# (80 rounds) / (2 rounds/iteration) + (1 iteration)
|
||||
# +1 iteration because the scheduler leads hashing by 1 iteration
|
||||
.if t < 2
|
||||
# BSWAP 2 QWORDS
|
||||
movdqa XMM_QWORD_BSWAP(%rip), %xmm1
|
||||
movdqu MSG(t), %xmm0
|
||||
pshufb %xmm1, %xmm0 # BSWAP
|
||||
movdqa %xmm0, W_t(t) # Store Scheduled Pair
|
||||
paddq K_t(t), %xmm0 # Compute W[t]+K[t]
|
||||
movdqa %xmm0, WK_2(t) # Store into WK for rounds
|
||||
.elseif t < 16
|
||||
# BSWAP 2 QWORDS# Compute 2 Rounds
|
||||
movdqu MSG(t), %xmm0
|
||||
pshufb %xmm1, %xmm0 # BSWAP
|
||||
SHA512_Round t-2 # Round t-2
|
||||
movdqa %xmm0, W_t(t) # Store Scheduled Pair
|
||||
paddq K_t(t), %xmm0 # Compute W[t]+K[t]
|
||||
SHA512_Round t-1 # Round t-1
|
||||
movdqa %xmm0, WK_2(t) # Store W[t]+K[t] into WK
|
||||
.elseif t < 79
|
||||
# Schedule 2 QWORDS# Compute 2 Rounds
|
||||
SHA512_2Sched_2Round_sse t
|
||||
.else
|
||||
# Compute 2 Rounds
|
||||
SHA512_Round t-2
|
||||
SHA512_Round t-1
|
||||
.endif
|
||||
t = t+2
|
||||
.endr
|
||||
|
||||
# Update digest
|
||||
add a_64, DIGEST(0)
|
||||
add b_64, DIGEST(1)
|
||||
add c_64, DIGEST(2)
|
||||
add d_64, DIGEST(3)
|
||||
add e_64, DIGEST(4)
|
||||
add f_64, DIGEST(5)
|
||||
add g_64, DIGEST(6)
|
||||
add h_64, DIGEST(7)
|
||||
|
||||
# Advance to next message block
|
||||
add $16*8, msg
|
||||
dec msglen
|
||||
jnz updateblock
|
||||
|
||||
# Restore GPRs
|
||||
mov frame_GPRSAVE(%rsp), %rbx
|
||||
mov frame_GPRSAVE +8*1(%rsp), %r12
|
||||
mov frame_GPRSAVE +8*2(%rsp), %r13
|
||||
mov frame_GPRSAVE +8*3(%rsp), %r14
|
||||
mov frame_GPRSAVE +8*4(%rsp), %r15
|
||||
|
||||
# Restore Stack Pointer
|
||||
mov frame_RSPSAVE(%rsp), %rsp
|
||||
|
||||
nowork:
|
||||
ret
|
||||
ENDPROC(sha512_transform_ssse3)
|
||||
|
||||
########################################################################
|
||||
### Binary Data
|
||||
|
||||
.data
|
||||
|
||||
.align 16
|
||||
|
||||
# Mask for byte-swapping a couple of qwords in an XMM register using (v)pshufb.
|
||||
XMM_QWORD_BSWAP:
|
||||
.octa 0x08090a0b0c0d0e0f0001020304050607
|
||||
|
||||
# K[t] used in SHA512 hashing
|
||||
K512:
|
||||
.quad 0x428a2f98d728ae22,0x7137449123ef65cd
|
||||
.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc
|
||||
.quad 0x3956c25bf348b538,0x59f111f1b605d019
|
||||
.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118
|
||||
.quad 0xd807aa98a3030242,0x12835b0145706fbe
|
||||
.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2
|
||||
.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1
|
||||
.quad 0x9bdc06a725c71235,0xc19bf174cf692694
|
||||
.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3
|
||||
.quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65
|
||||
.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483
|
||||
.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5
|
||||
.quad 0x983e5152ee66dfab,0xa831c66d2db43210
|
||||
.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4
|
||||
.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725
|
||||
.quad 0x06ca6351e003826f,0x142929670a0e6e70
|
||||
.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926
|
||||
.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df
|
||||
.quad 0x650a73548baf63de,0x766a0abb3c77b2a8
|
||||
.quad 0x81c2c92e47edaee6,0x92722c851482353b
|
||||
.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001
|
||||
.quad 0xc24b8b70d0f89791,0xc76c51a30654be30
|
||||
.quad 0xd192e819d6ef5218,0xd69906245565a910
|
||||
.quad 0xf40e35855771202a,0x106aa07032bbd1b8
|
||||
.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53
|
||||
.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8
|
||||
.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb
|
||||
.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3
|
||||
.quad 0x748f82ee5defb2fc,0x78a5636f43172f60
|
||||
.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec
|
||||
.quad 0x90befffa23631e28,0xa4506cebde82bde9
|
||||
.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b
|
||||
.quad 0xca273eceea26619c,0xd186b8c721c0c207
|
||||
.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178
|
||||
.quad 0x06f067aa72176fba,0x0a637dc5a2c898a6
|
||||
.quad 0x113f9804bef90dae,0x1b710b35131c471b
|
||||
.quad 0x28db77f523047d84,0x32caab7b40c72493
|
||||
.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c
|
||||
.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a
|
||||
.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817
|
||||
#endif
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2014 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sha512
|
||||
|
||||
import (
|
||||
"hash"
|
||||
"io"
|
||||
|
||||
"crypto/sha512"
|
||||
)
|
||||
|
||||
// The size of a SHA512 checksum in bytes.
|
||||
const (
|
||||
Size = sha512.Size
|
||||
)
|
||||
|
||||
// Sum512 - single caller sha512 helper
|
||||
func Sum512(data []byte) []byte {
|
||||
d := sha512.New()
|
||||
d.Write(data)
|
||||
return d.Sum(nil)
|
||||
}
|
||||
|
||||
// Sum - io.Reader based streaming sha512 helper
|
||||
func Sum(reader io.Reader) ([]byte, error) {
|
||||
d := sha512.New()
|
||||
var err error
|
||||
for err == nil {
|
||||
length := 0
|
||||
byteBuffer := make([]byte, 1024*1024)
|
||||
length, err = reader.Read(byteBuffer)
|
||||
byteBuffer = byteBuffer[0:length]
|
||||
d.Write(byteBuffer)
|
||||
}
|
||||
if err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
return d.Sum(nil), nil
|
||||
}
|
||||
|
||||
// New returns a new hash.Hash computing SHA512.
|
||||
func New() hash.Hash {
|
||||
return sha512.New()
|
||||
}
|
||||
@@ -1,184 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file of
|
||||
// Golang project:
|
||||
// https://github.com/golang/go/blob/master/LICENSE
|
||||
|
||||
// Using this part of Minio codebase under the license
|
||||
// Apache License Version 2.0 with modifications
|
||||
|
||||
// Package sha512 implements the SHA512 hash algorithms as defined
|
||||
// in FIPS 180-2.
|
||||
package sha512
|
||||
|
||||
import (
|
||||
"hash"
|
||||
"io"
|
||||
|
||||
"github.com/minio/minio/pkg/cpu"
|
||||
)
|
||||
|
||||
// The size of a SHA512 checksum in bytes.
|
||||
const Size = 64
|
||||
|
||||
// The blocksize of SHA512 in bytes.
|
||||
const BlockSize = 128
|
||||
|
||||
const (
|
||||
chunk = 128
|
||||
init0 = 0x6a09e667f3bcc908
|
||||
init1 = 0xbb67ae8584caa73b
|
||||
init2 = 0x3c6ef372fe94f82b
|
||||
init3 = 0xa54ff53a5f1d36f1
|
||||
init4 = 0x510e527fade682d1
|
||||
init5 = 0x9b05688c2b3e6c1f
|
||||
init6 = 0x1f83d9abfb41bd6b
|
||||
init7 = 0x5be0cd19137e2179
|
||||
)
|
||||
|
||||
// digest represents the partial evaluation of a checksum.
|
||||
type digest struct {
|
||||
h [8]uint64
|
||||
x [chunk]byte
|
||||
nx int
|
||||
len uint64
|
||||
}
|
||||
|
||||
func block(dig *digest, p []byte) {
|
||||
switch true {
|
||||
case cpu.HasAVX2() == true:
|
||||
blockAVX2(dig, p)
|
||||
case cpu.HasAVX() == true:
|
||||
blockAVX(dig, p)
|
||||
case cpu.HasSSE41() == true:
|
||||
blockSSE(dig, p)
|
||||
default:
|
||||
blockGeneric(dig, p)
|
||||
}
|
||||
}
|
||||
|
||||
// Reset digest to its default value
|
||||
func (d *digest) Reset() {
|
||||
d.h[0] = init0
|
||||
d.h[1] = init1
|
||||
d.h[2] = init2
|
||||
d.h[3] = init3
|
||||
d.h[4] = init4
|
||||
d.h[5] = init5
|
||||
d.h[6] = init6
|
||||
d.h[7] = init7
|
||||
d.nx = 0
|
||||
d.len = 0
|
||||
}
|
||||
|
||||
// New returns a new hash.Hash computing the SHA512 checksum.
|
||||
func New() hash.Hash {
|
||||
d := new(digest)
|
||||
d.Reset()
|
||||
return d
|
||||
}
|
||||
|
||||
// Return output array byte size
|
||||
func (d *digest) Size() int { return Size }
|
||||
|
||||
// Return blockSize
|
||||
func (d *digest) BlockSize() int { return BlockSize }
|
||||
|
||||
// Write blocks
|
||||
func (d *digest) Write(p []byte) (nn int, err error) {
|
||||
nn = len(p)
|
||||
d.len += uint64(nn)
|
||||
if d.nx > 0 {
|
||||
n := copy(d.x[d.nx:], p)
|
||||
d.nx += n
|
||||
if d.nx == chunk {
|
||||
block(d, d.x[:])
|
||||
d.nx = 0
|
||||
}
|
||||
p = p[n:]
|
||||
}
|
||||
if len(p) >= chunk {
|
||||
n := len(p) &^ (chunk - 1)
|
||||
block(d, p[:n])
|
||||
p = p[n:]
|
||||
}
|
||||
if len(p) > 0 {
|
||||
d.nx = copy(d.x[:], p)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Calculate sha512
|
||||
func (d *digest) Sum(in []byte) []byte {
|
||||
// Make a copy of d0 so that caller can keep writing and summing.
|
||||
d0 := *d
|
||||
hash := d0.checkSum()
|
||||
return append(in, hash[:]...)
|
||||
}
|
||||
|
||||
// internal checksum calculation, returns [Size]byte
|
||||
func (d *digest) checkSum() [Size]byte {
|
||||
// Padding. Add a 1 bit and 0 bits until 112 bytes mod 128.
|
||||
len := d.len
|
||||
var tmp [128]byte
|
||||
tmp[0] = 0x80
|
||||
if len%128 < 112 {
|
||||
d.Write(tmp[0 : 112-len%128])
|
||||
} else {
|
||||
d.Write(tmp[0 : 128+112-len%128])
|
||||
}
|
||||
|
||||
// Length in bits.
|
||||
len <<= 3
|
||||
for i := uint(0); i < 16; i++ {
|
||||
tmp[i] = byte(len >> (120 - 8*i))
|
||||
}
|
||||
d.Write(tmp[0:16])
|
||||
|
||||
if d.nx != 0 {
|
||||
panic("d.nx != 0")
|
||||
}
|
||||
|
||||
h := d.h[:]
|
||||
|
||||
var digest [Size]byte
|
||||
for i, s := range h {
|
||||
digest[i*8] = byte(s >> 56)
|
||||
digest[i*8+1] = byte(s >> 48)
|
||||
digest[i*8+2] = byte(s >> 40)
|
||||
digest[i*8+3] = byte(s >> 32)
|
||||
digest[i*8+4] = byte(s >> 24)
|
||||
digest[i*8+5] = byte(s >> 16)
|
||||
digest[i*8+6] = byte(s >> 8)
|
||||
digest[i*8+7] = byte(s)
|
||||
}
|
||||
|
||||
return digest
|
||||
}
|
||||
|
||||
/// Convenience functions
|
||||
|
||||
// Sum512 - single caller sha512 helper
|
||||
func Sum512(data []byte) []byte {
|
||||
var d digest
|
||||
d.Reset()
|
||||
d.Write(data)
|
||||
return d.Sum(nil)
|
||||
}
|
||||
|
||||
// Sum - io.Reader based streaming sha512 helper
|
||||
func Sum(reader io.Reader) ([]byte, error) {
|
||||
h := New()
|
||||
var err error
|
||||
for err == nil {
|
||||
length := 0
|
||||
byteBuffer := make([]byte, 1024*1024)
|
||||
length, err = reader.Read(byteBuffer)
|
||||
byteBuffer = byteBuffer[0:length]
|
||||
h.Write(byteBuffer)
|
||||
}
|
||||
if err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
return h.Sum(nil), nil
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file of
|
||||
// Golang project:
|
||||
// https://github.com/golang/go/blob/master/LICENSE
|
||||
|
||||
// Using this part of Minio codebase under the license
|
||||
// Apache License Version 2.0 with modifications
|
||||
|
||||
// SHA512 hash algorithm. See FIPS 180-2.
|
||||
|
||||
package sha512
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type sha512Test struct {
|
||||
out string
|
||||
in string
|
||||
}
|
||||
|
||||
var golden = []sha512Test{
|
||||
{"cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", ""},
|
||||
{"1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75", "a"},
|
||||
{"2d408a0717ec188158278a796c689044361dc6fdde28d6f04973b80896e1823975cdbf12eb63f9e0591328ee235d80e9b5bf1aa6a44f4617ff3caf6400eb172d", "ab"},
|
||||
{"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f", "abc"},
|
||||
{"d8022f2060ad6efd297ab73dcc5355c9b214054b0d1776a136a669d26a7d3b14f73aa0d0ebff19ee333368f0164b6419a96da49e3e481753e7e96b716bdccb6f", "abcd"},
|
||||
{"878ae65a92e86cac011a570d4c30a7eaec442b85ce8eca0c2952b5e3cc0628c2e79d889ad4d5c7c626986d452dd86374b6ffaa7cd8b67665bef2289a5c70b0a1", "abcde"},
|
||||
{"e32ef19623e8ed9d267f657a81944b3d07adbb768518068e88435745564e8d4150a0a703be2a7d88b61e3d390c2bb97e2d4c311fdc69d6b1267f05f59aa920e7", "abcdef"},
|
||||
{"d716a4188569b68ab1b6dfac178e570114cdf0ea3a1cc0e31486c3e41241bc6a76424e8c37ab26f096fc85ef9886c8cb634187f4fddff645fb099f1ff54c6b8c", "abcdefg"},
|
||||
{"a3a8c81bc97c2560010d7389bc88aac974a104e0e2381220c6e084c4dccd1d2d17d4f86db31c2a851dc80e6681d74733c55dcd03dd96f6062cdda12a291ae6ce", "abcdefgh"},
|
||||
{"f22d51d25292ca1d0f68f69aedc7897019308cc9db46efb75a03dd494fc7f126c010e8ade6a00a0c1a5f1b75d81e0ed5a93ce98dc9b833db7839247b1d9c24fe", "abcdefghi"},
|
||||
{"ef6b97321f34b1fea2169a7db9e1960b471aa13302a988087357c520be957ca119c3ba68e6b4982c019ec89de3865ccf6a3cda1fe11e59f98d99f1502c8b9745", "abcdefghij"},
|
||||
{"2210d99af9c8bdecda1b4beff822136753d8342505ddce37f1314e2cdbb488c6016bdaa9bd2ffa513dd5de2e4b50f031393d8ab61f773b0e0130d7381e0f8a1d", "Discard medicine more than two years old."},
|
||||
{"a687a8985b4d8d0a24f115fe272255c6afaf3909225838546159c1ed685c211a203796ae8ecc4c81a5b6315919b3a64f10713da07e341fcdbb08541bf03066ce", "He who has a shady past knows that nice guys finish last."},
|
||||
{"8ddb0392e818b7d585ab22769a50df660d9f6d559cca3afc5691b8ca91b8451374e42bcdabd64589ed7c91d85f626596228a5c8572677eb98bc6b624befb7af8", "I wouldn't marry him with a ten foot pole."},
|
||||
{"26ed8f6ca7f8d44b6a8a54ae39640fa8ad5c673f70ee9ce074ba4ef0d483eea00bab2f61d8695d6b34df9c6c48ae36246362200ed820448bdc03a720366a87c6", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"},
|
||||
{"e5a14bf044be69615aade89afcf1ab0389d5fc302a884d403579d1386a2400c089b0dbb387ed0f463f9ee342f8244d5a38cfbc0e819da9529fbff78368c9a982", "The days of the digital watch are numbered. -Tom Stoppard"},
|
||||
{"420a1faa48919e14651bed45725abe0f7a58e0f099424c4e5a49194946e38b46c1f8034b18ef169b2e31050d1648e0b982386595f7df47da4b6fd18e55333015", "Nepal premier won't resign."},
|
||||
{"d926a863beadb20134db07683535c72007b0e695045876254f341ddcccde132a908c5af57baa6a6a9c63e6649bba0c213dc05fadcf9abccea09f23dcfb637fbe", "For every action there is an equal and opposite government program."},
|
||||
{"9a98dd9bb67d0da7bf83da5313dff4fd60a4bac0094f1b05633690ffa7f6d61de9a1d4f8617937d560833a9aaa9ccafe3fd24db418d0e728833545cadd3ad92d", "His money is twice tainted: 'taint yours and 'taint mine."},
|
||||
{"d7fde2d2351efade52f4211d3746a0780a26eec3df9b2ed575368a8a1c09ec452402293a8ea4eceb5a4f60064ea29b13cdd86918cd7a4faf366160b009804107", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"},
|
||||
{"b0f35ffa2697359c33a56f5c0cf715c7aeed96da9905ca2698acadb08fbc9e669bf566b6bd5d61a3e86dc22999bcc9f2224e33d1d4f32a228cf9d0349e2db518", "It's a tiny change to the code and not completely disgusting. - Bob Manchek"},
|
||||
{"3d2e5f91778c9e66f7e061293aaa8a8fc742dd3b2e4f483772464b1144189b49273e610e5cccd7a81a19ca1fa70f16b10f1a100a4d8c1372336be8484c64b311", "size: a.out: bad magic"},
|
||||
{"b2f68ff58ac015efb1c94c908b0d8c2bf06f491e4de8e6302c49016f7f8a33eac3e959856c7fddbc464de618701338a4b46f76dbfaf9a1e5262b5f40639771c7", "The major problem is with sendmail. -Mark Horton"},
|
||||
{"d8c92db5fdf52cf8215e4df3b4909d29203ff4d00e9ad0b64a6a4e04dec5e74f62e7c35c7fb881bd5de95442123df8f57a489b0ae616bd326f84d10021121c57", "Give me a rock, paper and scissors and I will move the world. CCFestoon"},
|
||||
{"19a9f8dc0a233e464e8566ad3ca9b91e459a7b8c4780985b015776e1bf239a19bc233d0556343e2b0a9bc220900b4ebf4f8bdf89ff8efeaf79602d6849e6f72e", "If the enemy is within range, then so are you."},
|
||||
{"00b4c41f307bde87301cdc5b5ab1ae9a592e8ecbb2021dd7bc4b34e2ace60741cc362560bec566ba35178595a91932b8d5357e2c9cec92d393b0fa7831852476", "It's well we cannot hear the screams/That we create in others' dreams."},
|
||||
{"91eccc3d5375fd026e4d6787874b1dce201cecd8a27dbded5065728cb2d09c58a3d467bb1faf353bf7ba567e005245d5321b55bc344f7c07b91cb6f26c959be7", "You remind me of a TV show, but that's all right: I watch it anyway."},
|
||||
{"fabbbe22180f1f137cfdc9556d2570e775d1ae02a597ded43a72a40f9b485d500043b7be128fb9fcd982b83159a0d99aa855a9e7cc4240c00dc01a9bdf8218d7", "C is as portable as Stonehedge!!"},
|
||||
{"2ecdec235c1fa4fc2a154d8fba1dddb8a72a1ad73838b51d792331d143f8b96a9f6fcb0f34d7caa351fe6d88771c4f105040e0392f06e0621689d33b2f3ba92e", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"},
|
||||
{"7ad681f6f96f82f7abfa7ecc0334e8fa16d3dc1cdc45b60b7af43fe4075d2357c0c1d60e98350f1afb1f2fe7a4d7cd2ad55b88e458e06b73c40b437331f5dab4", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule"},
|
||||
{"833f9248ab4a3b9e5131f745fda1ffd2dd435b30e965957e78291c7ab73605fd1912b0794e5c233ab0a12d205a39778d19b83515d6a47003f19cdee51d98c7e0", "How can you write a big system without C++? -Paul Glick"},
|
||||
}
|
||||
|
||||
func TestGolden(t *testing.T) {
|
||||
for i := 0; i < len(golden); i++ {
|
||||
g := golden[i]
|
||||
s := fmt.Sprintf("%x", Sum512([]byte(g.in)))
|
||||
if s != g.out {
|
||||
t.Fatalf("Sum512 function: sha512(%s) = %s want %s", g.in, s, g.out)
|
||||
}
|
||||
c := New()
|
||||
for j := 0; j < 3; j++ {
|
||||
if j < 2 {
|
||||
io.WriteString(c, g.in)
|
||||
} else {
|
||||
io.WriteString(c, g.in[0:len(g.in)/2])
|
||||
c.Sum(nil)
|
||||
io.WriteString(c, g.in[len(g.in)/2:])
|
||||
}
|
||||
s := fmt.Sprintf("%x", c.Sum(nil))
|
||||
if s != g.out {
|
||||
t.Fatalf("sha512[%d](%s) = %s want %s", j, g.in, s, g.out)
|
||||
}
|
||||
c.Reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSize(t *testing.T) {
|
||||
c := New()
|
||||
if got := c.Size(); got != Size {
|
||||
t.Errorf("Size = %d; want %d", got, Size)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockSize(t *testing.T) {
|
||||
c := New()
|
||||
if got := c.BlockSize(); got != BlockSize {
|
||||
t.Errorf("BlockSize = %d; want %d", got, BlockSize)
|
||||
}
|
||||
}
|
||||
|
||||
var bench = New()
|
||||
var buf = make([]byte, 1024*1024)
|
||||
|
||||
func benchmarkSize(b *testing.B, size int) {
|
||||
b.SetBytes(int64(size))
|
||||
sum := make([]byte, bench.Size())
|
||||
for i := 0; i < b.N; i++ {
|
||||
bench.Reset()
|
||||
bench.Write(buf[:size])
|
||||
bench.Sum(sum[:0])
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkHash8Bytes(b *testing.B) {
|
||||
benchmarkSize(b, 8)
|
||||
}
|
||||
|
||||
func BenchmarkHash1K(b *testing.B) {
|
||||
benchmarkSize(b, 1024)
|
||||
}
|
||||
|
||||
func BenchmarkHash8K(b *testing.B) {
|
||||
benchmarkSize(b, 8192)
|
||||
}
|
||||
|
||||
func BenchmarkHash1M(b *testing.B) {
|
||||
benchmarkSize(b, 1024*1024)
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2014 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sha512
|
||||
|
||||
import (
|
||||
"hash"
|
||||
"io"
|
||||
|
||||
"crypto/sha512"
|
||||
)
|
||||
|
||||
// The size of a SHA512 checksum in bytes.
|
||||
const (
|
||||
Size = sha512.Size
|
||||
)
|
||||
|
||||
// Sum512 - single caller sha512 helper
|
||||
func Sum512(data []byte) []byte {
|
||||
d := sha512.New()
|
||||
d.Write(data)
|
||||
return d.Sum(nil)
|
||||
}
|
||||
|
||||
// Sum - io.Reader based streaming sha512 helper
|
||||
func Sum(reader io.Reader) ([]byte, error) {
|
||||
d := sha512.New()
|
||||
var err error
|
||||
for err == nil {
|
||||
length := 0
|
||||
byteBuffer := make([]byte, 1024*1024)
|
||||
length, err = reader.Read(byteBuffer)
|
||||
byteBuffer = byteBuffer[0:length]
|
||||
d.Write(byteBuffer)
|
||||
}
|
||||
if err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
return d.Sum(nil), nil
|
||||
}
|
||||
|
||||
// New returns a new hash.Hash computing SHA512.
|
||||
func New() hash.Hash {
|
||||
return sha512.New()
|
||||
}
|
||||
@@ -1,180 +0,0 @@
|
||||
// +build amd64
|
||||
|
||||
//
|
||||
// Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Software block transform are provided by The Go Authors:
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file of
|
||||
// Golang project:
|
||||
// https://github.com/golang/go/blob/master/LICENSE
|
||||
|
||||
package sha512
|
||||
|
||||
// #cgo CFLAGS: -DHAS_SSE41 -DHAS_AVX -DHAS_AVX2
|
||||
// #include <stdint.h>
|
||||
// void sha512_transform_ssse3 (const void* M, void* D, uint64_t L);
|
||||
// void sha512_transform_avx (const void* M, void* D, uint64_t L);
|
||||
// void sha512_transform_rorx (const void* M, void* D, uint64_t L);
|
||||
import "C"
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func blockSSE(dig *digest, p []byte) {
|
||||
C.sha512_transform_ssse3(unsafe.Pointer(&p[0]), unsafe.Pointer(&dig.h[0]), (C.uint64_t)(len(p)/chunk))
|
||||
}
|
||||
|
||||
func blockAVX(dig *digest, p []byte) {
|
||||
C.sha512_transform_avx(unsafe.Pointer(&p[0]), unsafe.Pointer(&dig.h[0]), (C.uint64_t)(len(p)/chunk))
|
||||
}
|
||||
|
||||
func blockAVX2(dig *digest, p []byte) {
|
||||
C.sha512_transform_rorx(unsafe.Pointer(&p[0]), unsafe.Pointer(&dig.h[0]), (C.uint64_t)(len(p)/chunk))
|
||||
}
|
||||
|
||||
func blockGeneric(dig *digest, p []byte) {
|
||||
var w [80]uint64
|
||||
h0, h1, h2, h3, h4, h5, h6, h7 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7]
|
||||
for len(p) >= chunk {
|
||||
for i := 0; i < 16; i++ {
|
||||
j := i * 8
|
||||
w[i] = uint64(p[j])<<56 | uint64(p[j+1])<<48 | uint64(p[j+2])<<40 | uint64(p[j+3])<<32 |
|
||||
uint64(p[j+4])<<24 | uint64(p[j+5])<<16 | uint64(p[j+6])<<8 | uint64(p[j+7])
|
||||
}
|
||||
for i := 16; i < 80; i++ {
|
||||
v1 := w[i-2]
|
||||
t1 := (v1>>19 | v1<<(64-19)) ^ (v1>>61 | v1<<(64-61)) ^ (v1 >> 6)
|
||||
v2 := w[i-15]
|
||||
t2 := (v2>>1 | v2<<(64-1)) ^ (v2>>8 | v2<<(64-8)) ^ (v2 >> 7)
|
||||
|
||||
w[i] = t1 + w[i-7] + t2 + w[i-16]
|
||||
}
|
||||
|
||||
a, b, c, d, e, f, g, h := h0, h1, h2, h3, h4, h5, h6, h7
|
||||
|
||||
for i := 0; i < 80; i++ {
|
||||
t1 := h + ((e>>14 | e<<(64-14)) ^ (e>>18 | e<<(64-18)) ^ (e>>41 | e<<(64-41))) + ((e & f) ^ (^e & g)) + _K[i] + w[i]
|
||||
|
||||
t2 := ((a>>28 | a<<(64-28)) ^ (a>>34 | a<<(64-34)) ^ (a>>39 | a<<(64-39))) + ((a & b) ^ (a & c) ^ (b & c))
|
||||
|
||||
h = g
|
||||
g = f
|
||||
f = e
|
||||
e = d + t1
|
||||
d = c
|
||||
c = b
|
||||
b = a
|
||||
a = t1 + t2
|
||||
}
|
||||
|
||||
h0 += a
|
||||
h1 += b
|
||||
h2 += c
|
||||
h3 += d
|
||||
h4 += e
|
||||
h5 += f
|
||||
h6 += g
|
||||
h7 += h
|
||||
|
||||
p = p[chunk:]
|
||||
}
|
||||
|
||||
dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] = h0, h1, h2, h3, h4, h5, h6, h7
|
||||
}
|
||||
|
||||
var _K = []uint64{
|
||||
0x428a2f98d728ae22,
|
||||
0x7137449123ef65cd,
|
||||
0xb5c0fbcfec4d3b2f,
|
||||
0xe9b5dba58189dbbc,
|
||||
0x3956c25bf348b538,
|
||||
0x59f111f1b605d019,
|
||||
0x923f82a4af194f9b,
|
||||
0xab1c5ed5da6d8118,
|
||||
0xd807aa98a3030242,
|
||||
0x12835b0145706fbe,
|
||||
0x243185be4ee4b28c,
|
||||
0x550c7dc3d5ffb4e2,
|
||||
0x72be5d74f27b896f,
|
||||
0x80deb1fe3b1696b1,
|
||||
0x9bdc06a725c71235,
|
||||
0xc19bf174cf692694,
|
||||
0xe49b69c19ef14ad2,
|
||||
0xefbe4786384f25e3,
|
||||
0x0fc19dc68b8cd5b5,
|
||||
0x240ca1cc77ac9c65,
|
||||
0x2de92c6f592b0275,
|
||||
0x4a7484aa6ea6e483,
|
||||
0x5cb0a9dcbd41fbd4,
|
||||
0x76f988da831153b5,
|
||||
0x983e5152ee66dfab,
|
||||
0xa831c66d2db43210,
|
||||
0xb00327c898fb213f,
|
||||
0xbf597fc7beef0ee4,
|
||||
0xc6e00bf33da88fc2,
|
||||
0xd5a79147930aa725,
|
||||
0x06ca6351e003826f,
|
||||
0x142929670a0e6e70,
|
||||
0x27b70a8546d22ffc,
|
||||
0x2e1b21385c26c926,
|
||||
0x4d2c6dfc5ac42aed,
|
||||
0x53380d139d95b3df,
|
||||
0x650a73548baf63de,
|
||||
0x766a0abb3c77b2a8,
|
||||
0x81c2c92e47edaee6,
|
||||
0x92722c851482353b,
|
||||
0xa2bfe8a14cf10364,
|
||||
0xa81a664bbc423001,
|
||||
0xc24b8b70d0f89791,
|
||||
0xc76c51a30654be30,
|
||||
0xd192e819d6ef5218,
|
||||
0xd69906245565a910,
|
||||
0xf40e35855771202a,
|
||||
0x106aa07032bbd1b8,
|
||||
0x19a4c116b8d2d0c8,
|
||||
0x1e376c085141ab53,
|
||||
0x2748774cdf8eeb99,
|
||||
0x34b0bcb5e19b48a8,
|
||||
0x391c0cb3c5c95a63,
|
||||
0x4ed8aa4ae3418acb,
|
||||
0x5b9cca4f7763e373,
|
||||
0x682e6ff3d6b2b8a3,
|
||||
0x748f82ee5defb2fc,
|
||||
0x78a5636f43172f60,
|
||||
0x84c87814a1f0ab72,
|
||||
0x8cc702081a6439ec,
|
||||
0x90befffa23631e28,
|
||||
0xa4506cebde82bde9,
|
||||
0xbef9a3f7b2c67915,
|
||||
0xc67178f2e372532b,
|
||||
0xca273eceea26619c,
|
||||
0xd186b8c721c0c207,
|
||||
0xeada7dd6cde0eb1e,
|
||||
0xf57d4f7fee6ed178,
|
||||
0x06f067aa72176fba,
|
||||
0x0a637dc5a2c898a6,
|
||||
0x113f9804bef90dae,
|
||||
0x1b710b35131c471b,
|
||||
0x28db77f523047d84,
|
||||
0x32caab7b40c72493,
|
||||
0x3c9ebe0a15c9bebc,
|
||||
0x431d67c49c100d4c,
|
||||
0x4cc5d4becb3e42b6,
|
||||
0x597f299cfc657e2a,
|
||||
0x5fcb6fab3ad6faec,
|
||||
0x6c44198c4a475817,
|
||||
}
|
||||
@@ -1,202 +0,0 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -1,3 +0,0 @@
|
||||
# Donut
|
||||
|
||||
donut - Donut (do not delete) on disk format implementation released under [Apache license v2](./LICENSE).
|
||||
@@ -1,47 +0,0 @@
|
||||
package donut
|
||||
|
||||
// BucketACL - bucket level access control
|
||||
type BucketACL string
|
||||
|
||||
// different types of ACL's currently supported for buckets
|
||||
const (
|
||||
BucketPrivate = BucketACL("private")
|
||||
BucketPublicRead = BucketACL("public-read")
|
||||
BucketPublicReadWrite = BucketACL("public-read-write")
|
||||
)
|
||||
|
||||
func (b BucketACL) String() string {
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// IsPrivate - is acl Private
|
||||
func (b BucketACL) IsPrivate() bool {
|
||||
return b == BucketACL("private")
|
||||
}
|
||||
|
||||
// IsPublicRead - is acl PublicRead
|
||||
func (b BucketACL) IsPublicRead() bool {
|
||||
return b == BucketACL("public-read")
|
||||
}
|
||||
|
||||
// IsPublicReadWrite - is acl PublicReadWrite
|
||||
func (b BucketACL) IsPublicReadWrite() bool {
|
||||
return b == BucketACL("public-read-write")
|
||||
}
|
||||
|
||||
// IsValidBucketACL - is provided acl string supported
|
||||
func IsValidBucketACL(acl string) bool {
|
||||
switch acl {
|
||||
case "private":
|
||||
fallthrough
|
||||
case "public-read":
|
||||
fallthrough
|
||||
case "public-read-write":
|
||||
return true
|
||||
case "":
|
||||
// by default its "private"
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -1,639 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package donut
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/minio/minio/pkg/crypto/sha256"
|
||||
"github.com/minio/minio/pkg/crypto/sha512"
|
||||
"github.com/minio/minio/pkg/donut/disk"
|
||||
"github.com/minio/minio/pkg/probe"
|
||||
signv4 "github.com/minio/minio/pkg/signature"
|
||||
)
|
||||
|
||||
const (
|
||||
blockSize = 10 * 1024 * 1024
|
||||
)
|
||||
|
||||
// internal struct carrying bucket specific information
|
||||
type bucket struct {
|
||||
name string
|
||||
acl string
|
||||
time time.Time
|
||||
donutName string
|
||||
nodes map[string]node
|
||||
lock *sync.Mutex
|
||||
}
|
||||
|
||||
// newBucket - instantiate a new bucket
|
||||
func newBucket(bucketName, aclType, donutName string, nodes map[string]node) (bucket, BucketMetadata, *probe.Error) {
|
||||
if strings.TrimSpace(bucketName) == "" || strings.TrimSpace(donutName) == "" {
|
||||
return bucket{}, BucketMetadata{}, probe.NewError(InvalidArgument{})
|
||||
}
|
||||
|
||||
b := bucket{}
|
||||
t := time.Now().UTC()
|
||||
b.name = bucketName
|
||||
b.acl = aclType
|
||||
b.time = t
|
||||
b.donutName = donutName
|
||||
b.nodes = nodes
|
||||
b.lock = new(sync.Mutex)
|
||||
|
||||
metadata := BucketMetadata{}
|
||||
metadata.Version = bucketMetadataVersion
|
||||
metadata.Name = bucketName
|
||||
metadata.ACL = BucketACL(aclType)
|
||||
metadata.Created = t
|
||||
metadata.Metadata = make(map[string]string)
|
||||
metadata.BucketObjects = make(map[string]struct{})
|
||||
|
||||
return b, metadata, nil
|
||||
}
|
||||
|
||||
// getBucketName -
|
||||
func (b bucket) getBucketName() string {
|
||||
return b.name
|
||||
}
|
||||
|
||||
// getBucketMetadataReaders -
|
||||
func (b bucket) getBucketMetadataReaders() (map[int]io.ReadCloser, *probe.Error) {
|
||||
readers := make(map[int]io.ReadCloser)
|
||||
var disks map[int]disk.Disk
|
||||
var err *probe.Error
|
||||
for _, node := range b.nodes {
|
||||
disks, err = node.ListDisks()
|
||||
if err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
}
|
||||
var bucketMetaDataReader io.ReadCloser
|
||||
for order, disk := range disks {
|
||||
bucketMetaDataReader, err = disk.Open(filepath.Join(b.donutName, bucketMetadataConfig))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
readers[order] = bucketMetaDataReader
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
return readers, nil
|
||||
}
|
||||
|
||||
// getBucketMetadata -
|
||||
func (b bucket) getBucketMetadata() (*AllBuckets, *probe.Error) {
|
||||
metadata := new(AllBuckets)
|
||||
var readers map[int]io.ReadCloser
|
||||
{
|
||||
var err *probe.Error
|
||||
readers, err = b.getBucketMetadataReaders()
|
||||
if err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
}
|
||||
for _, reader := range readers {
|
||||
defer reader.Close()
|
||||
}
|
||||
var err error
|
||||
for _, reader := range readers {
|
||||
jenc := json.NewDecoder(reader)
|
||||
if err = jenc.Decode(metadata); err == nil {
|
||||
return metadata, nil
|
||||
}
|
||||
}
|
||||
return nil, probe.NewError(err)
|
||||
}
|
||||
|
||||
// GetObjectMetadata - get metadata for an object
|
||||
func (b bucket) GetObjectMetadata(objectName string) (ObjectMetadata, *probe.Error) {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
return b.readObjectMetadata(normalizeObjectName(objectName))
|
||||
}
|
||||
|
||||
// ListObjects - list all objects
|
||||
func (b bucket) ListObjects(prefix, marker, delimiter string, maxkeys int) (ListObjectsResults, *probe.Error) {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
if maxkeys <= 0 {
|
||||
maxkeys = 1000
|
||||
}
|
||||
var isTruncated bool
|
||||
var objects []string
|
||||
bucketMetadata, err := b.getBucketMetadata()
|
||||
if err != nil {
|
||||
return ListObjectsResults{}, err.Trace()
|
||||
}
|
||||
for objectName := range bucketMetadata.Buckets[b.getBucketName()].Multiparts {
|
||||
if strings.HasPrefix(objectName, strings.TrimSpace(prefix)) {
|
||||
if objectName > marker {
|
||||
objects = append(objects, objectName)
|
||||
}
|
||||
}
|
||||
}
|
||||
for objectName := range bucketMetadata.Buckets[b.getBucketName()].BucketObjects {
|
||||
if strings.HasPrefix(objectName, strings.TrimSpace(prefix)) {
|
||||
if objectName > marker {
|
||||
objects = append(objects, objectName)
|
||||
}
|
||||
}
|
||||
}
|
||||
if strings.TrimSpace(prefix) != "" {
|
||||
objects = TrimPrefix(objects, prefix)
|
||||
}
|
||||
var prefixes []string
|
||||
var filteredObjects []string
|
||||
filteredObjects = objects
|
||||
if strings.TrimSpace(delimiter) != "" {
|
||||
filteredObjects = HasNoDelimiter(objects, delimiter)
|
||||
prefixes = HasDelimiter(objects, delimiter)
|
||||
prefixes = SplitDelimiter(prefixes, delimiter)
|
||||
prefixes = SortUnique(prefixes)
|
||||
}
|
||||
var results []string
|
||||
var commonPrefixes []string
|
||||
|
||||
for _, commonPrefix := range prefixes {
|
||||
commonPrefixes = append(commonPrefixes, prefix+commonPrefix)
|
||||
}
|
||||
filteredObjects = RemoveDuplicates(filteredObjects)
|
||||
sort.Strings(filteredObjects)
|
||||
for _, objectName := range filteredObjects {
|
||||
if len(results) >= maxkeys {
|
||||
isTruncated = true
|
||||
break
|
||||
}
|
||||
results = append(results, prefix+objectName)
|
||||
}
|
||||
results = RemoveDuplicates(results)
|
||||
commonPrefixes = RemoveDuplicates(commonPrefixes)
|
||||
sort.Strings(commonPrefixes)
|
||||
|
||||
listObjects := ListObjectsResults{}
|
||||
listObjects.Objects = make(map[string]ObjectMetadata)
|
||||
listObjects.CommonPrefixes = commonPrefixes
|
||||
listObjects.IsTruncated = isTruncated
|
||||
|
||||
for _, objectName := range results {
|
||||
objMetadata, err := b.readObjectMetadata(normalizeObjectName(objectName))
|
||||
if err != nil {
|
||||
return ListObjectsResults{}, err.Trace()
|
||||
}
|
||||
listObjects.Objects[objectName] = objMetadata
|
||||
}
|
||||
return listObjects, nil
|
||||
}
|
||||
|
||||
// ReadObject - open an object to read
|
||||
func (b bucket) ReadObject(objectName string) (reader io.ReadCloser, size int64, err *probe.Error) {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
reader, writer := io.Pipe()
|
||||
// get list of objects
|
||||
bucketMetadata, err := b.getBucketMetadata()
|
||||
if err != nil {
|
||||
return nil, 0, err.Trace()
|
||||
}
|
||||
// check if object exists
|
||||
if _, ok := bucketMetadata.Buckets[b.getBucketName()].BucketObjects[objectName]; !ok {
|
||||
return nil, 0, probe.NewError(ObjectNotFound{Object: objectName})
|
||||
}
|
||||
objMetadata, err := b.readObjectMetadata(normalizeObjectName(objectName))
|
||||
if err != nil {
|
||||
return nil, 0, err.Trace()
|
||||
}
|
||||
// read and reply back to GetObject() request in a go-routine
|
||||
go b.readObjectData(normalizeObjectName(objectName), writer, objMetadata)
|
||||
return reader, objMetadata.Size, nil
|
||||
}
|
||||
|
||||
// WriteObject - write a new object into bucket
|
||||
func (b bucket) WriteObject(objectName string, objectData io.Reader, size int64, expectedMD5Sum string, metadata map[string]string, signature *signv4.Signature) (ObjectMetadata, *probe.Error) {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
if objectName == "" || objectData == nil {
|
||||
return ObjectMetadata{}, probe.NewError(InvalidArgument{})
|
||||
}
|
||||
writers, err := b.getObjectWriters(normalizeObjectName(objectName), "data")
|
||||
if err != nil {
|
||||
return ObjectMetadata{}, err.Trace()
|
||||
}
|
||||
sumMD5 := md5.New()
|
||||
sum512 := sha512.New()
|
||||
var sum256 hash.Hash
|
||||
var mwriter io.Writer
|
||||
|
||||
if signature != nil {
|
||||
sum256 = sha256.New()
|
||||
mwriter = io.MultiWriter(sumMD5, sum256, sum512)
|
||||
} else {
|
||||
mwriter = io.MultiWriter(sumMD5, sum512)
|
||||
}
|
||||
objMetadata := ObjectMetadata{}
|
||||
objMetadata.Version = objectMetadataVersion
|
||||
objMetadata.Created = time.Now().UTC()
|
||||
// if total writers are only '1' do not compute erasure
|
||||
switch len(writers) == 1 {
|
||||
case true:
|
||||
mw := io.MultiWriter(writers[0], mwriter)
|
||||
totalLength, err := io.Copy(mw, objectData)
|
||||
if err != nil {
|
||||
CleanupWritersOnError(writers)
|
||||
return ObjectMetadata{}, probe.NewError(err)
|
||||
}
|
||||
objMetadata.Size = totalLength
|
||||
case false:
|
||||
// calculate data and parity dictated by total number of writers
|
||||
k, m, err := b.getDataAndParity(len(writers))
|
||||
if err != nil {
|
||||
CleanupWritersOnError(writers)
|
||||
return ObjectMetadata{}, err.Trace()
|
||||
}
|
||||
// write encoded data with k, m and writers
|
||||
chunkCount, totalLength, err := b.writeObjectData(k, m, writers, objectData, size, mwriter)
|
||||
if err != nil {
|
||||
CleanupWritersOnError(writers)
|
||||
return ObjectMetadata{}, err.Trace()
|
||||
}
|
||||
/// donutMetadata section
|
||||
objMetadata.BlockSize = blockSize
|
||||
objMetadata.ChunkCount = chunkCount
|
||||
objMetadata.DataDisks = k
|
||||
objMetadata.ParityDisks = m
|
||||
objMetadata.Size = int64(totalLength)
|
||||
}
|
||||
objMetadata.Bucket = b.getBucketName()
|
||||
objMetadata.Object = objectName
|
||||
dataMD5sum := sumMD5.Sum(nil)
|
||||
dataSHA512sum := sum512.Sum(nil)
|
||||
if signature != nil {
|
||||
ok, err := signature.DoesSignatureMatch(hex.EncodeToString(sum256.Sum(nil)))
|
||||
if err != nil {
|
||||
// error occurred while doing signature calculation, we return and also cleanup any temporary writers.
|
||||
CleanupWritersOnError(writers)
|
||||
return ObjectMetadata{}, err.Trace()
|
||||
}
|
||||
if !ok {
|
||||
// purge all writers, when control flow reaches here
|
||||
//
|
||||
// Signature mismatch occurred all temp files to be removed and all data purged.
|
||||
CleanupWritersOnError(writers)
|
||||
return ObjectMetadata{}, probe.NewError(signv4.DoesNotMatch{})
|
||||
}
|
||||
}
|
||||
objMetadata.MD5Sum = hex.EncodeToString(dataMD5sum)
|
||||
objMetadata.SHA512Sum = hex.EncodeToString(dataSHA512sum)
|
||||
|
||||
// Verify if the written object is equal to what is expected, only if it is requested as such
|
||||
if strings.TrimSpace(expectedMD5Sum) != "" {
|
||||
if err := b.isMD5SumEqual(strings.TrimSpace(expectedMD5Sum), objMetadata.MD5Sum); err != nil {
|
||||
return ObjectMetadata{}, err.Trace()
|
||||
}
|
||||
}
|
||||
objMetadata.Metadata = metadata
|
||||
// write object specific metadata
|
||||
if err := b.writeObjectMetadata(normalizeObjectName(objectName), objMetadata); err != nil {
|
||||
// purge all writers, when control flow reaches here
|
||||
CleanupWritersOnError(writers)
|
||||
return ObjectMetadata{}, err.Trace()
|
||||
}
|
||||
// close all writers, when control flow reaches here
|
||||
for _, writer := range writers {
|
||||
writer.Close()
|
||||
}
|
||||
return objMetadata, nil
|
||||
}
|
||||
|
||||
// isMD5SumEqual - returns error if md5sum mismatches, other its `nil`
|
||||
func (b bucket) isMD5SumEqual(expectedMD5Sum, actualMD5Sum string) *probe.Error {
|
||||
if strings.TrimSpace(expectedMD5Sum) != "" && strings.TrimSpace(actualMD5Sum) != "" {
|
||||
expectedMD5SumBytes, err := hex.DecodeString(expectedMD5Sum)
|
||||
if err != nil {
|
||||
return probe.NewError(err)
|
||||
}
|
||||
actualMD5SumBytes, err := hex.DecodeString(actualMD5Sum)
|
||||
if err != nil {
|
||||
return probe.NewError(err)
|
||||
}
|
||||
if !bytes.Equal(expectedMD5SumBytes, actualMD5SumBytes) {
|
||||
return probe.NewError(BadDigest{})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return probe.NewError(InvalidArgument{})
|
||||
}
|
||||
|
||||
// writeObjectMetadata - write additional object metadata
|
||||
func (b bucket) writeObjectMetadata(objectName string, objMetadata ObjectMetadata) *probe.Error {
|
||||
if objMetadata.Object == "" {
|
||||
return probe.NewError(InvalidArgument{})
|
||||
}
|
||||
objMetadataWriters, err := b.getObjectWriters(objectName, objectMetadataConfig)
|
||||
if err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
for _, objMetadataWriter := range objMetadataWriters {
|
||||
jenc := json.NewEncoder(objMetadataWriter)
|
||||
if err := jenc.Encode(&objMetadata); err != nil {
|
||||
// Close writers and purge all temporary entries
|
||||
CleanupWritersOnError(objMetadataWriters)
|
||||
return probe.NewError(err)
|
||||
}
|
||||
}
|
||||
for _, objMetadataWriter := range objMetadataWriters {
|
||||
objMetadataWriter.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// readObjectMetadata - read object metadata
|
||||
func (b bucket) readObjectMetadata(objectName string) (ObjectMetadata, *probe.Error) {
|
||||
if objectName == "" {
|
||||
return ObjectMetadata{}, probe.NewError(InvalidArgument{})
|
||||
}
|
||||
objMetadata := ObjectMetadata{}
|
||||
objMetadataReaders, err := b.getObjectReaders(objectName, objectMetadataConfig)
|
||||
if err != nil {
|
||||
return ObjectMetadata{}, err.Trace()
|
||||
}
|
||||
for _, objMetadataReader := range objMetadataReaders {
|
||||
defer objMetadataReader.Close()
|
||||
}
|
||||
{
|
||||
var err error
|
||||
for _, objMetadataReader := range objMetadataReaders {
|
||||
jdec := json.NewDecoder(objMetadataReader)
|
||||
if err = jdec.Decode(&objMetadata); err == nil {
|
||||
return objMetadata, nil
|
||||
}
|
||||
}
|
||||
return ObjectMetadata{}, probe.NewError(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO - This a temporary normalization of objectNames, need to find a better way
|
||||
//
|
||||
// normalizedObjectName - all objectNames with "/" get normalized to a simple objectName
|
||||
//
|
||||
// example:
|
||||
// user provided value - "this/is/my/deep/directory/structure"
|
||||
// donut normalized value - "this-is-my-deep-directory-structure"
|
||||
//
|
||||
func normalizeObjectName(objectName string) string {
|
||||
// replace every '/' with '-'
|
||||
return strings.Replace(objectName, "/", "-", -1)
|
||||
}
|
||||
|
||||
// getDataAndParity - calculate k, m (data and parity) values from number of disks
|
||||
func (b bucket) getDataAndParity(totalWriters int) (k uint8, m uint8, err *probe.Error) {
|
||||
if totalWriters <= 1 {
|
||||
return 0, 0, probe.NewError(InvalidArgument{})
|
||||
}
|
||||
quotient := totalWriters / 2 // not using float or abs to let integer round off to lower value
|
||||
// quotient cannot be bigger than (255 / 2) = 127
|
||||
if quotient > 127 {
|
||||
return 0, 0, probe.NewError(ParityOverflow{})
|
||||
}
|
||||
remainder := totalWriters % 2 // will be 1 for odd and 0 for even numbers
|
||||
k = uint8(quotient + remainder)
|
||||
m = uint8(quotient)
|
||||
return k, m, nil
|
||||
}
|
||||
|
||||
// writeObjectData -
|
||||
func (b bucket) writeObjectData(k, m uint8, writers []io.WriteCloser, objectData io.Reader, size int64, hashWriter io.Writer) (int, int, *probe.Error) {
|
||||
encoder, err := newEncoder(k, m)
|
||||
if err != nil {
|
||||
return 0, 0, err.Trace()
|
||||
}
|
||||
chunkSize := int64(10 * 1024 * 1024)
|
||||
chunkCount := 0
|
||||
totalLength := 0
|
||||
|
||||
var e error
|
||||
for e == nil {
|
||||
var length int
|
||||
inputData := make([]byte, chunkSize)
|
||||
length, e = objectData.Read(inputData)
|
||||
if length != 0 {
|
||||
encodedBlocks, err := encoder.Encode(inputData[0:length])
|
||||
if err != nil {
|
||||
return 0, 0, err.Trace()
|
||||
}
|
||||
if _, err := hashWriter.Write(inputData[0:length]); err != nil {
|
||||
return 0, 0, probe.NewError(err)
|
||||
}
|
||||
for blockIndex, block := range encodedBlocks {
|
||||
errCh := make(chan error, 1)
|
||||
go func(writer io.Writer, reader io.Reader, errCh chan<- error) {
|
||||
defer close(errCh)
|
||||
_, err := io.Copy(writer, reader)
|
||||
errCh <- err
|
||||
}(writers[blockIndex], bytes.NewReader(block), errCh)
|
||||
if err := <-errCh; err != nil {
|
||||
// Returning error is fine here CleanupErrors() would cleanup writers
|
||||
return 0, 0, probe.NewError(err)
|
||||
}
|
||||
}
|
||||
totalLength += length
|
||||
chunkCount = chunkCount + 1
|
||||
}
|
||||
}
|
||||
if e != io.EOF {
|
||||
return 0, 0, probe.NewError(e)
|
||||
}
|
||||
return chunkCount, totalLength, nil
|
||||
}
|
||||
|
||||
// readObjectData -
|
||||
func (b bucket) readObjectData(objectName string, writer *io.PipeWriter, objMetadata ObjectMetadata) {
|
||||
readers, err := b.getObjectReaders(objectName, "data")
|
||||
if err != nil {
|
||||
writer.CloseWithError(probe.WrapError(err))
|
||||
return
|
||||
}
|
||||
for _, reader := range readers {
|
||||
defer reader.Close()
|
||||
}
|
||||
var expected512Sum, expectedMd5sum []byte
|
||||
{
|
||||
var err error
|
||||
expectedMd5sum, err = hex.DecodeString(objMetadata.MD5Sum)
|
||||
if err != nil {
|
||||
writer.CloseWithError(probe.WrapError(probe.NewError(err)))
|
||||
return
|
||||
}
|
||||
expected512Sum, err = hex.DecodeString(objMetadata.SHA512Sum)
|
||||
if err != nil {
|
||||
writer.CloseWithError(probe.WrapError(probe.NewError(err)))
|
||||
return
|
||||
}
|
||||
}
|
||||
hasher := md5.New()
|
||||
sum512hasher := sha256.New()
|
||||
mwriter := io.MultiWriter(writer, hasher, sum512hasher)
|
||||
switch len(readers) > 1 {
|
||||
case true:
|
||||
encoder, err := newEncoder(objMetadata.DataDisks, objMetadata.ParityDisks)
|
||||
if err != nil {
|
||||
writer.CloseWithError(probe.WrapError(err))
|
||||
return
|
||||
}
|
||||
totalLeft := objMetadata.Size
|
||||
for i := 0; i < objMetadata.ChunkCount; i++ {
|
||||
decodedData, err := b.decodeEncodedData(totalLeft, int64(objMetadata.BlockSize), readers, encoder, writer)
|
||||
if err != nil {
|
||||
writer.CloseWithError(probe.WrapError(err))
|
||||
return
|
||||
}
|
||||
if _, err := io.Copy(mwriter, bytes.NewReader(decodedData)); err != nil {
|
||||
writer.CloseWithError(probe.WrapError(probe.NewError(err)))
|
||||
return
|
||||
}
|
||||
totalLeft = totalLeft - int64(objMetadata.BlockSize)
|
||||
}
|
||||
case false:
|
||||
_, err := io.Copy(writer, readers[0])
|
||||
if err != nil {
|
||||
writer.CloseWithError(probe.WrapError(probe.NewError(err)))
|
||||
return
|
||||
}
|
||||
}
|
||||
// check if decodedData md5sum matches
|
||||
if !bytes.Equal(expectedMd5sum, hasher.Sum(nil)) {
|
||||
writer.CloseWithError(probe.WrapError(probe.NewError(ChecksumMismatch{})))
|
||||
return
|
||||
}
|
||||
if !bytes.Equal(expected512Sum, sum512hasher.Sum(nil)) {
|
||||
writer.CloseWithError(probe.WrapError(probe.NewError(ChecksumMismatch{})))
|
||||
return
|
||||
}
|
||||
writer.Close()
|
||||
return
|
||||
}
|
||||
|
||||
// decodeEncodedData -
|
||||
func (b bucket) decodeEncodedData(totalLeft, blockSize int64, readers map[int]io.ReadCloser, encoder encoder, writer *io.PipeWriter) ([]byte, *probe.Error) {
|
||||
var curBlockSize int64
|
||||
if blockSize < totalLeft {
|
||||
curBlockSize = blockSize
|
||||
} else {
|
||||
curBlockSize = totalLeft
|
||||
}
|
||||
curChunkSize, err := encoder.GetEncodedBlockLen(int(curBlockSize))
|
||||
if err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
encodedBytes := make([][]byte, encoder.k+encoder.m)
|
||||
errCh := make(chan error, len(readers))
|
||||
var errRet error
|
||||
var readCnt int
|
||||
|
||||
for i, reader := range readers {
|
||||
go func(reader io.Reader, i int) {
|
||||
encodedBytes[i] = make([]byte, curChunkSize)
|
||||
_, err := io.ReadFull(reader, encodedBytes[i])
|
||||
if err != nil {
|
||||
encodedBytes[i] = nil
|
||||
errCh <- err
|
||||
return
|
||||
}
|
||||
errCh <- nil
|
||||
}(reader, i)
|
||||
// read through errCh for any errors
|
||||
err := <-errCh
|
||||
if err != nil {
|
||||
errRet = err
|
||||
} else {
|
||||
readCnt++
|
||||
}
|
||||
}
|
||||
if readCnt < int(encoder.k) {
|
||||
return nil, probe.NewError(errRet)
|
||||
}
|
||||
decodedData, err := encoder.Decode(encodedBytes, int(curBlockSize))
|
||||
if err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
return decodedData, nil
|
||||
}
|
||||
|
||||
// getObjectReaders -
|
||||
func (b bucket) getObjectReaders(objectName, objectMeta string) (map[int]io.ReadCloser, *probe.Error) {
|
||||
readers := make(map[int]io.ReadCloser)
|
||||
var disks map[int]disk.Disk
|
||||
var err *probe.Error
|
||||
nodeSlice := 0
|
||||
for _, node := range b.nodes {
|
||||
disks, err = node.ListDisks()
|
||||
if err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
for order, disk := range disks {
|
||||
var objectSlice io.ReadCloser
|
||||
bucketSlice := fmt.Sprintf("%s$%d$%d", b.name, nodeSlice, order)
|
||||
objectPath := filepath.Join(b.donutName, bucketSlice, objectName, objectMeta)
|
||||
objectSlice, err = disk.Open(objectPath)
|
||||
if err == nil {
|
||||
readers[order] = objectSlice
|
||||
}
|
||||
}
|
||||
nodeSlice = nodeSlice + 1
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
return readers, nil
|
||||
}
|
||||
|
||||
// getObjectWriters -
|
||||
func (b bucket) getObjectWriters(objectName, objectMeta string) ([]io.WriteCloser, *probe.Error) {
|
||||
var writers []io.WriteCloser
|
||||
nodeSlice := 0
|
||||
for _, node := range b.nodes {
|
||||
disks, err := node.ListDisks()
|
||||
if err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
writers = make([]io.WriteCloser, len(disks))
|
||||
for order, disk := range disks {
|
||||
bucketSlice := fmt.Sprintf("%s$%d$%d", b.name, nodeSlice, order)
|
||||
objectPath := filepath.Join(b.donutName, bucketSlice, objectName, objectMeta)
|
||||
objectSlice, err := disk.CreateFile(objectPath)
|
||||
if err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
writers[order] = objectSlice
|
||||
}
|
||||
nodeSlice = nodeSlice + 1
|
||||
}
|
||||
return writers, nil
|
||||
}
|
||||
Vendored
-204
@@ -1,204 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// Package data implements in memory caching methods for data
|
||||
package data
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var noExpiration = time.Duration(0)
|
||||
|
||||
// Cache holds the required variables to compose an in memory cache system
|
||||
// which also provides expiring key mechanism and also maxSize
|
||||
type Cache struct {
|
||||
// Mutex is used for handling the concurrent
|
||||
// read/write requests for cache
|
||||
sync.Mutex
|
||||
|
||||
// items hold the cached objects
|
||||
items *list.List
|
||||
|
||||
// reverseItems holds the time that related item's updated at
|
||||
reverseItems map[interface{}]*list.Element
|
||||
|
||||
// maxSize is a total size for overall cache
|
||||
maxSize uint64
|
||||
|
||||
// currentSize is a current size in memory
|
||||
currentSize uint64
|
||||
|
||||
// OnEvicted - callback function for eviction
|
||||
OnEvicted func(a ...interface{})
|
||||
|
||||
// totalEvicted counter to keep track of total expirations
|
||||
totalEvicted int
|
||||
}
|
||||
|
||||
// Stats current cache statistics
|
||||
type Stats struct {
|
||||
Bytes uint64
|
||||
Items int
|
||||
Evicted int
|
||||
}
|
||||
|
||||
type element struct {
|
||||
key interface{}
|
||||
value []byte
|
||||
}
|
||||
|
||||
// NewCache creates an inmemory cache
|
||||
//
|
||||
// maxSize is used for expiring objects before we run out of memory
|
||||
// expiration is used for expiration of a key from cache
|
||||
func NewCache(maxSize uint64) *Cache {
|
||||
return &Cache{
|
||||
items: list.New(),
|
||||
reverseItems: make(map[interface{}]*list.Element),
|
||||
maxSize: maxSize,
|
||||
}
|
||||
}
|
||||
|
||||
// SetMaxSize set a new max size
|
||||
func (r *Cache) SetMaxSize(maxSize uint64) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
r.maxSize = maxSize
|
||||
return
|
||||
}
|
||||
|
||||
// Stats get current cache statistics
|
||||
func (r *Cache) Stats() Stats {
|
||||
return Stats{
|
||||
Bytes: r.currentSize,
|
||||
Items: r.items.Len(),
|
||||
Evicted: r.totalEvicted,
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns a value of a given key if it exists
|
||||
func (r *Cache) Get(key interface{}) ([]byte, bool) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
ele, hit := r.reverseItems[key]
|
||||
if !hit {
|
||||
return nil, false
|
||||
}
|
||||
r.items.MoveToFront(ele)
|
||||
return ele.Value.(*element).value, true
|
||||
}
|
||||
|
||||
// Len returns length of the value of a given key, returns zero if key doesn't exist
|
||||
func (r *Cache) Len(key interface{}) int {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
_, ok := r.reverseItems[key]
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
return len(r.reverseItems[key].Value.(*element).value)
|
||||
}
|
||||
|
||||
// Append will append new data to an existing key,
|
||||
// if key doesn't exist it behaves like Set()
|
||||
func (r *Cache) Append(key interface{}, value []byte) bool {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
valueLen := uint64(len(value))
|
||||
if r.maxSize > 0 {
|
||||
// check if the size of the object is not bigger than the
|
||||
// capacity of the cache
|
||||
if valueLen > r.maxSize {
|
||||
return false
|
||||
}
|
||||
// remove random key if only we reach the maxSize threshold
|
||||
for (r.currentSize + valueLen) > r.maxSize {
|
||||
r.doDeleteOldest()
|
||||
break
|
||||
}
|
||||
}
|
||||
ele, hit := r.reverseItems[key]
|
||||
if !hit {
|
||||
ele := r.items.PushFront(&element{key, value})
|
||||
r.currentSize += valueLen
|
||||
r.reverseItems[key] = ele
|
||||
return true
|
||||
}
|
||||
r.items.MoveToFront(ele)
|
||||
r.currentSize += valueLen
|
||||
ele.Value.(*element).value = append(ele.Value.(*element).value, value...)
|
||||
return true
|
||||
}
|
||||
|
||||
// Set will persist a value to the cache
|
||||
func (r *Cache) Set(key interface{}, value []byte) bool {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
valueLen := uint64(len(value))
|
||||
if r.maxSize > 0 {
|
||||
// check if the size of the object is not bigger than the
|
||||
// capacity of the cache
|
||||
if valueLen > r.maxSize {
|
||||
return false
|
||||
}
|
||||
// remove random key if only we reach the maxSize threshold
|
||||
for (r.currentSize + valueLen) > r.maxSize {
|
||||
r.doDeleteOldest()
|
||||
}
|
||||
}
|
||||
if _, hit := r.reverseItems[key]; hit {
|
||||
return false
|
||||
}
|
||||
ele := r.items.PushFront(&element{key, value})
|
||||
r.currentSize += valueLen
|
||||
r.reverseItems[key] = ele
|
||||
return true
|
||||
}
|
||||
|
||||
// Delete deletes a given key if exists
|
||||
func (r *Cache) Delete(key interface{}) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
ele, ok := r.reverseItems[key]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if ele != nil {
|
||||
r.currentSize -= uint64(len(r.reverseItems[key].Value.(*element).value))
|
||||
r.items.Remove(ele)
|
||||
delete(r.reverseItems, key)
|
||||
r.totalEvicted++
|
||||
if r.OnEvicted != nil {
|
||||
r.OnEvicted(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Cache) doDeleteOldest() {
|
||||
ele := r.items.Back()
|
||||
if ele != nil {
|
||||
r.currentSize -= uint64(len(r.reverseItems[ele.Value.(*element).key].Value.(*element).value))
|
||||
delete(r.reverseItems, ele.Value.(*element).key)
|
||||
r.items.Remove(ele)
|
||||
r.totalEvicted++
|
||||
if r.OnEvicted != nil {
|
||||
r.OnEvicted(ele.Value.(*element).key)
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
-45
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package data
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "gopkg.in/check.v1"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) { TestingT(t) }
|
||||
|
||||
type MySuite struct{}
|
||||
|
||||
var _ = Suite(&MySuite{})
|
||||
|
||||
func (s *MySuite) TestCache(c *C) {
|
||||
cache := NewCache(1000)
|
||||
data := []byte("Hello, world!")
|
||||
ok := cache.Set("filename", data)
|
||||
|
||||
c.Assert(ok, Equals, true)
|
||||
storedata, ok := cache.Get("filename")
|
||||
|
||||
c.Assert(ok, Equals, true)
|
||||
c.Assert(data, DeepEquals, storedata)
|
||||
|
||||
cache.Delete("filename")
|
||||
_, ok = cache.Get("filename")
|
||||
c.Assert(ok, Equals, false)
|
||||
}
|
||||
Vendored
-110
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// Package metadata implements in memory caching methods for metadata information
|
||||
package metadata
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var noExpiration = time.Duration(0)
|
||||
|
||||
// Cache holds the required variables to compose an in memory cache system
|
||||
// which also provides expiring key mechanism and also maxSize
|
||||
type Cache struct {
|
||||
// Mutex is used for handling the concurrent
|
||||
// read/write requests for cache
|
||||
sync.Mutex
|
||||
|
||||
// items hold the cached objects
|
||||
items map[string]interface{}
|
||||
|
||||
// updatedAt holds the time that related item's updated at
|
||||
updatedAt map[string]time.Time
|
||||
}
|
||||
|
||||
// Stats current cache statistics
|
||||
type Stats struct {
|
||||
Items int
|
||||
}
|
||||
|
||||
// NewCache creates an inmemory cache
|
||||
//
|
||||
func NewCache() *Cache {
|
||||
return &Cache{
|
||||
items: make(map[string]interface{}),
|
||||
updatedAt: map[string]time.Time{},
|
||||
}
|
||||
}
|
||||
|
||||
// Stats get current cache statistics
|
||||
func (r *Cache) Stats() Stats {
|
||||
return Stats{
|
||||
Items: len(r.items),
|
||||
}
|
||||
}
|
||||
|
||||
// GetAll returs all the items
|
||||
func (r *Cache) GetAll() map[string]interface{} {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
// copy
|
||||
items := r.items
|
||||
return items
|
||||
}
|
||||
|
||||
// Get returns a value of a given key if it exists
|
||||
func (r *Cache) Get(key string) interface{} {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
value, ok := r.items[key]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
// Exists returns true if key exists
|
||||
func (r *Cache) Exists(key string) bool {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
_, ok := r.items[key]
|
||||
return ok
|
||||
}
|
||||
|
||||
// Set will persist a value to the cache
|
||||
func (r *Cache) Set(key string, value interface{}) bool {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
r.items[key] = value
|
||||
return true
|
||||
}
|
||||
|
||||
// Delete deletes a given key if exists
|
||||
func (r *Cache) Delete(key string) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
r.doDelete(key)
|
||||
}
|
||||
|
||||
func (r *Cache) doDelete(key string) {
|
||||
if _, ok := r.items[key]; ok {
|
||||
delete(r.items, key)
|
||||
delete(r.updatedAt, key)
|
||||
}
|
||||
}
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package metadata
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "gopkg.in/check.v1"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) { TestingT(t) }
|
||||
|
||||
type MySuite struct{}
|
||||
|
||||
var _ = Suite(&MySuite{})
|
||||
|
||||
func (s *MySuite) TestCache(c *C) {
|
||||
cache := NewCache()
|
||||
data := []byte("Hello, world!")
|
||||
ok := cache.Set("filename", data)
|
||||
|
||||
c.Assert(ok, Equals, true)
|
||||
storedata := cache.Get("filename")
|
||||
|
||||
c.Assert(ok, Equals, true)
|
||||
c.Assert(data, DeepEquals, storedata)
|
||||
|
||||
cache.Delete("filename")
|
||||
|
||||
ok = cache.Exists("filename")
|
||||
c.Assert(ok, Equals, false)
|
||||
}
|
||||
@@ -1,190 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package donut
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"io"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/minio/minio/pkg/atomic"
|
||||
)
|
||||
|
||||
// IsValidDonut - verify donut name is correct
|
||||
func IsValidDonut(donutName string) bool {
|
||||
if len(donutName) < 3 || len(donutName) > 63 {
|
||||
return false
|
||||
}
|
||||
if donutName[0] == '.' || donutName[len(donutName)-1] == '.' {
|
||||
return false
|
||||
}
|
||||
if match, _ := regexp.MatchString("\\.\\.", donutName); match == true {
|
||||
return false
|
||||
}
|
||||
// We don't support donutNames with '.' in them
|
||||
match, _ := regexp.MatchString("^[a-zA-Z][a-zA-Z0-9\\-]+[a-zA-Z0-9]$", donutName)
|
||||
return match
|
||||
}
|
||||
|
||||
// IsValidBucket - verify bucket name in accordance with
|
||||
// - http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingBucket.html
|
||||
func IsValidBucket(bucket string) bool {
|
||||
if len(bucket) < 3 || len(bucket) > 63 {
|
||||
return false
|
||||
}
|
||||
if bucket[0] == '.' || bucket[len(bucket)-1] == '.' {
|
||||
return false
|
||||
}
|
||||
if match, _ := regexp.MatchString("\\.\\.", bucket); match == true {
|
||||
return false
|
||||
}
|
||||
// We don't support buckets with '.' in them
|
||||
match, _ := regexp.MatchString("^[a-zA-Z][a-zA-Z0-9\\-]+[a-zA-Z0-9]$", bucket)
|
||||
return match
|
||||
}
|
||||
|
||||
// IsValidObjectName - verify object name in accordance with
|
||||
// - http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html
|
||||
func IsValidObjectName(object string) bool {
|
||||
if strings.TrimSpace(object) == "" {
|
||||
return false
|
||||
}
|
||||
if len(object) > 1024 || len(object) == 0 {
|
||||
return false
|
||||
}
|
||||
if !utf8.ValidString(object) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// IsValidPrefix - verify prefix name is correct, an empty prefix is valid
|
||||
func IsValidPrefix(prefix string) bool {
|
||||
if strings.TrimSpace(prefix) == "" {
|
||||
return true
|
||||
}
|
||||
return IsValidObjectName(prefix)
|
||||
}
|
||||
|
||||
// ProxyWriter implements io.Writer to trap written bytes
|
||||
type ProxyWriter struct {
|
||||
writer io.Writer
|
||||
writtenBytes []byte
|
||||
}
|
||||
|
||||
func (r *ProxyWriter) Write(p []byte) (n int, err error) {
|
||||
n, err = r.writer.Write(p)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
r.writtenBytes = append(r.writtenBytes, p[0:n]...)
|
||||
return
|
||||
}
|
||||
|
||||
// NewProxyWriter - wrap around a given writer with ProxyWriter
|
||||
func NewProxyWriter(w io.Writer) *ProxyWriter {
|
||||
return &ProxyWriter{writer: w, writtenBytes: nil}
|
||||
}
|
||||
|
||||
// Delimiter delims the string at delimiter
|
||||
func Delimiter(object, delimiter string) string {
|
||||
readBuffer := bytes.NewBufferString(object)
|
||||
reader := bufio.NewReader(readBuffer)
|
||||
stringReader := strings.NewReader(delimiter)
|
||||
delimited, _ := stringReader.ReadByte()
|
||||
delimitedStr, _ := reader.ReadString(delimited)
|
||||
return delimitedStr
|
||||
}
|
||||
|
||||
// RemoveDuplicates removes duplicate elements from a slice
|
||||
func RemoveDuplicates(slice []string) []string {
|
||||
newSlice := []string{}
|
||||
seen := make(map[string]struct{})
|
||||
for _, val := range slice {
|
||||
if _, ok := seen[val]; !ok {
|
||||
newSlice = append(newSlice, val)
|
||||
seen[val] = struct{}{} // avoiding byte allocation
|
||||
}
|
||||
}
|
||||
return newSlice
|
||||
}
|
||||
|
||||
// TrimPrefix trims off a prefix string from all the elements in a given slice
|
||||
func TrimPrefix(objects []string, prefix string) []string {
|
||||
var results []string
|
||||
for _, object := range objects {
|
||||
results = append(results, strings.TrimPrefix(object, prefix))
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
// HasNoDelimiter provides a new slice from an input slice which has elements without delimiter
|
||||
func HasNoDelimiter(objects []string, delim string) []string {
|
||||
var results []string
|
||||
for _, object := range objects {
|
||||
if !strings.Contains(object, delim) {
|
||||
results = append(results, object)
|
||||
}
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
// HasDelimiter provides a new slice from an input slice which has elements with a delimiter
|
||||
func HasDelimiter(objects []string, delim string) []string {
|
||||
var results []string
|
||||
for _, object := range objects {
|
||||
if strings.Contains(object, delim) {
|
||||
results = append(results, object)
|
||||
}
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
// SplitDelimiter provides a new slice from an input slice by splitting a delimiter
|
||||
func SplitDelimiter(objects []string, delim string) []string {
|
||||
var results []string
|
||||
for _, object := range objects {
|
||||
parts := strings.Split(object, delim)
|
||||
results = append(results, parts[0]+delim)
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
// SortUnique sort a slice in lexical order, removing duplicate elements
|
||||
func SortUnique(objects []string) []string {
|
||||
objectMap := make(map[string]string)
|
||||
for _, v := range objects {
|
||||
objectMap[v] = v
|
||||
}
|
||||
var results []string
|
||||
for k := range objectMap {
|
||||
results = append(results, k)
|
||||
}
|
||||
sort.Strings(results)
|
||||
return results
|
||||
}
|
||||
|
||||
// CleanupWritersOnError purge writers on error
|
||||
func CleanupWritersOnError(writers []io.WriteCloser) {
|
||||
for _, writer := range writers {
|
||||
writer.(*atomic.File).CloseAndPurge()
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package donut
|
||||
|
||||
import (
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/minio/minio/pkg/probe"
|
||||
"github.com/minio/minio/pkg/quick"
|
||||
)
|
||||
|
||||
// getDonutConfigPath get donut config file path
|
||||
func getDonutConfigPath() (string, *probe.Error) {
|
||||
if customConfigPath != "" {
|
||||
return customConfigPath, nil
|
||||
}
|
||||
u, err := user.Current()
|
||||
if err != nil {
|
||||
return "", probe.NewError(err)
|
||||
}
|
||||
donutConfigPath := filepath.Join(u.HomeDir, ".minio", "donut.json")
|
||||
return donutConfigPath, nil
|
||||
}
|
||||
|
||||
// internal variable only accessed via get/set methods
|
||||
var customConfigPath string
|
||||
|
||||
// SetDonutConfigPath - set custom donut config path
|
||||
func SetDonutConfigPath(configPath string) {
|
||||
customConfigPath = configPath
|
||||
}
|
||||
|
||||
// SaveConfig save donut config
|
||||
func SaveConfig(a *Config) *probe.Error {
|
||||
donutConfigPath, err := getDonutConfigPath()
|
||||
if err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
qc, err := quick.New(a)
|
||||
if err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
if err := qc.Save(donutConfigPath); err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadConfig load donut config
|
||||
func LoadConfig() (*Config, *probe.Error) {
|
||||
donutConfigPath, err := getDonutConfigPath()
|
||||
if err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
a := &Config{}
|
||||
a.Version = "0.0.1"
|
||||
qc, err := quick.New(a)
|
||||
if err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
if err := qc.Load(donutConfigPath); err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
return qc.Data().(*Config), nil
|
||||
}
|
||||
@@ -1,222 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impliedisk.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package disk
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/minio/minio/pkg/atomic"
|
||||
"github.com/minio/minio/pkg/probe"
|
||||
)
|
||||
|
||||
// Disk container for disk parameters
|
||||
type Disk struct {
|
||||
lock *sync.Mutex
|
||||
path string
|
||||
fsInfo map[string]string
|
||||
}
|
||||
|
||||
// New - instantiate new disk
|
||||
func New(diskPath string) (Disk, *probe.Error) {
|
||||
if diskPath == "" {
|
||||
return Disk{}, probe.NewError(InvalidArgument{})
|
||||
}
|
||||
st, err := os.Stat(diskPath)
|
||||
if err != nil {
|
||||
return Disk{}, probe.NewError(err)
|
||||
}
|
||||
|
||||
if !st.IsDir() {
|
||||
return Disk{}, probe.NewError(syscall.ENOTDIR)
|
||||
}
|
||||
s := syscall.Statfs_t{}
|
||||
err = syscall.Statfs(diskPath, &s)
|
||||
if err != nil {
|
||||
return Disk{}, probe.NewError(err)
|
||||
}
|
||||
disk := Disk{
|
||||
lock: &sync.Mutex{},
|
||||
path: diskPath,
|
||||
fsInfo: make(map[string]string),
|
||||
}
|
||||
if fsType := getFSType(s.Type); fsType != "UNKNOWN" {
|
||||
disk.fsInfo["FSType"] = fsType
|
||||
disk.fsInfo["MountPoint"] = disk.path
|
||||
return disk, nil
|
||||
}
|
||||
return Disk{}, probe.NewError(UnsupportedFilesystem{Type: strconv.FormatInt(int64(s.Type), 10)})
|
||||
}
|
||||
|
||||
// IsUsable - is disk usable, alive
|
||||
func (disk Disk) IsUsable() bool {
|
||||
_, err := os.Stat(disk.path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// GetPath - get root disk path
|
||||
func (disk Disk) GetPath() string {
|
||||
return disk.path
|
||||
}
|
||||
|
||||
// GetFSInfo - get disk filesystem and its usage information
|
||||
func (disk Disk) GetFSInfo() map[string]string {
|
||||
disk.lock.Lock()
|
||||
defer disk.lock.Unlock()
|
||||
|
||||
s := syscall.Statfs_t{}
|
||||
err := syscall.Statfs(disk.path, &s)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
disk.fsInfo["Total"] = formatBytes(int64(s.Bsize) * int64(s.Blocks))
|
||||
disk.fsInfo["Free"] = formatBytes(int64(s.Bsize) * int64(s.Bfree))
|
||||
disk.fsInfo["TotalB"] = strconv.FormatInt(int64(s.Bsize)*int64(s.Blocks), 10)
|
||||
disk.fsInfo["FreeB"] = strconv.FormatInt(int64(s.Bsize)*int64(s.Bfree), 10)
|
||||
return disk.fsInfo
|
||||
}
|
||||
|
||||
// MakeDir - make a directory inside disk root path
|
||||
func (disk Disk) MakeDir(dirname string) *probe.Error {
|
||||
disk.lock.Lock()
|
||||
defer disk.lock.Unlock()
|
||||
if err := os.MkdirAll(filepath.Join(disk.path, dirname), 0700); err != nil {
|
||||
return probe.NewError(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListDir - list a directory inside disk root path, get only directories
|
||||
func (disk Disk) ListDir(dirname string) ([]os.FileInfo, *probe.Error) {
|
||||
disk.lock.Lock()
|
||||
defer disk.lock.Unlock()
|
||||
|
||||
dir, err := os.Open(filepath.Join(disk.path, dirname))
|
||||
if err != nil {
|
||||
return nil, probe.NewError(err)
|
||||
}
|
||||
defer dir.Close()
|
||||
contents, err := dir.Readdir(-1)
|
||||
if err != nil {
|
||||
return nil, probe.NewError(err)
|
||||
}
|
||||
var directories []os.FileInfo
|
||||
for _, content := range contents {
|
||||
// Include only directories, ignore everything else
|
||||
if content.IsDir() {
|
||||
directories = append(directories, content)
|
||||
}
|
||||
}
|
||||
return directories, nil
|
||||
}
|
||||
|
||||
// ListFiles - list a directory inside disk root path, get only files
|
||||
func (disk Disk) ListFiles(dirname string) ([]os.FileInfo, *probe.Error) {
|
||||
disk.lock.Lock()
|
||||
defer disk.lock.Unlock()
|
||||
|
||||
dir, err := os.Open(filepath.Join(disk.path, dirname))
|
||||
if err != nil {
|
||||
return nil, probe.NewError(err)
|
||||
}
|
||||
defer dir.Close()
|
||||
contents, err := dir.Readdir(-1)
|
||||
if err != nil {
|
||||
return nil, probe.NewError(err)
|
||||
}
|
||||
var files []os.FileInfo
|
||||
for _, content := range contents {
|
||||
// Include only regular files, ignore everything else
|
||||
if content.Mode().IsRegular() {
|
||||
files = append(files, content)
|
||||
}
|
||||
}
|
||||
return files, nil
|
||||
}
|
||||
|
||||
// CreateFile - create a file inside disk root path, replies with custome disk.File which provides atomic writes
|
||||
func (disk Disk) CreateFile(filename string) (*atomic.File, *probe.Error) {
|
||||
disk.lock.Lock()
|
||||
defer disk.lock.Unlock()
|
||||
|
||||
if filename == "" {
|
||||
return nil, probe.NewError(InvalidArgument{})
|
||||
}
|
||||
|
||||
f, err := atomic.FileCreate(filepath.Join(disk.path, filename))
|
||||
if err != nil {
|
||||
return nil, probe.NewError(err)
|
||||
}
|
||||
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// Open - read a file inside disk root path
|
||||
func (disk Disk) Open(filename string) (*os.File, *probe.Error) {
|
||||
disk.lock.Lock()
|
||||
defer disk.lock.Unlock()
|
||||
|
||||
if filename == "" {
|
||||
return nil, probe.NewError(InvalidArgument{})
|
||||
}
|
||||
dataFile, err := os.Open(filepath.Join(disk.path, filename))
|
||||
if err != nil {
|
||||
return nil, probe.NewError(err)
|
||||
}
|
||||
return dataFile, nil
|
||||
}
|
||||
|
||||
// OpenFile - Use with caution
|
||||
func (disk Disk) OpenFile(filename string, flags int, perm os.FileMode) (*os.File, *probe.Error) {
|
||||
disk.lock.Lock()
|
||||
defer disk.lock.Unlock()
|
||||
|
||||
if filename == "" {
|
||||
return nil, probe.NewError(InvalidArgument{})
|
||||
}
|
||||
dataFile, err := os.OpenFile(filepath.Join(disk.path, filename), flags, perm)
|
||||
if err != nil {
|
||||
return nil, probe.NewError(err)
|
||||
}
|
||||
return dataFile, nil
|
||||
}
|
||||
|
||||
// formatBytes - Convert bytes to human readable string. Like a 2 MB, 64.2 KB, 52 B
|
||||
func formatBytes(i int64) (result string) {
|
||||
switch {
|
||||
case i > (1024 * 1024 * 1024 * 1024):
|
||||
result = fmt.Sprintf("%.02f TB", float64(i)/1024/1024/1024/1024)
|
||||
case i > (1024 * 1024 * 1024):
|
||||
result = fmt.Sprintf("%.02f GB", float64(i)/1024/1024/1024)
|
||||
case i > (1024 * 1024):
|
||||
result = fmt.Sprintf("%.02f MB", float64(i)/1024/1024)
|
||||
case i > 1024:
|
||||
result = fmt.Sprintf("%.02f KB", float64(i)/1024)
|
||||
default:
|
||||
result = fmt.Sprintf("%d B", i)
|
||||
}
|
||||
result = strings.Trim(result, " ")
|
||||
return
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package disk
|
||||
|
||||
import "strconv"
|
||||
|
||||
// fsType2StrinMap - list of filesystems supported by donut
|
||||
var fsType2StringMap = map[string]string{
|
||||
"11": "HFS",
|
||||
}
|
||||
|
||||
// getFSType - get filesystem type
|
||||
func getFSType(fsType uint32) string {
|
||||
fsTypeHex := strconv.FormatUint(uint64(fsType), 16)
|
||||
fsTypeString, ok := fsType2StringMap[fsTypeHex]
|
||||
if ok == false {
|
||||
return "UNKNOWN"
|
||||
}
|
||||
return fsTypeString
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package disk
|
||||
|
||||
import "strconv"
|
||||
|
||||
// fsType2StringMap - list of filesystems supported by donut on linux
|
||||
var fsType2StringMap = map[string]string{
|
||||
"1021994": "TMPFS",
|
||||
"137d": "EXT",
|
||||
"4244": "HFS",
|
||||
"4d44": "MSDOS",
|
||||
"52654973": "REISERFS",
|
||||
"5346544e": "NTFS",
|
||||
"58465342": "XFS",
|
||||
"61756673": "AUFS",
|
||||
"6969": "NFS",
|
||||
"ef51": "EXT2OLD",
|
||||
"ef53": "EXT4",
|
||||
"f15f": "ecryptfs",
|
||||
}
|
||||
|
||||
// getFSType - get filesystem type
|
||||
func getFSType(fsType int64) string {
|
||||
fsTypeHex := strconv.FormatInt(fsType, 16)
|
||||
fsTypeString, ok := fsType2StringMap[fsTypeHex]
|
||||
if ok == false {
|
||||
return "UNKNOWN"
|
||||
}
|
||||
return fsTypeString
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impliedisk.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package disk
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
. "gopkg.in/check.v1"
|
||||
)
|
||||
|
||||
func TestDisk(t *testing.T) { TestingT(t) }
|
||||
|
||||
type MyDiskSuite struct {
|
||||
path string
|
||||
disk Disk
|
||||
}
|
||||
|
||||
var _ = Suite(&MyDiskSuite{})
|
||||
|
||||
func (s *MyDiskSuite) SetUpSuite(c *C) {
|
||||
path, err := ioutil.TempDir(os.TempDir(), "disk-")
|
||||
c.Assert(err, IsNil)
|
||||
s.path = path
|
||||
d, perr := New(s.path)
|
||||
c.Assert(perr, IsNil)
|
||||
s.disk = d
|
||||
}
|
||||
|
||||
func (s *MyDiskSuite) TearDownSuite(c *C) {
|
||||
os.RemoveAll(s.path)
|
||||
}
|
||||
|
||||
func (s *MyDiskSuite) TestDiskInfo(c *C) {
|
||||
c.Assert(s.path, Equals, s.disk.GetPath())
|
||||
fsInfo := s.disk.GetFSInfo()
|
||||
c.Assert(fsInfo["MountPoint"], Equals, s.disk.GetPath())
|
||||
c.Assert(fsInfo["FSType"], Not(Equals), "UNKNOWN")
|
||||
}
|
||||
|
||||
func (s *MyDiskSuite) TestDiskCreateDir(c *C) {
|
||||
c.Assert(s.disk.MakeDir("hello"), IsNil)
|
||||
}
|
||||
|
||||
func (s *MyDiskSuite) TestDiskCreateFile(c *C) {
|
||||
f, err := s.disk.CreateFile("hello1")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(f.Name(), Not(Equals), filepath.Join(s.path, "hello1"))
|
||||
// close renames the file
|
||||
f.Close()
|
||||
|
||||
// Open should be a success
|
||||
_, err = s.disk.Open("hello1")
|
||||
c.Assert(err, IsNil)
|
||||
}
|
||||
|
||||
func (s *MyDiskSuite) TestDiskOpen(c *C) {
|
||||
f1, err := s.disk.CreateFile("hello2")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(f1.Name(), Not(Equals), filepath.Join(s.path, "hello2"))
|
||||
// close renames the file
|
||||
f1.Close()
|
||||
|
||||
f2, err := s.disk.Open("hello2")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(f2.Name(), Equals, filepath.Join(s.path, "hello2"))
|
||||
defer f2.Close()
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impliedisk.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package disk
|
||||
|
||||
// InvalidArgument invalid argument
|
||||
type InvalidArgument struct{}
|
||||
|
||||
func (e InvalidArgument) Error() string {
|
||||
return "Invalid argument"
|
||||
}
|
||||
|
||||
// UnsupportedFilesystem unsupported filesystem type
|
||||
type UnsupportedFilesystem struct {
|
||||
Type string
|
||||
}
|
||||
|
||||
func (e UnsupportedFilesystem) Error() string {
|
||||
return "Unsupported filesystem: " + e.Type
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
##### Users Collection
|
||||
|
||||
```js
|
||||
|
||||
"minio": {
|
||||
"version": 1,
|
||||
"users": [{
|
||||
"secretAccessKey": String,
|
||||
"accessKeyId": String,
|
||||
"status": String // enum: ok, disabled, deleted
|
||||
}],
|
||||
"hosts": [{
|
||||
"address": String,
|
||||
"uuid": String,
|
||||
"status": String, // enum: ok, disabled, deleted, busy, offline.
|
||||
"disks": [{
|
||||
"disk": String,
|
||||
"uuid": String,
|
||||
"status": String // ok, offline, disabled, busy.
|
||||
}]
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
##### Bucket Collection
|
||||
|
||||
```js
|
||||
"buckets": {
|
||||
"bucket": String, // index
|
||||
"deleted": Boolean,
|
||||
"permissions": String
|
||||
}
|
||||
```
|
||||
|
||||
##### Object Collection
|
||||
|
||||
```js
|
||||
"objects": {
|
||||
"key": String, // index
|
||||
"createdAt": Date,
|
||||
"hosts[16]": [{
|
||||
"host": String,
|
||||
"disk": String,
|
||||
}],
|
||||
"deleted": Boolean
|
||||
}
|
||||
```
|
||||
|
||||
```js
|
||||
"meta": {
|
||||
"key": String, // index
|
||||
"type": String // content-type
|
||||
// type speific meta
|
||||
}
|
||||
```
|
||||
@@ -1,680 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package donut
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/minio/minio/pkg/crypto/sha256"
|
||||
"github.com/minio/minio/pkg/crypto/sha512"
|
||||
"github.com/minio/minio/pkg/donut/disk"
|
||||
"github.com/minio/minio/pkg/probe"
|
||||
signv4 "github.com/minio/minio/pkg/signature"
|
||||
)
|
||||
|
||||
// config files used inside Donut
|
||||
const (
|
||||
// bucket, object metadata
|
||||
bucketMetadataConfig = "bucketMetadata.json"
|
||||
objectMetadataConfig = "objectMetadata.json"
|
||||
|
||||
// versions
|
||||
objectMetadataVersion = "1.0.0"
|
||||
bucketMetadataVersion = "1.0.0"
|
||||
)
|
||||
|
||||
/// v1 API functions
|
||||
|
||||
// makeBucket - make a new bucket
|
||||
func (donut API) makeBucket(bucket string, acl BucketACL) *probe.Error {
|
||||
if bucket == "" || strings.TrimSpace(bucket) == "" {
|
||||
return probe.NewError(InvalidArgument{})
|
||||
}
|
||||
return donut.makeDonutBucket(bucket, acl.String())
|
||||
}
|
||||
|
||||
// getBucketMetadata - get bucket metadata
|
||||
func (donut API) getBucketMetadata(bucketName string) (BucketMetadata, *probe.Error) {
|
||||
if err := donut.listDonutBuckets(); err != nil {
|
||||
return BucketMetadata{}, err.Trace()
|
||||
}
|
||||
if _, ok := donut.buckets[bucketName]; !ok {
|
||||
return BucketMetadata{}, probe.NewError(BucketNotFound{Bucket: bucketName})
|
||||
}
|
||||
metadata, err := donut.getDonutBucketMetadata()
|
||||
if err != nil {
|
||||
return BucketMetadata{}, err.Trace()
|
||||
}
|
||||
return metadata.Buckets[bucketName], nil
|
||||
}
|
||||
|
||||
// setBucketMetadata - set bucket metadata
|
||||
func (donut API) setBucketMetadata(bucketName string, bucketMetadata map[string]string) *probe.Error {
|
||||
if err := donut.listDonutBuckets(); err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
metadata, err := donut.getDonutBucketMetadata()
|
||||
if err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
oldBucketMetadata := metadata.Buckets[bucketName]
|
||||
acl, ok := bucketMetadata["acl"]
|
||||
if !ok {
|
||||
return probe.NewError(InvalidArgument{})
|
||||
}
|
||||
oldBucketMetadata.ACL = BucketACL(acl)
|
||||
metadata.Buckets[bucketName] = oldBucketMetadata
|
||||
return donut.setDonutBucketMetadata(metadata)
|
||||
}
|
||||
|
||||
// listBuckets - return list of buckets
|
||||
func (donut API) listBuckets() (map[string]BucketMetadata, *probe.Error) {
|
||||
if err := donut.listDonutBuckets(); err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
metadata, err := donut.getDonutBucketMetadata()
|
||||
if err != nil {
|
||||
// intentionally left out the error when Donut is empty
|
||||
// but we need to revisit this area in future - since we need
|
||||
// to figure out between acceptable and unacceptable errors
|
||||
return make(map[string]BucketMetadata), nil
|
||||
}
|
||||
if metadata == nil {
|
||||
return make(map[string]BucketMetadata), nil
|
||||
}
|
||||
return metadata.Buckets, nil
|
||||
}
|
||||
|
||||
// listObjects - return list of objects
|
||||
func (donut API) listObjects(bucket, prefix, marker, delimiter string, maxkeys int) (ListObjectsResults, *probe.Error) {
|
||||
if err := donut.listDonutBuckets(); err != nil {
|
||||
return ListObjectsResults{}, err.Trace()
|
||||
}
|
||||
if _, ok := donut.buckets[bucket]; !ok {
|
||||
return ListObjectsResults{}, probe.NewError(BucketNotFound{Bucket: bucket})
|
||||
}
|
||||
listObjects, err := donut.buckets[bucket].ListObjects(prefix, marker, delimiter, maxkeys)
|
||||
if err != nil {
|
||||
return ListObjectsResults{}, err.Trace()
|
||||
}
|
||||
return listObjects, nil
|
||||
}
|
||||
|
||||
// putObject - put object
|
||||
func (donut API) putObject(bucket, object, expectedMD5Sum string, reader io.Reader, size int64, metadata map[string]string, signature *signv4.Signature) (ObjectMetadata, *probe.Error) {
|
||||
if bucket == "" || strings.TrimSpace(bucket) == "" {
|
||||
return ObjectMetadata{}, probe.NewError(InvalidArgument{})
|
||||
}
|
||||
if object == "" || strings.TrimSpace(object) == "" {
|
||||
return ObjectMetadata{}, probe.NewError(InvalidArgument{})
|
||||
}
|
||||
if err := donut.listDonutBuckets(); err != nil {
|
||||
return ObjectMetadata{}, err.Trace()
|
||||
}
|
||||
if _, ok := donut.buckets[bucket]; !ok {
|
||||
return ObjectMetadata{}, probe.NewError(BucketNotFound{Bucket: bucket})
|
||||
}
|
||||
bucketMeta, err := donut.getDonutBucketMetadata()
|
||||
if err != nil {
|
||||
return ObjectMetadata{}, err.Trace()
|
||||
}
|
||||
if _, ok := bucketMeta.Buckets[bucket].BucketObjects[object]; ok {
|
||||
return ObjectMetadata{}, probe.NewError(ObjectExists{Object: object})
|
||||
}
|
||||
objMetadata, err := donut.buckets[bucket].WriteObject(object, reader, size, expectedMD5Sum, metadata, signature)
|
||||
if err != nil {
|
||||
return ObjectMetadata{}, err.Trace()
|
||||
}
|
||||
bucketMeta.Buckets[bucket].BucketObjects[object] = struct{}{}
|
||||
if err := donut.setDonutBucketMetadata(bucketMeta); err != nil {
|
||||
return ObjectMetadata{}, err.Trace()
|
||||
}
|
||||
return objMetadata, nil
|
||||
}
|
||||
|
||||
// putObject - put object
|
||||
func (donut API) putObjectPart(bucket, object, expectedMD5Sum, uploadID string, partID int, reader io.Reader, size int64, metadata map[string]string, signature *signv4.Signature) (PartMetadata, *probe.Error) {
|
||||
if bucket == "" || strings.TrimSpace(bucket) == "" {
|
||||
return PartMetadata{}, probe.NewError(InvalidArgument{})
|
||||
}
|
||||
if object == "" || strings.TrimSpace(object) == "" {
|
||||
return PartMetadata{}, probe.NewError(InvalidArgument{})
|
||||
}
|
||||
if err := donut.listDonutBuckets(); err != nil {
|
||||
return PartMetadata{}, err.Trace()
|
||||
}
|
||||
if _, ok := donut.buckets[bucket]; !ok {
|
||||
return PartMetadata{}, probe.NewError(BucketNotFound{Bucket: bucket})
|
||||
}
|
||||
bucketMeta, err := donut.getDonutBucketMetadata()
|
||||
if err != nil {
|
||||
return PartMetadata{}, err.Trace()
|
||||
}
|
||||
if _, ok := bucketMeta.Buckets[bucket].Multiparts[object]; !ok {
|
||||
return PartMetadata{}, probe.NewError(InvalidUploadID{UploadID: uploadID})
|
||||
}
|
||||
if _, ok := bucketMeta.Buckets[bucket].BucketObjects[object]; ok {
|
||||
return PartMetadata{}, probe.NewError(ObjectExists{Object: object})
|
||||
}
|
||||
objectPart := object + "/" + "multipart" + "/" + strconv.Itoa(partID)
|
||||
objmetadata, err := donut.buckets[bucket].WriteObject(objectPart, reader, size, expectedMD5Sum, metadata, signature)
|
||||
if err != nil {
|
||||
return PartMetadata{}, err.Trace()
|
||||
}
|
||||
partMetadata := PartMetadata{
|
||||
PartNumber: partID,
|
||||
LastModified: objmetadata.Created,
|
||||
ETag: objmetadata.MD5Sum,
|
||||
Size: objmetadata.Size,
|
||||
}
|
||||
multipartSession := bucketMeta.Buckets[bucket].Multiparts[object]
|
||||
multipartSession.Parts[strconv.Itoa(partID)] = partMetadata
|
||||
bucketMeta.Buckets[bucket].Multiparts[object] = multipartSession
|
||||
if err := donut.setDonutBucketMetadata(bucketMeta); err != nil {
|
||||
return PartMetadata{}, err.Trace()
|
||||
}
|
||||
return partMetadata, nil
|
||||
}
|
||||
|
||||
// getObject - get object
|
||||
func (donut API) getObject(bucket, object string) (reader io.ReadCloser, size int64, err *probe.Error) {
|
||||
if bucket == "" || strings.TrimSpace(bucket) == "" {
|
||||
return nil, 0, probe.NewError(InvalidArgument{})
|
||||
}
|
||||
if object == "" || strings.TrimSpace(object) == "" {
|
||||
return nil, 0, probe.NewError(InvalidArgument{})
|
||||
}
|
||||
if err := donut.listDonutBuckets(); err != nil {
|
||||
return nil, 0, err.Trace()
|
||||
}
|
||||
if _, ok := donut.buckets[bucket]; !ok {
|
||||
return nil, 0, probe.NewError(BucketNotFound{Bucket: bucket})
|
||||
}
|
||||
return donut.buckets[bucket].ReadObject(object)
|
||||
}
|
||||
|
||||
// getObjectMetadata - get object metadata
|
||||
func (donut API) getObjectMetadata(bucket, object string) (ObjectMetadata, *probe.Error) {
|
||||
if err := donut.listDonutBuckets(); err != nil {
|
||||
return ObjectMetadata{}, err.Trace()
|
||||
}
|
||||
if _, ok := donut.buckets[bucket]; !ok {
|
||||
return ObjectMetadata{}, probe.NewError(BucketNotFound{Bucket: bucket})
|
||||
}
|
||||
bucketMeta, err := donut.getDonutBucketMetadata()
|
||||
if err != nil {
|
||||
return ObjectMetadata{}, err.Trace()
|
||||
}
|
||||
if _, ok := bucketMeta.Buckets[bucket].BucketObjects[object]; !ok {
|
||||
return ObjectMetadata{}, probe.NewError(ObjectNotFound{Object: object})
|
||||
}
|
||||
objectMetadata, err := donut.buckets[bucket].GetObjectMetadata(object)
|
||||
if err != nil {
|
||||
return ObjectMetadata{}, err.Trace()
|
||||
}
|
||||
return objectMetadata, nil
|
||||
}
|
||||
|
||||
// newMultipartUpload - new multipart upload request
|
||||
func (donut API) newMultipartUpload(bucket, object, contentType string) (string, *probe.Error) {
|
||||
if err := donut.listDonutBuckets(); err != nil {
|
||||
return "", err.Trace()
|
||||
}
|
||||
if _, ok := donut.buckets[bucket]; !ok {
|
||||
return "", probe.NewError(BucketNotFound{Bucket: bucket})
|
||||
}
|
||||
allbuckets, err := donut.getDonutBucketMetadata()
|
||||
if err != nil {
|
||||
return "", err.Trace()
|
||||
}
|
||||
bucketMetadata := allbuckets.Buckets[bucket]
|
||||
multiparts := make(map[string]MultiPartSession)
|
||||
if len(bucketMetadata.Multiparts) > 0 {
|
||||
multiparts = bucketMetadata.Multiparts
|
||||
}
|
||||
|
||||
id := []byte(strconv.Itoa(rand.Int()) + bucket + object + time.Now().String())
|
||||
uploadIDSum := sha512.Sum512(id)
|
||||
uploadID := base64.URLEncoding.EncodeToString(uploadIDSum[:])[:47]
|
||||
|
||||
multipartSession := MultiPartSession{
|
||||
UploadID: uploadID,
|
||||
Initiated: time.Now().UTC(),
|
||||
Parts: make(map[string]PartMetadata),
|
||||
TotalParts: 0,
|
||||
}
|
||||
multiparts[object] = multipartSession
|
||||
bucketMetadata.Multiparts = multiparts
|
||||
allbuckets.Buckets[bucket] = bucketMetadata
|
||||
|
||||
if err := donut.setDonutBucketMetadata(allbuckets); err != nil {
|
||||
return "", err.Trace()
|
||||
}
|
||||
|
||||
return uploadID, nil
|
||||
}
|
||||
|
||||
// listObjectParts list all object parts
|
||||
func (donut API) listObjectParts(bucket, object string, resources ObjectResourcesMetadata) (ObjectResourcesMetadata, *probe.Error) {
|
||||
if bucket == "" || strings.TrimSpace(bucket) == "" {
|
||||
return ObjectResourcesMetadata{}, probe.NewError(InvalidArgument{})
|
||||
}
|
||||
if object == "" || strings.TrimSpace(object) == "" {
|
||||
return ObjectResourcesMetadata{}, probe.NewError(InvalidArgument{})
|
||||
}
|
||||
if err := donut.listDonutBuckets(); err != nil {
|
||||
return ObjectResourcesMetadata{}, err.Trace()
|
||||
}
|
||||
if _, ok := donut.buckets[bucket]; !ok {
|
||||
return ObjectResourcesMetadata{}, probe.NewError(BucketNotFound{Bucket: bucket})
|
||||
}
|
||||
allBuckets, err := donut.getDonutBucketMetadata()
|
||||
if err != nil {
|
||||
return ObjectResourcesMetadata{}, err.Trace()
|
||||
}
|
||||
bucketMetadata := allBuckets.Buckets[bucket]
|
||||
if _, ok := bucketMetadata.Multiparts[object]; !ok {
|
||||
return ObjectResourcesMetadata{}, probe.NewError(InvalidUploadID{UploadID: resources.UploadID})
|
||||
}
|
||||
if bucketMetadata.Multiparts[object].UploadID != resources.UploadID {
|
||||
return ObjectResourcesMetadata{}, probe.NewError(InvalidUploadID{UploadID: resources.UploadID})
|
||||
}
|
||||
objectResourcesMetadata := resources
|
||||
objectResourcesMetadata.Bucket = bucket
|
||||
objectResourcesMetadata.Key = object
|
||||
var parts []*PartMetadata
|
||||
var startPartNumber int
|
||||
switch {
|
||||
case objectResourcesMetadata.PartNumberMarker == 0:
|
||||
startPartNumber = 1
|
||||
default:
|
||||
startPartNumber = objectResourcesMetadata.PartNumberMarker
|
||||
}
|
||||
for i := startPartNumber; i <= bucketMetadata.Multiparts[object].TotalParts; i++ {
|
||||
if len(parts) > objectResourcesMetadata.MaxParts {
|
||||
sort.Sort(partNumber(parts))
|
||||
objectResourcesMetadata.IsTruncated = true
|
||||
objectResourcesMetadata.Part = parts
|
||||
objectResourcesMetadata.NextPartNumberMarker = i
|
||||
return objectResourcesMetadata, nil
|
||||
}
|
||||
part, ok := bucketMetadata.Multiparts[object].Parts[strconv.Itoa(i)]
|
||||
if !ok {
|
||||
return ObjectResourcesMetadata{}, probe.NewError(InvalidPart{})
|
||||
}
|
||||
parts = append(parts, &part)
|
||||
}
|
||||
sort.Sort(partNumber(parts))
|
||||
objectResourcesMetadata.Part = parts
|
||||
return objectResourcesMetadata, nil
|
||||
}
|
||||
|
||||
// completeMultipartUpload complete an incomplete multipart upload
|
||||
func (donut API) completeMultipartUpload(bucket, object, uploadID string, data io.Reader, signature *signv4.Signature) (ObjectMetadata, *probe.Error) {
|
||||
if bucket == "" || strings.TrimSpace(bucket) == "" {
|
||||
return ObjectMetadata{}, probe.NewError(InvalidArgument{})
|
||||
}
|
||||
if object == "" || strings.TrimSpace(object) == "" {
|
||||
return ObjectMetadata{}, probe.NewError(InvalidArgument{})
|
||||
}
|
||||
if err := donut.listDonutBuckets(); err != nil {
|
||||
return ObjectMetadata{}, err.Trace()
|
||||
}
|
||||
if _, ok := donut.buckets[bucket]; !ok {
|
||||
return ObjectMetadata{}, probe.NewError(BucketNotFound{Bucket: bucket})
|
||||
}
|
||||
allBuckets, err := donut.getDonutBucketMetadata()
|
||||
if err != nil {
|
||||
return ObjectMetadata{}, err.Trace()
|
||||
}
|
||||
bucketMetadata := allBuckets.Buckets[bucket]
|
||||
if _, ok := bucketMetadata.Multiparts[object]; !ok {
|
||||
return ObjectMetadata{}, probe.NewError(InvalidUploadID{UploadID: uploadID})
|
||||
}
|
||||
if bucketMetadata.Multiparts[object].UploadID != uploadID {
|
||||
return ObjectMetadata{}, probe.NewError(InvalidUploadID{UploadID: uploadID})
|
||||
}
|
||||
var partBytes []byte
|
||||
{
|
||||
var err error
|
||||
partBytes, err = ioutil.ReadAll(data)
|
||||
if err != nil {
|
||||
return ObjectMetadata{}, probe.NewError(err)
|
||||
}
|
||||
}
|
||||
if signature != nil {
|
||||
ok, err := signature.DoesSignatureMatch(hex.EncodeToString(sha256.Sum256(partBytes)[:]))
|
||||
if err != nil {
|
||||
return ObjectMetadata{}, err.Trace()
|
||||
}
|
||||
if !ok {
|
||||
return ObjectMetadata{}, probe.NewError(signv4.DoesNotMatch{})
|
||||
}
|
||||
}
|
||||
parts := &CompleteMultipartUpload{}
|
||||
if err := xml.Unmarshal(partBytes, parts); err != nil {
|
||||
return ObjectMetadata{}, probe.NewError(MalformedXML{})
|
||||
}
|
||||
if !sort.IsSorted(completedParts(parts.Part)) {
|
||||
return ObjectMetadata{}, probe.NewError(InvalidPartOrder{})
|
||||
}
|
||||
for _, part := range parts.Part {
|
||||
if strings.Trim(part.ETag, "\"") != bucketMetadata.Multiparts[object].Parts[strconv.Itoa(part.PartNumber)].ETag {
|
||||
return ObjectMetadata{}, probe.NewError(InvalidPart{})
|
||||
}
|
||||
}
|
||||
var finalETagBytes []byte
|
||||
var finalSize int64
|
||||
totalParts := strconv.Itoa(bucketMetadata.Multiparts[object].TotalParts)
|
||||
for _, part := range bucketMetadata.Multiparts[object].Parts {
|
||||
partETagBytes, err := hex.DecodeString(part.ETag)
|
||||
if err != nil {
|
||||
return ObjectMetadata{}, probe.NewError(err)
|
||||
}
|
||||
finalETagBytes = append(finalETagBytes, partETagBytes...)
|
||||
finalSize += part.Size
|
||||
}
|
||||
finalETag := hex.EncodeToString(finalETagBytes)
|
||||
objMetadata := ObjectMetadata{}
|
||||
objMetadata.MD5Sum = finalETag + "-" + totalParts
|
||||
objMetadata.Object = object
|
||||
objMetadata.Bucket = bucket
|
||||
objMetadata.Size = finalSize
|
||||
objMetadata.Created = bucketMetadata.Multiparts[object].Parts[totalParts].LastModified
|
||||
return objMetadata, nil
|
||||
}
|
||||
|
||||
// listMultipartUploads list all multipart uploads
|
||||
func (donut API) listMultipartUploads(bucket string, resources BucketMultipartResourcesMetadata) (BucketMultipartResourcesMetadata, *probe.Error) {
|
||||
if err := donut.listDonutBuckets(); err != nil {
|
||||
return BucketMultipartResourcesMetadata{}, err.Trace()
|
||||
}
|
||||
if _, ok := donut.buckets[bucket]; !ok {
|
||||
return BucketMultipartResourcesMetadata{}, probe.NewError(BucketNotFound{Bucket: bucket})
|
||||
}
|
||||
allbuckets, err := donut.getDonutBucketMetadata()
|
||||
if err != nil {
|
||||
return BucketMultipartResourcesMetadata{}, err.Trace()
|
||||
}
|
||||
bucketMetadata := allbuckets.Buckets[bucket]
|
||||
var uploads []*UploadMetadata
|
||||
for key, session := range bucketMetadata.Multiparts {
|
||||
if strings.HasPrefix(key, resources.Prefix) {
|
||||
if len(uploads) > resources.MaxUploads {
|
||||
sort.Sort(byKey(uploads))
|
||||
resources.Upload = uploads
|
||||
resources.NextKeyMarker = key
|
||||
resources.NextUploadIDMarker = session.UploadID
|
||||
resources.IsTruncated = true
|
||||
return resources, nil
|
||||
}
|
||||
// uploadIDMarker is ignored if KeyMarker is empty
|
||||
switch {
|
||||
case resources.KeyMarker != "" && resources.UploadIDMarker == "":
|
||||
if key > resources.KeyMarker {
|
||||
upload := new(UploadMetadata)
|
||||
upload.Key = key
|
||||
upload.UploadID = session.UploadID
|
||||
upload.Initiated = session.Initiated
|
||||
uploads = append(uploads, upload)
|
||||
}
|
||||
case resources.KeyMarker != "" && resources.UploadIDMarker != "":
|
||||
if session.UploadID > resources.UploadIDMarker {
|
||||
if key >= resources.KeyMarker {
|
||||
upload := new(UploadMetadata)
|
||||
upload.Key = key
|
||||
upload.UploadID = session.UploadID
|
||||
upload.Initiated = session.Initiated
|
||||
uploads = append(uploads, upload)
|
||||
}
|
||||
}
|
||||
default:
|
||||
upload := new(UploadMetadata)
|
||||
upload.Key = key
|
||||
upload.UploadID = session.UploadID
|
||||
upload.Initiated = session.Initiated
|
||||
uploads = append(uploads, upload)
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.Sort(byKey(uploads))
|
||||
resources.Upload = uploads
|
||||
return resources, nil
|
||||
}
|
||||
|
||||
// abortMultipartUpload - abort a incomplete multipart upload
|
||||
func (donut API) abortMultipartUpload(bucket, object, uploadID string) *probe.Error {
|
||||
if err := donut.listDonutBuckets(); err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
if _, ok := donut.buckets[bucket]; !ok {
|
||||
return probe.NewError(BucketNotFound{Bucket: bucket})
|
||||
}
|
||||
allbuckets, err := donut.getDonutBucketMetadata()
|
||||
if err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
bucketMetadata := allbuckets.Buckets[bucket]
|
||||
if _, ok := bucketMetadata.Multiparts[object]; !ok {
|
||||
return probe.NewError(InvalidUploadID{UploadID: uploadID})
|
||||
}
|
||||
if bucketMetadata.Multiparts[object].UploadID != uploadID {
|
||||
return probe.NewError(InvalidUploadID{UploadID: uploadID})
|
||||
}
|
||||
delete(bucketMetadata.Multiparts, object)
|
||||
|
||||
allbuckets.Buckets[bucket] = bucketMetadata
|
||||
if err := donut.setDonutBucketMetadata(allbuckets); err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//// internal functions
|
||||
|
||||
// getBucketMetadataWriters -
|
||||
func (donut API) getBucketMetadataWriters() ([]io.WriteCloser, *probe.Error) {
|
||||
var writers []io.WriteCloser
|
||||
for _, node := range donut.nodes {
|
||||
disks, err := node.ListDisks()
|
||||
if err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
writers = make([]io.WriteCloser, len(disks))
|
||||
for order, disk := range disks {
|
||||
bucketMetaDataWriter, err := disk.CreateFile(filepath.Join(donut.config.DonutName, bucketMetadataConfig))
|
||||
if err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
writers[order] = bucketMetaDataWriter
|
||||
}
|
||||
}
|
||||
return writers, nil
|
||||
}
|
||||
|
||||
// getBucketMetadataReaders - readers are returned in map rather than slice
|
||||
func (donut API) getBucketMetadataReaders() (map[int]io.ReadCloser, *probe.Error) {
|
||||
readers := make(map[int]io.ReadCloser)
|
||||
disks := make(map[int]disk.Disk)
|
||||
var err *probe.Error
|
||||
for _, node := range donut.nodes {
|
||||
nDisks := make(map[int]disk.Disk)
|
||||
nDisks, err = node.ListDisks()
|
||||
if err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
for k, v := range nDisks {
|
||||
disks[k] = v
|
||||
}
|
||||
}
|
||||
var bucketMetaDataReader io.ReadCloser
|
||||
for order, disk := range disks {
|
||||
bucketMetaDataReader, err = disk.Open(filepath.Join(donut.config.DonutName, bucketMetadataConfig))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
readers[order] = bucketMetaDataReader
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
return readers, nil
|
||||
}
|
||||
|
||||
// setDonutBucketMetadata -
|
||||
func (donut API) setDonutBucketMetadata(metadata *AllBuckets) *probe.Error {
|
||||
writers, err := donut.getBucketMetadataWriters()
|
||||
if err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
for _, writer := range writers {
|
||||
jenc := json.NewEncoder(writer)
|
||||
if err := jenc.Encode(metadata); err != nil {
|
||||
CleanupWritersOnError(writers)
|
||||
return probe.NewError(err)
|
||||
}
|
||||
}
|
||||
for _, writer := range writers {
|
||||
writer.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getDonutBucketMetadata -
|
||||
func (donut API) getDonutBucketMetadata() (*AllBuckets, *probe.Error) {
|
||||
metadata := &AllBuckets{}
|
||||
readers, err := donut.getBucketMetadataReaders()
|
||||
if err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
for _, reader := range readers {
|
||||
defer reader.Close()
|
||||
}
|
||||
{
|
||||
var err error
|
||||
for _, reader := range readers {
|
||||
jenc := json.NewDecoder(reader)
|
||||
if err = jenc.Decode(metadata); err == nil {
|
||||
return metadata, nil
|
||||
}
|
||||
}
|
||||
return nil, probe.NewError(err)
|
||||
}
|
||||
}
|
||||
|
||||
// makeDonutBucket -
|
||||
func (donut API) makeDonutBucket(bucketName, acl string) *probe.Error {
|
||||
if err := donut.listDonutBuckets(); err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
if _, ok := donut.buckets[bucketName]; ok {
|
||||
return probe.NewError(BucketExists{Bucket: bucketName})
|
||||
}
|
||||
bkt, bucketMetadata, err := newBucket(bucketName, acl, donut.config.DonutName, donut.nodes)
|
||||
if err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
nodeNumber := 0
|
||||
donut.buckets[bucketName] = bkt
|
||||
for _, node := range donut.nodes {
|
||||
disks := make(map[int]disk.Disk)
|
||||
disks, err = node.ListDisks()
|
||||
if err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
for order, disk := range disks {
|
||||
bucketSlice := fmt.Sprintf("%s$%d$%d", bucketName, nodeNumber, order)
|
||||
err := disk.MakeDir(filepath.Join(donut.config.DonutName, bucketSlice))
|
||||
if err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
}
|
||||
nodeNumber = nodeNumber + 1
|
||||
}
|
||||
var metadata *AllBuckets
|
||||
metadata, err = donut.getDonutBucketMetadata()
|
||||
if err != nil {
|
||||
if os.IsNotExist(err.ToGoError()) {
|
||||
metadata = new(AllBuckets)
|
||||
metadata.Buckets = make(map[string]BucketMetadata)
|
||||
metadata.Buckets[bucketName] = bucketMetadata
|
||||
err = donut.setDonutBucketMetadata(metadata)
|
||||
if err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return err.Trace()
|
||||
}
|
||||
metadata.Buckets[bucketName] = bucketMetadata
|
||||
err = donut.setDonutBucketMetadata(metadata)
|
||||
if err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// listDonutBuckets -
|
||||
func (donut API) listDonutBuckets() *probe.Error {
|
||||
var disks map[int]disk.Disk
|
||||
var err *probe.Error
|
||||
for _, node := range donut.nodes {
|
||||
disks, err = node.ListDisks()
|
||||
if err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
}
|
||||
var dirs []os.FileInfo
|
||||
for _, disk := range disks {
|
||||
dirs, err = disk.ListDir(donut.config.DonutName)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
// if all disks are missing then return error
|
||||
if err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
for _, dir := range dirs {
|
||||
splitDir := strings.Split(dir.Name(), "$")
|
||||
if len(splitDir) < 3 {
|
||||
return probe.NewError(CorruptedBackend{Backend: dir.Name()})
|
||||
}
|
||||
bucketName := splitDir[0]
|
||||
// we dont need this once we cache from makeDonutBucket()
|
||||
bkt, _, err := newBucket(bucketName, "private", donut.config.DonutName, donut.nodes)
|
||||
if err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
donut.buckets[bucketName] = bkt
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,290 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impliedd.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package donut
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
. "gopkg.in/check.v1"
|
||||
)
|
||||
|
||||
func TestDonut(t *testing.T) { TestingT(t) }
|
||||
|
||||
type MyDonutSuite struct {
|
||||
root string
|
||||
}
|
||||
|
||||
var _ = Suite(&MyDonutSuite{})
|
||||
|
||||
// create a dummy TestNodeDiskMap
|
||||
func createTestNodeDiskMap(p string) map[string][]string {
|
||||
nodes := make(map[string][]string)
|
||||
nodes["localhost"] = make([]string, 16)
|
||||
for i := 0; i < len(nodes["localhost"]); i++ {
|
||||
diskPath := filepath.Join(p, strconv.Itoa(i))
|
||||
if _, err := os.Stat(diskPath); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
os.MkdirAll(diskPath, 0700)
|
||||
}
|
||||
}
|
||||
nodes["localhost"][i] = diskPath
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
|
||||
var dd Interface
|
||||
|
||||
func (s *MyDonutSuite) SetUpSuite(c *C) {
|
||||
root, err := ioutil.TempDir(os.TempDir(), "donut-")
|
||||
c.Assert(err, IsNil)
|
||||
s.root = root
|
||||
|
||||
conf := new(Config)
|
||||
conf.Version = "0.0.1"
|
||||
conf.DonutName = "test"
|
||||
conf.NodeDiskMap = createTestNodeDiskMap(root)
|
||||
conf.MaxSize = 100000
|
||||
SetDonutConfigPath(filepath.Join(root, "donut.json"))
|
||||
perr := SaveConfig(conf)
|
||||
c.Assert(perr, IsNil)
|
||||
|
||||
dd, perr = New()
|
||||
c.Assert(perr, IsNil)
|
||||
|
||||
// testing empty donut
|
||||
buckets, perr := dd.ListBuckets()
|
||||
c.Assert(perr, IsNil)
|
||||
c.Assert(len(buckets), Equals, 0)
|
||||
}
|
||||
|
||||
func (s *MyDonutSuite) TearDownSuite(c *C) {
|
||||
os.RemoveAll(s.root)
|
||||
}
|
||||
|
||||
// test make bucket without name
|
||||
func (s *MyDonutSuite) TestBucketWithoutNameFails(c *C) {
|
||||
// fail to create new bucket without a name
|
||||
err := dd.MakeBucket("", "private", nil, nil)
|
||||
c.Assert(err, Not(IsNil))
|
||||
|
||||
err = dd.MakeBucket(" ", "private", nil, nil)
|
||||
c.Assert(err, Not(IsNil))
|
||||
}
|
||||
|
||||
// test empty bucket
|
||||
func (s *MyDonutSuite) TestEmptyBucket(c *C) {
|
||||
c.Assert(dd.MakeBucket("foo1", "private", nil, nil), IsNil)
|
||||
// check if bucket is empty
|
||||
var resources BucketResourcesMetadata
|
||||
resources.Maxkeys = 1
|
||||
objectsMetadata, resources, err := dd.ListObjects("foo1", resources)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(len(objectsMetadata), Equals, 0)
|
||||
c.Assert(resources.CommonPrefixes, DeepEquals, []string{})
|
||||
c.Assert(resources.IsTruncated, Equals, false)
|
||||
}
|
||||
|
||||
// test bucket list
|
||||
func (s *MyDonutSuite) TestMakeBucketAndList(c *C) {
|
||||
// create bucket
|
||||
err := dd.MakeBucket("foo2", "private", nil, nil)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
// check bucket exists
|
||||
buckets, err := dd.ListBuckets()
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(len(buckets), Equals, 5)
|
||||
c.Assert(buckets[0].ACL, Equals, BucketACL("private"))
|
||||
}
|
||||
|
||||
// test re-create bucket
|
||||
func (s *MyDonutSuite) TestMakeBucketWithSameNameFails(c *C) {
|
||||
err := dd.MakeBucket("foo3", "private", nil, nil)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
err = dd.MakeBucket("foo3", "private", nil, nil)
|
||||
c.Assert(err, Not(IsNil))
|
||||
}
|
||||
|
||||
// test make multiple buckets
|
||||
func (s *MyDonutSuite) TestCreateMultipleBucketsAndList(c *C) {
|
||||
// add a second bucket
|
||||
err := dd.MakeBucket("foo4", "private", nil, nil)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
err = dd.MakeBucket("bar1", "private", nil, nil)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
buckets, err := dd.ListBuckets()
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
c.Assert(len(buckets), Equals, 2)
|
||||
c.Assert(buckets[0].Name, Equals, "bar1")
|
||||
c.Assert(buckets[1].Name, Equals, "foo4")
|
||||
|
||||
err = dd.MakeBucket("foobar1", "private", nil, nil)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
buckets, err = dd.ListBuckets()
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
c.Assert(len(buckets), Equals, 3)
|
||||
c.Assert(buckets[2].Name, Equals, "foobar1")
|
||||
}
|
||||
|
||||
// test object create without bucket
|
||||
func (s *MyDonutSuite) TestNewObjectFailsWithoutBucket(c *C) {
|
||||
_, err := dd.CreateObject("unknown", "obj", "", 0, nil, nil, nil)
|
||||
c.Assert(err, Not(IsNil))
|
||||
}
|
||||
|
||||
// test create object metadata
|
||||
func (s *MyDonutSuite) TestNewObjectMetadata(c *C) {
|
||||
data := "Hello World"
|
||||
hasher := md5.New()
|
||||
hasher.Write([]byte(data))
|
||||
expectedMd5Sum := base64.StdEncoding.EncodeToString(hasher.Sum(nil))
|
||||
reader := ioutil.NopCloser(bytes.NewReader([]byte(data)))
|
||||
|
||||
err := dd.MakeBucket("foo6", "private", nil, nil)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
objectMetadata, err := dd.CreateObject("foo6", "obj", expectedMd5Sum, int64(len(data)), reader, map[string]string{"contentType": "application/json"}, nil)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(objectMetadata.MD5Sum, Equals, hex.EncodeToString(hasher.Sum(nil)))
|
||||
c.Assert(objectMetadata.Metadata["contentType"], Equals, "application/json")
|
||||
}
|
||||
|
||||
// test create object fails without name
|
||||
func (s *MyDonutSuite) TestNewObjectFailsWithEmptyName(c *C) {
|
||||
_, err := dd.CreateObject("foo", "", "", 0, nil, nil, nil)
|
||||
c.Assert(err, Not(IsNil))
|
||||
}
|
||||
|
||||
// test create object
|
||||
func (s *MyDonutSuite) TestNewObjectCanBeWritten(c *C) {
|
||||
err := dd.MakeBucket("foo", "private", nil, nil)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
data := "Hello World"
|
||||
|
||||
hasher := md5.New()
|
||||
hasher.Write([]byte(data))
|
||||
expectedMd5Sum := base64.StdEncoding.EncodeToString(hasher.Sum(nil))
|
||||
reader := ioutil.NopCloser(bytes.NewReader([]byte(data)))
|
||||
|
||||
actualMetadata, err := dd.CreateObject("foo", "obj", expectedMd5Sum, int64(len(data)), reader, map[string]string{"contentType": "application/octet-stream"}, nil)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(actualMetadata.MD5Sum, Equals, hex.EncodeToString(hasher.Sum(nil)))
|
||||
|
||||
var buffer bytes.Buffer
|
||||
size, err := dd.GetObject(&buffer, "foo", "obj", 0, 0)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(size, Equals, int64(len(data)))
|
||||
c.Assert(buffer.Bytes(), DeepEquals, []byte(data))
|
||||
|
||||
actualMetadata, err = dd.GetObjectMetadata("foo", "obj")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(hex.EncodeToString(hasher.Sum(nil)), Equals, actualMetadata.MD5Sum)
|
||||
c.Assert(int64(len(data)), Equals, actualMetadata.Size)
|
||||
}
|
||||
|
||||
// test list objects
|
||||
func (s *MyDonutSuite) TestMultipleNewObjects(c *C) {
|
||||
c.Assert(dd.MakeBucket("foo5", "private", nil, nil), IsNil)
|
||||
|
||||
one := ioutil.NopCloser(bytes.NewReader([]byte("one")))
|
||||
|
||||
_, err := dd.CreateObject("foo5", "obj1", "", int64(len("one")), one, nil, nil)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
two := ioutil.NopCloser(bytes.NewReader([]byte("two")))
|
||||
_, err = dd.CreateObject("foo5", "obj2", "", int64(len("two")), two, nil, nil)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
var buffer1 bytes.Buffer
|
||||
size, err := dd.GetObject(&buffer1, "foo5", "obj1", 0, 0)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(size, Equals, int64(len([]byte("one"))))
|
||||
c.Assert(buffer1.Bytes(), DeepEquals, []byte("one"))
|
||||
|
||||
var buffer2 bytes.Buffer
|
||||
size, err = dd.GetObject(&buffer2, "foo5", "obj2", 0, 0)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(size, Equals, int64(len([]byte("two"))))
|
||||
|
||||
c.Assert(buffer2.Bytes(), DeepEquals, []byte("two"))
|
||||
|
||||
/// test list of objects
|
||||
|
||||
// test list objects with prefix and delimiter
|
||||
var resources BucketResourcesMetadata
|
||||
resources.Prefix = "o"
|
||||
resources.Delimiter = "1"
|
||||
resources.Maxkeys = 10
|
||||
objectsMetadata, resources, err := dd.ListObjects("foo5", resources)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(resources.IsTruncated, Equals, false)
|
||||
c.Assert(resources.CommonPrefixes[0], Equals, "obj1")
|
||||
|
||||
// test list objects with only delimiter
|
||||
resources.Prefix = ""
|
||||
resources.Delimiter = "1"
|
||||
resources.Maxkeys = 10
|
||||
objectsMetadata, resources, err = dd.ListObjects("foo5", resources)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(objectsMetadata[0].Object, Equals, "obj2")
|
||||
c.Assert(resources.IsTruncated, Equals, false)
|
||||
c.Assert(resources.CommonPrefixes[0], Equals, "obj1")
|
||||
|
||||
// test list objects with only prefix
|
||||
resources.Prefix = "o"
|
||||
resources.Delimiter = ""
|
||||
resources.Maxkeys = 10
|
||||
objectsMetadata, resources, err = dd.ListObjects("foo5", resources)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(resources.IsTruncated, Equals, false)
|
||||
c.Assert(objectsMetadata[0].Object, Equals, "obj1")
|
||||
c.Assert(objectsMetadata[1].Object, Equals, "obj2")
|
||||
|
||||
three := ioutil.NopCloser(bytes.NewReader([]byte("three")))
|
||||
_, err = dd.CreateObject("foo5", "obj3", "", int64(len("three")), three, nil, nil)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
var buffer bytes.Buffer
|
||||
size, err = dd.GetObject(&buffer, "foo5", "obj3", 0, 0)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(size, Equals, int64(len([]byte("three"))))
|
||||
c.Assert(buffer.Bytes(), DeepEquals, []byte("three"))
|
||||
|
||||
// test list objects with maxkeys
|
||||
resources.Prefix = "o"
|
||||
resources.Delimiter = ""
|
||||
resources.Maxkeys = 2
|
||||
objectsMetadata, resources, err = dd.ListObjects("foo5", resources)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(resources.IsTruncated, Equals, true)
|
||||
c.Assert(len(objectsMetadata), Equals, 2)
|
||||
}
|
||||
@@ -1,636 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package donut
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"runtime/debug"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/minio/minio/pkg/crypto/sha256"
|
||||
"github.com/minio/minio/pkg/donut/cache/data"
|
||||
"github.com/minio/minio/pkg/donut/cache/metadata"
|
||||
"github.com/minio/minio/pkg/probe"
|
||||
"github.com/minio/minio/pkg/quick"
|
||||
signv4 "github.com/minio/minio/pkg/signature"
|
||||
)
|
||||
|
||||
// total Number of buckets allowed
|
||||
const (
|
||||
totalBuckets = 100
|
||||
)
|
||||
|
||||
// Config donut config
|
||||
type Config struct {
|
||||
Version string `json:"version"`
|
||||
MaxSize uint64 `json:"max-size"`
|
||||
DonutName string `json:"donut-name"`
|
||||
NodeDiskMap map[string][]string `json:"node-disk-map"`
|
||||
}
|
||||
|
||||
// API - local variables
|
||||
type API struct {
|
||||
config *Config
|
||||
lock *sync.Mutex
|
||||
objects *data.Cache
|
||||
multiPartObjects map[string]*data.Cache
|
||||
storedBuckets *metadata.Cache
|
||||
nodes map[string]node
|
||||
buckets map[string]bucket
|
||||
}
|
||||
|
||||
// storedBucket saved bucket
|
||||
type storedBucket struct {
|
||||
bucketMetadata BucketMetadata
|
||||
objectMetadata map[string]ObjectMetadata
|
||||
partMetadata map[string]map[int]PartMetadata
|
||||
multiPartSession map[string]MultiPartSession
|
||||
}
|
||||
|
||||
// New instantiate a new donut
|
||||
func New() (Interface, *probe.Error) {
|
||||
var conf *Config
|
||||
var err *probe.Error
|
||||
conf, err = LoadConfig()
|
||||
if err != nil {
|
||||
conf = &Config{
|
||||
Version: "0.0.1",
|
||||
MaxSize: 512000000,
|
||||
NodeDiskMap: nil,
|
||||
DonutName: "",
|
||||
}
|
||||
if err := quick.CheckData(conf); err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
}
|
||||
a := API{config: conf}
|
||||
a.storedBuckets = metadata.NewCache()
|
||||
a.nodes = make(map[string]node)
|
||||
a.buckets = make(map[string]bucket)
|
||||
a.objects = data.NewCache(a.config.MaxSize)
|
||||
a.multiPartObjects = make(map[string]*data.Cache)
|
||||
a.objects.OnEvicted = a.evictedObject
|
||||
a.lock = new(sync.Mutex)
|
||||
|
||||
if len(a.config.NodeDiskMap) > 0 {
|
||||
for k, v := range a.config.NodeDiskMap {
|
||||
if len(v) == 0 {
|
||||
return nil, probe.NewError(InvalidDisksArgument{})
|
||||
}
|
||||
err := a.AttachNode(k, v)
|
||||
if err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
}
|
||||
/// Initialization, populate all buckets into memory
|
||||
buckets, err := a.listBuckets()
|
||||
if err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
for k, v := range buckets {
|
||||
var newBucket = storedBucket{}
|
||||
newBucket.bucketMetadata = v
|
||||
newBucket.objectMetadata = make(map[string]ObjectMetadata)
|
||||
newBucket.multiPartSession = make(map[string]MultiPartSession)
|
||||
newBucket.partMetadata = make(map[string]map[int]PartMetadata)
|
||||
a.storedBuckets.Set(k, newBucket)
|
||||
}
|
||||
a.Heal()
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
/// V2 API functions
|
||||
|
||||
// GetObject - GET object from cache buffer
|
||||
func (donut API) GetObject(w io.Writer, bucket string, object string, start, length int64) (int64, *probe.Error) {
|
||||
donut.lock.Lock()
|
||||
defer donut.lock.Unlock()
|
||||
|
||||
if !IsValidBucket(bucket) {
|
||||
return 0, probe.NewError(BucketNameInvalid{Bucket: bucket})
|
||||
}
|
||||
if !IsValidObjectName(object) {
|
||||
return 0, probe.NewError(ObjectNameInvalid{Object: object})
|
||||
}
|
||||
if start < 0 {
|
||||
return 0, probe.NewError(InvalidRange{
|
||||
Start: start,
|
||||
Length: length,
|
||||
})
|
||||
}
|
||||
if !donut.storedBuckets.Exists(bucket) {
|
||||
return 0, probe.NewError(BucketNotFound{Bucket: bucket})
|
||||
}
|
||||
objectKey := bucket + "/" + object
|
||||
data, ok := donut.objects.Get(objectKey)
|
||||
var written int64
|
||||
if !ok {
|
||||
if len(donut.config.NodeDiskMap) > 0 {
|
||||
reader, size, err := donut.getObject(bucket, object)
|
||||
if err != nil {
|
||||
return 0, err.Trace()
|
||||
}
|
||||
if start > 0 {
|
||||
if _, err := io.CopyN(ioutil.Discard, reader, start); err != nil {
|
||||
return 0, probe.NewError(err)
|
||||
}
|
||||
}
|
||||
// new proxy writer to capture data read from disk
|
||||
pw := NewProxyWriter(w)
|
||||
{
|
||||
var err error
|
||||
if length > 0 {
|
||||
written, err = io.CopyN(pw, reader, length)
|
||||
if err != nil {
|
||||
return 0, probe.NewError(err)
|
||||
}
|
||||
} else {
|
||||
written, err = io.CopyN(pw, reader, size)
|
||||
if err != nil {
|
||||
return 0, probe.NewError(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
/// cache object read from disk
|
||||
ok := donut.objects.Append(objectKey, pw.writtenBytes)
|
||||
pw.writtenBytes = nil
|
||||
go debug.FreeOSMemory()
|
||||
if !ok {
|
||||
return 0, probe.NewError(InternalError{})
|
||||
}
|
||||
return written, nil
|
||||
}
|
||||
return 0, probe.NewError(ObjectNotFound{Object: object})
|
||||
}
|
||||
var err error
|
||||
if start == 0 && length == 0 {
|
||||
written, err = io.CopyN(w, bytes.NewBuffer(data), int64(donut.objects.Len(objectKey)))
|
||||
if err != nil {
|
||||
return 0, probe.NewError(err)
|
||||
}
|
||||
return written, nil
|
||||
}
|
||||
written, err = io.CopyN(w, bytes.NewBuffer(data[start:]), length)
|
||||
if err != nil {
|
||||
return 0, probe.NewError(err)
|
||||
}
|
||||
return written, nil
|
||||
}
|
||||
|
||||
// GetBucketMetadata -
|
||||
func (donut API) GetBucketMetadata(bucket string) (BucketMetadata, *probe.Error) {
|
||||
donut.lock.Lock()
|
||||
defer donut.lock.Unlock()
|
||||
|
||||
if !IsValidBucket(bucket) {
|
||||
return BucketMetadata{}, probe.NewError(BucketNameInvalid{Bucket: bucket})
|
||||
}
|
||||
if !donut.storedBuckets.Exists(bucket) {
|
||||
if len(donut.config.NodeDiskMap) > 0 {
|
||||
bucketMetadata, err := donut.getBucketMetadata(bucket)
|
||||
if err != nil {
|
||||
return BucketMetadata{}, err.Trace()
|
||||
}
|
||||
storedBucket := donut.storedBuckets.Get(bucket).(storedBucket)
|
||||
storedBucket.bucketMetadata = bucketMetadata
|
||||
donut.storedBuckets.Set(bucket, storedBucket)
|
||||
}
|
||||
return BucketMetadata{}, probe.NewError(BucketNotFound{Bucket: bucket})
|
||||
}
|
||||
return donut.storedBuckets.Get(bucket).(storedBucket).bucketMetadata, nil
|
||||
}
|
||||
|
||||
// SetBucketMetadata -
|
||||
func (donut API) SetBucketMetadata(bucket string, metadata map[string]string) *probe.Error {
|
||||
donut.lock.Lock()
|
||||
defer donut.lock.Unlock()
|
||||
|
||||
if !IsValidBucket(bucket) {
|
||||
return probe.NewError(BucketNameInvalid{Bucket: bucket})
|
||||
}
|
||||
if !donut.storedBuckets.Exists(bucket) {
|
||||
return probe.NewError(BucketNotFound{Bucket: bucket})
|
||||
}
|
||||
if len(donut.config.NodeDiskMap) > 0 {
|
||||
if err := donut.setBucketMetadata(bucket, metadata); err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
}
|
||||
storedBucket := donut.storedBuckets.Get(bucket).(storedBucket)
|
||||
storedBucket.bucketMetadata.ACL = BucketACL(metadata["acl"])
|
||||
donut.storedBuckets.Set(bucket, storedBucket)
|
||||
return nil
|
||||
}
|
||||
|
||||
// isMD5SumEqual - returns error if md5sum mismatches, success its `nil`
|
||||
func isMD5SumEqual(expectedMD5Sum, actualMD5Sum string) *probe.Error {
|
||||
if strings.TrimSpace(expectedMD5Sum) != "" && strings.TrimSpace(actualMD5Sum) != "" {
|
||||
expectedMD5SumBytes, err := hex.DecodeString(expectedMD5Sum)
|
||||
if err != nil {
|
||||
return probe.NewError(err)
|
||||
}
|
||||
actualMD5SumBytes, err := hex.DecodeString(actualMD5Sum)
|
||||
if err != nil {
|
||||
return probe.NewError(err)
|
||||
}
|
||||
if !bytes.Equal(expectedMD5SumBytes, actualMD5SumBytes) {
|
||||
return probe.NewError(BadDigest{})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return probe.NewError(InvalidArgument{})
|
||||
}
|
||||
|
||||
// CreateObject - create an object
|
||||
func (donut API) CreateObject(bucket, key, expectedMD5Sum string, size int64, data io.Reader, metadata map[string]string, signature *signv4.Signature) (ObjectMetadata, *probe.Error) {
|
||||
donut.lock.Lock()
|
||||
defer donut.lock.Unlock()
|
||||
|
||||
contentType := metadata["contentType"]
|
||||
objectMetadata, err := donut.createObject(bucket, key, contentType, expectedMD5Sum, size, data, signature)
|
||||
// free
|
||||
debug.FreeOSMemory()
|
||||
|
||||
return objectMetadata, err.Trace()
|
||||
}
|
||||
|
||||
// createObject - PUT object to cache buffer
|
||||
func (donut API) createObject(bucket, key, contentType, expectedMD5Sum string, size int64, data io.Reader, signature *signv4.Signature) (ObjectMetadata, *probe.Error) {
|
||||
if len(donut.config.NodeDiskMap) == 0 {
|
||||
if size > int64(donut.config.MaxSize) {
|
||||
generic := GenericObjectError{Bucket: bucket, Object: key}
|
||||
return ObjectMetadata{}, probe.NewError(EntityTooLarge{
|
||||
GenericObjectError: generic,
|
||||
Size: strconv.FormatInt(size, 10),
|
||||
MaxSize: strconv.FormatUint(donut.config.MaxSize, 10),
|
||||
})
|
||||
}
|
||||
}
|
||||
if !IsValidBucket(bucket) {
|
||||
return ObjectMetadata{}, probe.NewError(BucketNameInvalid{Bucket: bucket})
|
||||
}
|
||||
if !IsValidObjectName(key) {
|
||||
return ObjectMetadata{}, probe.NewError(ObjectNameInvalid{Object: key})
|
||||
}
|
||||
if !donut.storedBuckets.Exists(bucket) {
|
||||
return ObjectMetadata{}, probe.NewError(BucketNotFound{Bucket: bucket})
|
||||
}
|
||||
storedBucket := donut.storedBuckets.Get(bucket).(storedBucket)
|
||||
// get object key
|
||||
objectKey := bucket + "/" + key
|
||||
if _, ok := storedBucket.objectMetadata[objectKey]; ok == true {
|
||||
return ObjectMetadata{}, probe.NewError(ObjectExists{Object: key})
|
||||
}
|
||||
|
||||
if contentType == "" {
|
||||
contentType = "application/octet-stream"
|
||||
}
|
||||
contentType = strings.TrimSpace(contentType)
|
||||
if strings.TrimSpace(expectedMD5Sum) != "" {
|
||||
expectedMD5SumBytes, err := base64.StdEncoding.DecodeString(strings.TrimSpace(expectedMD5Sum))
|
||||
if err != nil {
|
||||
// pro-actively close the connection
|
||||
return ObjectMetadata{}, probe.NewError(InvalidDigest{Md5: expectedMD5Sum})
|
||||
}
|
||||
expectedMD5Sum = hex.EncodeToString(expectedMD5SumBytes)
|
||||
}
|
||||
|
||||
if len(donut.config.NodeDiskMap) > 0 {
|
||||
objMetadata, err := donut.putObject(
|
||||
bucket,
|
||||
key,
|
||||
expectedMD5Sum,
|
||||
data,
|
||||
size,
|
||||
map[string]string{
|
||||
"contentType": contentType,
|
||||
"contentLength": strconv.FormatInt(size, 10),
|
||||
},
|
||||
signature,
|
||||
)
|
||||
if err != nil {
|
||||
return ObjectMetadata{}, err.Trace()
|
||||
}
|
||||
storedBucket.objectMetadata[objectKey] = objMetadata
|
||||
donut.storedBuckets.Set(bucket, storedBucket)
|
||||
return objMetadata, nil
|
||||
}
|
||||
|
||||
// calculate md5
|
||||
hash := md5.New()
|
||||
sha256hash := sha256.New()
|
||||
|
||||
var err error
|
||||
var totalLength int64
|
||||
for err == nil {
|
||||
var length int
|
||||
byteBuffer := make([]byte, 1024*1024)
|
||||
length, err = data.Read(byteBuffer)
|
||||
if length != 0 {
|
||||
hash.Write(byteBuffer[0:length])
|
||||
sha256hash.Write(byteBuffer[0:length])
|
||||
ok := donut.objects.Append(objectKey, byteBuffer[0:length])
|
||||
if !ok {
|
||||
return ObjectMetadata{}, probe.NewError(InternalError{})
|
||||
}
|
||||
totalLength += int64(length)
|
||||
go debug.FreeOSMemory()
|
||||
}
|
||||
}
|
||||
if size != 0 {
|
||||
if totalLength != size {
|
||||
// Delete perhaps the object is already saved, due to the nature of append()
|
||||
donut.objects.Delete(objectKey)
|
||||
return ObjectMetadata{}, probe.NewError(IncompleteBody{Bucket: bucket, Object: key})
|
||||
}
|
||||
}
|
||||
if err != io.EOF {
|
||||
return ObjectMetadata{}, probe.NewError(err)
|
||||
}
|
||||
md5SumBytes := hash.Sum(nil)
|
||||
md5Sum := hex.EncodeToString(md5SumBytes)
|
||||
// Verify if the written object is equal to what is expected, only if it is requested as such
|
||||
if strings.TrimSpace(expectedMD5Sum) != "" {
|
||||
if err := isMD5SumEqual(strings.TrimSpace(expectedMD5Sum), md5Sum); err != nil {
|
||||
// Delete perhaps the object is already saved, due to the nature of append()
|
||||
donut.objects.Delete(objectKey)
|
||||
return ObjectMetadata{}, probe.NewError(BadDigest{})
|
||||
}
|
||||
}
|
||||
if signature != nil {
|
||||
ok, err := signature.DoesSignatureMatch(hex.EncodeToString(sha256hash.Sum(nil)))
|
||||
if err != nil {
|
||||
// Delete perhaps the object is already saved, due to the nature of append()
|
||||
donut.objects.Delete(objectKey)
|
||||
return ObjectMetadata{}, err.Trace()
|
||||
}
|
||||
if !ok {
|
||||
// Delete perhaps the object is already saved, due to the nature of append()
|
||||
donut.objects.Delete(objectKey)
|
||||
return ObjectMetadata{}, probe.NewError(signv4.DoesNotMatch{})
|
||||
}
|
||||
}
|
||||
|
||||
m := make(map[string]string)
|
||||
m["contentType"] = contentType
|
||||
newObject := ObjectMetadata{
|
||||
Bucket: bucket,
|
||||
Object: key,
|
||||
|
||||
Metadata: m,
|
||||
Created: time.Now().UTC(),
|
||||
MD5Sum: md5Sum,
|
||||
Size: int64(totalLength),
|
||||
}
|
||||
|
||||
storedBucket.objectMetadata[objectKey] = newObject
|
||||
donut.storedBuckets.Set(bucket, storedBucket)
|
||||
return newObject, nil
|
||||
}
|
||||
|
||||
// MakeBucket - create bucket in cache
|
||||
func (donut API) MakeBucket(bucketName, acl string, location io.Reader, signature *signv4.Signature) *probe.Error {
|
||||
donut.lock.Lock()
|
||||
defer donut.lock.Unlock()
|
||||
|
||||
// do not have to parse location constraint, using this just for signature verification
|
||||
locationSum := "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
if location != nil {
|
||||
locationConstraintBytes, err := ioutil.ReadAll(location)
|
||||
if err != nil {
|
||||
return probe.NewError(InternalError{})
|
||||
}
|
||||
locationSum = hex.EncodeToString(sha256.Sum256(locationConstraintBytes)[:])
|
||||
}
|
||||
|
||||
if signature != nil {
|
||||
ok, err := signature.DoesSignatureMatch(locationSum)
|
||||
if err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
if !ok {
|
||||
return probe.NewError(signv4.DoesNotMatch{})
|
||||
}
|
||||
}
|
||||
|
||||
if donut.storedBuckets.Stats().Items == totalBuckets {
|
||||
return probe.NewError(TooManyBuckets{Bucket: bucketName})
|
||||
}
|
||||
if !IsValidBucket(bucketName) {
|
||||
return probe.NewError(BucketNameInvalid{Bucket: bucketName})
|
||||
}
|
||||
if !IsValidBucketACL(acl) {
|
||||
return probe.NewError(InvalidACL{ACL: acl})
|
||||
}
|
||||
if donut.storedBuckets.Exists(bucketName) {
|
||||
return probe.NewError(BucketExists{Bucket: bucketName})
|
||||
}
|
||||
|
||||
if strings.TrimSpace(acl) == "" {
|
||||
// default is private
|
||||
acl = "private"
|
||||
}
|
||||
if len(donut.config.NodeDiskMap) > 0 {
|
||||
if err := donut.makeBucket(bucketName, BucketACL(acl)); err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
}
|
||||
var newBucket = storedBucket{}
|
||||
newBucket.objectMetadata = make(map[string]ObjectMetadata)
|
||||
newBucket.multiPartSession = make(map[string]MultiPartSession)
|
||||
newBucket.partMetadata = make(map[string]map[int]PartMetadata)
|
||||
newBucket.bucketMetadata = BucketMetadata{}
|
||||
newBucket.bucketMetadata.Name = bucketName
|
||||
newBucket.bucketMetadata.Created = time.Now().UTC()
|
||||
newBucket.bucketMetadata.ACL = BucketACL(acl)
|
||||
donut.storedBuckets.Set(bucketName, newBucket)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListObjects - list objects from cache
|
||||
func (donut API) ListObjects(bucket string, resources BucketResourcesMetadata) ([]ObjectMetadata, BucketResourcesMetadata, *probe.Error) {
|
||||
donut.lock.Lock()
|
||||
defer donut.lock.Unlock()
|
||||
|
||||
if !IsValidBucket(bucket) {
|
||||
return nil, BucketResourcesMetadata{IsTruncated: false}, probe.NewError(BucketNameInvalid{Bucket: bucket})
|
||||
}
|
||||
if !IsValidPrefix(resources.Prefix) {
|
||||
return nil, BucketResourcesMetadata{IsTruncated: false}, probe.NewError(ObjectNameInvalid{Object: resources.Prefix})
|
||||
}
|
||||
if !donut.storedBuckets.Exists(bucket) {
|
||||
return nil, BucketResourcesMetadata{IsTruncated: false}, probe.NewError(BucketNotFound{Bucket: bucket})
|
||||
}
|
||||
var results []ObjectMetadata
|
||||
var keys []string
|
||||
if len(donut.config.NodeDiskMap) > 0 {
|
||||
listObjects, err := donut.listObjects(
|
||||
bucket,
|
||||
resources.Prefix,
|
||||
resources.Marker,
|
||||
resources.Delimiter,
|
||||
resources.Maxkeys,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, BucketResourcesMetadata{IsTruncated: false}, err.Trace()
|
||||
}
|
||||
resources.CommonPrefixes = listObjects.CommonPrefixes
|
||||
resources.IsTruncated = listObjects.IsTruncated
|
||||
for key := range listObjects.Objects {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, key := range keys {
|
||||
results = append(results, listObjects.Objects[key])
|
||||
}
|
||||
if resources.IsTruncated && resources.Delimiter != "" {
|
||||
resources.NextMarker = results[len(results)-1].Object
|
||||
}
|
||||
return results, resources, nil
|
||||
}
|
||||
storedBucket := donut.storedBuckets.Get(bucket).(storedBucket)
|
||||
for key := range storedBucket.objectMetadata {
|
||||
if strings.HasPrefix(key, bucket+"/") {
|
||||
key = key[len(bucket)+1:]
|
||||
if strings.HasPrefix(key, resources.Prefix) {
|
||||
if key > resources.Marker {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if strings.TrimSpace(resources.Prefix) != "" {
|
||||
keys = TrimPrefix(keys, resources.Prefix)
|
||||
}
|
||||
var prefixes []string
|
||||
var filteredKeys []string
|
||||
filteredKeys = keys
|
||||
if strings.TrimSpace(resources.Delimiter) != "" {
|
||||
filteredKeys = HasNoDelimiter(keys, resources.Delimiter)
|
||||
prefixes = HasDelimiter(keys, resources.Delimiter)
|
||||
prefixes = SplitDelimiter(prefixes, resources.Delimiter)
|
||||
prefixes = SortUnique(prefixes)
|
||||
}
|
||||
for _, commonPrefix := range prefixes {
|
||||
resources.CommonPrefixes = append(resources.CommonPrefixes, resources.Prefix+commonPrefix)
|
||||
}
|
||||
filteredKeys = RemoveDuplicates(filteredKeys)
|
||||
sort.Strings(filteredKeys)
|
||||
|
||||
for _, key := range filteredKeys {
|
||||
if len(results) == resources.Maxkeys {
|
||||
resources.IsTruncated = true
|
||||
if resources.IsTruncated && resources.Delimiter != "" {
|
||||
resources.NextMarker = results[len(results)-1].Object
|
||||
}
|
||||
return results, resources, nil
|
||||
}
|
||||
object := storedBucket.objectMetadata[bucket+"/"+resources.Prefix+key]
|
||||
results = append(results, object)
|
||||
}
|
||||
resources.CommonPrefixes = RemoveDuplicates(resources.CommonPrefixes)
|
||||
sort.Strings(resources.CommonPrefixes)
|
||||
return results, resources, nil
|
||||
}
|
||||
|
||||
// byBucketName is a type for sorting bucket metadata by bucket name
|
||||
type byBucketName []BucketMetadata
|
||||
|
||||
func (b byBucketName) Len() int { return len(b) }
|
||||
func (b byBucketName) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
|
||||
func (b byBucketName) Less(i, j int) bool { return b[i].Name < b[j].Name }
|
||||
|
||||
// ListBuckets - List buckets from cache
|
||||
func (donut API) ListBuckets() ([]BucketMetadata, *probe.Error) {
|
||||
donut.lock.Lock()
|
||||
defer donut.lock.Unlock()
|
||||
|
||||
var results []BucketMetadata
|
||||
if len(donut.config.NodeDiskMap) > 0 {
|
||||
buckets, err := donut.listBuckets()
|
||||
if err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
for _, bucketMetadata := range buckets {
|
||||
results = append(results, bucketMetadata)
|
||||
}
|
||||
sort.Sort(byBucketName(results))
|
||||
return results, nil
|
||||
}
|
||||
for _, bucket := range donut.storedBuckets.GetAll() {
|
||||
results = append(results, bucket.(storedBucket).bucketMetadata)
|
||||
}
|
||||
sort.Sort(byBucketName(results))
|
||||
return results, nil
|
||||
}
|
||||
|
||||
// GetObjectMetadata - get object metadata from cache
|
||||
func (donut API) GetObjectMetadata(bucket, key string) (ObjectMetadata, *probe.Error) {
|
||||
donut.lock.Lock()
|
||||
defer donut.lock.Unlock()
|
||||
|
||||
// check if bucket exists
|
||||
if !IsValidBucket(bucket) {
|
||||
return ObjectMetadata{}, probe.NewError(BucketNameInvalid{Bucket: bucket})
|
||||
}
|
||||
if !IsValidObjectName(key) {
|
||||
return ObjectMetadata{}, probe.NewError(ObjectNameInvalid{Object: key})
|
||||
}
|
||||
if !donut.storedBuckets.Exists(bucket) {
|
||||
return ObjectMetadata{}, probe.NewError(BucketNotFound{Bucket: bucket})
|
||||
}
|
||||
storedBucket := donut.storedBuckets.Get(bucket).(storedBucket)
|
||||
objectKey := bucket + "/" + key
|
||||
if objMetadata, ok := storedBucket.objectMetadata[objectKey]; ok == true {
|
||||
return objMetadata, nil
|
||||
}
|
||||
if len(donut.config.NodeDiskMap) > 0 {
|
||||
objMetadata, err := donut.getObjectMetadata(bucket, key)
|
||||
if err != nil {
|
||||
return ObjectMetadata{}, err.Trace()
|
||||
}
|
||||
// update
|
||||
storedBucket.objectMetadata[objectKey] = objMetadata
|
||||
donut.storedBuckets.Set(bucket, storedBucket)
|
||||
return objMetadata, nil
|
||||
}
|
||||
return ObjectMetadata{}, probe.NewError(ObjectNotFound{Object: key})
|
||||
}
|
||||
|
||||
// evictedObject callback function called when an item is evicted from memory
|
||||
func (donut API) evictedObject(a ...interface{}) {
|
||||
cacheStats := donut.objects.Stats()
|
||||
log.Printf("CurrentSize: %d, CurrentItems: %d, TotalEvicted: %d",
|
||||
cacheStats.Bytes, cacheStats.Items, cacheStats.Evicted)
|
||||
key := a[0].(string)
|
||||
// loop through all buckets
|
||||
for _, bucket := range donut.storedBuckets.GetAll() {
|
||||
delete(bucket.(storedBucket).objectMetadata, key)
|
||||
}
|
||||
debug.FreeOSMemory()
|
||||
}
|
||||
@@ -1,265 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impliedc.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package donut
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
. "gopkg.in/check.v1"
|
||||
)
|
||||
|
||||
func TestCache(t *testing.T) { TestingT(t) }
|
||||
|
||||
type MyCacheSuite struct {
|
||||
root string
|
||||
}
|
||||
|
||||
var _ = Suite(&MyCacheSuite{})
|
||||
|
||||
var dc Interface
|
||||
|
||||
func (s *MyCacheSuite) SetUpSuite(c *C) {
|
||||
root, err := ioutil.TempDir(os.TempDir(), "donut-")
|
||||
c.Assert(err, IsNil)
|
||||
s.root = root
|
||||
|
||||
SetDonutConfigPath(filepath.Join(root, "donut.json"))
|
||||
dc, _ = New()
|
||||
|
||||
// testing empty cache
|
||||
var buckets []BucketMetadata
|
||||
buckets, perr := dc.ListBuckets()
|
||||
c.Assert(perr, IsNil)
|
||||
c.Assert(len(buckets), Equals, 0)
|
||||
}
|
||||
|
||||
func (s *MyCacheSuite) TearDownSuite(c *C) {
|
||||
os.RemoveAll(s.root)
|
||||
}
|
||||
|
||||
// test make bucket without name
|
||||
func (s *MyCacheSuite) TestBucketWithoutNameFails(c *C) {
|
||||
// fail to create new bucket without a name
|
||||
err := dc.MakeBucket("", "private", nil, nil)
|
||||
c.Assert(err, Not(IsNil))
|
||||
|
||||
err = dc.MakeBucket(" ", "private", nil, nil)
|
||||
c.Assert(err, Not(IsNil))
|
||||
}
|
||||
|
||||
// test empty bucket
|
||||
func (s *MyCacheSuite) TestEmptyBucket(c *C) {
|
||||
c.Assert(dc.MakeBucket("foo1", "private", nil, nil), IsNil)
|
||||
// check if bucket is empty
|
||||
var resources BucketResourcesMetadata
|
||||
resources.Maxkeys = 1
|
||||
objectsMetadata, resources, err := dc.ListObjects("foo1", resources)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(len(objectsMetadata), Equals, 0)
|
||||
c.Assert(resources.CommonPrefixes, DeepEquals, []string{})
|
||||
c.Assert(resources.IsTruncated, Equals, false)
|
||||
}
|
||||
|
||||
// test bucket list
|
||||
func (s *MyCacheSuite) TestMakeBucketAndList(c *C) {
|
||||
// create bucket
|
||||
err := dc.MakeBucket("foo2", "private", nil, nil)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
// check bucket exists
|
||||
buckets, err := dc.ListBuckets()
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(len(buckets), Equals, 5)
|
||||
c.Assert(buckets[0].ACL, Equals, BucketACL("private"))
|
||||
}
|
||||
|
||||
// test re-create bucket
|
||||
func (s *MyCacheSuite) TestMakeBucketWithSameNameFails(c *C) {
|
||||
err := dc.MakeBucket("foo3", "private", nil, nil)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
err = dc.MakeBucket("foo3", "private", nil, nil)
|
||||
c.Assert(err, Not(IsNil))
|
||||
}
|
||||
|
||||
// test make multiple buckets
|
||||
func (s *MyCacheSuite) TestCreateMultipleBucketsAndList(c *C) {
|
||||
// add a second bucket
|
||||
err := dc.MakeBucket("foo4", "private", nil, nil)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
err = dc.MakeBucket("bar1", "private", nil, nil)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
buckets, err := dc.ListBuckets()
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
c.Assert(len(buckets), Equals, 2)
|
||||
c.Assert(buckets[0].Name, Equals, "bar1")
|
||||
c.Assert(buckets[1].Name, Equals, "foo4")
|
||||
|
||||
err = dc.MakeBucket("foobar1", "private", nil, nil)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
buckets, err = dc.ListBuckets()
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
c.Assert(len(buckets), Equals, 3)
|
||||
c.Assert(buckets[2].Name, Equals, "foobar1")
|
||||
}
|
||||
|
||||
// test object create without bucket
|
||||
func (s *MyCacheSuite) TestNewObjectFailsWithoutBucket(c *C) {
|
||||
_, err := dc.CreateObject("unknown", "obj", "", 0, nil, nil, nil)
|
||||
c.Assert(err, Not(IsNil))
|
||||
}
|
||||
|
||||
// test create object metadata
|
||||
func (s *MyCacheSuite) TestNewObjectMetadata(c *C) {
|
||||
data := "Hello World"
|
||||
hasher := md5.New()
|
||||
hasher.Write([]byte(data))
|
||||
expectedMd5Sum := base64.StdEncoding.EncodeToString(hasher.Sum(nil))
|
||||
reader := ioutil.NopCloser(bytes.NewReader([]byte(data)))
|
||||
|
||||
err := dc.MakeBucket("foo6", "private", nil, nil)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
objectMetadata, err := dc.CreateObject("foo6", "obj", expectedMd5Sum, int64(len(data)), reader, map[string]string{"contentType": "application/json"}, nil)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(objectMetadata.MD5Sum, Equals, hex.EncodeToString(hasher.Sum(nil)))
|
||||
c.Assert(objectMetadata.Metadata["contentType"], Equals, "application/json")
|
||||
}
|
||||
|
||||
// test create object fails without name
|
||||
func (s *MyCacheSuite) TestNewObjectFailsWithEmptyName(c *C) {
|
||||
_, err := dc.CreateObject("foo", "", "", 0, nil, nil, nil)
|
||||
c.Assert(err, Not(IsNil))
|
||||
}
|
||||
|
||||
// test create object
|
||||
func (s *MyCacheSuite) TestNewObjectCanBeWritten(c *C) {
|
||||
err := dc.MakeBucket("foo", "private", nil, nil)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
data := "Hello World"
|
||||
|
||||
hasher := md5.New()
|
||||
hasher.Write([]byte(data))
|
||||
expectedMd5Sum := base64.StdEncoding.EncodeToString(hasher.Sum(nil))
|
||||
reader := ioutil.NopCloser(bytes.NewReader([]byte(data)))
|
||||
|
||||
actualMetadata, err := dc.CreateObject("foo", "obj", expectedMd5Sum, int64(len(data)), reader, map[string]string{"contentType": "application/octet-stream"}, nil)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(actualMetadata.MD5Sum, Equals, hex.EncodeToString(hasher.Sum(nil)))
|
||||
|
||||
var buffer bytes.Buffer
|
||||
size, err := dc.GetObject(&buffer, "foo", "obj", 0, 0)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(size, Equals, int64(len(data)))
|
||||
c.Assert(buffer.Bytes(), DeepEquals, []byte(data))
|
||||
|
||||
actualMetadata, err = dc.GetObjectMetadata("foo", "obj")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(hex.EncodeToString(hasher.Sum(nil)), Equals, actualMetadata.MD5Sum)
|
||||
c.Assert(int64(len(data)), Equals, actualMetadata.Size)
|
||||
}
|
||||
|
||||
// test list objects
|
||||
func (s *MyCacheSuite) TestMultipleNewObjects(c *C) {
|
||||
c.Assert(dc.MakeBucket("foo5", "private", nil, nil), IsNil)
|
||||
|
||||
one := ioutil.NopCloser(bytes.NewReader([]byte("one")))
|
||||
|
||||
_, err := dc.CreateObject("foo5", "obj1", "", int64(len("one")), one, nil, nil)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
two := ioutil.NopCloser(bytes.NewReader([]byte("two")))
|
||||
_, err = dc.CreateObject("foo5", "obj2", "", int64(len("two")), two, nil, nil)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
var buffer1 bytes.Buffer
|
||||
size, err := dc.GetObject(&buffer1, "foo5", "obj1", 0, 0)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(size, Equals, int64(len([]byte("one"))))
|
||||
c.Assert(buffer1.Bytes(), DeepEquals, []byte("one"))
|
||||
|
||||
var buffer2 bytes.Buffer
|
||||
size, err = dc.GetObject(&buffer2, "foo5", "obj2", 0, 0)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(size, Equals, int64(len([]byte("two"))))
|
||||
|
||||
c.Assert(buffer2.Bytes(), DeepEquals, []byte("two"))
|
||||
|
||||
/// test list of objects
|
||||
|
||||
// test list objects with prefix and delimiter
|
||||
var resources BucketResourcesMetadata
|
||||
resources.Prefix = "o"
|
||||
resources.Delimiter = "1"
|
||||
resources.Maxkeys = 10
|
||||
objectsMetadata, resources, err := dc.ListObjects("foo5", resources)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(resources.IsTruncated, Equals, false)
|
||||
c.Assert(resources.CommonPrefixes[0], Equals, "obj1")
|
||||
|
||||
// test list objects with only delimiter
|
||||
resources.Prefix = ""
|
||||
resources.Delimiter = "1"
|
||||
resources.Maxkeys = 10
|
||||
objectsMetadata, resources, err = dc.ListObjects("foo5", resources)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(objectsMetadata[0].Object, Equals, "obj2")
|
||||
c.Assert(resources.IsTruncated, Equals, false)
|
||||
c.Assert(resources.CommonPrefixes[0], Equals, "obj1")
|
||||
|
||||
// test list objects with only prefix
|
||||
resources.Prefix = "o"
|
||||
resources.Delimiter = ""
|
||||
resources.Maxkeys = 10
|
||||
objectsMetadata, resources, err = dc.ListObjects("foo5", resources)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(resources.IsTruncated, Equals, false)
|
||||
c.Assert(objectsMetadata[0].Object, Equals, "obj1")
|
||||
c.Assert(objectsMetadata[1].Object, Equals, "obj2")
|
||||
|
||||
three := ioutil.NopCloser(bytes.NewReader([]byte("three")))
|
||||
_, err = dc.CreateObject("foo5", "obj3", "", int64(len("three")), three, nil, nil)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
var buffer bytes.Buffer
|
||||
size, err = dc.GetObject(&buffer, "foo5", "obj3", 0, 0)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(size, Equals, int64(len([]byte("three"))))
|
||||
c.Assert(buffer.Bytes(), DeepEquals, []byte("three"))
|
||||
|
||||
// test list objects with maxkeys
|
||||
resources.Prefix = "o"
|
||||
resources.Delimiter = ""
|
||||
resources.Maxkeys = 2
|
||||
objectsMetadata, resources, err = dc.ListObjects("foo5", resources)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(resources.IsTruncated, Equals, true)
|
||||
c.Assert(len(objectsMetadata), Equals, 2)
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package donut
|
||||
|
||||
import (
|
||||
encoding "github.com/minio/minio/pkg/erasure"
|
||||
"github.com/minio/minio/pkg/probe"
|
||||
)
|
||||
|
||||
// encoder internal struct
|
||||
type encoder struct {
|
||||
encoder *encoding.Erasure
|
||||
k, m uint8
|
||||
}
|
||||
|
||||
// newEncoder - instantiate a new encoder
|
||||
func newEncoder(k, m uint8) (encoder, *probe.Error) {
|
||||
e := encoder{}
|
||||
params, err := encoding.ValidateParams(k, m)
|
||||
if err != nil {
|
||||
return encoder{}, probe.NewError(err)
|
||||
}
|
||||
e.encoder = encoding.NewErasure(params)
|
||||
e.k = k
|
||||
e.m = m
|
||||
return e, nil
|
||||
}
|
||||
|
||||
// TODO - think again if this is needed
|
||||
// GetEncodedBlockLen - wrapper around erasure function with the same name
|
||||
func (e encoder) GetEncodedBlockLen(dataLength int) (int, *probe.Error) {
|
||||
if dataLength <= 0 {
|
||||
return 0, probe.NewError(InvalidArgument{})
|
||||
}
|
||||
return encoding.GetEncodedBlockLen(dataLength, e.k), nil
|
||||
}
|
||||
|
||||
// Encode - erasure code input bytes
|
||||
func (e encoder) Encode(data []byte) ([][]byte, *probe.Error) {
|
||||
if data == nil {
|
||||
return nil, probe.NewError(InvalidArgument{})
|
||||
}
|
||||
encodedData, err := e.encoder.Encode(data)
|
||||
if err != nil {
|
||||
return nil, probe.NewError(err)
|
||||
}
|
||||
return encodedData, nil
|
||||
}
|
||||
|
||||
// Decode - erasure decode input encoded bytes
|
||||
func (e encoder) Decode(encodedData [][]byte, dataLength int) ([]byte, *probe.Error) {
|
||||
decodedData, err := e.encoder.Decode(encodedData, dataLength)
|
||||
if err != nil {
|
||||
return nil, probe.NewError(err)
|
||||
}
|
||||
return decodedData, nil
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package donut
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/minio/minio/pkg/donut/disk"
|
||||
"github.com/minio/minio/pkg/probe"
|
||||
)
|
||||
|
||||
// healBuckets heal bucket slices
|
||||
func (donut API) healBuckets() *probe.Error {
|
||||
if err := donut.listDonutBuckets(); err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
bucketMetadata, err := donut.getDonutBucketMetadata()
|
||||
if err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
disks := make(map[int]disk.Disk)
|
||||
for _, node := range donut.nodes {
|
||||
nDisks, err := node.ListDisks()
|
||||
if err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
for k, v := range nDisks {
|
||||
disks[k] = v
|
||||
}
|
||||
}
|
||||
for order, disk := range disks {
|
||||
if disk.IsUsable() {
|
||||
disk.MakeDir(donut.config.DonutName)
|
||||
bucketMetadataWriter, err := disk.CreateFile(filepath.Join(donut.config.DonutName, bucketMetadataConfig))
|
||||
if err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
defer bucketMetadataWriter.Close()
|
||||
jenc := json.NewEncoder(bucketMetadataWriter)
|
||||
if err := jenc.Encode(bucketMetadata); err != nil {
|
||||
return probe.NewError(err)
|
||||
}
|
||||
for bucket := range bucketMetadata.Buckets {
|
||||
bucketSlice := fmt.Sprintf("%s$0$%d", bucket, order) // TODO handle node slices
|
||||
err := disk.MakeDir(filepath.Join(donut.config.DonutName, bucketSlice))
|
||||
if err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package donut
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/minio/minio/pkg/probe"
|
||||
signv4 "github.com/minio/minio/pkg/signature"
|
||||
)
|
||||
|
||||
// Collection of Donut specification interfaces
|
||||
|
||||
// Interface is a collection of cloud storage and management interface
|
||||
type Interface interface {
|
||||
CloudStorage
|
||||
Management
|
||||
}
|
||||
|
||||
// CloudStorage is a donut cloud storage interface
|
||||
type CloudStorage interface {
|
||||
// Storage service operations
|
||||
GetBucketMetadata(bucket string) (BucketMetadata, *probe.Error)
|
||||
SetBucketMetadata(bucket string, metadata map[string]string) *probe.Error
|
||||
ListBuckets() ([]BucketMetadata, *probe.Error)
|
||||
MakeBucket(bucket string, ACL string, location io.Reader, signature *signv4.Signature) *probe.Error
|
||||
|
||||
// Bucket operations
|
||||
ListObjects(string, BucketResourcesMetadata) ([]ObjectMetadata, BucketResourcesMetadata, *probe.Error)
|
||||
|
||||
// Object operations
|
||||
GetObject(w io.Writer, bucket, object string, start, length int64) (int64, *probe.Error)
|
||||
GetObjectMetadata(bucket, object string) (ObjectMetadata, *probe.Error)
|
||||
// bucket, object, expectedMD5Sum, size, reader, metadata, signature
|
||||
CreateObject(string, string, string, int64, io.Reader, map[string]string, *signv4.Signature) (ObjectMetadata, *probe.Error)
|
||||
|
||||
Multipart
|
||||
}
|
||||
|
||||
// Multipart API
|
||||
type Multipart interface {
|
||||
NewMultipartUpload(bucket, key, contentType string) (string, *probe.Error)
|
||||
AbortMultipartUpload(bucket, key, uploadID string) *probe.Error
|
||||
CreateObjectPart(string, string, string, int, string, string, int64, io.Reader, *signv4.Signature) (string, *probe.Error)
|
||||
CompleteMultipartUpload(bucket, key, uploadID string, data io.Reader, signature *signv4.Signature) (ObjectMetadata, *probe.Error)
|
||||
ListMultipartUploads(string, BucketMultipartResourcesMetadata) (BucketMultipartResourcesMetadata, *probe.Error)
|
||||
ListObjectParts(string, string, ObjectResourcesMetadata) (ObjectResourcesMetadata, *probe.Error)
|
||||
}
|
||||
|
||||
// Management is a donut management system interface
|
||||
type Management interface {
|
||||
Heal() *probe.Error
|
||||
Rebalance() *probe.Error
|
||||
Info() (map[string][]string, *probe.Error)
|
||||
|
||||
AttachNode(hostname string, disks []string) *probe.Error
|
||||
DetachNode(hostname string) *probe.Error
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package donut
|
||||
|
||||
import (
|
||||
"github.com/minio/minio/pkg/donut/disk"
|
||||
"github.com/minio/minio/pkg/probe"
|
||||
)
|
||||
|
||||
// Info - return info about donut configuration
|
||||
func (donut API) Info() (nodeDiskMap map[string][]string, err *probe.Error) {
|
||||
nodeDiskMap = make(map[string][]string)
|
||||
for nodeName, n := range donut.nodes {
|
||||
disks, err := n.ListDisks()
|
||||
if err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
diskList := make([]string, len(disks))
|
||||
for diskOrder, disk := range disks {
|
||||
diskList[diskOrder] = disk.GetPath()
|
||||
}
|
||||
nodeDiskMap[nodeName] = diskList
|
||||
}
|
||||
return nodeDiskMap, nil
|
||||
}
|
||||
|
||||
// AttachNode - attach node
|
||||
func (donut API) AttachNode(hostname string, disks []string) *probe.Error {
|
||||
if hostname == "" || len(disks) == 0 {
|
||||
return probe.NewError(InvalidArgument{})
|
||||
}
|
||||
n, err := newNode(hostname)
|
||||
if err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
donut.nodes[hostname] = n
|
||||
for i, d := range disks {
|
||||
newDisk, err := disk.New(d)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if err := newDisk.MakeDir(donut.config.DonutName); err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
if err := n.AttachDisk(newDisk, i); err != nil {
|
||||
return err.Trace()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DetachNode - detach node
|
||||
func (donut API) DetachNode(hostname string) *probe.Error {
|
||||
delete(donut.nodes, hostname)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Rebalance - rebalance an existing donut with new disks and nodes
|
||||
func (donut API) Rebalance() *probe.Error {
|
||||
return probe.NewError(APINotImplemented{API: "management.Rebalance"})
|
||||
}
|
||||
|
||||
// Heal - heal your donuts
|
||||
func (donut API) Heal() *probe.Error {
|
||||
// TODO handle data heal
|
||||
return donut.healBuckets()
|
||||
}
|
||||
@@ -1,513 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package donut
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"crypto/sha512"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/xml"
|
||||
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"runtime/debug"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/minio/minio/pkg/crypto/sha256"
|
||||
"github.com/minio/minio/pkg/donut/cache/data"
|
||||
"github.com/minio/minio/pkg/probe"
|
||||
signv4 "github.com/minio/minio/pkg/signature"
|
||||
)
|
||||
|
||||
/// V2 API functions
|
||||
|
||||
// NewMultipartUpload - initiate a new multipart session
|
||||
func (donut API) NewMultipartUpload(bucket, key, contentType string) (string, *probe.Error) {
|
||||
donut.lock.Lock()
|
||||
defer donut.lock.Unlock()
|
||||
|
||||
if !IsValidBucket(bucket) {
|
||||
return "", probe.NewError(BucketNameInvalid{Bucket: bucket})
|
||||
}
|
||||
if !IsValidObjectName(key) {
|
||||
return "", probe.NewError(ObjectNameInvalid{Object: key})
|
||||
}
|
||||
// if len(donut.config.NodeDiskMap) > 0 {
|
||||
// return donut.newMultipartUpload(bucket, key, contentType)
|
||||
// }
|
||||
if !donut.storedBuckets.Exists(bucket) {
|
||||
return "", probe.NewError(BucketNotFound{Bucket: bucket})
|
||||
}
|
||||
storedBucket := donut.storedBuckets.Get(bucket).(storedBucket)
|
||||
objectKey := bucket + "/" + key
|
||||
if _, ok := storedBucket.objectMetadata[objectKey]; ok == true {
|
||||
return "", probe.NewError(ObjectExists{Object: key})
|
||||
}
|
||||
id := []byte(strconv.Itoa(rand.Int()) + bucket + key + time.Now().UTC().String())
|
||||
uploadIDSum := sha512.Sum512(id)
|
||||
uploadID := base64.URLEncoding.EncodeToString(uploadIDSum[:])[:47]
|
||||
|
||||
storedBucket.multiPartSession[key] = MultiPartSession{
|
||||
UploadID: uploadID,
|
||||
Initiated: time.Now().UTC(),
|
||||
TotalParts: 0,
|
||||
}
|
||||
storedBucket.partMetadata[key] = make(map[int]PartMetadata)
|
||||
multiPartCache := data.NewCache(0)
|
||||
multiPartCache.OnEvicted = donut.evictedPart
|
||||
donut.multiPartObjects[uploadID] = multiPartCache
|
||||
donut.storedBuckets.Set(bucket, storedBucket)
|
||||
return uploadID, nil
|
||||
}
|
||||
|
||||
// AbortMultipartUpload - abort an incomplete multipart session
|
||||
func (donut API) AbortMultipartUpload(bucket, key, uploadID string) *probe.Error {
|
||||
donut.lock.Lock()
|
||||
defer donut.lock.Unlock()
|
||||
|
||||
if !IsValidBucket(bucket) {
|
||||
return probe.NewError(BucketNameInvalid{Bucket: bucket})
|
||||
}
|
||||
if !IsValidObjectName(key) {
|
||||
return probe.NewError(ObjectNameInvalid{Object: key})
|
||||
}
|
||||
// TODO: multipart support for donut is broken, since we haven't finalized the format in which
|
||||
// it can be stored, disabling this for now until we get the underlying layout stable.
|
||||
//
|
||||
// if len(donut.config.NodeDiskMap) > 0 {
|
||||
// return donut.abortMultipartUpload(bucket, key, uploadID)
|
||||
// }
|
||||
if !donut.storedBuckets.Exists(bucket) {
|
||||
return probe.NewError(BucketNotFound{Bucket: bucket})
|
||||
}
|
||||
storedBucket := donut.storedBuckets.Get(bucket).(storedBucket)
|
||||
if storedBucket.multiPartSession[key].UploadID != uploadID {
|
||||
return probe.NewError(InvalidUploadID{UploadID: uploadID})
|
||||
}
|
||||
donut.cleanupMultipartSession(bucket, key, uploadID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateObjectPart - create a part in a multipart session
|
||||
func (donut API) CreateObjectPart(bucket, key, uploadID string, partID int, contentType, expectedMD5Sum string, size int64, data io.Reader, signature *signv4.Signature) (string, *probe.Error) {
|
||||
donut.lock.Lock()
|
||||
etag, err := donut.createObjectPart(bucket, key, uploadID, partID, "", expectedMD5Sum, size, data, signature)
|
||||
donut.lock.Unlock()
|
||||
// possible free
|
||||
debug.FreeOSMemory()
|
||||
|
||||
return etag, err.Trace()
|
||||
}
|
||||
|
||||
// createObject - internal wrapper function called by CreateObjectPart
|
||||
func (donut API) createObjectPart(bucket, key, uploadID string, partID int, contentType, expectedMD5Sum string, size int64, data io.Reader, signature *signv4.Signature) (string, *probe.Error) {
|
||||
if !IsValidBucket(bucket) {
|
||||
return "", probe.NewError(BucketNameInvalid{Bucket: bucket})
|
||||
}
|
||||
if !IsValidObjectName(key) {
|
||||
return "", probe.NewError(ObjectNameInvalid{Object: key})
|
||||
}
|
||||
// TODO: multipart support for donut is broken, since we haven't finalized the format in which
|
||||
// it can be stored, disabling this for now until we get the underlying layout stable.
|
||||
//
|
||||
/*
|
||||
if len(donut.config.NodeDiskMap) > 0 {
|
||||
metadata := make(map[string]string)
|
||||
if contentType == "" {
|
||||
contentType = "application/octet-stream"
|
||||
}
|
||||
contentType = strings.TrimSpace(contentType)
|
||||
metadata["contentType"] = contentType
|
||||
if strings.TrimSpace(expectedMD5Sum) != "" {
|
||||
expectedMD5SumBytes, err := base64.StdEncoding.DecodeString(strings.TrimSpace(expectedMD5Sum))
|
||||
if err != nil {
|
||||
// pro-actively close the connection
|
||||
return "", probe.NewError(InvalidDigest{Md5: expectedMD5Sum})
|
||||
}
|
||||
expectedMD5Sum = hex.EncodeToString(expectedMD5SumBytes)
|
||||
}
|
||||
partMetadata, err := donut.putObjectPart(bucket, key, expectedMD5Sum, uploadID, partID, data, size, metadata, signature)
|
||||
if err != nil {
|
||||
return "", err.Trace()
|
||||
}
|
||||
return partMetadata.ETag, nil
|
||||
}
|
||||
*/
|
||||
if !donut.storedBuckets.Exists(bucket) {
|
||||
return "", probe.NewError(BucketNotFound{Bucket: bucket})
|
||||
}
|
||||
strBucket := donut.storedBuckets.Get(bucket).(storedBucket)
|
||||
// Verify upload id
|
||||
if strBucket.multiPartSession[key].UploadID != uploadID {
|
||||
return "", probe.NewError(InvalidUploadID{UploadID: uploadID})
|
||||
}
|
||||
|
||||
// get object key
|
||||
parts := strBucket.partMetadata[key]
|
||||
if _, ok := parts[partID]; ok {
|
||||
return parts[partID].ETag, nil
|
||||
}
|
||||
|
||||
if contentType == "" {
|
||||
contentType = "application/octet-stream"
|
||||
}
|
||||
contentType = strings.TrimSpace(contentType)
|
||||
if strings.TrimSpace(expectedMD5Sum) != "" {
|
||||
expectedMD5SumBytes, err := base64.StdEncoding.DecodeString(strings.TrimSpace(expectedMD5Sum))
|
||||
if err != nil {
|
||||
// pro-actively close the connection
|
||||
return "", probe.NewError(InvalidDigest{Md5: expectedMD5Sum})
|
||||
}
|
||||
expectedMD5Sum = hex.EncodeToString(expectedMD5SumBytes)
|
||||
}
|
||||
|
||||
// calculate md5
|
||||
hash := md5.New()
|
||||
sha256hash := sha256.New()
|
||||
|
||||
var totalLength int64
|
||||
var err error
|
||||
for err == nil {
|
||||
var length int
|
||||
byteBuffer := make([]byte, 1024*1024)
|
||||
length, err = data.Read(byteBuffer) // do not read error return error here, we will handle this error later
|
||||
if length != 0 {
|
||||
hash.Write(byteBuffer[0:length])
|
||||
sha256hash.Write(byteBuffer[0:length])
|
||||
ok := donut.multiPartObjects[uploadID].Append(partID, byteBuffer[0:length])
|
||||
if !ok {
|
||||
return "", probe.NewError(InternalError{})
|
||||
}
|
||||
totalLength += int64(length)
|
||||
go debug.FreeOSMemory()
|
||||
}
|
||||
}
|
||||
if totalLength != size {
|
||||
donut.multiPartObjects[uploadID].Delete(partID)
|
||||
return "", probe.NewError(IncompleteBody{Bucket: bucket, Object: key})
|
||||
}
|
||||
if err != io.EOF {
|
||||
return "", probe.NewError(err)
|
||||
}
|
||||
|
||||
md5SumBytes := hash.Sum(nil)
|
||||
md5Sum := hex.EncodeToString(md5SumBytes)
|
||||
// Verify if the written object is equal to what is expected, only if it is requested as such
|
||||
if strings.TrimSpace(expectedMD5Sum) != "" {
|
||||
if err := isMD5SumEqual(strings.TrimSpace(expectedMD5Sum), md5Sum); err != nil {
|
||||
return "", err.Trace()
|
||||
}
|
||||
}
|
||||
|
||||
if signature != nil {
|
||||
{
|
||||
ok, err := signature.DoesSignatureMatch(hex.EncodeToString(sha256hash.Sum(nil)))
|
||||
if err != nil {
|
||||
return "", err.Trace()
|
||||
}
|
||||
if !ok {
|
||||
return "", probe.NewError(signv4.DoesNotMatch{})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newPart := PartMetadata{
|
||||
PartNumber: partID,
|
||||
LastModified: time.Now().UTC(),
|
||||
ETag: md5Sum,
|
||||
Size: totalLength,
|
||||
}
|
||||
|
||||
parts[partID] = newPart
|
||||
strBucket.partMetadata[key] = parts
|
||||
multiPartSession := strBucket.multiPartSession[key]
|
||||
multiPartSession.TotalParts++
|
||||
strBucket.multiPartSession[key] = multiPartSession
|
||||
donut.storedBuckets.Set(bucket, strBucket)
|
||||
return md5Sum, nil
|
||||
}
|
||||
|
||||
// cleanupMultipartSession invoked during an abort or complete multipart session to cleanup session from memory
|
||||
func (donut API) cleanupMultipartSession(bucket, key, uploadID string) {
|
||||
storedBucket := donut.storedBuckets.Get(bucket).(storedBucket)
|
||||
for i := 1; i <= storedBucket.multiPartSession[key].TotalParts; i++ {
|
||||
donut.multiPartObjects[uploadID].Delete(i)
|
||||
}
|
||||
delete(storedBucket.multiPartSession, key)
|
||||
delete(storedBucket.partMetadata, key)
|
||||
donut.storedBuckets.Set(bucket, storedBucket)
|
||||
}
|
||||
|
||||
func (donut API) mergeMultipart(parts *CompleteMultipartUpload, uploadID string, fullObjectWriter *io.PipeWriter) {
|
||||
for _, part := range parts.Part {
|
||||
recvMD5 := part.ETag
|
||||
object, ok := donut.multiPartObjects[uploadID].Get(part.PartNumber)
|
||||
if ok == false {
|
||||
fullObjectWriter.CloseWithError(probe.WrapError(probe.NewError(InvalidPart{})))
|
||||
return
|
||||
}
|
||||
calcMD5Bytes := md5.Sum(object)
|
||||
// complete multi part request header md5sum per part is hex encoded
|
||||
recvMD5Bytes, err := hex.DecodeString(strings.Trim(recvMD5, "\""))
|
||||
if err != nil {
|
||||
fullObjectWriter.CloseWithError(probe.WrapError(probe.NewError(InvalidDigest{Md5: recvMD5})))
|
||||
return
|
||||
}
|
||||
if !bytes.Equal(recvMD5Bytes, calcMD5Bytes[:]) {
|
||||
fullObjectWriter.CloseWithError(probe.WrapError(probe.NewError(BadDigest{})))
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := io.Copy(fullObjectWriter, bytes.NewReader(object)); err != nil {
|
||||
fullObjectWriter.CloseWithError(probe.WrapError(probe.NewError(err)))
|
||||
return
|
||||
}
|
||||
object = nil
|
||||
}
|
||||
fullObjectWriter.Close()
|
||||
return
|
||||
}
|
||||
|
||||
// CompleteMultipartUpload - complete a multipart upload and persist the data
|
||||
func (donut API) CompleteMultipartUpload(bucket, key, uploadID string, data io.Reader, signature *signv4.Signature) (ObjectMetadata, *probe.Error) {
|
||||
donut.lock.Lock()
|
||||
defer donut.lock.Unlock()
|
||||
size := int64(donut.multiPartObjects[uploadID].Stats().Bytes)
|
||||
fullObjectReader, err := donut.completeMultipartUploadV2(bucket, key, uploadID, data, signature)
|
||||
if err != nil {
|
||||
return ObjectMetadata{}, err.Trace()
|
||||
}
|
||||
objectMetadata, err := donut.createObject(bucket, key, "", "", size, fullObjectReader, nil)
|
||||
if err != nil {
|
||||
// No need to call internal cleanup functions here, caller should call AbortMultipartUpload()
|
||||
// which would in-turn cleanup properly in accordance with S3 Spec
|
||||
return ObjectMetadata{}, err.Trace()
|
||||
}
|
||||
donut.cleanupMultipartSession(bucket, key, uploadID)
|
||||
return objectMetadata, nil
|
||||
}
|
||||
|
||||
func (donut API) completeMultipartUploadV2(bucket, key, uploadID string, data io.Reader, signature *signv4.Signature) (io.Reader, *probe.Error) {
|
||||
if !IsValidBucket(bucket) {
|
||||
return nil, probe.NewError(BucketNameInvalid{Bucket: bucket})
|
||||
}
|
||||
if !IsValidObjectName(key) {
|
||||
return nil, probe.NewError(ObjectNameInvalid{Object: key})
|
||||
}
|
||||
|
||||
// TODO: multipart support for donut is broken, since we haven't finalized the format in which
|
||||
// it can be stored, disabling this for now until we get the underlying layout stable.
|
||||
//
|
||||
// if len(donut.config.NodeDiskMap) > 0 {
|
||||
// donut.lock.Unlock()
|
||||
// return donut.completeMultipartUpload(bucket, key, uploadID, data, signature)
|
||||
// }
|
||||
|
||||
if !donut.storedBuckets.Exists(bucket) {
|
||||
return nil, probe.NewError(BucketNotFound{Bucket: bucket})
|
||||
}
|
||||
storedBucket := donut.storedBuckets.Get(bucket).(storedBucket)
|
||||
// Verify upload id
|
||||
if storedBucket.multiPartSession[key].UploadID != uploadID {
|
||||
return nil, probe.NewError(InvalidUploadID{UploadID: uploadID})
|
||||
}
|
||||
partBytes, err := ioutil.ReadAll(data)
|
||||
if err != nil {
|
||||
return nil, probe.NewError(err)
|
||||
}
|
||||
if signature != nil {
|
||||
ok, err := signature.DoesSignatureMatch(hex.EncodeToString(sha256.Sum256(partBytes)[:]))
|
||||
if err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
if !ok {
|
||||
return nil, probe.NewError(signv4.DoesNotMatch{})
|
||||
}
|
||||
}
|
||||
parts := &CompleteMultipartUpload{}
|
||||
if err := xml.Unmarshal(partBytes, parts); err != nil {
|
||||
return nil, probe.NewError(MalformedXML{})
|
||||
}
|
||||
if !sort.IsSorted(completedParts(parts.Part)) {
|
||||
return nil, probe.NewError(InvalidPartOrder{})
|
||||
}
|
||||
|
||||
fullObjectReader, fullObjectWriter := io.Pipe()
|
||||
go donut.mergeMultipart(parts, uploadID, fullObjectWriter)
|
||||
|
||||
return fullObjectReader, nil
|
||||
}
|
||||
|
||||
// byKey is a sortable interface for UploadMetadata slice
|
||||
type byKey []*UploadMetadata
|
||||
|
||||
func (a byKey) Len() int { return len(a) }
|
||||
func (a byKey) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a byKey) Less(i, j int) bool { return a[i].Key < a[j].Key }
|
||||
|
||||
// ListMultipartUploads - list incomplete multipart sessions for a given bucket
|
||||
func (donut API) ListMultipartUploads(bucket string, resources BucketMultipartResourcesMetadata) (BucketMultipartResourcesMetadata, *probe.Error) {
|
||||
// TODO handle delimiter, low priority
|
||||
donut.lock.Lock()
|
||||
defer donut.lock.Unlock()
|
||||
|
||||
if !IsValidBucket(bucket) {
|
||||
return BucketMultipartResourcesMetadata{}, probe.NewError(BucketNameInvalid{Bucket: bucket})
|
||||
}
|
||||
|
||||
// TODO: multipart support for donut is broken, since we haven't finalized the format in which
|
||||
// it can be stored, disabling this for now until we get the underlying layout stable.
|
||||
//
|
||||
// if len(donut.config.NodeDiskMap) > 0 {
|
||||
// return donut.listMultipartUploads(bucket, resources)
|
||||
// }
|
||||
|
||||
if !donut.storedBuckets.Exists(bucket) {
|
||||
return BucketMultipartResourcesMetadata{}, probe.NewError(BucketNotFound{Bucket: bucket})
|
||||
}
|
||||
|
||||
storedBucket := donut.storedBuckets.Get(bucket).(storedBucket)
|
||||
var uploads []*UploadMetadata
|
||||
|
||||
for key, session := range storedBucket.multiPartSession {
|
||||
if strings.HasPrefix(key, resources.Prefix) {
|
||||
if len(uploads) > resources.MaxUploads {
|
||||
sort.Sort(byKey(uploads))
|
||||
resources.Upload = uploads
|
||||
resources.NextKeyMarker = key
|
||||
resources.NextUploadIDMarker = session.UploadID
|
||||
resources.IsTruncated = true
|
||||
return resources, nil
|
||||
}
|
||||
// uploadIDMarker is ignored if KeyMarker is empty
|
||||
switch {
|
||||
case resources.KeyMarker != "" && resources.UploadIDMarker == "":
|
||||
if key > resources.KeyMarker {
|
||||
upload := new(UploadMetadata)
|
||||
upload.Key = key
|
||||
upload.UploadID = session.UploadID
|
||||
upload.Initiated = session.Initiated
|
||||
uploads = append(uploads, upload)
|
||||
}
|
||||
case resources.KeyMarker != "" && resources.UploadIDMarker != "":
|
||||
if session.UploadID > resources.UploadIDMarker {
|
||||
if key >= resources.KeyMarker {
|
||||
upload := new(UploadMetadata)
|
||||
upload.Key = key
|
||||
upload.UploadID = session.UploadID
|
||||
upload.Initiated = session.Initiated
|
||||
uploads = append(uploads, upload)
|
||||
}
|
||||
}
|
||||
default:
|
||||
upload := new(UploadMetadata)
|
||||
upload.Key = key
|
||||
upload.UploadID = session.UploadID
|
||||
upload.Initiated = session.Initiated
|
||||
uploads = append(uploads, upload)
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.Sort(byKey(uploads))
|
||||
resources.Upload = uploads
|
||||
return resources, nil
|
||||
}
|
||||
|
||||
// partNumber is a sortable interface for Part slice
|
||||
type partNumber []*PartMetadata
|
||||
|
||||
func (a partNumber) Len() int { return len(a) }
|
||||
func (a partNumber) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a partNumber) Less(i, j int) bool { return a[i].PartNumber < a[j].PartNumber }
|
||||
|
||||
// ListObjectParts - list parts from incomplete multipart session for a given object
|
||||
func (donut API) ListObjectParts(bucket, key string, resources ObjectResourcesMetadata) (ObjectResourcesMetadata, *probe.Error) {
|
||||
// Verify upload id
|
||||
donut.lock.Lock()
|
||||
defer donut.lock.Unlock()
|
||||
|
||||
if !IsValidBucket(bucket) {
|
||||
return ObjectResourcesMetadata{}, probe.NewError(BucketNameInvalid{Bucket: bucket})
|
||||
}
|
||||
if !IsValidObjectName(key) {
|
||||
return ObjectResourcesMetadata{}, probe.NewError(ObjectNameInvalid{Object: key})
|
||||
}
|
||||
|
||||
// TODO: multipart support for donut is broken, since we haven't finalized the format in which
|
||||
// it can be stored, disabling this for now until we get the underlying layout stable.
|
||||
//
|
||||
// if len(donut.config.NodeDiskMap) > 0 {
|
||||
// return donut.listObjectParts(bucket, key, resources)
|
||||
// }
|
||||
|
||||
if !donut.storedBuckets.Exists(bucket) {
|
||||
return ObjectResourcesMetadata{}, probe.NewError(BucketNotFound{Bucket: bucket})
|
||||
}
|
||||
storedBucket := donut.storedBuckets.Get(bucket).(storedBucket)
|
||||
if _, ok := storedBucket.multiPartSession[key]; ok == false {
|
||||
return ObjectResourcesMetadata{}, probe.NewError(ObjectNotFound{Object: key})
|
||||
}
|
||||
if storedBucket.multiPartSession[key].UploadID != resources.UploadID {
|
||||
return ObjectResourcesMetadata{}, probe.NewError(InvalidUploadID{UploadID: resources.UploadID})
|
||||
}
|
||||
storedParts := storedBucket.partMetadata[key]
|
||||
objectResourcesMetadata := resources
|
||||
objectResourcesMetadata.Bucket = bucket
|
||||
objectResourcesMetadata.Key = key
|
||||
var parts []*PartMetadata
|
||||
var startPartNumber int
|
||||
switch {
|
||||
case objectResourcesMetadata.PartNumberMarker == 0:
|
||||
startPartNumber = 1
|
||||
default:
|
||||
startPartNumber = objectResourcesMetadata.PartNumberMarker
|
||||
}
|
||||
for i := startPartNumber; i <= storedBucket.multiPartSession[key].TotalParts; i++ {
|
||||
if len(parts) > objectResourcesMetadata.MaxParts {
|
||||
sort.Sort(partNumber(parts))
|
||||
objectResourcesMetadata.IsTruncated = true
|
||||
objectResourcesMetadata.Part = parts
|
||||
objectResourcesMetadata.NextPartNumberMarker = i
|
||||
return objectResourcesMetadata, nil
|
||||
}
|
||||
part, ok := storedParts[i]
|
||||
if !ok {
|
||||
return ObjectResourcesMetadata{}, probe.NewError(InvalidPart{})
|
||||
}
|
||||
parts = append(parts, &part)
|
||||
}
|
||||
sort.Sort(partNumber(parts))
|
||||
objectResourcesMetadata.Part = parts
|
||||
return objectResourcesMetadata, nil
|
||||
}
|
||||
|
||||
// evictedPart - call back function called by caching module during individual cache evictions
|
||||
func (donut API) evictedPart(a ...interface{}) {
|
||||
// loop through all buckets
|
||||
buckets := donut.storedBuckets.GetAll()
|
||||
for bucketName, bucket := range buckets {
|
||||
b := bucket.(storedBucket)
|
||||
donut.storedBuckets.Set(bucketName, b)
|
||||
}
|
||||
debug.FreeOSMemory()
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package donut
|
||||
|
||||
import (
|
||||
"github.com/minio/minio/pkg/donut/disk"
|
||||
"github.com/minio/minio/pkg/probe"
|
||||
)
|
||||
|
||||
// node struct internal
|
||||
type node struct {
|
||||
hostname string
|
||||
disks map[int]disk.Disk
|
||||
}
|
||||
|
||||
// newNode - instantiates a new node
|
||||
func newNode(hostname string) (node, *probe.Error) {
|
||||
if hostname == "" {
|
||||
return node{}, probe.NewError(InvalidArgument{})
|
||||
}
|
||||
disks := make(map[int]disk.Disk)
|
||||
n := node{
|
||||
hostname: hostname,
|
||||
disks: disks,
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// GetHostname - return hostname
|
||||
func (n node) GetHostname() string {
|
||||
return n.hostname
|
||||
}
|
||||
|
||||
// ListDisks - return number of disks
|
||||
func (n node) ListDisks() (map[int]disk.Disk, *probe.Error) {
|
||||
return n.disks, nil
|
||||
}
|
||||
|
||||
// AttachDisk - attach a disk
|
||||
func (n node) AttachDisk(disk disk.Disk, diskOrder int) *probe.Error {
|
||||
if diskOrder < 0 {
|
||||
return probe.NewError(InvalidArgument{})
|
||||
}
|
||||
n.disks[diskOrder] = disk
|
||||
return nil
|
||||
}
|
||||
|
||||
// DetachDisk - detach a disk
|
||||
func (n node) DetachDisk(diskOrder int) *probe.Error {
|
||||
delete(n.disks, diskOrder)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SaveConfig - save node configuration
|
||||
func (n node) SaveConfig() *probe.Error {
|
||||
return probe.NewError(NotImplemented{Function: "SaveConfig"})
|
||||
}
|
||||
|
||||
// LoadConfig - load node configuration from saved configs
|
||||
func (n node) LoadConfig() *probe.Error {
|
||||
return probe.NewError(NotImplemented{Function: "LoadConfig"})
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
*.syso
|
||||
@@ -1,64 +0,0 @@
|
||||
## Ubuntu (Kylin) 14.04
|
||||
### Build Dependencies
|
||||
This installation document assumes Ubuntu 14.04+ on x86-64 platform.
|
||||
|
||||
##### Install Git, GCC, yasm
|
||||
```sh
|
||||
$ sudo apt-get install git build-essential yasm
|
||||
```
|
||||
|
||||
##### Install Go 1.5+
|
||||
|
||||
Download Go 1.5+ from [https://golang.org/dl/](https://golang.org/dl/).
|
||||
|
||||
```sh
|
||||
$ wget https://storage.googleapis.com/golang/go1.5.linux-amd64.tar.gz
|
||||
$ mkdir -p ${HOME}/bin/
|
||||
$ mkdir -p ${HOME}/go/
|
||||
$ tar -C ${HOME}/bin/ -xzf go1.5.linux-amd64.tar.gz
|
||||
```
|
||||
##### Setup GOROOT and GOPATH
|
||||
|
||||
Add the following exports to your ``~/.bashrc``. Environment variable GOROOT specifies the location of your golang binaries
|
||||
and GOPATH specifies the location of your project workspace.
|
||||
|
||||
```sh
|
||||
$ export GOROOT=${HOME}/bin/go
|
||||
$ export GOPATH=${HOME}/go
|
||||
$ export PATH=$PATH:${HOME}/bin/go/bin:${GOPATH}/bin
|
||||
```
|
||||
|
||||
## OS X (Yosemite) 10.10
|
||||
### Build Dependencies
|
||||
This installation document assumes OS X Yosemite 10.10+ on x86-64 platform.
|
||||
|
||||
##### Install brew
|
||||
```sh
|
||||
$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
|
||||
```
|
||||
|
||||
##### Install Git, Python
|
||||
```sh
|
||||
$ brew install git python yasm
|
||||
```
|
||||
|
||||
##### Install Go 1.5+
|
||||
|
||||
Install golang binaries using `brew`
|
||||
|
||||
```sh
|
||||
$ brew install go
|
||||
$ mkdir -p $HOME/go
|
||||
```
|
||||
|
||||
##### Setup GOROOT and GOPATH
|
||||
|
||||
Add the following exports to your ``~/.bashrc``. Environment variable GOROOT specifies the location of your golang binaries
|
||||
and GOPATH specifies the location of your project workspace.
|
||||
|
||||
```sh
|
||||
$ export GOPATH=${HOME}/go
|
||||
$ export GOVERSION=$(brew list go | head -n 1 | cut -d '/' -f 6)
|
||||
$ export GOROOT=$(brew --prefix)/Cellar/go/${GOVERSION}/libexec
|
||||
$ export PATH=$PATH:${GOPATH}/bin
|
||||
```
|
||||
@@ -1,26 +0,0 @@
|
||||
Copyright(c) 2011-2014 Intel Corporation All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Intel Corporation nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -1,202 +0,0 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -1,25 +0,0 @@
|
||||
## Introduction
|
||||
|
||||
Erasure is an open source Golang library written on top of ISAL (Intel Intelligent Storage Library) released under [Apache license v2](./LICENSE)
|
||||
|
||||
### Developers
|
||||
* [Get Source](./CONTRIBUTING.md)
|
||||
* [Build Dependencies](./BUILDDEPS.md)
|
||||
* [Development Workflow](./CONTRIBUTING.md#developer-guidelines)
|
||||
* [Developer discussions and bugs](https://github.com/minio/minio/issues)
|
||||
|
||||
### Supported platforms
|
||||
|
||||
| Name | Supported |
|
||||
| ------------- | ------------- |
|
||||
| Linux | Yes |
|
||||
| Windows | Not yet |
|
||||
| Mac OSX | Yes |
|
||||
|
||||
### Supported architectures
|
||||
|
||||
| Arch | Supported |
|
||||
| ------------- | ------------- |
|
||||
| x86-64 | Yes |
|
||||
| arm64 | Not yet|
|
||||
| i386 | Never |
|
||||
@@ -1,49 +0,0 @@
|
||||
================================================================================
|
||||
v2.10 Intel Intelligent Storage Acceleration Library Release Notes
|
||||
Open Source Version
|
||||
================================================================================
|
||||
|
||||
================================================================================
|
||||
RELEASE NOTE CONTENTS
|
||||
================================================================================
|
||||
1. KNOWN ISSUES
|
||||
2. FIXED ISSUES
|
||||
3. CHANGE LOG & FEATURES ADDED
|
||||
|
||||
================================================================================
|
||||
1. KNOWN ISSUES
|
||||
================================================================================
|
||||
|
||||
* Only erasure code unit included in open source version at this time.
|
||||
|
||||
* Perf tests do not run in Windows environment.
|
||||
|
||||
* Leaving <unit>/bin directories from builds in unit directories will cause the
|
||||
top-level make build to fail. Build only in top-level or ensure unit
|
||||
directories are clean of objects and /bin.
|
||||
|
||||
* 32-bit lib is not supported in Windows.
|
||||
|
||||
================================================================================
|
||||
2. FIXED ISSUES
|
||||
================================================================================
|
||||
v2.10
|
||||
|
||||
* Fix for windows register save overlap in gf_{3-6}vect_dot_prod_sse.asm. Only
|
||||
affects windows versions of erasure code. GP register saves/restore were
|
||||
pushed to same stack area as XMM.
|
||||
|
||||
================================================================================
|
||||
3. CHANGE LOG & FEATURES ADDED
|
||||
================================================================================
|
||||
v2.10
|
||||
|
||||
* Erasure code updates
|
||||
- New AVX and AVX2 support functions.
|
||||
- Changes min len requirement on gf_vect_dot_prod() to 32 from 16.
|
||||
- Tests include both source and parity recovery with ec_encode_data().
|
||||
- New encoding examples with Vandermonde or Cauchy matrix.
|
||||
|
||||
v2.8
|
||||
|
||||
* First open release of erasure code unit that is part of ISA-L.
|
||||
@@ -1,3 +0,0 @@
|
||||
v1.0 - Erasure Golang Package
|
||||
============================
|
||||
- First release, supports only amd64 or x86-64 architecture
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2014 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package erasure
|
||||
|
||||
// #include <stdint.h>
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// intSlice2CIntArray converts Go int slice to C int array
|
||||
func intSlice2CIntArray(srcErrList []int) *C.int32_t {
|
||||
if len(srcErrList) == 0 {
|
||||
return (*C.int32_t)(unsafe.Pointer(nil))
|
||||
}
|
||||
var sizeErrInt = int(unsafe.Sizeof(srcErrList[0]))
|
||||
switch sizeInt {
|
||||
case sizeErrInt:
|
||||
return (*C.int32_t)(unsafe.Pointer(&srcErrList[0]))
|
||||
case sizeInt8:
|
||||
int8Array := make([]int8, len(srcErrList))
|
||||
for i, v := range srcErrList {
|
||||
int8Array[i] = int8(v)
|
||||
}
|
||||
return (*C.int32_t)(unsafe.Pointer(&int8Array[0]))
|
||||
case sizeInt16:
|
||||
int16Array := make([]int16, len(srcErrList))
|
||||
for i, v := range srcErrList {
|
||||
int16Array[i] = int16(v)
|
||||
}
|
||||
return (*C.int32_t)(unsafe.Pointer(&int16Array[0]))
|
||||
case sizeInt32:
|
||||
int32Array := make([]int32, len(srcErrList))
|
||||
for i, v := range srcErrList {
|
||||
int32Array[i] = int32(v)
|
||||
}
|
||||
return (*C.int32_t)(unsafe.Pointer(&int32Array[0]))
|
||||
case sizeInt64:
|
||||
int64Array := make([]int64, len(srcErrList))
|
||||
for i, v := range srcErrList {
|
||||
int64Array[i] = int64(v)
|
||||
}
|
||||
return (*C.int32_t)(unsafe.Pointer(&int64Array[0]))
|
||||
default:
|
||||
panic(fmt.Sprintf("Unsupported: %d", sizeInt))
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
// Package erasure is a Go wrapper for the Intel Intelligent Storage
|
||||
// Acceleration Library (Intel ISA-L). Intel ISA-L is a CPU optimized
|
||||
// implementation of erasure coding algorithms.
|
||||
//
|
||||
// For more information on Intel ISA-L, please visit:
|
||||
// https://01.org/intel%C2%AE-storage-acceleration-library-open-source-version
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// Encode encodes a block of data. The input is the original data. The output
|
||||
// is a 2 tuple containing (k + m) chunks of erasure encoded data and the
|
||||
// length of the original object.
|
||||
//
|
||||
// Decode decodes 2 tuple data containing (k + m) chunks back into its original form.
|
||||
// Additionally original block length should also be provided as input.
|
||||
//
|
||||
// Decoded data is exactly similar in length and content as the original data.
|
||||
//
|
||||
// Encoding data may be performed in 3 steps.
|
||||
//
|
||||
// 1. Create a parse set of encoder parameters
|
||||
// 2. Create a new encoder
|
||||
// 3. Encode data
|
||||
//
|
||||
// Decoding data is also performed in 3 steps.
|
||||
//
|
||||
// 1. Create a parse set of encoder parameters for validation
|
||||
// 2. Create a new encoder
|
||||
// 3. Decode data
|
||||
//
|
||||
// Erasure parameters contain three configurable elements:
|
||||
// ValidateParams(k, m, technique int) (ErasureParams, error)
|
||||
// k - Number of rows in matrix
|
||||
// m - Number of colums in matrix
|
||||
// technique - Matrix type, can be either Cauchy (recommended) or Vandermonde
|
||||
// constraints: k + m < Galois Field (2^8)
|
||||
//
|
||||
// Choosing right parity and matrix technique is left for application to decide.
|
||||
//
|
||||
// But here are the few points to keep in mind
|
||||
//
|
||||
// Matrix Type:
|
||||
// - Vandermonde is most commonly used method for choosing coefficients in erasure
|
||||
// encoding but does not guarantee invertable for every sub matrix.
|
||||
// - Whereas Cauchy is our recommended method for choosing coefficients in erasure coding.
|
||||
// Since any sub-matrix of a Cauchy matrix is invertable.
|
||||
//
|
||||
// Total blocks:
|
||||
// - Data blocks and Parity blocks should not be greater than 'Galois Field' (2^8)
|
||||
//
|
||||
// Example
|
||||
//
|
||||
// Creating and using an encoder
|
||||
// var bytes []byte
|
||||
// params := erasure.ValidateParams(10, 5)
|
||||
// encoder := erasure.NewErasure(params)
|
||||
// encodedData, length := encoder.Encode(bytes)
|
||||
//
|
||||
// Creating and using a decoder
|
||||
// var encodedData [][]byte
|
||||
// var length int
|
||||
// params := erasure.ValidateParams(10, 5)
|
||||
// encoder := erasure.NewErasure(params)
|
||||
// originalData, err := encoder.Decode(encodedData, length)
|
||||
//
|
||||
package erasure
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -1,41 +0,0 @@
|
||||
/**********************************************************************
|
||||
Copyright(c) 2011-2015 Intel Corporation All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Intel Corporation nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _ISAL_H_
|
||||
#define _ISAL_H_
|
||||
|
||||
#define ISAL_MAJOR_VERSION 2
|
||||
#define ISAL_MINOR_VERSION 13
|
||||
#define ISAL_PATCH_VERSION 0
|
||||
#define ISAL_MAKE_VERSION(maj, min, patch) ((maj) * 0x10000 + (min) * 0x100 + (patch))
|
||||
#define ISAL_VERSION ISAL_MAKE_VERSION(ISAL_MAJOR_VERSION, ISAL_MINOR_VERSION, ISAL_PATCH_VERSION)
|
||||
|
||||
#include "ec_code.h"
|
||||
#include "gf_vect_mul.h"
|
||||
#endif //_ISAL_H_
|
||||
@@ -1,348 +0,0 @@
|
||||
/**********************************************************************
|
||||
Copyright(c) 2011-2015 Intel Corporation All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Intel Corporation nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**********************************************************************/
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h> // for memset
|
||||
#include "ec_code.h"
|
||||
#include "ec_base.h" // for GF tables
|
||||
#include "ec_types.h"
|
||||
|
||||
unsigned char gf_mul(unsigned char a, unsigned char b)
|
||||
{
|
||||
#ifndef GF_LARGE_TABLES
|
||||
int i;
|
||||
|
||||
if ((a == 0) || (b == 0))
|
||||
return 0;
|
||||
|
||||
return gff_base[(i = gflog_base[a] + gflog_base[b]) > 254 ? i - 255 : i];
|
||||
#else
|
||||
return gf_mul_table_base[b * 256 + a];
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned char gf_inv(unsigned char a)
|
||||
{
|
||||
#ifndef GF_LARGE_TABLES
|
||||
if (a == 0)
|
||||
return 0;
|
||||
|
||||
return gff_base[255 - gflog_base[a]];
|
||||
#else
|
||||
return gf_inv_table_base[a];
|
||||
#endif
|
||||
}
|
||||
|
||||
void gf_gen_rs_matrix(unsigned char *a, int m, int k)
|
||||
{
|
||||
int i, j;
|
||||
unsigned char p, gen = 1;
|
||||
|
||||
memset(a, 0, k * m);
|
||||
for (i = 0; i < k; i++)
|
||||
a[k * i + i] = 1;
|
||||
|
||||
for (i = k; i < m; i++) {
|
||||
p = 1;
|
||||
for (j = 0; j < k; j++) {
|
||||
a[k * i + j] = p;
|
||||
p = gf_mul(p, gen);
|
||||
}
|
||||
gen = gf_mul(gen, 2);
|
||||
}
|
||||
}
|
||||
|
||||
void gf_gen_cauchy1_matrix(unsigned char *a, int m, int k)
|
||||
{
|
||||
int i, j;
|
||||
unsigned char *p;
|
||||
|
||||
// Identity matrix in high position
|
||||
memset(a, 0, k * m);
|
||||
for (i = 0; i < k; i++)
|
||||
a[k * i + i] = 1;
|
||||
|
||||
// For the rest choose 1/(i + j) | i != j
|
||||
p = &a[k * k];
|
||||
for (i = k; i < m; i++)
|
||||
for (j = 0; j < k; j++)
|
||||
*p++ = gf_inv(i ^ j);
|
||||
|
||||
}
|
||||
|
||||
int gf_invert_matrix(unsigned char *in_mat, unsigned char *out_mat, const int n)
|
||||
{
|
||||
int i, j, k;
|
||||
unsigned char temp;
|
||||
|
||||
// Set out_mat[] to the identity matrix
|
||||
for (i = 0; i < n * n; i++) // memset(out_mat, 0, n*n)
|
||||
out_mat[i] = 0;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
out_mat[i * n + i] = 1;
|
||||
|
||||
// Inverse
|
||||
for (i = 0; i < n; i++) {
|
||||
// Check for 0 in pivot element
|
||||
if (in_mat[i * n + i] == 0) {
|
||||
// Find a row with non-zero in current column and swap
|
||||
for (j = i + 1; j < n; j++)
|
||||
if (in_mat[j * n + i])
|
||||
break;
|
||||
|
||||
if (j == n) // Couldn't find means it's singular
|
||||
return -1;
|
||||
|
||||
for (k = 0; k < n; k++) { // Swap rows i,j
|
||||
temp = in_mat[i * n + k];
|
||||
in_mat[i * n + k] = in_mat[j * n + k];
|
||||
in_mat[j * n + k] = temp;
|
||||
|
||||
temp = out_mat[i * n + k];
|
||||
out_mat[i * n + k] = out_mat[j * n + k];
|
||||
out_mat[j * n + k] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
temp = gf_inv(in_mat[i * n + i]); // 1/pivot
|
||||
for (j = 0; j < n; j++) { // Scale row i by 1/pivot
|
||||
in_mat[i * n + j] = gf_mul(in_mat[i * n + j], temp);
|
||||
out_mat[i * n + j] = gf_mul(out_mat[i * n + j], temp);
|
||||
}
|
||||
|
||||
for (j = 0; j < n; j++) {
|
||||
if (j == i)
|
||||
continue;
|
||||
|
||||
temp = in_mat[j * n + i];
|
||||
for (k = 0; k < n; k++) {
|
||||
out_mat[j * n + k] ^= gf_mul(temp, out_mat[i * n + k]);
|
||||
in_mat[j * n + k] ^= gf_mul(temp, in_mat[i * n + k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Calculates const table gftbl in GF(2^8) from single input A
|
||||
// gftbl(A) = {A{00}, A{01}, A{02}, ... , A{0f} }, {A{00}, A{10}, A{20}, ... , A{f0} }
|
||||
|
||||
void gf_vect_mul_init(unsigned char c, unsigned char *tbl)
|
||||
{
|
||||
unsigned char c2 = (c << 1) ^ ((c & 0x80) ? 0x1d : 0); //Mult by GF{2}
|
||||
unsigned char c4 = (c2 << 1) ^ ((c2 & 0x80) ? 0x1d : 0); //Mult by GF{2}
|
||||
unsigned char c8 = (c4 << 1) ^ ((c4 & 0x80) ? 0x1d : 0); //Mult by GF{2}
|
||||
|
||||
#if __WORDSIZE == 64 || _WIN64 || __x86_64__
|
||||
unsigned long long v1, v2, v4, v8, *t;
|
||||
unsigned long long v10, v20, v40, v80;
|
||||
unsigned char c17, c18, c20, c24;
|
||||
|
||||
t = (unsigned long long *)tbl;
|
||||
|
||||
v1 = c * 0x0100010001000100ull;
|
||||
v2 = c2 * 0x0101000001010000ull;
|
||||
v4 = c4 * 0x0101010100000000ull;
|
||||
v8 = c8 * 0x0101010101010101ull;
|
||||
|
||||
v4 = v1 ^ v2 ^ v4;
|
||||
t[0] = v4;
|
||||
t[1] = v8 ^ v4;
|
||||
|
||||
c17 = (c8 << 1) ^ ((c8 & 0x80) ? 0x1d : 0); //Mult by GF{2}
|
||||
c18 = (c17 << 1) ^ ((c17 & 0x80) ? 0x1d : 0); //Mult by GF{2}
|
||||
c20 = (c18 << 1) ^ ((c18 & 0x80) ? 0x1d : 0); //Mult by GF{2}
|
||||
c24 = (c20 << 1) ^ ((c20 & 0x80) ? 0x1d : 0); //Mult by GF{2}
|
||||
|
||||
v10 = c17 * 0x0100010001000100ull;
|
||||
v20 = c18 * 0x0101000001010000ull;
|
||||
v40 = c20 * 0x0101010100000000ull;
|
||||
v80 = c24 * 0x0101010101010101ull;
|
||||
|
||||
v40 = v10 ^ v20 ^ v40;
|
||||
t[2] = v40;
|
||||
t[3] = v80 ^ v40;
|
||||
|
||||
#else // 32-bit or other
|
||||
unsigned char c3, c5, c6, c7, c9, c10, c11, c12, c13, c14, c15;
|
||||
unsigned char c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30,
|
||||
c31;
|
||||
|
||||
c3 = c2 ^ c;
|
||||
c5 = c4 ^ c;
|
||||
c6 = c4 ^ c2;
|
||||
c7 = c4 ^ c3;
|
||||
|
||||
c9 = c8 ^ c;
|
||||
c10 = c8 ^ c2;
|
||||
c11 = c8 ^ c3;
|
||||
c12 = c8 ^ c4;
|
||||
c13 = c8 ^ c5;
|
||||
c14 = c8 ^ c6;
|
||||
c15 = c8 ^ c7;
|
||||
|
||||
tbl[0] = 0;
|
||||
tbl[1] = c;
|
||||
tbl[2] = c2;
|
||||
tbl[3] = c3;
|
||||
tbl[4] = c4;
|
||||
tbl[5] = c5;
|
||||
tbl[6] = c6;
|
||||
tbl[7] = c7;
|
||||
tbl[8] = c8;
|
||||
tbl[9] = c9;
|
||||
tbl[10] = c10;
|
||||
tbl[11] = c11;
|
||||
tbl[12] = c12;
|
||||
tbl[13] = c13;
|
||||
tbl[14] = c14;
|
||||
tbl[15] = c15;
|
||||
|
||||
c17 = (c8 << 1) ^ ((c8 & 0x80) ? 0x1d : 0); //Mult by GF{2}
|
||||
c18 = (c17 << 1) ^ ((c17 & 0x80) ? 0x1d : 0); //Mult by GF{2}
|
||||
c19 = c18 ^ c17;
|
||||
c20 = (c18 << 1) ^ ((c18 & 0x80) ? 0x1d : 0); //Mult by GF{2}
|
||||
c21 = c20 ^ c17;
|
||||
c22 = c20 ^ c18;
|
||||
c23 = c20 ^ c19;
|
||||
c24 = (c20 << 1) ^ ((c20 & 0x80) ? 0x1d : 0); //Mult by GF{2}
|
||||
c25 = c24 ^ c17;
|
||||
c26 = c24 ^ c18;
|
||||
c27 = c24 ^ c19;
|
||||
c28 = c24 ^ c20;
|
||||
c29 = c24 ^ c21;
|
||||
c30 = c24 ^ c22;
|
||||
c31 = c24 ^ c23;
|
||||
|
||||
tbl[16] = 0;
|
||||
tbl[17] = c17;
|
||||
tbl[18] = c18;
|
||||
tbl[19] = c19;
|
||||
tbl[20] = c20;
|
||||
tbl[21] = c21;
|
||||
tbl[22] = c22;
|
||||
tbl[23] = c23;
|
||||
tbl[24] = c24;
|
||||
tbl[25] = c25;
|
||||
tbl[26] = c26;
|
||||
tbl[27] = c27;
|
||||
tbl[28] = c28;
|
||||
tbl[29] = c29;
|
||||
tbl[30] = c30;
|
||||
tbl[31] = c31;
|
||||
|
||||
#endif //__WORDSIZE == 64 || _WIN64 || __x86_64__
|
||||
}
|
||||
|
||||
void gf_vect_dot_prod_base(int len, int vlen, unsigned char *v,
|
||||
unsigned char **src, unsigned char *dest)
|
||||
{
|
||||
int i, j;
|
||||
unsigned char s;
|
||||
for (i = 0; i < len; i++) {
|
||||
s = 0;
|
||||
for (j = 0; j < vlen; j++)
|
||||
s ^= gf_mul(src[j][i], v[j * 32 + 1]);
|
||||
|
||||
dest[i] = s;
|
||||
}
|
||||
}
|
||||
|
||||
void gf_vect_mad_base(int len, int vec, int vec_i,
|
||||
unsigned char *v, unsigned char *src, unsigned char *dest)
|
||||
{
|
||||
int i;
|
||||
unsigned char s;
|
||||
for (i = 0; i < len; i++) {
|
||||
s = dest[i];
|
||||
s ^= gf_mul(src[i], v[vec_i * 32 + 1]);
|
||||
dest[i] = s;
|
||||
}
|
||||
}
|
||||
|
||||
void ec_encode_data_base(int len, int srcs, int dests, unsigned char *v,
|
||||
unsigned char **src, unsigned char **dest)
|
||||
{
|
||||
int i, j, l;
|
||||
unsigned char s;
|
||||
|
||||
for (l = 0; l < dests; l++) {
|
||||
for (i = 0; i < len; i++) {
|
||||
s = 0;
|
||||
for (j = 0; j < srcs; j++)
|
||||
s ^= gf_mul(src[j][i], v[j * 32 + l * srcs * 32 + 1]);
|
||||
|
||||
dest[l][i] = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ec_encode_data_update_base(int len, int k, int rows, int vec_i, unsigned char *v,
|
||||
unsigned char *data, unsigned char **dest)
|
||||
{
|
||||
int i, l;
|
||||
unsigned char s;
|
||||
|
||||
for (l = 0; l < rows; l++) {
|
||||
for (i = 0; i < len; i++) {
|
||||
s = dest[l][i];
|
||||
s ^= gf_mul(data[i], v[vec_i * 32 + l * k * 32 + 1]);
|
||||
|
||||
dest[l][i] = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gf_vect_mul_base(int len, unsigned char *a, unsigned char *src, unsigned char *dest)
|
||||
{
|
||||
//2nd element of table array is ref value used to fill it in
|
||||
unsigned char c = a[1];
|
||||
while (len-- > 0)
|
||||
*dest++ = gf_mul(c, *src++);
|
||||
}
|
||||
|
||||
struct slver {
|
||||
UINT16 snum;
|
||||
UINT8 ver;
|
||||
UINT8 core;
|
||||
};
|
||||
|
||||
// Version info
|
||||
struct slver gf_vect_mul_init_slver_00020035;
|
||||
struct slver gf_vect_mul_init_slver = { 0x0035, 0x02, 0x00 };
|
||||
|
||||
struct slver ec_encode_data_base_slver_00010135;
|
||||
struct slver ec_encode_data_base_slver = { 0x0135, 0x01, 0x00 };
|
||||
|
||||
struct slver gf_vect_mul_base_slver_00010136;
|
||||
struct slver gf_vect_mul_base_slver = { 0x0136, 0x01, 0x00 };
|
||||
|
||||
struct slver gf_vect_dot_prod_base_slver_00010137;
|
||||
struct slver gf_vect_dot_prod_base_slver = { 0x0137, 0x01, 0x00 };
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,933 +0,0 @@
|
||||
/**********************************************************************
|
||||
Copyright(c) 2011-2015 Intel Corporation All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Intel Corporation nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**********************************************************************/
|
||||
|
||||
|
||||
#ifndef _ERASURE_CODE_H_
|
||||
#define _ERASURE_CODE_H_
|
||||
|
||||
/**
|
||||
* @file erasure_code.h
|
||||
* @brief Interface to functions supporting erasure code encode and decode.
|
||||
*
|
||||
* This file defines the interface to optimized functions used in erasure
|
||||
* codes. Encode and decode of erasures in GF(2^8) are made by calculating the
|
||||
* dot product of the symbols (bytes in GF(2^8)) across a set of buffers and a
|
||||
* set of coefficients. Values for the coefficients are determined by the type
|
||||
* of erasure code. Using a general dot product means that any sequence of
|
||||
* coefficients may be used including erasure codes based on random
|
||||
* coefficients.
|
||||
* Multiple versions of dot product are supplied to calculate 1-6 output
|
||||
* vectors in one pass.
|
||||
* Base GF multiply and divide functions can be sped up by defining
|
||||
* GF_LARGE_TABLES at the expense of memory size.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "gf_vect_mul.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize tables for fast Erasure Code encode and decode.
|
||||
*
|
||||
* Generates the expanded tables needed for fast encode or decode for erasure
|
||||
* codes on blocks of data. 32bytes is generated for each input coefficient.
|
||||
*
|
||||
* @param k The number of vector sources or rows in the generator matrix
|
||||
* for coding.
|
||||
* @param rows The number of output vectors to concurrently encode/decode.
|
||||
* @param a Pointer to sets of arrays of input coefficients used to encode
|
||||
* or decode data.
|
||||
* @param gftbls Pointer to start of space for concatenated output tables
|
||||
* generated from input coefficients. Must be of size 32*k*rows.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void ec_init_tables(int k, int rows, unsigned char* a, unsigned char* gftbls);
|
||||
|
||||
/**
|
||||
* @brief Generate or decode erasure codes on blocks of data, runs appropriate version.
|
||||
*
|
||||
* Given a list of source data blocks, generate one or multiple blocks of
|
||||
* encoded data as specified by a matrix of GF(2^8) coefficients. When given a
|
||||
* suitable set of coefficients, this function will perform the fast generation
|
||||
* or decoding of Reed-Solomon type erasure codes.
|
||||
*
|
||||
* This function determines what instruction sets are enabled and
|
||||
* selects the appropriate version at runtime.
|
||||
*
|
||||
* @param len Length of each block of data (vector) of source or dest data.
|
||||
* @param k The number of vector sources or rows in the generator matrix
|
||||
* for coding.
|
||||
* @param rows The number of output vectors to concurrently encode/decode.
|
||||
* @param gftbls Pointer to array of input tables generated from coding
|
||||
* coefficients in ec_init_tables(). Must be of size 32*k*rows
|
||||
* @param data Array of pointers to source input buffers.
|
||||
* @param coding Array of pointers to coded output buffers.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void ec_encode_data(int len, int k, int rows, unsigned char *gftbls, unsigned char **data,
|
||||
unsigned char **coding);
|
||||
|
||||
/**
|
||||
* @brief Generate or decode erasure codes on blocks of data.
|
||||
*
|
||||
* Arch specific version of ec_encode_data() with same parameters.
|
||||
* @requires SSE4.1
|
||||
*/
|
||||
void ec_encode_data_sse(int len, int k, int rows, unsigned char *gftbls, unsigned char **data,
|
||||
unsigned char **coding);
|
||||
|
||||
/**
|
||||
* @brief Generate or decode erasure codes on blocks of data.
|
||||
*
|
||||
* Arch specific version of ec_encode_data() with same parameters.
|
||||
* @requires AVX
|
||||
*/
|
||||
void ec_encode_data_avx(int len, int k, int rows, unsigned char *gftbls, unsigned char **data,
|
||||
unsigned char **coding);
|
||||
|
||||
/**
|
||||
* @brief Generate or decode erasure codes on blocks of data.
|
||||
*
|
||||
* Arch specific version of ec_encode_data() with same parameters.
|
||||
* @requires AVX2
|
||||
*/
|
||||
void ec_encode_data_avx2(int len, int k, int rows, unsigned char *gftbls, unsigned char **data,
|
||||
unsigned char **coding);
|
||||
|
||||
/**
|
||||
* @brief Generate or decode erasure codes on blocks of data, runs baseline version.
|
||||
*
|
||||
* Baseline version of ec_encode_data() with same parameters.
|
||||
*/
|
||||
void ec_encode_data_base(int len, int srcs, int dests, unsigned char *v, unsigned char **src,
|
||||
unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief Generate update for encode or decode of erasure codes from single source, runs appropriate version.
|
||||
*
|
||||
* Given one source data block, update one or multiple blocks of encoded data as
|
||||
* specified by a matrix of GF(2^8) coefficients. When given a suitable set of
|
||||
* coefficients, this function will perform the fast generation or decoding of
|
||||
* Reed-Solomon type erasure codes from one input source at a time.
|
||||
*
|
||||
* This function determines what instruction sets are enabled and selects the
|
||||
* appropriate version at runtime.
|
||||
*
|
||||
* @param len Length of each block of data (vector) of source or dest data.
|
||||
* @param k The number of vector sources or rows in the generator matrix
|
||||
* for coding.
|
||||
* @param rows The number of output vectors to concurrently encode/decode.
|
||||
* @param vec_i The vector index corresponding to the single input source.
|
||||
* @param g_tbls Pointer to array of input tables generated from coding
|
||||
* coefficients in ec_init_tables(). Must be of size 32*k*rows
|
||||
* @param data Pointer to single input source used to update output parity.
|
||||
* @param coding Array of pointers to coded output buffers.
|
||||
* @returns none
|
||||
*/
|
||||
void ec_encode_data_update(int len, int k, int rows, int vec_i, unsigned char *g_tbls,
|
||||
unsigned char *data, unsigned char **coding);
|
||||
|
||||
/**
|
||||
* @brief Generate update for encode or decode of erasure codes from single source.
|
||||
*
|
||||
* Arch specific version of ec_encode_data_update() with same parameters.
|
||||
* @requires SSE4.1
|
||||
*/
|
||||
|
||||
void ec_encode_data_update_sse(int len, int k, int rows, int vec_i, unsigned char *g_tbls,
|
||||
unsigned char *data, unsigned char **coding);
|
||||
|
||||
/**
|
||||
* @brief Generate update for encode or decode of erasure codes from single source.
|
||||
*
|
||||
* Arch specific version of ec_encode_data_update() with same parameters.
|
||||
* @requires AVX
|
||||
*/
|
||||
|
||||
void ec_encode_data_update_avx(int len, int k, int rows, int vec_i, unsigned char *g_tbls,
|
||||
unsigned char *data, unsigned char **coding);
|
||||
|
||||
/**
|
||||
* @brief Generate update for encode or decode of erasure codes from single source.
|
||||
*
|
||||
* Arch specific version of ec_encode_data_update() with same parameters.
|
||||
* @requires AVX2
|
||||
*/
|
||||
|
||||
void ec_encode_data_update_avx2(int len, int k, int rows, int vec_i, unsigned char *g_tbls,
|
||||
unsigned char *data, unsigned char **coding);
|
||||
|
||||
/**
|
||||
* @brief Generate update for encode or decode of erasure codes from single source.
|
||||
*
|
||||
* Baseline version of ec_encode_data_update().
|
||||
*/
|
||||
|
||||
void ec_encode_data_update_base(int len, int k, int rows, int vec_i, unsigned char *v,
|
||||
unsigned char *data, unsigned char **dest);
|
||||
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector dot product.
|
||||
*
|
||||
* Does a GF(2^8) dot product across each byte of the input array and a constant
|
||||
* set of coefficients to produce each byte of the output. Can be used for
|
||||
* erasure coding encode and decode. Function requires pre-calculation of a
|
||||
* 32*vlen byte constant array based on the input coefficients.
|
||||
* @requires SSE4.1
|
||||
*
|
||||
* @param len Length of each vector in bytes. Must be >= 16.
|
||||
* @param vlen Number of vector sources.
|
||||
* @param gftbls Pointer to 32*vlen byte array of pre-calculated constants based
|
||||
* on the array of input coefficients.
|
||||
* @param src Array of pointers to source inputs.
|
||||
* @param dest Pointer to destination data array.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_vect_dot_prod_sse(int len, int vlen, unsigned char *gftbls,
|
||||
unsigned char **src, unsigned char *dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector dot product.
|
||||
*
|
||||
* Does a GF(2^8) dot product across each byte of the input array and a constant
|
||||
* set of coefficients to produce each byte of the output. Can be used for
|
||||
* erasure coding encode and decode. Function requires pre-calculation of a
|
||||
* 32*vlen byte constant array based on the input coefficients.
|
||||
* @requires AVX
|
||||
*
|
||||
* @param len Length of each vector in bytes. Must be >= 16.
|
||||
* @param vlen Number of vector sources.
|
||||
* @param gftbls Pointer to 32*vlen byte array of pre-calculated constants based
|
||||
* on the array of input coefficients.
|
||||
* @param src Array of pointers to source inputs.
|
||||
* @param dest Pointer to destination data array.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_vect_dot_prod_avx(int len, int vlen, unsigned char *gftbls,
|
||||
unsigned char **src, unsigned char *dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector dot product.
|
||||
*
|
||||
* Does a GF(2^8) dot product across each byte of the input array and a constant
|
||||
* set of coefficients to produce each byte of the output. Can be used for
|
||||
* erasure coding encode and decode. Function requires pre-calculation of a
|
||||
* 32*vlen byte constant array based on the input coefficients.
|
||||
* @requires AVX2
|
||||
*
|
||||
* @param len Length of each vector in bytes. Must be >= 32.
|
||||
* @param vlen Number of vector sources.
|
||||
* @param gftbls Pointer to 32*vlen byte array of pre-calculated constants based
|
||||
* on the array of input coefficients.
|
||||
* @param src Array of pointers to source inputs.
|
||||
* @param dest Pointer to destination data array.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_vect_dot_prod_avx2(int len, int vlen, unsigned char *gftbls,
|
||||
unsigned char **src, unsigned char *dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector dot product with two outputs.
|
||||
*
|
||||
* Vector dot product optimized to calculate two ouputs at a time. Does two
|
||||
* GF(2^8) dot products across each byte of the input array and two constant
|
||||
* sets of coefficients to produce each byte of the outputs. Can be used for
|
||||
* erasure coding encode and decode. Function requires pre-calculation of a
|
||||
* 2*32*vlen byte constant array based on the two sets of input coefficients.
|
||||
* @requires SSE4.1
|
||||
*
|
||||
* @param len Length of each vector in bytes. Must be >= 16.
|
||||
* @param vlen Number of vector sources.
|
||||
* @param gftbls Pointer to 2*32*vlen byte array of pre-calculated constants
|
||||
* based on the array of input coefficients.
|
||||
* @param src Array of pointers to source inputs.
|
||||
* @param dest Array of pointers to destination data buffers.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_2vect_dot_prod_sse(int len, int vlen, unsigned char *gftbls,
|
||||
unsigned char **src, unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector dot product with two outputs.
|
||||
*
|
||||
* Vector dot product optimized to calculate two ouputs at a time. Does two
|
||||
* GF(2^8) dot products across each byte of the input array and two constant
|
||||
* sets of coefficients to produce each byte of the outputs. Can be used for
|
||||
* erasure coding encode and decode. Function requires pre-calculation of a
|
||||
* 2*32*vlen byte constant array based on the two sets of input coefficients.
|
||||
* @requires AVX
|
||||
*
|
||||
* @param len Length of each vector in bytes. Must be >= 16.
|
||||
* @param vlen Number of vector sources.
|
||||
* @param gftbls Pointer to 2*32*vlen byte array of pre-calculated constants
|
||||
* based on the array of input coefficients.
|
||||
* @param src Array of pointers to source inputs.
|
||||
* @param dest Array of pointers to destination data buffers.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_2vect_dot_prod_avx(int len, int vlen, unsigned char *gftbls,
|
||||
unsigned char **src, unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector dot product with two outputs.
|
||||
*
|
||||
* Vector dot product optimized to calculate two ouputs at a time. Does two
|
||||
* GF(2^8) dot products across each byte of the input array and two constant
|
||||
* sets of coefficients to produce each byte of the outputs. Can be used for
|
||||
* erasure coding encode and decode. Function requires pre-calculation of a
|
||||
* 2*32*vlen byte constant array based on the two sets of input coefficients.
|
||||
* @requires AVX2
|
||||
*
|
||||
* @param len Length of each vector in bytes. Must be >= 32.
|
||||
* @param vlen Number of vector sources.
|
||||
* @param gftbls Pointer to 2*32*vlen byte array of pre-calculated constants
|
||||
* based on the array of input coefficients.
|
||||
* @param src Array of pointers to source inputs.
|
||||
* @param dest Array of pointers to destination data buffers.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_2vect_dot_prod_avx2(int len, int vlen, unsigned char *gftbls,
|
||||
unsigned char **src, unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector dot product with three outputs.
|
||||
*
|
||||
* Vector dot product optimized to calculate three ouputs at a time. Does three
|
||||
* GF(2^8) dot products across each byte of the input array and three constant
|
||||
* sets of coefficients to produce each byte of the outputs. Can be used for
|
||||
* erasure coding encode and decode. Function requires pre-calculation of a
|
||||
* 3*32*vlen byte constant array based on the three sets of input coefficients.
|
||||
* @requires SSE4.1
|
||||
*
|
||||
* @param len Length of each vector in bytes. Must be >= 16.
|
||||
* @param vlen Number of vector sources.
|
||||
* @param gftbls Pointer to 3*32*vlen byte array of pre-calculated constants
|
||||
* based on the array of input coefficients.
|
||||
* @param src Array of pointers to source inputs.
|
||||
* @param dest Array of pointers to destination data buffers.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_3vect_dot_prod_sse(int len, int vlen, unsigned char *gftbls,
|
||||
unsigned char **src, unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector dot product with three outputs.
|
||||
*
|
||||
* Vector dot product optimized to calculate three ouputs at a time. Does three
|
||||
* GF(2^8) dot products across each byte of the input array and three constant
|
||||
* sets of coefficients to produce each byte of the outputs. Can be used for
|
||||
* erasure coding encode and decode. Function requires pre-calculation of a
|
||||
* 3*32*vlen byte constant array based on the three sets of input coefficients.
|
||||
* @requires AVX
|
||||
*
|
||||
* @param len Length of each vector in bytes. Must be >= 16.
|
||||
* @param vlen Number of vector sources.
|
||||
* @param gftbls Pointer to 3*32*vlen byte array of pre-calculated constants
|
||||
* based on the array of input coefficients.
|
||||
* @param src Array of pointers to source inputs.
|
||||
* @param dest Array of pointers to destination data buffers.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_3vect_dot_prod_avx(int len, int vlen, unsigned char *gftbls,
|
||||
unsigned char **src, unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector dot product with three outputs.
|
||||
*
|
||||
* Vector dot product optimized to calculate three ouputs at a time. Does three
|
||||
* GF(2^8) dot products across each byte of the input array and three constant
|
||||
* sets of coefficients to produce each byte of the outputs. Can be used for
|
||||
* erasure coding encode and decode. Function requires pre-calculation of a
|
||||
* 3*32*vlen byte constant array based on the three sets of input coefficients.
|
||||
* @requires AVX2
|
||||
*
|
||||
* @param len Length of each vector in bytes. Must be >= 32.
|
||||
* @param vlen Number of vector sources.
|
||||
* @param gftbls Pointer to 3*32*vlen byte array of pre-calculated constants
|
||||
* based on the array of input coefficients.
|
||||
* @param src Array of pointers to source inputs.
|
||||
* @param dest Array of pointers to destination data buffers.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_3vect_dot_prod_avx2(int len, int vlen, unsigned char *gftbls,
|
||||
unsigned char **src, unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector dot product with four outputs.
|
||||
*
|
||||
* Vector dot product optimized to calculate four ouputs at a time. Does four
|
||||
* GF(2^8) dot products across each byte of the input array and four constant
|
||||
* sets of coefficients to produce each byte of the outputs. Can be used for
|
||||
* erasure coding encode and decode. Function requires pre-calculation of a
|
||||
* 4*32*vlen byte constant array based on the four sets of input coefficients.
|
||||
* @requires SSE4.1
|
||||
*
|
||||
* @param len Length of each vector in bytes. Must be >= 16.
|
||||
* @param vlen Number of vector sources.
|
||||
* @param gftbls Pointer to 4*32*vlen byte array of pre-calculated constants
|
||||
* based on the array of input coefficients.
|
||||
* @param src Array of pointers to source inputs.
|
||||
* @param dest Array of pointers to destination data buffers.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_4vect_dot_prod_sse(int len, int vlen, unsigned char *gftbls,
|
||||
unsigned char **src, unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector dot product with four outputs.
|
||||
*
|
||||
* Vector dot product optimized to calculate four ouputs at a time. Does four
|
||||
* GF(2^8) dot products across each byte of the input array and four constant
|
||||
* sets of coefficients to produce each byte of the outputs. Can be used for
|
||||
* erasure coding encode and decode. Function requires pre-calculation of a
|
||||
* 4*32*vlen byte constant array based on the four sets of input coefficients.
|
||||
* @requires AVX
|
||||
*
|
||||
* @param len Length of each vector in bytes. Must be >= 16.
|
||||
* @param vlen Number of vector sources.
|
||||
* @param gftbls Pointer to 4*32*vlen byte array of pre-calculated constants
|
||||
* based on the array of input coefficients.
|
||||
* @param src Array of pointers to source inputs.
|
||||
* @param dest Array of pointers to destination data buffers.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_4vect_dot_prod_avx(int len, int vlen, unsigned char *gftbls,
|
||||
unsigned char **src, unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector dot product with four outputs.
|
||||
*
|
||||
* Vector dot product optimized to calculate four ouputs at a time. Does four
|
||||
* GF(2^8) dot products across each byte of the input array and four constant
|
||||
* sets of coefficients to produce each byte of the outputs. Can be used for
|
||||
* erasure coding encode and decode. Function requires pre-calculation of a
|
||||
* 4*32*vlen byte constant array based on the four sets of input coefficients.
|
||||
* @requires AVX2
|
||||
*
|
||||
* @param len Length of each vector in bytes. Must be >= 32.
|
||||
* @param vlen Number of vector sources.
|
||||
* @param gftbls Pointer to 4*32*vlen byte array of pre-calculated constants
|
||||
* based on the array of input coefficients.
|
||||
* @param src Array of pointers to source inputs.
|
||||
* @param dest Array of pointers to destination data buffers.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_4vect_dot_prod_avx2(int len, int vlen, unsigned char *gftbls,
|
||||
unsigned char **src, unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector dot product with five outputs.
|
||||
*
|
||||
* Vector dot product optimized to calculate five ouputs at a time. Does five
|
||||
* GF(2^8) dot products across each byte of the input array and five constant
|
||||
* sets of coefficients to produce each byte of the outputs. Can be used for
|
||||
* erasure coding encode and decode. Function requires pre-calculation of a
|
||||
* 5*32*vlen byte constant array based on the five sets of input coefficients.
|
||||
* @requires SSE4.1
|
||||
*
|
||||
* @param len Length of each vector in bytes. Must >= 16.
|
||||
* @param vlen Number of vector sources.
|
||||
* @param gftbls Pointer to 5*32*vlen byte array of pre-calculated constants
|
||||
* based on the array of input coefficients.
|
||||
* @param src Array of pointers to source inputs.
|
||||
* @param dest Array of pointers to destination data buffers.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_5vect_dot_prod_sse(int len, int vlen, unsigned char *gftbls,
|
||||
unsigned char **src, unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector dot product with five outputs.
|
||||
*
|
||||
* Vector dot product optimized to calculate five ouputs at a time. Does five
|
||||
* GF(2^8) dot products across each byte of the input array and five constant
|
||||
* sets of coefficients to produce each byte of the outputs. Can be used for
|
||||
* erasure coding encode and decode. Function requires pre-calculation of a
|
||||
* 5*32*vlen byte constant array based on the five sets of input coefficients.
|
||||
* @requires AVX
|
||||
*
|
||||
* @param len Length of each vector in bytes. Must >= 16.
|
||||
* @param vlen Number of vector sources.
|
||||
* @param gftbls Pointer to 5*32*vlen byte array of pre-calculated constants
|
||||
* based on the array of input coefficients.
|
||||
* @param src Array of pointers to source inputs.
|
||||
* @param dest Array of pointers to destination data buffers.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_5vect_dot_prod_avx(int len, int vlen, unsigned char *gftbls,
|
||||
unsigned char **src, unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector dot product with five outputs.
|
||||
*
|
||||
* Vector dot product optimized to calculate five ouputs at a time. Does five
|
||||
* GF(2^8) dot products across each byte of the input array and five constant
|
||||
* sets of coefficients to produce each byte of the outputs. Can be used for
|
||||
* erasure coding encode and decode. Function requires pre-calculation of a
|
||||
* 5*32*vlen byte constant array based on the five sets of input coefficients.
|
||||
* @requires AVX2
|
||||
*
|
||||
* @param len Length of each vector in bytes. Must >= 32.
|
||||
* @param vlen Number of vector sources.
|
||||
* @param gftbls Pointer to 5*32*vlen byte array of pre-calculated constants
|
||||
* based on the array of input coefficients.
|
||||
* @param src Array of pointers to source inputs.
|
||||
* @param dest Array of pointers to destination data buffers.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_5vect_dot_prod_avx2(int len, int vlen, unsigned char *gftbls,
|
||||
unsigned char **src, unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector dot product with six outputs.
|
||||
*
|
||||
* Vector dot product optimized to calculate six ouputs at a time. Does six
|
||||
* GF(2^8) dot products across each byte of the input array and six constant
|
||||
* sets of coefficients to produce each byte of the outputs. Can be used for
|
||||
* erasure coding encode and decode. Function requires pre-calculation of a
|
||||
* 6*32*vlen byte constant array based on the six sets of input coefficients.
|
||||
* @requires SSE4.1
|
||||
*
|
||||
* @param len Length of each vector in bytes. Must be >= 16.
|
||||
* @param vlen Number of vector sources.
|
||||
* @param gftbls Pointer to 6*32*vlen byte array of pre-calculated constants
|
||||
* based on the array of input coefficients.
|
||||
* @param src Array of pointers to source inputs.
|
||||
* @param dest Array of pointers to destination data buffers.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_6vect_dot_prod_sse(int len, int vlen, unsigned char *gftbls,
|
||||
unsigned char **src, unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector dot product with six outputs.
|
||||
*
|
||||
* Vector dot product optimized to calculate six ouputs at a time. Does six
|
||||
* GF(2^8) dot products across each byte of the input array and six constant
|
||||
* sets of coefficients to produce each byte of the outputs. Can be used for
|
||||
* erasure coding encode and decode. Function requires pre-calculation of a
|
||||
* 6*32*vlen byte constant array based on the six sets of input coefficients.
|
||||
* @requires AVX
|
||||
*
|
||||
* @param len Length of each vector in bytes. Must be >= 16.
|
||||
* @param vlen Number of vector sources.
|
||||
* @param gftbls Pointer to 6*32*vlen byte array of pre-calculated constants
|
||||
* based on the array of input coefficients.
|
||||
* @param src Array of pointers to source inputs.
|
||||
* @param dest Array of pointers to destination data buffers.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_6vect_dot_prod_avx(int len, int vlen, unsigned char *gftbls,
|
||||
unsigned char **src, unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector dot product with six outputs.
|
||||
*
|
||||
* Vector dot product optimized to calculate six ouputs at a time. Does six
|
||||
* GF(2^8) dot products across each byte of the input array and six constant
|
||||
* sets of coefficients to produce each byte of the outputs. Can be used for
|
||||
* erasure coding encode and decode. Function requires pre-calculation of a
|
||||
* 6*32*vlen byte constant array based on the six sets of input coefficients.
|
||||
* @requires AVX2
|
||||
*
|
||||
* @param len Length of each vector in bytes. Must be >= 32.
|
||||
* @param vlen Number of vector sources.
|
||||
* @param gftbls Pointer to 6*32*vlen byte array of pre-calculated constants
|
||||
* based on the array of input coefficients.
|
||||
* @param src Array of pointers to source inputs.
|
||||
* @param dest Array of pointers to destination data buffers.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_6vect_dot_prod_avx2(int len, int vlen, unsigned char *gftbls,
|
||||
unsigned char **src, unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector dot product, runs baseline version.
|
||||
*
|
||||
* Does a GF(2^8) dot product across each byte of the input array and a constant
|
||||
* set of coefficients to produce each byte of the output. Can be used for
|
||||
* erasure coding encode and decode. Function requires pre-calculation of a
|
||||
* 32*vlen byte constant array based on the input coefficients.
|
||||
*
|
||||
* @param len Length of each vector in bytes. Must be >= 16.
|
||||
* @param vlen Number of vector sources.
|
||||
* @param gftbls Pointer to 32*vlen byte array of pre-calculated constants based
|
||||
* on the array of input coefficients. Only elements 32*CONST*j + 1
|
||||
* of this array are used, where j = (0, 1, 2...) and CONST is the
|
||||
* number of elements in the array of input coefficients. The
|
||||
* elements used correspond to the original input coefficients.
|
||||
* @param src Array of pointers to source inputs.
|
||||
* @param dest Pointer to destination data array.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_vect_dot_prod_base(int len, int vlen, unsigned char *gftbls,
|
||||
unsigned char **src, unsigned char *dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector dot product, runs appropriate version.
|
||||
*
|
||||
* Does a GF(2^8) dot product across each byte of the input array and a constant
|
||||
* set of coefficients to produce each byte of the output. Can be used for
|
||||
* erasure coding encode and decode. Function requires pre-calculation of a
|
||||
* 32*vlen byte constant array based on the input coefficients.
|
||||
*
|
||||
* This function determines what instruction sets are enabled and
|
||||
* selects the appropriate version at runtime.
|
||||
*
|
||||
* @param len Length of each vector in bytes. Must be >= 32.
|
||||
* @param vlen Number of vector sources.
|
||||
* @param gftbls Pointer to 32*vlen byte array of pre-calculated constants based
|
||||
* on the array of input coefficients.
|
||||
* @param src Array of pointers to source inputs.
|
||||
* @param dest Pointer to destination data array.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_vect_dot_prod(int len, int vlen, unsigned char *gftbls,
|
||||
unsigned char **src, unsigned char *dest);
|
||||
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector multiply accumulate, runs appropriate version.
|
||||
*
|
||||
* Does a GF(2^8) multiply across each byte of input source with expanded
|
||||
* constant and add to destination array. Can be used for erasure coding encode
|
||||
* and decode update when only one source is available at a time. Function
|
||||
* requires pre-calculation of a 32*vec byte constant array based on the input
|
||||
* coefficients.
|
||||
*
|
||||
* This function determines what instruction sets are enabled and selects the
|
||||
* appropriate version at runtime.
|
||||
*
|
||||
* @param len Length of each vector in bytes. Must be >= 32.
|
||||
* @param vec The number of vector sources or rows in the generator matrix
|
||||
* for coding.
|
||||
* @param vec_i The vector index corresponding to the single input source.
|
||||
* @param gftbls Pointer to array of input tables generated from coding
|
||||
* coefficients in ec_init_tables(). Must be of size 32*vec.
|
||||
* @param src Array of pointers to source inputs.
|
||||
* @param dest Pointer to destination data array.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_vect_mad(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src,
|
||||
unsigned char *dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector multiply accumulate, arch specific version.
|
||||
*
|
||||
* Arch specific version of gf_vect_mad() with same parameters.
|
||||
* @requires SSE4.1
|
||||
*/
|
||||
|
||||
void gf_vect_mad_sse(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src,
|
||||
unsigned char *dest);
|
||||
/**
|
||||
* @brief GF(2^8) vector multiply accumulate, arch specific version.
|
||||
*
|
||||
* Arch specific version of gf_vect_mad() with same parameters.
|
||||
* @requires AVX
|
||||
*/
|
||||
|
||||
void gf_vect_mad_avx(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src,
|
||||
unsigned char *dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector multiply accumulate, arch specific version.
|
||||
*
|
||||
* Arch specific version of gf_vect_mad() with same parameters.
|
||||
* @requires AVX2
|
||||
*/
|
||||
|
||||
void gf_vect_mad_avx2(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src,
|
||||
unsigned char *dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector multiply accumulate, baseline version.
|
||||
*
|
||||
* Baseline version of gf_vect_mad() with same parameters.
|
||||
*/
|
||||
|
||||
void gf_vect_mad_base(int len, int vec, int vec_i, unsigned char *v, unsigned char *src,
|
||||
unsigned char *dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector multiply with 2 accumulate. SSE version.
|
||||
*
|
||||
* Does a GF(2^8) multiply across each byte of input source with expanded
|
||||
* constants and add to destination arrays. Can be used for erasure coding
|
||||
* encode and decode update when only one source is available at a
|
||||
* time. Function requires pre-calculation of a 32*vec byte constant array based
|
||||
* on the input coefficients.
|
||||
* @requires SSE4.1
|
||||
*
|
||||
* @param len Length of each vector in bytes. Must be >= 32.
|
||||
* @param vec The number of vector sources or rows in the generator matrix
|
||||
* for coding.
|
||||
* @param vec_i The vector index corresponding to the single input source.
|
||||
* @param gftbls Pointer to array of input tables generated from coding
|
||||
* coefficients in ec_init_tables(). Must be of size 32*vec.
|
||||
* @param src Pointer to source input array.
|
||||
* @param dest Array of pointers to destination input/outputs.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_2vect_mad_sse(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src,
|
||||
unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector multiply with 2 accumulate. AVX version of gf_2vect_mad_sse().
|
||||
* @requires AVX
|
||||
*/
|
||||
void gf_2vect_mad_avx(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src,
|
||||
unsigned char **dest);
|
||||
/**
|
||||
* @brief GF(2^8) vector multiply with 2 accumulate. AVX2 version of gf_2vect_mad_sse().
|
||||
* @requires AVX2
|
||||
*/
|
||||
void gf_2vect_mad_avx2(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src,
|
||||
unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector multiply with 3 accumulate. SSE version.
|
||||
*
|
||||
* Does a GF(2^8) multiply across each byte of input source with expanded
|
||||
* constants and add to destination arrays. Can be used for erasure coding
|
||||
* encode and decode update when only one source is available at a
|
||||
* time. Function requires pre-calculation of a 32*vec byte constant array based
|
||||
* on the input coefficients.
|
||||
* @requires SSE4.1
|
||||
*
|
||||
* @param len Length of each vector in bytes. Must be >= 32.
|
||||
* @param vec The number of vector sources or rows in the generator matrix
|
||||
* for coding.
|
||||
* @param vec_i The vector index corresponding to the single input source.
|
||||
* @param gftbls Pointer to array of input tables generated from coding
|
||||
* coefficients in ec_init_tables(). Must be of size 32*vec.
|
||||
* @param src Pointer to source input array.
|
||||
* @param dest Array of pointers to destination input/outputs.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_3vect_mad_sse(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src,
|
||||
unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector multiply with 3 accumulate. AVX version of gf_3vect_mad_sse().
|
||||
* @requires AVX
|
||||
*/
|
||||
void gf_3vect_mad_avx(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src,
|
||||
unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector multiply with 3 accumulate. AVX2 version of gf_3vect_mad_sse().
|
||||
* @requires AVX2
|
||||
*/
|
||||
void gf_3vect_mad_avx2(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src,
|
||||
unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector multiply with 4 accumulate. SSE version.
|
||||
*
|
||||
* Does a GF(2^8) multiply across each byte of input source with expanded
|
||||
* constants and add to destination arrays. Can be used for erasure coding
|
||||
* encode and decode update when only one source is available at a
|
||||
* time. Function requires pre-calculation of a 32*vec byte constant array based
|
||||
* on the input coefficients.
|
||||
* @requires SSE4.1
|
||||
*
|
||||
* @param len Length of each vector in bytes. Must be >= 32.
|
||||
* @param vec The number of vector sources or rows in the generator matrix
|
||||
* for coding.
|
||||
* @param vec_i The vector index corresponding to the single input source.
|
||||
* @param gftbls Pointer to array of input tables generated from coding
|
||||
* coefficients in ec_init_tables(). Must be of size 32*vec.
|
||||
* @param src Pointer to source input array.
|
||||
* @param dest Array of pointers to destination input/outputs.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_4vect_mad_sse(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src,
|
||||
unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector multiply with 4 accumulate. AVX version of gf_4vect_mad_sse().
|
||||
* @requires AVX
|
||||
*/
|
||||
void gf_4vect_mad_avx(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src,
|
||||
unsigned char **dest);
|
||||
/**
|
||||
* @brief GF(2^8) vector multiply with 4 accumulate. AVX2 version of gf_4vect_mad_sse().
|
||||
* @requires AVX2
|
||||
*/
|
||||
void gf_4vect_mad_avx2(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src,
|
||||
unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector multiply with 5 accumulate. SSE version.
|
||||
* @requires SSE4.1
|
||||
*/
|
||||
void gf_5vect_mad_sse(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src,
|
||||
unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector multiply with 5 accumulate. AVX version.
|
||||
* @requires AVX
|
||||
*/
|
||||
void gf_5vect_mad_avx(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src,
|
||||
unsigned char **dest);
|
||||
/**
|
||||
* @brief GF(2^8) vector multiply with 5 accumulate. AVX2 version.
|
||||
* @requires AVX2
|
||||
*/
|
||||
void gf_5vect_mad_avx2(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src,
|
||||
unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector multiply with 6 accumulate. SSE version.
|
||||
* @requires SSE4.1
|
||||
*/
|
||||
void gf_6vect_mad_sse(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src,
|
||||
unsigned char **dest);
|
||||
/**
|
||||
* @brief GF(2^8) vector multiply with 6 accumulate. AVX version.
|
||||
* @requires AVX
|
||||
*/
|
||||
void gf_6vect_mad_avx(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src,
|
||||
unsigned char **dest);
|
||||
|
||||
/**
|
||||
* @brief GF(2^8) vector multiply with 6 accumulate. AVX2 version.
|
||||
* @requires AVX2
|
||||
*/
|
||||
void gf_6vect_mad_avx2(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src,
|
||||
unsigned char **dest);
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* The remaining are lib support functions used in GF(2^8) operations.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Single element GF(2^8) multiply.
|
||||
*
|
||||
* @param a Multiplicand a
|
||||
* @param b Multiplicand b
|
||||
* @returns Product of a and b in GF(2^8)
|
||||
*/
|
||||
|
||||
unsigned char gf_mul(unsigned char a, unsigned char b);
|
||||
|
||||
/**
|
||||
* @brief Single element GF(2^8) inverse.
|
||||
*
|
||||
* @param a Input element
|
||||
* @returns Field element b such that a x b = {1}
|
||||
*/
|
||||
|
||||
unsigned char gf_inv(unsigned char a);
|
||||
|
||||
/**
|
||||
* @brief Generate a matrix of coefficients to be used for encoding.
|
||||
*
|
||||
* Vandermonde matrix example of encoding coefficients where high portion of
|
||||
* matrix is identity matrix I and lower portion is constructed as 2^{i*(j-k+1)}
|
||||
* i:{0,k-1} j:{k,m-1}. Commonly used method for choosing coefficients in
|
||||
* erasure encoding but does not guarantee invertable for every sub matrix. For
|
||||
* large k it is possible to find cases where the decode matrix chosen from
|
||||
* sources and parity not in erasure are not invertable. Users may want to
|
||||
* adjust for k > 5.
|
||||
*
|
||||
* @param a [mxk] array to hold coefficients
|
||||
* @param m number of rows in matrix corresponding to srcs + parity.
|
||||
* @param k number of columns in matrix corresponding to srcs.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_gen_rs_matrix(unsigned char *a, int m, int k);
|
||||
|
||||
/**
|
||||
* @brief Generate a Cauchy matrix of coefficients to be used for encoding.
|
||||
*
|
||||
* Cauchy matrix example of encoding coefficients where high portion of matrix
|
||||
* is identity matrix I and lower portion is constructed as 1/(i + j) | i != j,
|
||||
* i:{0,k-1} j:{k,m-1}. Any sub-matrix of a Cauchy matrix should be invertable.
|
||||
*
|
||||
* @param a [mxk] array to hold coefficients
|
||||
* @param m number of rows in matrix corresponding to srcs + parity.
|
||||
* @param k number of columns in matrix corresponding to srcs.
|
||||
* @returns none
|
||||
*/
|
||||
|
||||
void gf_gen_cauchy1_matrix(unsigned char *a, int m, int k);
|
||||
|
||||
/**
|
||||
* @brief Invert a matrix in GF(2^8)
|
||||
*
|
||||
* @param in input matrix
|
||||
* @param out output matrix such that [in] x [out] = [I] - identity matrix
|
||||
* @param n size of matrix [nxn]
|
||||
* @returns 0 successful, other fail on singular input matrix
|
||||
*/
|
||||
|
||||
int gf_invert_matrix(unsigned char *in, unsigned char *out, const int n);
|
||||
|
||||
|
||||
/*************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //_ERASURE_CODE_H_
|
||||
@@ -1,267 +0,0 @@
|
||||
/**********************************************************************
|
||||
Copyright(c) 2011-2015 Intel Corporation All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Intel Corporation nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**********************************************************************/
|
||||
#include <limits.h>
|
||||
#include "ec_code.h"
|
||||
#include "ec_types.h"
|
||||
|
||||
void ec_init_tables(int k, int rows, unsigned char *a, unsigned char *g_tbls)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < rows; i++) {
|
||||
for (j = 0; j < k; j++) {
|
||||
gf_vect_mul_init(*a++, g_tbls);
|
||||
g_tbls += 32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ec_encode_data_sse(int len, int k, int rows, unsigned char *g_tbls, unsigned char **data,
|
||||
unsigned char **coding)
|
||||
{
|
||||
|
||||
if (len < 16) {
|
||||
ec_encode_data_base(len, k, rows, g_tbls, data, coding);
|
||||
return;
|
||||
}
|
||||
|
||||
while (rows >= 4) {
|
||||
gf_4vect_dot_prod_sse(len, k, g_tbls, data, coding);
|
||||
g_tbls += 4 * k * 32;
|
||||
coding += 4;
|
||||
rows -= 4;
|
||||
}
|
||||
switch (rows) {
|
||||
case 3:
|
||||
gf_3vect_dot_prod_sse(len, k, g_tbls, data, coding);
|
||||
break;
|
||||
case 2:
|
||||
gf_2vect_dot_prod_sse(len, k, g_tbls, data, coding);
|
||||
break;
|
||||
case 1:
|
||||
gf_vect_dot_prod_sse(len, k, g_tbls, data, *coding);
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ec_encode_data_avx(int len, int k, int rows, unsigned char *g_tbls, unsigned char **data,
|
||||
unsigned char **coding)
|
||||
{
|
||||
if (len < 16) {
|
||||
ec_encode_data_base(len, k, rows, g_tbls, data, coding);
|
||||
return;
|
||||
}
|
||||
|
||||
while (rows >= 4) {
|
||||
gf_4vect_dot_prod_avx(len, k, g_tbls, data, coding);
|
||||
g_tbls += 4 * k * 32;
|
||||
coding += 4;
|
||||
rows -= 4;
|
||||
}
|
||||
switch (rows) {
|
||||
case 3:
|
||||
gf_3vect_dot_prod_avx(len, k, g_tbls, data, coding);
|
||||
break;
|
||||
case 2:
|
||||
gf_2vect_dot_prod_avx(len, k, g_tbls, data, coding);
|
||||
break;
|
||||
case 1:
|
||||
gf_vect_dot_prod_avx(len, k, g_tbls, data, *coding);
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ec_encode_data_avx2(int len, int k, int rows, unsigned char *g_tbls, unsigned char **data,
|
||||
unsigned char **coding)
|
||||
{
|
||||
|
||||
if (len < 32) {
|
||||
ec_encode_data_base(len, k, rows, g_tbls, data, coding);
|
||||
return;
|
||||
}
|
||||
|
||||
while (rows >= 4) {
|
||||
gf_4vect_dot_prod_avx2(len, k, g_tbls, data, coding);
|
||||
g_tbls += 4 * k * 32;
|
||||
coding += 4;
|
||||
rows -= 4;
|
||||
}
|
||||
switch (rows) {
|
||||
case 3:
|
||||
gf_3vect_dot_prod_avx2(len, k, g_tbls, data, coding);
|
||||
break;
|
||||
case 2:
|
||||
gf_2vect_dot_prod_avx2(len, k, g_tbls, data, coding);
|
||||
break;
|
||||
case 1:
|
||||
gf_vect_dot_prod_avx2(len, k, g_tbls, data, *coding);
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if __WORDSIZE == 64 || _WIN64 || __x86_64__
|
||||
|
||||
void ec_encode_data_update_sse(int len, int k, int rows, int vec_i, unsigned char *g_tbls,
|
||||
unsigned char *data, unsigned char **coding)
|
||||
{
|
||||
if (len < 16) {
|
||||
ec_encode_data_update_base(len, k, rows, vec_i, g_tbls, data, coding);
|
||||
return;
|
||||
}
|
||||
|
||||
while (rows > 6) {
|
||||
gf_6vect_mad_sse(len, k, vec_i, g_tbls, data, coding);
|
||||
g_tbls += 6 * k * 32;
|
||||
coding += 6;
|
||||
rows -= 6;
|
||||
}
|
||||
switch (rows) {
|
||||
case 6:
|
||||
gf_6vect_mad_sse(len, k, vec_i, g_tbls, data, coding);
|
||||
break;
|
||||
case 5:
|
||||
gf_5vect_mad_sse(len, k, vec_i, g_tbls, data, coding);
|
||||
break;
|
||||
case 4:
|
||||
gf_4vect_mad_sse(len, k, vec_i, g_tbls, data, coding);
|
||||
break;
|
||||
case 3:
|
||||
gf_3vect_mad_sse(len, k, vec_i, g_tbls, data, coding);
|
||||
break;
|
||||
case 2:
|
||||
gf_2vect_mad_sse(len, k, vec_i, g_tbls, data, coding);
|
||||
break;
|
||||
case 1:
|
||||
gf_vect_mad_sse(len, k, vec_i, g_tbls, data, *coding);
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ec_encode_data_update_avx(int len, int k, int rows, int vec_i, unsigned char *g_tbls,
|
||||
unsigned char *data, unsigned char **coding)
|
||||
{
|
||||
if (len < 16) {
|
||||
ec_encode_data_update_base(len, k, rows, vec_i, g_tbls, data, coding);
|
||||
return;
|
||||
}
|
||||
while (rows > 6) {
|
||||
gf_6vect_mad_avx(len, k, vec_i, g_tbls, data, coding);
|
||||
g_tbls += 6 * k * 32;
|
||||
coding += 6;
|
||||
rows -= 6;
|
||||
}
|
||||
switch (rows) {
|
||||
case 6:
|
||||
gf_6vect_mad_avx(len, k, vec_i, g_tbls, data, coding);
|
||||
break;
|
||||
case 5:
|
||||
gf_5vect_mad_avx(len, k, vec_i, g_tbls, data, coding);
|
||||
break;
|
||||
case 4:
|
||||
gf_4vect_mad_avx(len, k, vec_i, g_tbls, data, coding);
|
||||
break;
|
||||
case 3:
|
||||
gf_3vect_mad_avx(len, k, vec_i, g_tbls, data, coding);
|
||||
break;
|
||||
case 2:
|
||||
gf_2vect_mad_avx(len, k, vec_i, g_tbls, data, coding);
|
||||
break;
|
||||
case 1:
|
||||
gf_vect_mad_avx(len, k, vec_i, g_tbls, data, *coding);
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ec_encode_data_update_avx2(int len, int k, int rows, int vec_i, unsigned char *g_tbls,
|
||||
unsigned char *data, unsigned char **coding)
|
||||
{
|
||||
if (len < 32) {
|
||||
ec_encode_data_update_base(len, k, rows, vec_i, g_tbls, data, coding);
|
||||
return;
|
||||
}
|
||||
while (rows > 6) {
|
||||
gf_6vect_mad_avx2(len, k, vec_i, g_tbls, data, coding);
|
||||
g_tbls += 6 * k * 32;
|
||||
coding += 6;
|
||||
rows -= 6;
|
||||
}
|
||||
switch (rows) {
|
||||
case 6:
|
||||
gf_6vect_mad_avx2(len, k, vec_i, g_tbls, data, coding);
|
||||
break;
|
||||
case 5:
|
||||
gf_5vect_mad_avx2(len, k, vec_i, g_tbls, data, coding);
|
||||
break;
|
||||
case 4:
|
||||
gf_4vect_mad_avx2(len, k, vec_i, g_tbls, data, coding);
|
||||
break;
|
||||
case 3:
|
||||
gf_3vect_mad_avx2(len, k, vec_i, g_tbls, data, coding);
|
||||
break;
|
||||
case 2:
|
||||
gf_2vect_mad_avx2(len, k, vec_i, g_tbls, data, coding);
|
||||
break;
|
||||
case 1:
|
||||
gf_vect_mad_avx2(len, k, vec_i, g_tbls, data, *coding);
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //__WORDSIZE == 64 || _WIN64 || __x86_64__
|
||||
|
||||
struct slver {
|
||||
UINT16 snum;
|
||||
UINT8 ver;
|
||||
UINT8 core;
|
||||
};
|
||||
|
||||
// Version info
|
||||
struct slver ec_init_tables_slver_00010068;
|
||||
struct slver ec_init_tables_slver = { 0x0068, 0x01, 0x00 };
|
||||
|
||||
struct slver ec_encode_data_sse_slver_00020069;
|
||||
struct slver ec_encode_data_sse_slver = { 0x0069, 0x02, 0x00 };
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2014 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __COMMON_H__
|
||||
#define __COMMON_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int32_t minio_init_encoder (int k, int m,
|
||||
unsigned char **encode_matrix,
|
||||
unsigned char **encode_tbls);
|
||||
|
||||
int32_t minio_init_decoder (int32_t *error_index,
|
||||
int k, int n, int errs,
|
||||
unsigned char *encoding_matrix,
|
||||
unsigned char **decode_matrix,
|
||||
unsigned char **decode_tbls,
|
||||
uint32_t **decode_index);
|
||||
|
||||
int32_t minio_get_source_target (int errs, int k, int m,
|
||||
int32_t *error_index,
|
||||
uint32_t *decode_index,
|
||||
unsigned char **buffs,
|
||||
unsigned char ***source,
|
||||
unsigned char ***target);
|
||||
#endif /* __COMMON_H__ */
|
||||
@@ -1,142 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2014 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ec.h"
|
||||
#include "ec_minio_common.h"
|
||||
|
||||
static
|
||||
int32_t _minio_src_index_in_error (int r, int32_t *error_index, int errs)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < errs; i++) {
|
||||
if (error_index[i] == r) {
|
||||
// true
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// false
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Separate out source data and target buffers
|
||||
int32_t minio_get_source_target (int errs, int k, int m,
|
||||
int32_t *error_index,
|
||||
uint32_t *decode_index,
|
||||
unsigned char **buffs,
|
||||
unsigned char ***source,
|
||||
unsigned char ***target)
|
||||
{
|
||||
int i;
|
||||
unsigned char *tmp_source[k];
|
||||
unsigned char *tmp_target[m];
|
||||
|
||||
if (k < 0 || m < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset (tmp_source, 0, k);
|
||||
memset (tmp_target, 0, m);
|
||||
|
||||
for (i = 0; i < k; i++) {
|
||||
tmp_source[i] = (unsigned char *) buffs[decode_index[i]];
|
||||
}
|
||||
|
||||
for (i = 0; i < m; i++) {
|
||||
if (i < errs)
|
||||
tmp_target[i] = (unsigned char *) buffs[error_index[i]];
|
||||
}
|
||||
|
||||
*source = tmp_source;
|
||||
*target = tmp_target;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Generate decode matrix during the decoding phase
|
||||
*/
|
||||
|
||||
int minio_init_decoder (int32_t *error_index,
|
||||
int k, int n, int errs,
|
||||
unsigned char *encode_matrix,
|
||||
unsigned char **decode_matrix,
|
||||
unsigned char **decode_tbls,
|
||||
uint32_t **decode_index)
|
||||
{
|
||||
int i, j, r, l;
|
||||
|
||||
uint32_t *tmp_decode_index = (uint32_t *) malloc(sizeof(uint32_t) * k);
|
||||
unsigned char *input_matrix;
|
||||
unsigned char *inverse_matrix;
|
||||
unsigned char *tmp_decode_matrix;
|
||||
unsigned char *tmp_decode_tbls;
|
||||
|
||||
input_matrix = (unsigned char *) malloc(sizeof(unsigned char) * k * n);
|
||||
inverse_matrix = (unsigned char *) malloc(sizeof(unsigned char) * k * n);
|
||||
tmp_decode_matrix = (unsigned char *) malloc(sizeof(unsigned char) * k * n);;
|
||||
tmp_decode_tbls = (unsigned char *) malloc(sizeof(unsigned char) * k * n * 32);
|
||||
|
||||
for (i = 0, r = 0; i < k; i++, r++) {
|
||||
while (_minio_src_index_in_error(r, error_index, errs))
|
||||
r++;
|
||||
for (j = 0; j < k; j++) {
|
||||
input_matrix[k * i + j] = encode_matrix[k * r + j];
|
||||
}
|
||||
tmp_decode_index[i] = r;
|
||||
}
|
||||
|
||||
// Not all vandermonde matrix can be inverted
|
||||
if (gf_invert_matrix(input_matrix, inverse_matrix, k) < 0) {
|
||||
free(tmp_decode_matrix);
|
||||
free(tmp_decode_tbls);
|
||||
free(tmp_decode_index);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (l = 0; l < errs; l++) {
|
||||
if (error_index[l] < k) {
|
||||
// decoding matrix elements for data chunks
|
||||
for (j = 0; j < k; j++) {
|
||||
tmp_decode_matrix[k * l + j] =
|
||||
inverse_matrix[k *
|
||||
error_index[l] + j];
|
||||
}
|
||||
} else {
|
||||
// decoding matrix element for coding chunks
|
||||
for (i = 0; i < k; i++) {
|
||||
unsigned char s = 0;
|
||||
for (j = 0; j < k; j++) {
|
||||
s ^= gf_mul(inverse_matrix[j * k + i],
|
||||
encode_matrix[k *
|
||||
error_index[l] + j]);
|
||||
}
|
||||
tmp_decode_matrix[k * l + i] = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ec_init_tables (k, errs, tmp_decode_matrix, tmp_decode_tbls);
|
||||
|
||||
*decode_matrix = tmp_decode_matrix;
|
||||
*decode_tbls = tmp_decode_tbls;
|
||||
*decode_index = tmp_decode_index;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2014 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ec.h"
|
||||
#include "ec_minio_common.h"
|
||||
|
||||
/*
|
||||
Generate encode matrix during the encoding phase
|
||||
*/
|
||||
|
||||
int32_t minio_init_encoder (int k, int m, unsigned char **encode_matrix, unsigned char **encode_tbls)
|
||||
{
|
||||
unsigned char *tmp_matrix;
|
||||
unsigned char *tmp_tbls;
|
||||
|
||||
tmp_matrix = (unsigned char *) malloc (k * (k + m));
|
||||
tmp_tbls = (unsigned char *) malloc (k * (k + m) * 32);
|
||||
|
||||
if (k < 5) {
|
||||
/*
|
||||
Commonly used method for choosing coefficients in erasure
|
||||
encoding but does not guarantee invertable for every sub
|
||||
matrix. For large k it is possible to find cases where the
|
||||
decode matrix chosen from sources and parity not in erasure
|
||||
are not invertable. Users may want to adjust for k > 5.
|
||||
-- Intel
|
||||
*/
|
||||
gf_gen_rs_matrix (tmp_matrix, k + m, k);
|
||||
} else {
|
||||
gf_gen_cauchy1_matrix (tmp_matrix, k + m, k);
|
||||
}
|
||||
|
||||
ec_init_tables(k, m, &tmp_matrix[k * k], tmp_tbls);
|
||||
|
||||
*encode_matrix = tmp_matrix;
|
||||
*encode_tbls = tmp_tbls;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,404 +0,0 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Copyright(c) 2011-2015 Intel Corporation All rights reserved.
|
||||
;
|
||||
; Redistribution and use in source and binary forms, with or without
|
||||
; modification, are permitted provided that the following conditions
|
||||
; are met:
|
||||
; * Redistributions of source code must retain the above copyright
|
||||
; notice, this list of conditions and the following disclaimer.
|
||||
; * Redistributions in binary form must reproduce the above copyright
|
||||
; notice, this list of conditions and the following disclaimer in
|
||||
; the documentation and/or other materials provided with the
|
||||
; distribution.
|
||||
; * Neither the name of Intel Corporation nor the names of its
|
||||
; contributors may be used to endorse or promote products derived
|
||||
; from this software without specific prior written permission.
|
||||
;
|
||||
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
%ifidn __OUTPUT_FORMAT__, elf64
|
||||
%define WRT_OPT wrt ..plt
|
||||
%else
|
||||
%define WRT_OPT
|
||||
%endif
|
||||
|
||||
%include "ec_reg_sizes.asm"
|
||||
|
||||
%ifidn __OUTPUT_FORMAT__, elf32
|
||||
|
||||
[bits 32]
|
||||
|
||||
%define def_wrd dd
|
||||
%define wrd_sz dword
|
||||
%define arg1 esi
|
||||
%define arg2 eax
|
||||
%define arg3 ebx
|
||||
%define arg4 ecx
|
||||
%define arg5 edx
|
||||
|
||||
%else
|
||||
|
||||
default rel
|
||||
[bits 64]
|
||||
|
||||
%define def_wrd dq
|
||||
%define wrd_sz qword
|
||||
%define arg1 rsi
|
||||
%define arg2 rax
|
||||
%define arg3 rbx
|
||||
%define arg4 rcx
|
||||
%define arg5 rdx
|
||||
|
||||
|
||||
extern ec_encode_data_update_sse
|
||||
extern ec_encode_data_update_avx
|
||||
extern ec_encode_data_update_avx2
|
||||
extern gf_vect_mul_sse
|
||||
extern gf_vect_mul_avx
|
||||
|
||||
extern gf_vect_mad_sse
|
||||
extern gf_vect_mad_avx
|
||||
extern gf_vect_mad_avx2
|
||||
%endif
|
||||
|
||||
extern gf_vect_mul_base
|
||||
extern ec_encode_data_base
|
||||
extern ec_encode_data_update_base
|
||||
extern gf_vect_dot_prod_base
|
||||
extern gf_vect_mad_base
|
||||
|
||||
extern gf_vect_dot_prod_sse
|
||||
extern gf_vect_dot_prod_avx
|
||||
extern gf_vect_dot_prod_avx2
|
||||
extern ec_encode_data_sse
|
||||
extern ec_encode_data_avx
|
||||
extern ec_encode_data_avx2
|
||||
|
||||
|
||||
section .data
|
||||
;;; *_mbinit are initial values for *_dispatched; is updated on first call.
|
||||
;;; Therefore, *_dispatch_init is only executed on first call.
|
||||
|
||||
ec_encode_data_dispatched:
|
||||
def_wrd ec_encode_data_mbinit
|
||||
|
||||
gf_vect_mul_dispatched:
|
||||
def_wrd gf_vect_mul_mbinit
|
||||
|
||||
gf_vect_dot_prod_dispatched:
|
||||
def_wrd gf_vect_dot_prod_mbinit
|
||||
|
||||
ec_encode_data_update_dispatched:
|
||||
def_wrd ec_encode_data_update_mbinit
|
||||
|
||||
gf_vect_mad_dispatched:
|
||||
def_wrd gf_vect_mad_mbinit
|
||||
|
||||
section .text
|
||||
;;;;
|
||||
; ec_encode_data multibinary function
|
||||
;;;;
|
||||
global ec_encode_data:function
|
||||
ec_encode_data_mbinit:
|
||||
call ec_encode_data_dispatch_init
|
||||
|
||||
ec_encode_data:
|
||||
jmp wrd_sz [ec_encode_data_dispatched]
|
||||
|
||||
ec_encode_data_dispatch_init:
|
||||
push arg1
|
||||
push arg2
|
||||
push arg3
|
||||
push arg4
|
||||
push arg5
|
||||
lea arg1, [ec_encode_data_base WRT_OPT] ; Default
|
||||
|
||||
mov eax, 1
|
||||
cpuid
|
||||
lea arg3, [ec_encode_data_sse WRT_OPT]
|
||||
test ecx, FLAG_CPUID1_ECX_SSE4_1
|
||||
cmovne arg1, arg3
|
||||
|
||||
and ecx, (FLAG_CPUID1_ECX_AVX | FLAG_CPUID1_ECX_OSXSAVE)
|
||||
cmp ecx, (FLAG_CPUID1_ECX_AVX | FLAG_CPUID1_ECX_OSXSAVE)
|
||||
lea arg3, [ec_encode_data_avx WRT_OPT]
|
||||
|
||||
jne _done_ec_encode_data_init
|
||||
mov arg1, arg3
|
||||
|
||||
;; Try for AVX2
|
||||
xor ecx, ecx
|
||||
mov eax, 7
|
||||
cpuid
|
||||
test ebx, FLAG_CPUID1_EBX_AVX2
|
||||
lea arg3, [ec_encode_data_avx2 WRT_OPT]
|
||||
cmovne arg1, arg3
|
||||
;; Does it have xmm and ymm support
|
||||
xor ecx, ecx
|
||||
xgetbv
|
||||
and eax, FLAG_XGETBV_EAX_XMM_YMM
|
||||
cmp eax, FLAG_XGETBV_EAX_XMM_YMM
|
||||
je _done_ec_encode_data_init
|
||||
lea arg1, [ec_encode_data_sse WRT_OPT]
|
||||
|
||||
_done_ec_encode_data_init:
|
||||
pop arg5
|
||||
pop arg4
|
||||
pop arg3
|
||||
pop arg2
|
||||
mov [ec_encode_data_dispatched], arg1
|
||||
pop arg1
|
||||
ret
|
||||
|
||||
;;;;
|
||||
; gf_vect_mul multibinary function
|
||||
;;;;
|
||||
global gf_vect_mul:function
|
||||
gf_vect_mul_mbinit:
|
||||
call gf_vect_mul_dispatch_init
|
||||
|
||||
gf_vect_mul:
|
||||
jmp wrd_sz [gf_vect_mul_dispatched]
|
||||
|
||||
gf_vect_mul_dispatch_init:
|
||||
push arg1
|
||||
%ifidn __OUTPUT_FORMAT__, elf32 ;; 32-bit check
|
||||
lea arg1, [gf_vect_mul_base]
|
||||
%else
|
||||
push rax
|
||||
push rbx
|
||||
push rcx
|
||||
push rdx
|
||||
lea arg1, [gf_vect_mul_base WRT_OPT] ; Default
|
||||
|
||||
mov eax, 1
|
||||
cpuid
|
||||
test ecx, FLAG_CPUID1_ECX_SSE4_2
|
||||
lea rbx, [gf_vect_mul_sse WRT_OPT]
|
||||
je _done_gf_vect_mul_dispatch_init
|
||||
mov arg1, rbx
|
||||
|
||||
;; Try for AVX
|
||||
and ecx, (FLAG_CPUID1_ECX_OSXSAVE | FLAG_CPUID1_ECX_AVX)
|
||||
cmp ecx, (FLAG_CPUID1_ECX_OSXSAVE | FLAG_CPUID1_ECX_AVX)
|
||||
jne _done_gf_vect_mul_dispatch_init
|
||||
|
||||
;; Does it have xmm and ymm support
|
||||
xor ecx, ecx
|
||||
xgetbv
|
||||
and eax, FLAG_XGETBV_EAX_XMM_YMM
|
||||
cmp eax, FLAG_XGETBV_EAX_XMM_YMM
|
||||
jne _done_gf_vect_mul_dispatch_init
|
||||
lea arg1, [gf_vect_mul_avx WRT_OPT]
|
||||
|
||||
_done_gf_vect_mul_dispatch_init:
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop rbx
|
||||
pop rax
|
||||
%endif ;; END 32-bit check
|
||||
mov [gf_vect_mul_dispatched], arg1
|
||||
pop arg1
|
||||
ret
|
||||
|
||||
;;;;
|
||||
; ec_encode_data_update multibinary function
|
||||
;;;;
|
||||
global ec_encode_data_update:function
|
||||
ec_encode_data_update_mbinit:
|
||||
call ec_encode_data_update_dispatch_init
|
||||
|
||||
ec_encode_data_update:
|
||||
jmp wrd_sz [ec_encode_data_update_dispatched]
|
||||
|
||||
ec_encode_data_update_dispatch_init:
|
||||
push arg1
|
||||
%ifidn __OUTPUT_FORMAT__, elf32 ;; 32-bit check
|
||||
lea arg1, [ec_encode_data_update_base]
|
||||
%else
|
||||
push rax
|
||||
push rbx
|
||||
push rcx
|
||||
push rdx
|
||||
lea arg1, [ec_encode_data_update_base WRT_OPT] ; Default
|
||||
|
||||
mov eax, 1
|
||||
cpuid
|
||||
lea rbx, [ec_encode_data_update_sse WRT_OPT]
|
||||
test ecx, FLAG_CPUID1_ECX_SSE4_1
|
||||
cmovne arg1, rbx
|
||||
|
||||
and ecx, (FLAG_CPUID1_ECX_AVX | FLAG_CPUID1_ECX_OSXSAVE)
|
||||
cmp ecx, (FLAG_CPUID1_ECX_AVX | FLAG_CPUID1_ECX_OSXSAVE)
|
||||
lea rbx, [ec_encode_data_update_avx WRT_OPT]
|
||||
|
||||
jne _done_ec_encode_data_update_init
|
||||
mov rsi, rbx
|
||||
|
||||
;; Try for AVX2
|
||||
xor ecx, ecx
|
||||
mov eax, 7
|
||||
cpuid
|
||||
test ebx, FLAG_CPUID1_EBX_AVX2
|
||||
lea rbx, [ec_encode_data_update_avx2 WRT_OPT]
|
||||
cmovne rsi, rbx
|
||||
|
||||
;; Does it have xmm and ymm support
|
||||
xor ecx, ecx
|
||||
xgetbv
|
||||
and eax, FLAG_XGETBV_EAX_XMM_YMM
|
||||
cmp eax, FLAG_XGETBV_EAX_XMM_YMM
|
||||
je _done_ec_encode_data_update_init
|
||||
lea rsi, [ec_encode_data_update_sse WRT_OPT]
|
||||
|
||||
_done_ec_encode_data_update_init:
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop rbx
|
||||
pop rax
|
||||
%endif ;; END 32-bit check
|
||||
mov [ec_encode_data_update_dispatched], arg1
|
||||
pop arg1
|
||||
ret
|
||||
|
||||
;;;;
|
||||
; gf_vect_dot_prod multibinary function
|
||||
;;;;
|
||||
global gf_vect_dot_prod:function
|
||||
gf_vect_dot_prod_mbinit:
|
||||
call gf_vect_dot_prod_dispatch_init
|
||||
|
||||
gf_vect_dot_prod:
|
||||
jmp wrd_sz [gf_vect_dot_prod_dispatched]
|
||||
|
||||
gf_vect_dot_prod_dispatch_init:
|
||||
push arg1
|
||||
push arg2
|
||||
push arg3
|
||||
push arg4
|
||||
push arg5
|
||||
lea arg1, [gf_vect_dot_prod_base WRT_OPT] ; Default
|
||||
|
||||
mov eax, 1
|
||||
cpuid
|
||||
lea arg3, [gf_vect_dot_prod_sse WRT_OPT]
|
||||
test ecx, FLAG_CPUID1_ECX_SSE4_1
|
||||
cmovne arg1, arg3
|
||||
|
||||
and ecx, (FLAG_CPUID1_ECX_AVX | FLAG_CPUID1_ECX_OSXSAVE)
|
||||
cmp ecx, (FLAG_CPUID1_ECX_AVX | FLAG_CPUID1_ECX_OSXSAVE)
|
||||
lea arg3, [gf_vect_dot_prod_avx WRT_OPT]
|
||||
|
||||
jne _done_gf_vect_dot_prod_init
|
||||
mov arg1, arg3
|
||||
|
||||
;; Try for AVX2
|
||||
xor ecx, ecx
|
||||
mov eax, 7
|
||||
cpuid
|
||||
test ebx, FLAG_CPUID1_EBX_AVX2
|
||||
lea arg3, [gf_vect_dot_prod_avx2 WRT_OPT]
|
||||
cmovne arg1, arg3
|
||||
;; Does it have xmm and ymm support
|
||||
xor ecx, ecx
|
||||
xgetbv
|
||||
and eax, FLAG_XGETBV_EAX_XMM_YMM
|
||||
cmp eax, FLAG_XGETBV_EAX_XMM_YMM
|
||||
je _done_gf_vect_dot_prod_init
|
||||
lea arg1, [gf_vect_dot_prod_sse WRT_OPT]
|
||||
|
||||
_done_gf_vect_dot_prod_init:
|
||||
pop arg5
|
||||
pop arg4
|
||||
pop arg3
|
||||
pop arg2
|
||||
mov [gf_vect_dot_prod_dispatched], arg1
|
||||
pop arg1
|
||||
ret
|
||||
|
||||
;;;;
|
||||
; gf_vect_mad multibinary function
|
||||
;;;;
|
||||
global gf_vect_mad:function
|
||||
gf_vect_mad_mbinit:
|
||||
call gf_vect_mad_dispatch_init
|
||||
|
||||
gf_vect_mad:
|
||||
jmp wrd_sz [gf_vect_mad_dispatched]
|
||||
|
||||
gf_vect_mad_dispatch_init:
|
||||
push arg1
|
||||
%ifidn __OUTPUT_FORMAT__, elf32 ;; 32-bit check
|
||||
lea arg1, [gf_vect_mad_base]
|
||||
%else
|
||||
push rax
|
||||
push rbx
|
||||
push rcx
|
||||
push rdx
|
||||
lea arg1, [gf_vect_mad_base WRT_OPT] ; Default
|
||||
|
||||
mov eax, 1
|
||||
cpuid
|
||||
lea rbx, [gf_vect_mad_sse WRT_OPT]
|
||||
test ecx, FLAG_CPUID1_ECX_SSE4_1
|
||||
cmovne arg1, rbx
|
||||
|
||||
and ecx, (FLAG_CPUID1_ECX_AVX | FLAG_CPUID1_ECX_OSXSAVE)
|
||||
cmp ecx, (FLAG_CPUID1_ECX_AVX | FLAG_CPUID1_ECX_OSXSAVE)
|
||||
lea rbx, [gf_vect_mad_avx WRT_OPT]
|
||||
|
||||
jne _done_gf_vect_mad_init
|
||||
mov rsi, rbx
|
||||
|
||||
;; Try for AVX2
|
||||
xor ecx, ecx
|
||||
mov eax, 7
|
||||
cpuid
|
||||
test ebx, FLAG_CPUID1_EBX_AVX2
|
||||
lea rbx, [gf_vect_mad_avx2 WRT_OPT]
|
||||
cmovne rsi, rbx
|
||||
|
||||
;; Does it have xmm and ymm support
|
||||
xor ecx, ecx
|
||||
xgetbv
|
||||
and eax, FLAG_XGETBV_EAX_XMM_YMM
|
||||
cmp eax, FLAG_XGETBV_EAX_XMM_YMM
|
||||
je _done_gf_vect_mad_init
|
||||
lea rsi, [gf_vect_mad_sse WRT_OPT]
|
||||
|
||||
_done_gf_vect_mad_init:
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop rbx
|
||||
pop rax
|
||||
%endif ;; END 32-bit check
|
||||
mov [gf_vect_mad_dispatched], arg1
|
||||
pop arg1
|
||||
ret
|
||||
|
||||
%macro slversion 4
|
||||
global %1_slver_%2%3%4
|
||||
global %1_slver
|
||||
%1_slver:
|
||||
%1_slver_%2%3%4:
|
||||
dw 0x%4
|
||||
db 0x%3, 0x%2
|
||||
%endmacro
|
||||
|
||||
;;; func core, ver, snum
|
||||
slversion ec_encode_data, 00, 03, 0133
|
||||
slversion gf_vect_mul, 00, 02, 0134
|
||||
slversion ec_encode_data_update, 00, 02, 0212
|
||||
slversion gf_vect_dot_prod, 00, 02, 0138
|
||||
slversion gf_vect_mad, 00, 01, 0213
|
||||
@@ -1,107 +0,0 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Copyright(c) 2011-2015 Intel Corporation All rights reserved.
|
||||
;
|
||||
; Redistribution and use in source and binary forms, with or without
|
||||
; modification, are permitted provided that the following conditions
|
||||
; are met:
|
||||
; * Redistributions of source code must retain the above copyright
|
||||
; notice, this list of conditions and the following disclaimer.
|
||||
; * Redistributions in binary form must reproduce the above copyright
|
||||
; notice, this list of conditions and the following disclaimer in
|
||||
; the documentation and/or other materials provided with the
|
||||
; distribution.
|
||||
; * Neither the name of Intel Corporation nor the names of its
|
||||
; contributors may be used to endorse or promote products derived
|
||||
; from this software without specific prior written permission.
|
||||
;
|
||||
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
%define EFLAGS_HAS_CPUID (1<<21)
|
||||
%define FLAG_CPUID1_ECX_CLMUL (1<<1)
|
||||
%define FLAG_CPUID1_EDX_SSE2 (1<<26)
|
||||
%define FLAG_CPUID1_ECX_SSE3 (1)
|
||||
%define FLAG_CPUID1_ECX_SSE4_1 (1<<19)
|
||||
%define FLAG_CPUID1_ECX_SSE4_2 (1<<20)
|
||||
%define FLAG_CPUID1_ECX_POPCNT (1<<23)
|
||||
%define FLAG_CPUID1_ECX_AESNI (1<<25)
|
||||
%define FLAG_CPUID1_ECX_OSXSAVE (1<<27)
|
||||
%define FLAG_CPUID1_ECX_AVX (1<<28)
|
||||
%define FLAG_CPUID1_EBX_AVX2 (1<<5)
|
||||
%define FLAG_XGETBV_EAX_XMM_YMM 0x6
|
||||
|
||||
%define FLAG_CPUID1_EAX_AVOTON 0x000406d0
|
||||
|
||||
; define d and w variants for registers
|
||||
|
||||
%define raxd eax
|
||||
%define raxw ax
|
||||
%define raxb al
|
||||
|
||||
%define rbxd ebx
|
||||
%define rbxw bx
|
||||
%define rbxb bl
|
||||
|
||||
%define rcxd ecx
|
||||
%define rcxw cx
|
||||
%define rcxb cl
|
||||
|
||||
%define rdxd edx
|
||||
%define rdxw dx
|
||||
%define rdxb dl
|
||||
|
||||
%define rsid esi
|
||||
%define rsiw si
|
||||
%define rsib sil
|
||||
|
||||
%define rdid edi
|
||||
%define rdiw di
|
||||
%define rdib dil
|
||||
|
||||
%define rbpd ebp
|
||||
%define rbpw bp
|
||||
%define rbpb bpl
|
||||
|
||||
%define ymm0x xmm0
|
||||
%define ymm1x xmm1
|
||||
%define ymm2x xmm2
|
||||
%define ymm3x xmm3
|
||||
%define ymm4x xmm4
|
||||
%define ymm5x xmm5
|
||||
%define ymm6x xmm6
|
||||
%define ymm7x xmm7
|
||||
%define ymm8x xmm8
|
||||
%define ymm9x xmm9
|
||||
%define ymm10x xmm10
|
||||
%define ymm11x xmm11
|
||||
%define ymm12x xmm12
|
||||
%define ymm13x xmm13
|
||||
%define ymm14x xmm14
|
||||
%define ymm15x xmm15
|
||||
|
||||
%define DWORD(reg) reg %+ d
|
||||
%define WORD(reg) reg %+ w
|
||||
%define BYTE(reg) reg %+ b
|
||||
|
||||
%define XWORD(reg) reg %+ x
|
||||
|
||||
%ifidn __OUTPUT_FORMAT__,elf32
|
||||
section .note.GNU-stack noalloc noexec nowrite progbits
|
||||
section .text
|
||||
%endif
|
||||
|
||||
%ifidn __OUTPUT_FORMAT__,elf64
|
||||
section .note.GNU-stack noalloc noexec nowrite progbits
|
||||
section .text
|
||||
%endif
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/**********************************************************************
|
||||
Copyright(c) 2011-2015 Intel Corporation All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Intel Corporation nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**********************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* @file types.h
|
||||
* @brief Defines standard width types.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TYPES_H
|
||||
#define __TYPES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !defined(__unix__) && !defined(__APPLE__)
|
||||
#ifdef __MINGW32__
|
||||
# include <_mingw.h>
|
||||
#endif
|
||||
typedef unsigned __int64 UINT64;
|
||||
typedef __int64 INT64;
|
||||
typedef unsigned __int32 UINT32;
|
||||
typedef unsigned __int16 UINT16;
|
||||
typedef unsigned char UINT8;
|
||||
#else
|
||||
typedef unsigned long int UINT64;
|
||||
typedef long int INT64;
|
||||
typedef unsigned int UINT32;
|
||||
typedef unsigned short int UINT16;
|
||||
typedef unsigned char UINT8;
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__unix__) || defined(__APPLE__)
|
||||
# define DECLARE_ALIGNED(decl, alignval) decl __attribute__((aligned(alignval)))
|
||||
# define __forceinline static inline
|
||||
#else
|
||||
# define DECLARE_ALIGNED(decl, alignval) __declspec(align(alignval)) decl
|
||||
# define posix_memalign(p, algn, len) (NULL == (*((char**)(p)) = (void*) _aligned_malloc(len, algn)))
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
# define DEBUG_PRINT(x) printf x
|
||||
#else
|
||||
# define DEBUG_PRINT(x) do {} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //__TYPES_H
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2014 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package erasure
|
||||
|
||||
// #cgo CFLAGS: -O0
|
||||
// #include <stdlib.h>
|
||||
// #include "ec.h"
|
||||
// #include "ec_minio_common.h"
|
||||
import "C"
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Decode decodes erasure coded blocks of data into its original
|
||||
// form. Erasure coded data contains K data blocks and M parity
|
||||
// blocks. Decode can withstand data loss up to any M number of blocks.
|
||||
//
|
||||
// "encodedDataBlocks" is an array of K data blocks and M parity
|
||||
// blocks. Data blocks are position and order dependent. Missing blocks
|
||||
// are set to "nil". There must be at least "K" number of data|parity
|
||||
// blocks.
|
||||
//
|
||||
// "dataLen" is the length of original source data
|
||||
func (e *Erasure) Decode(encodedDataBlocks [][]byte, dataLen int) (decodedData []byte, err error) {
|
||||
e.mutex.Lock()
|
||||
defer e.mutex.Unlock()
|
||||
|
||||
var source, target **C.uchar
|
||||
|
||||
k := int(e.params.K)
|
||||
m := int(e.params.M)
|
||||
n := k + m
|
||||
// We need the data and parity blocks preserved in the same order. Missing blocks are set to nil.
|
||||
if len(encodedDataBlocks) != n {
|
||||
msg := fmt.Sprintf("Encoded data blocks slice must of length [%d]", n)
|
||||
return nil, errors.New(msg)
|
||||
}
|
||||
|
||||
// Length of a single encoded block
|
||||
encodedBlockLen := GetEncodedBlockLen(dataLen, uint8(k))
|
||||
|
||||
// Keep track of errors per block.
|
||||
missingEncodedBlocks := make([]int, n+1)
|
||||
var missingEncodedBlocksCount int
|
||||
|
||||
// Check for the missing encoded blocks
|
||||
for i := range encodedDataBlocks {
|
||||
if encodedDataBlocks[i] == nil || len(encodedDataBlocks[i]) == 0 {
|
||||
missingEncodedBlocks[missingEncodedBlocksCount] = i
|
||||
missingEncodedBlocksCount++
|
||||
}
|
||||
}
|
||||
|
||||
// Cannot reconstruct original data. Need at least M number of data or parity blocks.
|
||||
if missingEncodedBlocksCount > m {
|
||||
return nil, fmt.Errorf("Cannot reconstruct original data. Need at least [%d] data or parity blocks", m)
|
||||
}
|
||||
|
||||
// Convert from Go int slice to C int array
|
||||
missingEncodedBlocksC := intSlice2CIntArray(missingEncodedBlocks[:missingEncodedBlocksCount])
|
||||
|
||||
// Allocate buffer for the missing blocks
|
||||
for i := range encodedDataBlocks {
|
||||
if encodedDataBlocks[i] == nil || len(encodedDataBlocks[i]) == 0 {
|
||||
encodedDataBlocks[i] = make([]byte, encodedBlockLen)
|
||||
}
|
||||
}
|
||||
|
||||
// If not already initialized, recompute and cache
|
||||
if e.decodeMatrix == nil || e.decodeTbls == nil || e.decodeIndex == nil {
|
||||
var decodeMatrix, decodeTbls *C.uchar
|
||||
var decodeIndex *C.uint32_t
|
||||
|
||||
C.minio_init_decoder(missingEncodedBlocksC, C.int(k), C.int(n), C.int(missingEncodedBlocksCount),
|
||||
e.encodeMatrix, &decodeMatrix, &decodeTbls, &decodeIndex)
|
||||
|
||||
// cache this for future needs
|
||||
e.decodeMatrix = decodeMatrix
|
||||
e.decodeTbls = decodeTbls
|
||||
e.decodeIndex = decodeIndex
|
||||
}
|
||||
|
||||
// Make a slice of pointers to encoded blocks. Necessary to bridge to the C world.
|
||||
pointers := make([]*byte, n)
|
||||
for i := range encodedDataBlocks {
|
||||
pointers[i] = &encodedDataBlocks[i][0]
|
||||
}
|
||||
|
||||
// Get pointers to source "data" and target "parity" blocks from the output byte array.
|
||||
ret := C.minio_get_source_target(C.int(missingEncodedBlocksCount), C.int(k), C.int(m), missingEncodedBlocksC,
|
||||
e.decodeIndex, (**C.uchar)(unsafe.Pointer(&pointers[0])), &source, &target)
|
||||
if int(ret) == -1 {
|
||||
return nil, errors.New("Unable to decode data")
|
||||
}
|
||||
|
||||
// Decode data
|
||||
C.ec_encode_data(C.int(encodedBlockLen), C.int(k), C.int(missingEncodedBlocksCount), e.decodeTbls,
|
||||
source, target)
|
||||
|
||||
// Allocate buffer to output buffer
|
||||
decodedData = make([]byte, 0, encodedBlockLen*int(k))
|
||||
for i := 0; i < int(k); i++ {
|
||||
decodedData = append(decodedData, encodedDataBlocks[i]...)
|
||||
}
|
||||
|
||||
return decodedData[:dataLen], nil
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2014 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package erasure
|
||||
|
||||
// #include <stdlib.h>
|
||||
// #include "ec.h"
|
||||
// #include "ec_minio_common.h"
|
||||
import "C"
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Block alignment
|
||||
const (
|
||||
SIMDAlign = 32
|
||||
)
|
||||
|
||||
// Params is a configuration set for building an encoder. It is created using ValidateParams().
|
||||
type Params struct {
|
||||
K uint8
|
||||
M uint8
|
||||
}
|
||||
|
||||
// Erasure is an object used to encode and decode data.
|
||||
type Erasure struct {
|
||||
params *Params
|
||||
encodeMatrix, encodeTbls *C.uchar
|
||||
decodeMatrix, decodeTbls *C.uchar
|
||||
decodeIndex *C.uint32_t
|
||||
mutex *sync.Mutex
|
||||
}
|
||||
|
||||
// ValidateParams creates an Params object.
|
||||
//
|
||||
// k and m represent the matrix size, which corresponds to the protection level
|
||||
// technique is the matrix type. Valid inputs are Cauchy (recommended) or Vandermonde.
|
||||
//
|
||||
func ValidateParams(k, m uint8) (*Params, error) {
|
||||
if k < 1 {
|
||||
return nil, errors.New("k cannot be zero")
|
||||
}
|
||||
|
||||
if m < 1 {
|
||||
return nil, errors.New("m cannot be zero")
|
||||
}
|
||||
|
||||
if k+m > 255 {
|
||||
return nil, errors.New("(k + m) cannot be bigger than Galois field GF(2^8) - 1")
|
||||
}
|
||||
|
||||
return &Params{
|
||||
K: k,
|
||||
M: m,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewErasure creates an encoder object with a given set of parameters.
|
||||
func NewErasure(ep *Params) *Erasure {
|
||||
var k = C.int(ep.K)
|
||||
var m = C.int(ep.M)
|
||||
|
||||
var encodeMatrix *C.uchar
|
||||
var encodeTbls *C.uchar
|
||||
|
||||
C.minio_init_encoder(k, m, &encodeMatrix, &encodeTbls)
|
||||
|
||||
return &Erasure{
|
||||
params: ep,
|
||||
encodeMatrix: encodeMatrix,
|
||||
encodeTbls: encodeTbls,
|
||||
decodeMatrix: nil,
|
||||
decodeTbls: nil,
|
||||
decodeIndex: nil,
|
||||
mutex: new(sync.Mutex),
|
||||
}
|
||||
}
|
||||
|
||||
// GetEncodedBlocksLen - total length of all encoded blocks
|
||||
func GetEncodedBlocksLen(inputLen int, k, m uint8) (outputLen int) {
|
||||
outputLen = GetEncodedBlockLen(inputLen, k) * int(k+m)
|
||||
return outputLen
|
||||
}
|
||||
|
||||
// GetEncodedBlockLen - length per block of encoded blocks
|
||||
func GetEncodedBlockLen(inputLen int, k uint8) (encodedOutputLen int) {
|
||||
alignment := int(k) * SIMDAlign
|
||||
remainder := inputLen % alignment
|
||||
|
||||
paddedInputLen := inputLen
|
||||
if remainder != 0 {
|
||||
paddedInputLen = inputLen + (alignment - remainder)
|
||||
}
|
||||
encodedOutputLen = paddedInputLen / int(k)
|
||||
return encodedOutputLen
|
||||
}
|
||||
|
||||
// Encode erasure codes a block of data in "k" data blocks and "m" parity blocks.
|
||||
// Output is [k+m][]blocks of data and parity slices.
|
||||
func (e *Erasure) Encode(inputData []byte) (encodedBlocks [][]byte, err error) {
|
||||
e.mutex.Lock()
|
||||
defer e.mutex.Unlock()
|
||||
|
||||
k := int(e.params.K) // "k" data blocks
|
||||
m := int(e.params.M) // "m" parity blocks
|
||||
n := k + m // "n" total encoded blocks
|
||||
|
||||
// Length of a single encoded chunk.
|
||||
// Total number of encoded chunks = "k" data + "m" parity blocks
|
||||
encodedBlockLen := GetEncodedBlockLen(len(inputData), uint8(k))
|
||||
|
||||
// Length of total number of "k" data chunks
|
||||
encodedDataBlocksLen := encodedBlockLen * k
|
||||
|
||||
// Length of extra padding required for the data blocks.
|
||||
encodedDataBlocksPadLen := encodedDataBlocksLen - len(inputData)
|
||||
|
||||
// Extend inputData buffer to accommodate coded data blocks if necesssary
|
||||
if encodedDataBlocksPadLen > 0 {
|
||||
padding := make([]byte, encodedDataBlocksPadLen)
|
||||
// Expand with new padded blocks to the byte array
|
||||
inputData = append(inputData, padding...)
|
||||
}
|
||||
|
||||
// Extend inputData buffer to accommodate coded parity blocks
|
||||
{ // Local Scope
|
||||
encodedParityBlocksLen := encodedBlockLen * m
|
||||
parityBlocks := make([]byte, encodedParityBlocksLen)
|
||||
inputData = append(inputData, parityBlocks...)
|
||||
}
|
||||
|
||||
// Allocate memory to the "encoded blocks" return buffer
|
||||
encodedBlocks = make([][]byte, n) // Return buffer
|
||||
|
||||
// Neccessary to bridge Go to the C world. C requires 2D arry of pointers to
|
||||
// byte array. "encodedBlocks" is a 2D slice.
|
||||
pointersToEncodedBlock := make([]*byte, n) // Pointers to encoded blocks.
|
||||
|
||||
// Copy data block slices to encoded block buffer
|
||||
for i := 0; i < k; i++ {
|
||||
encodedBlocks[i] = inputData[i*encodedBlockLen : (i+1)*encodedBlockLen]
|
||||
pointersToEncodedBlock[i] = &encodedBlocks[i][0]
|
||||
}
|
||||
|
||||
// Copy erasure block slices to encoded block buffer
|
||||
for i := k; i < n; i++ {
|
||||
encodedBlocks[i] = make([]byte, encodedBlockLen)
|
||||
pointersToEncodedBlock[i] = &encodedBlocks[i][0]
|
||||
}
|
||||
|
||||
// Erasure code the data into K data blocks and M parity
|
||||
// blocks. Only the parity blocks are filled. Data blocks remain
|
||||
// intact.
|
||||
C.ec_encode_data(C.int(encodedBlockLen), C.int(k), C.int(m), e.encodeTbls,
|
||||
(**C.uchar)(unsafe.Pointer(&pointersToEncodedBlock[:k][0])), // Pointers to data blocks
|
||||
(**C.uchar)(unsafe.Pointer(&pointersToEncodedBlock[k:][0]))) // Pointers to parity blocks
|
||||
|
||||
return encodedBlocks, nil
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2014 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package erasure
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
. "gopkg.in/check.v1"
|
||||
)
|
||||
|
||||
type MySuite struct{}
|
||||
|
||||
var _ = Suite(&MySuite{})
|
||||
|
||||
func Test(t *testing.T) { TestingT(t) }
|
||||
|
||||
const (
|
||||
k = 10
|
||||
m = 5
|
||||
)
|
||||
|
||||
func corruptChunks(chunks [][]byte, errorIndex []int) [][]byte {
|
||||
for _, err := range errorIndex {
|
||||
chunks[err] = nil
|
||||
}
|
||||
return chunks
|
||||
}
|
||||
|
||||
func (s *MySuite) TestEncodeDecodeFailure(c *C) {
|
||||
ep, err := ValidateParams(k, m)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
data := []byte("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.")
|
||||
|
||||
e := NewErasure(ep)
|
||||
chunks, err := e.Encode(data)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
errorIndex := []int{0, 3, 5, 9, 11, 13}
|
||||
chunks = corruptChunks(chunks, errorIndex)
|
||||
|
||||
_, err = e.Decode(chunks, len(data))
|
||||
c.Assert(err, Not(IsNil))
|
||||
}
|
||||
|
||||
func (s *MySuite) TestEncodeDecodeSuccess(c *C) {
|
||||
ep, err := ValidateParams(k, m)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
data := []byte("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.")
|
||||
|
||||
e := NewErasure(ep)
|
||||
chunks, err := e.Encode(data)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
errorIndex := []int{0, 3, 5, 9, 13}
|
||||
chunks = corruptChunks(chunks, errorIndex)
|
||||
|
||||
recoveredData, err := e.Decode(chunks, len(data))
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
if !bytes.Equal(data, recoveredData) {
|
||||
c.Fatalf("Recovered data mismatches with original data")
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
// !build amd64
|
||||
|
||||
package erasure
|
||||
|
||||
//go:generate yasm -f macho64 --prefix=_ ec_multibinary.asm -o ec_multibinary.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_2vect_mad_avx2.asm -o gf_2vect_mad_avx2.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_2vect_mad_avx.asm -o gf_2vect_mad_avx.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_2vect_mad_sse.asm -o gf_2vect_mad_sse.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_3vect_mad_avx2.asm -o gf_3vect_mad_avx2.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_3vect_mad_avx.asm -o gf_3vect_mad_avx.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_3vect_mad_sse.asm -o gf_3vect_mad_sse.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_4vect_mad_avx2.asm -o gf_4vect_mad_avx2.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_4vect_mad_avx.asm -o gf_4vect_mad_avx.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_4vect_mad_sse.asm -o gf_4vect_mad_sse.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_5vect_mad_avx2.asm -o gf_5vect_mad_avx2.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_5vect_mad_avx.asm -o gf_5vect_mad_avx.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_5vect_mad_sse.asm -o gf_5vect_mad_sse.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_6vect_mad_avx2.asm -o gf_6vect_mad_avx2.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_6vect_mad_avx.asm -o gf_6vect_mad_avx.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_6vect_mad_sse.asm -o gf_6vect_mad_sse.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_vect_mad_avx2.asm -o gf_vect_mad_avx2.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_vect_mad_avx.asm -o gf_vect_mad_avx.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_vect_mad_sse.asm -o gf_vect_mad_sse.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_2vect_dot_prod_avx2.asm -o gf_2vect_dot_prod_avx2.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_2vect_dot_prod_avx.asm -o gf_2vect_dot_prod_avx.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_2vect_dot_prod_sse.asm -o gf_2vect_dot_prod_sse.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_3vect_dot_prod_avx2.asm -o gf_3vect_dot_prod_avx2.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_3vect_dot_prod_avx.asm -o gf_3vect_dot_prod_avx.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_3vect_dot_prod_sse.asm -o gf_3vect_dot_prod_sse.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_4vect_dot_prod_avx2.asm -o gf_4vect_dot_prod_avx2.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_4vect_dot_prod_avx.asm -o gf_4vect_dot_prod_avx.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_4vect_dot_prod_sse.asm -o gf_4vect_dot_prod_sse.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_5vect_dot_prod_avx2.asm -o gf_5vect_dot_prod_avx2.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_5vect_dot_prod_avx.asm -o gf_5vect_dot_prod_avx.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_5vect_dot_prod_sse.asm -o gf_5vect_dot_prod_sse.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_6vect_dot_prod_avx2.asm -o gf_6vect_dot_prod_avx2.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_6vect_dot_prod_avx.asm -o gf_6vect_dot_prod_avx.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_6vect_dot_prod_sse.asm -o gf_6vect_dot_prod_sse.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_vect_dot_prod_avx2.asm -o gf_vect_dot_prod_avx2.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_vect_dot_prod_avx.asm -o gf_vect_dot_prod_avx.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_vect_dot_prod_sse.asm -o gf_vect_dot_prod_sse.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_vect_mul_avx.asm -o gf_vect_mul_avx.syso
|
||||
//go:generate yasm -f macho64 --prefix=_ gf_vect_mul_sse.asm -o gf_vect_mul_sse.syso
|
||||
@@ -1,43 +0,0 @@
|
||||
// !build amd64
|
||||
|
||||
package erasure
|
||||
|
||||
//go:generate yasm -f elf64 ec_multibinary.asm -o ec_multibinary.syso
|
||||
//go:generate yasm -f elf64 gf_2vect_mad_avx2.asm -o gf_2vect_mad_avx2.syso
|
||||
//go:generate yasm -f elf64 gf_2vect_mad_avx.asm -o gf_2vect_mad_avx.syso
|
||||
//go:generate yasm -f elf64 gf_2vect_mad_sse.asm -o gf_2vect_mad_sse.syso
|
||||
//go:generate yasm -f elf64 gf_3vect_mad_avx2.asm -o gf_3vect_mad_avx2.syso
|
||||
//go:generate yasm -f elf64 gf_3vect_mad_avx.asm -o gf_3vect_mad_avx.syso
|
||||
//go:generate yasm -f elf64 gf_3vect_mad_sse.asm -o gf_3vect_mad_sse.syso
|
||||
//go:generate yasm -f elf64 gf_4vect_mad_avx2.asm -o gf_4vect_mad_avx2.syso
|
||||
//go:generate yasm -f elf64 gf_4vect_mad_avx.asm -o gf_4vect_mad_avx.syso
|
||||
//go:generate yasm -f elf64 gf_4vect_mad_sse.asm -o gf_4vect_mad_sse.syso
|
||||
//go:generate yasm -f elf64 gf_5vect_mad_avx2.asm -o gf_5vect_mad_avx2.syso
|
||||
//go:generate yasm -f elf64 gf_5vect_mad_avx.asm -o gf_5vect_mad_avx.syso
|
||||
//go:generate yasm -f elf64 gf_5vect_mad_sse.asm -o gf_5vect_mad_sse.syso
|
||||
//go:generate yasm -f elf64 gf_6vect_mad_avx2.asm -o gf_6vect_mad_avx2.syso
|
||||
//go:generate yasm -f elf64 gf_6vect_mad_avx.asm -o gf_6vect_mad_avx.syso
|
||||
//go:generate yasm -f elf64 gf_6vect_mad_sse.asm -o gf_6vect_mad_sse.syso
|
||||
//go:generate yasm -f elf64 gf_vect_mad_avx2.asm -o gf_vect_mad_avx2.syso
|
||||
//go:generate yasm -f elf64 gf_vect_mad_avx.asm -o gf_vect_mad_avx.syso
|
||||
//go:generate yasm -f elf64 gf_vect_mad_sse.asm -o gf_vect_mad_sse.syso
|
||||
//go:generate yasm -f elf64 gf_2vect_dot_prod_avx2.asm -o gf_2vect_dot_prod_avx2.syso
|
||||
//go:generate yasm -f elf64 gf_2vect_dot_prod_avx.asm -o gf_2vect_dot_prod_avx.syso
|
||||
//go:generate yasm -f elf64 gf_2vect_dot_prod_sse.asm -o gf_2vect_dot_prod_sse.syso
|
||||
//go:generate yasm -f elf64 gf_3vect_dot_prod_avx2.asm -o gf_3vect_dot_prod_avx2.syso
|
||||
//go:generate yasm -f elf64 gf_3vect_dot_prod_avx.asm -o gf_3vect_dot_prod_avx.syso
|
||||
//go:generate yasm -f elf64 gf_3vect_dot_prod_sse.asm -o gf_3vect_dot_prod_sse.syso
|
||||
//go:generate yasm -f elf64 gf_4vect_dot_prod_avx2.asm -o gf_4vect_dot_prod_avx2.syso
|
||||
//go:generate yasm -f elf64 gf_4vect_dot_prod_avx.asm -o gf_4vect_dot_prod_avx.syso
|
||||
//go:generate yasm -f elf64 gf_4vect_dot_prod_sse.asm -o gf_4vect_dot_prod_sse.syso
|
||||
//go:generate yasm -f elf64 gf_5vect_dot_prod_avx2.asm -o gf_5vect_dot_prod_avx2.syso
|
||||
//go:generate yasm -f elf64 gf_5vect_dot_prod_avx.asm -o gf_5vect_dot_prod_avx.syso
|
||||
//go:generate yasm -f elf64 gf_5vect_dot_prod_sse.asm -o gf_5vect_dot_prod_sse.syso
|
||||
//go:generate yasm -f elf64 gf_6vect_dot_prod_avx2.asm -o gf_6vect_dot_prod_avx2.syso
|
||||
//go:generate yasm -f elf64 gf_6vect_dot_prod_avx.asm -o gf_6vect_dot_prod_avx.syso
|
||||
//go:generate yasm -f elf64 gf_6vect_dot_prod_sse.asm -o gf_6vect_dot_prod_sse.syso
|
||||
//go:generate yasm -f elf64 gf_vect_dot_prod_avx2.asm -o gf_vect_dot_prod_avx2.syso
|
||||
//go:generate yasm -f elf64 gf_vect_dot_prod_avx.asm -o gf_vect_dot_prod_avx.syso
|
||||
//go:generate yasm -f elf64 gf_vect_dot_prod_sse.asm -o gf_vect_dot_prod_sse.syso
|
||||
//go:generate yasm -f elf64 gf_vect_mul_avx.asm -o gf_vect_mul_avx.syso
|
||||
//go:generate yasm -f elf64 gf_vect_mul_sse.asm -o gf_vect_mul_sse.syso
|
||||
@@ -1,43 +0,0 @@
|
||||
// !build amd64
|
||||
|
||||
package erasure
|
||||
|
||||
//go:generate yasm -f win64 ec_multibinary.asm -o ec_multibinary.syso
|
||||
//go:generate yasm -f win64 gf_2vect_mad_avx2.asm -o gf_2vect_mad_avx2.syso
|
||||
//go:generate yasm -f win64 gf_2vect_mad_avx.asm -o gf_2vect_mad_avx.syso
|
||||
//go:generate yasm -f win64 gf_2vect_mad_sse.asm -o gf_2vect_mad_sse.syso
|
||||
//go:generate yasm -f win64 gf_3vect_mad_avx2.asm -o gf_3vect_mad_avx2.syso
|
||||
//go:generate yasm -f win64 gf_3vect_mad_avx.asm -o gf_3vect_mad_avx.syso
|
||||
//go:generate yasm -f win64 gf_3vect_mad_sse.asm -o gf_3vect_mad_sse.syso
|
||||
//go:generate yasm -f win64 gf_4vect_mad_avx2.asm -o gf_4vect_mad_avx2.syso
|
||||
//go:generate yasm -f win64 gf_4vect_mad_avx.asm -o gf_4vect_mad_avx.syso
|
||||
//go:generate yasm -f win64 gf_4vect_mad_sse.asm -o gf_4vect_mad_sse.syso
|
||||
//go:generate yasm -f win64 gf_5vect_mad_avx2.asm -o gf_5vect_mad_avx2.syso
|
||||
//go:generate yasm -f win64 gf_5vect_mad_avx.asm -o gf_5vect_mad_avx.syso
|
||||
//go:generate yasm -f win64 gf_5vect_mad_sse.asm -o gf_5vect_mad_sse.syso
|
||||
//go:generate yasm -f win64 gf_6vect_mad_avx2.asm -o gf_6vect_mad_avx2.syso
|
||||
//go:generate yasm -f win64 gf_6vect_mad_avx.asm -o gf_6vect_mad_avx.syso
|
||||
//go:generate yasm -f win64 gf_6vect_mad_sse.asm -o gf_6vect_mad_sse.syso
|
||||
//go:generate yasm -f win64 gf_vect_mad_avx2.asm -o gf_vect_mad_avx2.syso
|
||||
//go:generate yasm -f win64 gf_vect_mad_avx.asm -o gf_vect_mad_avx.syso
|
||||
//go:generate yasm -f win64 gf_vect_mad_sse.asm -o gf_vect_mad_sse.syso
|
||||
//go:generate yasm -f win64 gf_2vect_dot_prod_avx2.asm -o gf_2vect_dot_prod_avx2.syso
|
||||
//go:generate yasm -f win64 gf_2vect_dot_prod_avx.asm -o gf_2vect_dot_prod_avx.syso
|
||||
//go:generate yasm -f win64 gf_2vect_dot_prod_sse.asm -o gf_2vect_dot_prod_sse.syso
|
||||
//go:generate yasm -f win64 gf_3vect_dot_prod_avx2.asm -o gf_3vect_dot_prod_avx2.syso
|
||||
//go:generate yasm -f win64 gf_3vect_dot_prod_avx.asm -o gf_3vect_dot_prod_avx.syso
|
||||
//go:generate yasm -f win64 gf_3vect_dot_prod_sse.asm -o gf_3vect_dot_prod_sse.syso
|
||||
//go:generate yasm -f win64 gf_4vect_dot_prod_avx2.asm -o gf_4vect_dot_prod_avx2.syso
|
||||
//go:generate yasm -f win64 gf_4vect_dot_prod_avx.asm -o gf_4vect_dot_prod_avx.syso
|
||||
//go:generate yasm -f win64 gf_4vect_dot_prod_sse.asm -o gf_4vect_dot_prod_sse.syso
|
||||
//go:generate yasm -f win64 gf_5vect_dot_prod_avx2.asm -o gf_5vect_dot_prod_avx2.syso
|
||||
//go:generate yasm -f win64 gf_5vect_dot_prod_avx.asm -o gf_5vect_dot_prod_avx.syso
|
||||
//go:generate yasm -f win64 gf_5vect_dot_prod_sse.asm -o gf_5vect_dot_prod_sse.syso
|
||||
//go:generate yasm -f win64 gf_6vect_dot_prod_avx2.asm -o gf_6vect_dot_prod_avx2.syso
|
||||
//go:generate yasm -f win64 gf_6vect_dot_prod_avx.asm -o gf_6vect_dot_prod_avx.syso
|
||||
//go:generate yasm -f win64 gf_6vect_dot_prod_sse.asm -o gf_6vect_dot_prod_sse.syso
|
||||
//go:generate yasm -f win64 gf_vect_dot_prod_avx2.asm -o gf_vect_dot_prod_avx2.syso
|
||||
//go:generate yasm -f win64 gf_vect_dot_prod_avx.asm -o gf_vect_dot_prod_avx.syso
|
||||
//go:generate yasm -f win64 gf_vect_dot_prod_sse.asm -o gf_vect_dot_prod_sse.syso
|
||||
//go:generate yasm -f win64 gf_vect_mul_avx.asm -o gf_vect_mul_avx.syso
|
||||
//go:generate yasm -f win64 gf_vect_mul_sse.asm -o gf_vect_mul_sse.syso
|
||||
@@ -1,374 +0,0 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Copyright(c) 2011-2015 Intel Corporation All rights reserved.
|
||||
;
|
||||
; Redistribution and use in source and binary forms, with or without
|
||||
; modification, are permitted provided that the following conditions
|
||||
; are met:
|
||||
; * Redistributions of source code must retain the above copyright
|
||||
; notice, this list of conditions and the following disclaimer.
|
||||
; * Redistributions in binary form must reproduce the above copyright
|
||||
; notice, this list of conditions and the following disclaimer in
|
||||
; the documentation and/or other materials provided with the
|
||||
; distribution.
|
||||
; * Neither the name of Intel Corporation nor the names of its
|
||||
; contributors may be used to endorse or promote products derived
|
||||
; from this software without specific prior written permission.
|
||||
;
|
||||
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;;;
|
||||
;;; gf_2vect_dot_prod_avx(len, vec, *g_tbls, **buffs, **dests);
|
||||
;;;
|
||||
|
||||
%ifidn __OUTPUT_FORMAT__, elf64
|
||||
%define arg0 rdi
|
||||
%define arg1 rsi
|
||||
%define arg2 rdx
|
||||
%define arg3 rcx
|
||||
%define arg4 r8
|
||||
%define arg5 r9
|
||||
|
||||
%define tmp r11
|
||||
%define tmp2 r10
|
||||
%define tmp3 r9
|
||||
%define tmp4 r12 ; must be saved and restored
|
||||
%define return rax
|
||||
%macro SLDR 2
|
||||
%endmacro
|
||||
%define SSTR SLDR
|
||||
%define PS 8
|
||||
%define LOG_PS 3
|
||||
|
||||
%define func(x) x:
|
||||
%macro FUNC_SAVE 0
|
||||
push r12
|
||||
%endmacro
|
||||
%macro FUNC_RESTORE 0
|
||||
pop r12
|
||||
%endmacro
|
||||
%endif
|
||||
|
||||
%ifidn __OUTPUT_FORMAT__, macho64
|
||||
%define arg0 rdi
|
||||
%define arg1 rsi
|
||||
%define arg2 rdx
|
||||
%define arg3 rcx
|
||||
%define arg4 r8
|
||||
%define arg5 r9
|
||||
|
||||
%define tmp r11
|
||||
%define tmp.w r11d
|
||||
%define tmp.b r11b
|
||||
%define tmp2 r10
|
||||
%define tmp3 r13 ; must be saved and restored
|
||||
%define tmp4 r12 ; must be saved and restored
|
||||
%define return rax
|
||||
%macro SLDR 2
|
||||
%endmacro
|
||||
%define SSTR SLDR
|
||||
%define PS 8
|
||||
%define LOG_PS 3
|
||||
|
||||
%define func(x) x:
|
||||
%macro FUNC_SAVE 0
|
||||
push r12
|
||||
push r13
|
||||
%endmacro
|
||||
%macro FUNC_RESTORE 0
|
||||
pop r13
|
||||
pop r12
|
||||
%endmacro
|
||||
%endif
|
||||
|
||||
%ifidn __OUTPUT_FORMAT__, win64
|
||||
%define arg0 rcx
|
||||
%define arg1 rdx
|
||||
%define arg2 r8
|
||||
%define arg3 r9
|
||||
|
||||
%define arg4 r12 ; must be saved, loaded and restored
|
||||
%define tmp r11
|
||||
%define tmp2 r10
|
||||
%define tmp3 r13 ; must be saved and restored
|
||||
%define tmp4 r14 ; must be saved and restored
|
||||
%define return rax
|
||||
%macro SLDR 2
|
||||
%endmacro
|
||||
%define SSTR SLDR
|
||||
%define PS 8
|
||||
%define LOG_PS 3
|
||||
%define stack_size 3*16 + 3*8 ; must be an odd multiple of 8
|
||||
%define arg(x) [rsp + stack_size + PS + PS*x]
|
||||
|
||||
%define func(x) proc_frame x
|
||||
%macro FUNC_SAVE 0
|
||||
alloc_stack stack_size
|
||||
save_xmm128 xmm6, 0*16
|
||||
save_xmm128 xmm7, 1*16
|
||||
save_xmm128 xmm8, 2*16
|
||||
save_reg r12, 3*16 + 0*8
|
||||
save_reg r13, 3*16 + 1*8
|
||||
save_reg r14, 3*16 + 2*8
|
||||
end_prolog
|
||||
mov arg4, arg(4)
|
||||
%endmacro
|
||||
|
||||
%macro FUNC_RESTORE 0
|
||||
vmovdqa xmm6, [rsp + 0*16]
|
||||
vmovdqa xmm7, [rsp + 1*16]
|
||||
vmovdqa xmm8, [rsp + 2*16]
|
||||
mov r12, [rsp + 3*16 + 0*8]
|
||||
mov r13, [rsp + 3*16 + 1*8]
|
||||
mov r14, [rsp + 3*16 + 2*8]
|
||||
add rsp, stack_size
|
||||
%endmacro
|
||||
%endif
|
||||
|
||||
%ifidn __OUTPUT_FORMAT__, elf32
|
||||
|
||||
;;;================== High Address;
|
||||
;;; arg4
|
||||
;;; arg3
|
||||
;;; arg2
|
||||
;;; arg1
|
||||
;;; arg0
|
||||
;;; return
|
||||
;;;<================= esp of caller
|
||||
;;; ebp
|
||||
;;;<================= ebp = esp
|
||||
;;; var0
|
||||
;;; esi
|
||||
;;; edi
|
||||
;;; ebx
|
||||
;;;<================= esp of callee
|
||||
;;;
|
||||
;;;================== Low Address;
|
||||
|
||||
%define PS 4
|
||||
%define LOG_PS 2
|
||||
%define func(x) x:
|
||||
%define arg(x) [ebp + PS*2 + PS*x]
|
||||
%define var(x) [ebp - PS - PS*x]
|
||||
|
||||
%define trans ecx
|
||||
%define trans2 esi
|
||||
%define arg0 trans ;trans and trans2 are for the variables in stack
|
||||
%define arg0_m arg(0)
|
||||
%define arg1 ebx
|
||||
%define arg2 arg2_m
|
||||
%define arg2_m arg(2)
|
||||
%define arg3 trans
|
||||
%define arg3_m arg(3)
|
||||
%define arg4 trans
|
||||
%define arg4_m arg(4)
|
||||
%define tmp edx
|
||||
%define tmp2 edi
|
||||
%define tmp3 trans2
|
||||
%define tmp4 trans2
|
||||
%define tmp4_m var(0)
|
||||
%define return eax
|
||||
%macro SLDR 2 ;; stack load/restore
|
||||
mov %1, %2
|
||||
%endmacro
|
||||
%define SSTR SLDR
|
||||
|
||||
%macro FUNC_SAVE 0
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
sub esp, PS*1 ;1 local variable
|
||||
push esi
|
||||
push edi
|
||||
push ebx
|
||||
mov arg1, arg(1)
|
||||
%endmacro
|
||||
|
||||
%macro FUNC_RESTORE 0
|
||||
pop ebx
|
||||
pop edi
|
||||
pop esi
|
||||
add esp, PS*1 ;1 local variable
|
||||
pop ebp
|
||||
%endmacro
|
||||
|
||||
%endif ; output formats
|
||||
|
||||
%define len arg0
|
||||
%define vec arg1
|
||||
%define mul_array arg2
|
||||
%define src arg3
|
||||
%define dest1 arg4
|
||||
|
||||
%define vec_i tmp2
|
||||
%define ptr tmp3
|
||||
%define dest2 tmp4
|
||||
%define pos return
|
||||
|
||||
%ifidn PS,4 ;32-bit code
|
||||
%define len_m arg0_m
|
||||
%define src_m arg3_m
|
||||
%define dest1_m arg4_m
|
||||
%define dest2_m tmp4_m
|
||||
%endif
|
||||
|
||||
%ifndef EC_ALIGNED_ADDR
|
||||
;;; Use Un-aligned load/store
|
||||
%define XLDR vmovdqu
|
||||
%define XSTR vmovdqu
|
||||
%else
|
||||
;;; Use Non-temporal load/stor
|
||||
%ifdef NO_NT_LDST
|
||||
%define XLDR vmovdqa
|
||||
%define XSTR vmovdqa
|
||||
%else
|
||||
%define XLDR vmovntdqa
|
||||
%define XSTR vmovntdq
|
||||
%endif
|
||||
%endif
|
||||
|
||||
%ifidn PS,8 ; 64-bit code
|
||||
default rel
|
||||
[bits 64]
|
||||
%endif
|
||||
|
||||
section .text
|
||||
|
||||
%ifidn PS,8 ;64-bit code
|
||||
%define xmask0f xmm8
|
||||
%define xgft1_lo xmm7
|
||||
%define xgft1_hi xmm6
|
||||
%define xgft2_lo xmm5
|
||||
%define xgft2_hi xmm4
|
||||
|
||||
%define x0 xmm0
|
||||
%define xtmpa xmm1
|
||||
%define xp1 xmm2
|
||||
%define xp2 xmm3
|
||||
%else ;32-bit code
|
||||
%define xmask0f xmm4
|
||||
%define xgft1_lo xmm7
|
||||
%define xgft1_hi xmm6
|
||||
%define xgft2_lo xgft1_lo
|
||||
%define xgft2_hi xgft1_hi
|
||||
|
||||
%define x0 xmm0
|
||||
%define xtmpa xmm1
|
||||
%define xp1 xmm2
|
||||
%define xp2 xmm3
|
||||
%endif
|
||||
|
||||
align 16
|
||||
global gf_2vect_dot_prod_avx:function
|
||||
func(gf_2vect_dot_prod_avx)
|
||||
FUNC_SAVE
|
||||
SLDR len, len_m
|
||||
sub len, 16
|
||||
SSTR len_m, len
|
||||
jl .return_fail
|
||||
xor pos, pos
|
||||
vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte
|
||||
sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS
|
||||
SLDR dest1, dest1_m
|
||||
mov dest2, [dest1+PS]
|
||||
SSTR dest2_m, dest2
|
||||
mov dest1, [dest1]
|
||||
SSTR dest1_m, dest1
|
||||
|
||||
.loop16
|
||||
vpxor xp1, xp1
|
||||
vpxor xp2, xp2
|
||||
mov tmp, mul_array
|
||||
xor vec_i, vec_i
|
||||
|
||||
.next_vect
|
||||
SLDR src, src_m
|
||||
mov ptr, [src+vec_i]
|
||||
|
||||
vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f}
|
||||
vmovdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0}
|
||||
%ifidn PS,8 ; 64-bit code
|
||||
vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f}
|
||||
vmovdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0}
|
||||
add tmp, 32
|
||||
add vec_i, PS
|
||||
%endif
|
||||
XLDR x0, [ptr+pos] ;Get next source vector
|
||||
|
||||
vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0
|
||||
vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0
|
||||
vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0
|
||||
|
||||
vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble
|
||||
vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble
|
||||
vpxor xgft1_hi, xgft1_lo ;GF add high and low partials
|
||||
vpxor xp1, xgft1_hi ;xp1 += partial
|
||||
|
||||
%ifidn PS,4 ; 32-bit code
|
||||
vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f}
|
||||
vmovdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0}
|
||||
add tmp, 32
|
||||
add vec_i, PS
|
||||
%endif
|
||||
vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble
|
||||
vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble
|
||||
vpxor xgft2_hi, xgft2_lo ;GF add high and low partials
|
||||
vpxor xp2, xgft2_hi ;xp2 += partial
|
||||
|
||||
cmp vec_i, vec
|
||||
jl .next_vect
|
||||
|
||||
SLDR dest1, dest1_m
|
||||
SLDR dest2, dest2_m
|
||||
XSTR [dest1+pos], xp1
|
||||
XSTR [dest2+pos], xp2
|
||||
|
||||
SLDR len, len_m
|
||||
add pos, 16 ;Loop on 16 bytes at a time
|
||||
cmp pos, len
|
||||
jle .loop16
|
||||
|
||||
lea tmp, [len + 16]
|
||||
cmp pos, tmp
|
||||
je .return_pass
|
||||
|
||||
;; Tail len
|
||||
mov pos, len ;Overlapped offset length-16
|
||||
jmp .loop16 ;Do one more overlap pass
|
||||
|
||||
.return_pass:
|
||||
mov return, 0
|
||||
FUNC_RESTORE
|
||||
ret
|
||||
|
||||
.return_fail:
|
||||
mov return, 1
|
||||
FUNC_RESTORE
|
||||
ret
|
||||
|
||||
endproc_frame
|
||||
|
||||
section .data
|
||||
|
||||
align 16
|
||||
mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f
|
||||
|
||||
%macro slversion 4
|
||||
global %1_slver_%2%3%4
|
||||
global %1_slver
|
||||
%1_slver:
|
||||
%1_slver_%2%3%4:
|
||||
dw 0x%4
|
||||
db 0x%3, 0x%2
|
||||
%endmacro
|
||||
;;; func core, ver, snum
|
||||
slversion gf_2vect_dot_prod_avx, 02, 04, 0191
|
||||
@@ -1,391 +0,0 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Copyright(c) 2011-2015 Intel Corporation All rights reserved.
|
||||
;
|
||||
; Redistribution and use in source and binary forms, with or without
|
||||
; modification, are permitted provided that the following conditions
|
||||
; are met:
|
||||
; * Redistributions of source code must retain the above copyright
|
||||
; notice, this list of conditions and the following disclaimer.
|
||||
; * Redistributions in binary form must reproduce the above copyright
|
||||
; notice, this list of conditions and the following disclaimer in
|
||||
; the documentation and/or other materials provided with the
|
||||
; distribution.
|
||||
; * Neither the name of Intel Corporation nor the names of its
|
||||
; contributors may be used to endorse or promote products derived
|
||||
; from this software without specific prior written permission.
|
||||
;
|
||||
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;;;
|
||||
;;; gf_2vect_dot_prod_avx2(len, vec, *g_tbls, **buffs, **dests);
|
||||
;;;
|
||||
|
||||
%ifidn __OUTPUT_FORMAT__, elf64
|
||||
%define arg0 rdi
|
||||
%define arg1 rsi
|
||||
%define arg2 rdx
|
||||
%define arg3 rcx
|
||||
%define arg4 r8
|
||||
%define arg5 r9
|
||||
|
||||
%define tmp r11
|
||||
%define tmp.w r11d
|
||||
%define tmp.b r11b
|
||||
%define tmp2 r10
|
||||
%define tmp3 r9
|
||||
%define tmp4 r12 ; must be saved and restored
|
||||
%define return rax
|
||||
%macro SLDR 2
|
||||
%endmacro
|
||||
%define SSTR SLDR
|
||||
%define PS 8
|
||||
%define LOG_PS 3
|
||||
|
||||
%define func(x) x:
|
||||
%macro FUNC_SAVE 0
|
||||
push r12
|
||||
%endmacro
|
||||
%macro FUNC_RESTORE 0
|
||||
pop r12
|
||||
%endmacro
|
||||
%endif
|
||||
|
||||
%ifidn __OUTPUT_FORMAT__, macho64
|
||||
%define arg0 rdi
|
||||
%define arg1 rsi
|
||||
%define arg2 rdx
|
||||
%define arg3 rcx
|
||||
%define arg4 r8
|
||||
%define arg5 r9
|
||||
|
||||
%define tmp r11
|
||||
%define tmp.w r11d
|
||||
%define tmp.b r11b
|
||||
%define tmp2 r10
|
||||
%define tmp3 r9
|
||||
%define tmp4 r12 ; must be saved and restored
|
||||
%define return rax
|
||||
%macro SLDR 2
|
||||
%endmacro
|
||||
%define SSTR SLDR
|
||||
%define PS 8
|
||||
%define LOG_PS 3
|
||||
|
||||
%define func(x) x:
|
||||
%macro FUNC_SAVE 0
|
||||
push r12
|
||||
%endmacro
|
||||
%macro FUNC_RESTORE 0
|
||||
pop r12
|
||||
%endmacro
|
||||
%endif
|
||||
|
||||
%ifidn __OUTPUT_FORMAT__, win64
|
||||
%define arg0 rcx
|
||||
%define arg1 rdx
|
||||
%define arg2 r8
|
||||
%define arg3 r9
|
||||
|
||||
%define arg4 r12 ; must be saved, loaded and restored
|
||||
%define tmp r11
|
||||
%define tmp.w r11d
|
||||
%define tmp.b r11b
|
||||
%define tmp2 r10
|
||||
%define tmp3 r13 ; must be saved and restored
|
||||
%define tmp4 r14 ; must be saved and restored
|
||||
%define return rax
|
||||
%macro SLDR 2
|
||||
%endmacro
|
||||
%define SSTR SLDR
|
||||
%define PS 8
|
||||
%define LOG_PS 3
|
||||
%define stack_size 3*16 + 3*8 ; must be an odd multiple of 8
|
||||
%define arg(x) [rsp + stack_size + PS + PS*x]
|
||||
|
||||
%define func(x) proc_frame x
|
||||
%macro FUNC_SAVE 0
|
||||
alloc_stack stack_size
|
||||
vmovdqa [rsp + 0*16], xmm6
|
||||
vmovdqa [rsp + 1*16], xmm7
|
||||
vmovdqa [rsp + 2*16], xmm8
|
||||
save_reg r12, 3*16 + 0*8
|
||||
save_reg r13, 3*16 + 1*8
|
||||
save_reg r14, 3*16 + 2*8
|
||||
end_prolog
|
||||
mov arg4, arg(4)
|
||||
%endmacro
|
||||
|
||||
%macro FUNC_RESTORE 0
|
||||
vmovdqa xmm6, [rsp + 0*16]
|
||||
vmovdqa xmm7, [rsp + 1*16]
|
||||
vmovdqa xmm8, [rsp + 2*16]
|
||||
mov r12, [rsp + 3*16 + 0*8]
|
||||
mov r13, [rsp + 3*16 + 1*8]
|
||||
mov r14, [rsp + 3*16 + 2*8]
|
||||
add rsp, stack_size
|
||||
%endmacro
|
||||
%endif
|
||||
|
||||
%ifidn __OUTPUT_FORMAT__, elf32
|
||||
|
||||
;;;================== High Address;
|
||||
;;; arg4
|
||||
;;; arg3
|
||||
;;; arg2
|
||||
;;; arg1
|
||||
;;; arg0
|
||||
;;; return
|
||||
;;;<================= esp of caller
|
||||
;;; ebp
|
||||
;;;<================= ebp = esp
|
||||
;;; var0
|
||||
;;; esi
|
||||
;;; edi
|
||||
;;; ebx
|
||||
;;;<================= esp of callee
|
||||
;;;
|
||||
;;;================== Low Address;
|
||||
|
||||
%define PS 4
|
||||
%define LOG_PS 2
|
||||
%define func(x) x:
|
||||
%define arg(x) [ebp + PS*2 + PS*x]
|
||||
%define var(x) [ebp - PS - PS*x]
|
||||
|
||||
%define trans ecx
|
||||
%define trans2 esi
|
||||
%define arg0 trans ;trans and trans2 are for the variables in stack
|
||||
%define arg0_m arg(0)
|
||||
%define arg1 ebx
|
||||
%define arg2 arg2_m
|
||||
%define arg2_m arg(2)
|
||||
%define arg3 trans
|
||||
%define arg3_m arg(3)
|
||||
%define arg4 trans
|
||||
%define arg4_m arg(4)
|
||||
%define tmp edx
|
||||
%define tmp.w edx
|
||||
%define tmp.b dl
|
||||
%define tmp2 edi
|
||||
%define tmp3 trans2
|
||||
%define tmp4 trans2
|
||||
%define tmp4_m var(0)
|
||||
%define return eax
|
||||
%macro SLDR 2 ;stack load/restore
|
||||
mov %1, %2
|
||||
%endmacro
|
||||
%define SSTR SLDR
|
||||
|
||||
%macro FUNC_SAVE 0
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
sub esp, PS*1 ;1 local variable
|
||||
push esi
|
||||
push edi
|
||||
push ebx
|
||||
mov arg1, arg(1)
|
||||
%endmacro
|
||||
|
||||
%macro FUNC_RESTORE 0
|
||||
pop ebx
|
||||
pop edi
|
||||
pop esi
|
||||
add esp, PS*1 ;1 local variable
|
||||
pop ebp
|
||||
%endmacro
|
||||
|
||||
%endif ; output formats
|
||||
|
||||
%define len arg0
|
||||
%define vec arg1
|
||||
%define mul_array arg2
|
||||
%define src arg3
|
||||
%define dest1 arg4
|
||||
|
||||
%define vec_i tmp2
|
||||
%define ptr tmp3
|
||||
%define dest2 tmp4
|
||||
%define pos return
|
||||
|
||||
%ifidn PS,4 ;32-bit code
|
||||
%define len_m arg0_m
|
||||
%define src_m arg3_m
|
||||
%define dest1_m arg4_m
|
||||
%define dest2_m tmp4_m
|
||||
%endif
|
||||
|
||||
%ifndef EC_ALIGNED_ADDR
|
||||
;;; Use Un-aligned load/store
|
||||
%define XLDR vmovdqu
|
||||
%define XSTR vmovdqu
|
||||
%else
|
||||
|
||||
;;; Use Non-temporal load/stor
|
||||
%ifdef NO_NT_LDST
|
||||
%define XLDR vmovdqa
|
||||
%define XSTR vmovdqa
|
||||
%else
|
||||
%define XLDR vmovntdqa
|
||||
%define XSTR vmovntdq
|
||||
%endif
|
||||
%endif
|
||||
|
||||
%ifidn PS,8 ;64-bit code
|
||||
default rel
|
||||
[bits 64]
|
||||
%endif
|
||||
|
||||
section .text
|
||||
|
||||
%ifidn PS,8 ;64-bit code
|
||||
%define xmask0f ymm8
|
||||
%define xmask0fx xmm8
|
||||
%define xgft1_lo ymm7
|
||||
%define xgft1_hi ymm6
|
||||
%define xgft2_lo ymm5
|
||||
%define xgft2_hi ymm4
|
||||
|
||||
%define x0 ymm0
|
||||
%define xtmpa ymm1
|
||||
%define xp1 ymm2
|
||||
%define xp2 ymm3
|
||||
%else ;32-bit code
|
||||
%define xmask0f ymm7
|
||||
%define xmask0fx xmm7
|
||||
%define xgft1_lo ymm5
|
||||
%define xgft1_hi ymm4
|
||||
%define xgft2_lo xgft1_lo
|
||||
%define xgft2_hi xgft1_hi
|
||||
|
||||
%define x0 ymm0
|
||||
%define xtmpa ymm1
|
||||
%define xp1 ymm2
|
||||
%define xp2 ymm3
|
||||
|
||||
%endif
|
||||
|
||||
align 16
|
||||
global gf_2vect_dot_prod_avx2:function
|
||||
func(gf_2vect_dot_prod_avx2)
|
||||
FUNC_SAVE
|
||||
SLDR len, len_m
|
||||
sub len, 32
|
||||
SSTR len_m, len
|
||||
jl .return_fail
|
||||
xor pos, pos
|
||||
mov tmp.b, 0x0f
|
||||
vpinsrb xmask0fx, xmask0fx, tmp.w, 0
|
||||
vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f...
|
||||
|
||||
sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS
|
||||
SLDR dest1, dest1_m
|
||||
mov dest2, [dest1+PS]
|
||||
SSTR dest2_m, dest2
|
||||
mov dest1, [dest1]
|
||||
SSTR dest1_m, dest1
|
||||
|
||||
.loop32
|
||||
vpxor xp1, xp1
|
||||
vpxor xp2, xp2
|
||||
mov tmp, mul_array
|
||||
xor vec_i, vec_i
|
||||
|
||||
.next_vect
|
||||
SLDR src, src_m
|
||||
mov ptr, [src+vec_i]
|
||||
|
||||
vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f}
|
||||
; " Ax{00}, Ax{10}, ..., Ax{f0}
|
||||
vperm2i128 xgft1_hi, xgft1_lo, xgft1_lo, 0x11 ; swapped to hi | hi
|
||||
vperm2i128 xgft1_lo, xgft1_lo, xgft1_lo, 0x00 ; swapped to lo | lo
|
||||
%ifidn PS,8 ; 64-bit code
|
||||
vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f}
|
||||
; " Bx{00}, Bx{10}, ..., Bx{f0}
|
||||
vperm2i128 xgft2_hi, xgft2_lo, xgft2_lo, 0x11 ; swapped to hi | hi
|
||||
vperm2i128 xgft2_lo, xgft2_lo, xgft2_lo, 0x00 ; swapped to lo | lo
|
||||
|
||||
XLDR x0, [ptr+pos] ;Get next source vector
|
||||
add tmp, 32
|
||||
add vec_i, PS
|
||||
%else
|
||||
XLDR x0, [ptr+pos] ;Get next source vector
|
||||
%endif
|
||||
|
||||
vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0
|
||||
vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0
|
||||
vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0
|
||||
|
||||
vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble
|
||||
vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble
|
||||
vpxor xgft1_hi, xgft1_lo ;GF add high and low partials
|
||||
vpxor xp1, xgft1_hi ;xp1 += partial
|
||||
|
||||
%ifidn PS,4 ; 32-bit code
|
||||
vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f}
|
||||
; " Bx{00}, Bx{10}, ..., Bx{f0}
|
||||
vperm2i128 xgft2_hi, xgft2_lo, xgft2_lo, 0x11 ; swapped to hi | hi
|
||||
vperm2i128 xgft2_lo, xgft2_lo, xgft2_lo, 0x00 ; swapped to lo | lo
|
||||
add tmp, 32
|
||||
add vec_i, PS
|
||||
%endif
|
||||
vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble
|
||||
vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble
|
||||
vpxor xgft2_hi, xgft2_lo ;GF add high and low partials
|
||||
vpxor xp2, xgft2_hi ;xp2 += partial
|
||||
|
||||
cmp vec_i, vec
|
||||
jl .next_vect
|
||||
|
||||
SLDR dest1, dest1_m
|
||||
SLDR dest2, dest2_m
|
||||
XSTR [dest1+pos], xp1
|
||||
XSTR [dest2+pos], xp2
|
||||
|
||||
SLDR len, len_m
|
||||
add pos, 32 ;Loop on 32 bytes at a time
|
||||
cmp pos, len
|
||||
jle .loop32
|
||||
|
||||
lea tmp, [len + 32]
|
||||
cmp pos, tmp
|
||||
je .return_pass
|
||||
|
||||
;; Tail len
|
||||
mov pos, len ;Overlapped offset length-16
|
||||
jmp .loop32 ;Do one more overlap pass
|
||||
|
||||
.return_pass:
|
||||
mov return, 0
|
||||
FUNC_RESTORE
|
||||
ret
|
||||
|
||||
.return_fail:
|
||||
mov return, 1
|
||||
FUNC_RESTORE
|
||||
ret
|
||||
|
||||
endproc_frame
|
||||
|
||||
section .data
|
||||
|
||||
%macro slversion 4
|
||||
global %1_slver_%2%3%4
|
||||
global %1_slver
|
||||
%1_slver:
|
||||
%1_slver_%2%3%4:
|
||||
dw 0x%4
|
||||
db 0x%3, 0x%2
|
||||
%endmacro
|
||||
;;; func core, ver, snum
|
||||
slversion gf_2vect_dot_prod_avx2, 04, 04, 0196
|
||||
@@ -1,376 +0,0 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Copyright(c) 2011-2015 Intel Corporation All rights reserved.
|
||||
;
|
||||
; Redistribution and use in source and binary forms, with or without
|
||||
; modification, are permitted provided that the following conditions
|
||||
; are met:
|
||||
; * Redistributions of source code must retain the above copyright
|
||||
; notice, this list of conditions and the following disclaimer.
|
||||
; * Redistributions in binary form must reproduce the above copyright
|
||||
; notice, this list of conditions and the following disclaimer in
|
||||
; the documentation and/or other materials provided with the
|
||||
; distribution.
|
||||
; * Neither the name of Intel Corporation nor the names of its
|
||||
; contributors may be used to endorse or promote products derived
|
||||
; from this software without specific prior written permission.
|
||||
;
|
||||
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;;;
|
||||
;;; gf_2vect_dot_prod_sse(len, vec, *g_tbls, **buffs, **dests);
|
||||
;;;
|
||||
|
||||
%ifidn __OUTPUT_FORMAT__, elf64
|
||||
%define arg0 rdi
|
||||
%define arg1 rsi
|
||||
%define arg2 rdx
|
||||
%define arg3 rcx
|
||||
%define arg4 r8
|
||||
%define arg5 r9
|
||||
|
||||
%define tmp r11
|
||||
%define tmp2 r10
|
||||
%define tmp3 r9
|
||||
%define tmp4 r12 ; must be saved and restored
|
||||
%define return rax
|
||||
%macro SLDR 2
|
||||
%endmacro
|
||||
%define SSTR SLDR
|
||||
%define PS 8
|
||||
%define LOG_PS 3
|
||||
|
||||
%define func(x) x:
|
||||
%macro FUNC_SAVE 0
|
||||
push r12
|
||||
%endmacro
|
||||
%macro FUNC_RESTORE 0
|
||||
pop r12
|
||||
%endmacro
|
||||
%endif
|
||||
|
||||
%ifidn __OUTPUT_FORMAT__, macho64
|
||||
%define arg0 rdi
|
||||
%define arg1 rsi
|
||||
%define arg2 rdx
|
||||
%define arg3 rcx
|
||||
%define arg4 r8
|
||||
%define arg5 r9
|
||||
|
||||
%define tmp r11
|
||||
%define tmp.w r11d
|
||||
%define tmp.b r11b
|
||||
%define tmp2 r10
|
||||
%define tmp3 r13 ; must be saved and restored
|
||||
%define tmp4 r12 ; must be saved and restored
|
||||
%define return rax
|
||||
%macro SLDR 2
|
||||
%endmacro
|
||||
%define SSTR SLDR
|
||||
%define PS 8
|
||||
%define LOG_PS 3
|
||||
|
||||
%define func(x) x:
|
||||
%macro FUNC_SAVE 0
|
||||
push r12
|
||||
push r13
|
||||
%endmacro
|
||||
%macro FUNC_RESTORE 0
|
||||
pop r13
|
||||
pop r12
|
||||
%endmacro
|
||||
%endif
|
||||
|
||||
%ifidn __OUTPUT_FORMAT__, win64
|
||||
%define arg0 rcx
|
||||
%define arg1 rdx
|
||||
%define arg2 r8
|
||||
%define arg3 r9
|
||||
|
||||
%define arg4 r12 ; must be saved, loaded and restored
|
||||
%define tmp r11
|
||||
%define tmp2 r10
|
||||
%define tmp3 r13 ; must be saved and restored
|
||||
%define tmp4 r14 ; must be saved and restored
|
||||
%define return rax
|
||||
%macro SLDR 2
|
||||
%endmacro
|
||||
%define SSTR SLDR
|
||||
%define PS 8
|
||||
%define LOG_PS 3
|
||||
%define stack_size 3*16 + 3*8 ; must be an odd multiple of 8
|
||||
%define arg(x) [rsp + stack_size + PS + PS*x]
|
||||
|
||||
%define func(x) proc_frame x
|
||||
%macro FUNC_SAVE 0
|
||||
alloc_stack stack_size
|
||||
save_xmm128 xmm6, 0*16
|
||||
save_xmm128 xmm7, 1*16
|
||||
save_xmm128 xmm8, 2*16
|
||||
save_reg r12, 3*16 + 0*8
|
||||
save_reg r13, 3*16 + 1*8
|
||||
save_reg r14, 3*16 + 2*8
|
||||
end_prolog
|
||||
mov arg4, arg(4)
|
||||
%endmacro
|
||||
|
||||
%macro FUNC_RESTORE 0
|
||||
movdqa xmm6, [rsp + 0*16]
|
||||
movdqa xmm7, [rsp + 1*16]
|
||||
movdqa xmm8, [rsp + 2*16]
|
||||
mov r12, [rsp + 3*16 + 0*8]
|
||||
mov r13, [rsp + 3*16 + 1*8]
|
||||
mov r14, [rsp + 3*16 + 2*8]
|
||||
add rsp, stack_size
|
||||
%endmacro
|
||||
%endif
|
||||
|
||||
%ifidn __OUTPUT_FORMAT__, elf32
|
||||
|
||||
;;;================== High Address;
|
||||
;;; arg4
|
||||
;;; arg3
|
||||
;;; arg2
|
||||
;;; arg1
|
||||
;;; arg0
|
||||
;;; return
|
||||
;;;<================= esp of caller
|
||||
;;; ebp
|
||||
;;;<================= ebp = esp
|
||||
;;; var0
|
||||
;;; esi
|
||||
;;; edi
|
||||
;;; ebx
|
||||
;;;<================= esp of callee
|
||||
;;;
|
||||
;;;================== Low Address;
|
||||
|
||||
%define PS 4
|
||||
%define LOG_PS 2
|
||||
%define func(x) x:
|
||||
%define arg(x) [ebp + PS*2 + PS*x]
|
||||
%define var(x) [ebp - PS - PS*x]
|
||||
|
||||
%define trans ecx
|
||||
%define trans2 esi
|
||||
%define arg0 trans ;trans and trans2 are for the variables in stack
|
||||
%define arg0_m arg(0)
|
||||
%define arg1 ebx
|
||||
%define arg2 arg2_m
|
||||
%define arg2_m arg(2)
|
||||
%define arg3 trans
|
||||
%define arg3_m arg(3)
|
||||
%define arg4 trans
|
||||
%define arg4_m arg(4)
|
||||
%define tmp edx
|
||||
%define tmp2 edi
|
||||
%define tmp3 trans2
|
||||
%define tmp4 trans2
|
||||
%define tmp4_m var(0)
|
||||
%define return eax
|
||||
%macro SLDR 2 ;; stack load/restore
|
||||
mov %1, %2
|
||||
%endmacro
|
||||
%define SSTR SLDR
|
||||
|
||||
%macro FUNC_SAVE 0
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
sub esp, PS*1 ;1 local variable
|
||||
push esi
|
||||
push edi
|
||||
push ebx
|
||||
mov arg1, arg(1)
|
||||
%endmacro
|
||||
|
||||
%macro FUNC_RESTORE 0
|
||||
pop ebx
|
||||
pop edi
|
||||
pop esi
|
||||
add esp, PS*1 ;1 local variable
|
||||
pop ebp
|
||||
%endmacro
|
||||
|
||||
%endif ; output formats
|
||||
|
||||
%define len arg0
|
||||
%define vec arg1
|
||||
%define mul_array arg2
|
||||
%define src arg3
|
||||
%define dest1 arg4
|
||||
|
||||
%define vec_i tmp2
|
||||
%define ptr tmp3
|
||||
%define dest2 tmp4
|
||||
%define pos return
|
||||
|
||||
%ifidn PS,4 ;32-bit code
|
||||
%define len_m arg0_m
|
||||
%define src_m arg3_m
|
||||
%define dest1_m arg4_m
|
||||
%define dest2_m tmp4_m
|
||||
%endif
|
||||
|
||||
%ifndef EC_ALIGNED_ADDR
|
||||
;;; Use Un-aligned load/store
|
||||
%define XLDR movdqu
|
||||
%define XSTR movdqu
|
||||
%else
|
||||
;;; Use Non-temporal load/stor
|
||||
%ifdef NO_NT_LDST
|
||||
%define XLDR movdqa
|
||||
%define XSTR movdqa
|
||||
%else
|
||||
%define XLDR movntdqa
|
||||
%define XSTR movntdq
|
||||
%endif
|
||||
%endif
|
||||
|
||||
%ifidn PS,8 ;64-bit code
|
||||
default rel
|
||||
[bits 64]
|
||||
%endif
|
||||
|
||||
section .text
|
||||
|
||||
%ifidn PS,8 ;64-bit code
|
||||
%define xmask0f xmm8
|
||||
%define xgft1_lo xmm7
|
||||
%define xgft1_hi xmm6
|
||||
%define xgft2_lo xmm5
|
||||
%define xgft2_hi xmm4
|
||||
|
||||
%define x0 xmm0
|
||||
%define xtmpa xmm1
|
||||
%define xp1 xmm2
|
||||
%define xp2 xmm3
|
||||
%else ;32-bit code
|
||||
%define xmask0f xmm4
|
||||
%define xgft1_lo xmm7
|
||||
%define xgft1_hi xmm6
|
||||
%define xgft2_lo xgft1_lo
|
||||
%define xgft2_hi xgft1_hi
|
||||
|
||||
%define x0 xmm0
|
||||
%define xtmpa xmm1
|
||||
%define xp1 xmm2
|
||||
%define xp2 xmm3
|
||||
%endif
|
||||
|
||||
align 16
|
||||
global gf_2vect_dot_prod_sse:function
|
||||
func(gf_2vect_dot_prod_sse)
|
||||
FUNC_SAVE
|
||||
SLDR len, len_m
|
||||
sub len, 16
|
||||
SSTR len_m, len
|
||||
jl .return_fail
|
||||
xor pos, pos
|
||||
movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte
|
||||
sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS
|
||||
SLDR dest1, dest1_m
|
||||
mov dest2, [dest1+PS]
|
||||
SSTR dest2_m, dest2
|
||||
mov dest1, [dest1]
|
||||
SSTR dest1_m, dest1
|
||||
|
||||
.loop16
|
||||
pxor xp1, xp1
|
||||
pxor xp2, xp2
|
||||
mov tmp, mul_array
|
||||
xor vec_i, vec_i
|
||||
|
||||
.next_vect
|
||||
SLDR src, src_m
|
||||
mov ptr, [src+vec_i]
|
||||
|
||||
movdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f}
|
||||
movdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0}
|
||||
%ifidn PS,8 ;64-bit code
|
||||
movdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f}
|
||||
movdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0}
|
||||
add tmp, 32
|
||||
add vec_i, PS
|
||||
%endif
|
||||
XLDR x0, [ptr+pos] ;Get next source vector
|
||||
|
||||
movdqa xtmpa, x0 ;Keep unshifted copy of src
|
||||
psraw x0, 4 ;Shift to put high nibble into bits 4-0
|
||||
pand x0, xmask0f ;Mask high src nibble in bits 4-0
|
||||
pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0
|
||||
|
||||
pshufb xgft1_hi, x0 ;Lookup mul table of high nibble
|
||||
pshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble
|
||||
pxor xgft1_hi, xgft1_lo ;GF add high and low partials
|
||||
pxor xp1, xgft1_hi ;xp1 += partial
|
||||
|
||||
%ifidn PS,4 ;32-bit code
|
||||
movdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f}
|
||||
movdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0}
|
||||
|
||||
add tmp, 32
|
||||
add vec_i, PS
|
||||
%endif
|
||||
pshufb xgft2_hi, x0 ;Lookup mul table of high nibble
|
||||
pshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble
|
||||
pxor xgft2_hi, xgft2_lo ;GF add high and low partials
|
||||
pxor xp2, xgft2_hi ;xp2 += partial
|
||||
|
||||
cmp vec_i, vec
|
||||
jl .next_vect
|
||||
|
||||
SLDR dest1, dest1_m
|
||||
SLDR dest2, dest2_m
|
||||
XSTR [dest1+pos], xp1
|
||||
XSTR [dest2+pos], xp2
|
||||
|
||||
SLDR len, len_m
|
||||
add pos, 16 ;Loop on 16 bytes at a time
|
||||
cmp pos, len
|
||||
jle .loop16
|
||||
|
||||
lea tmp, [len + 16]
|
||||
cmp pos, tmp
|
||||
je .return_pass
|
||||
|
||||
;; Tail len
|
||||
mov pos, len ;Overlapped offset length-16
|
||||
jmp .loop16 ;Do one more overlap pass
|
||||
|
||||
.return_pass:
|
||||
mov return, 0
|
||||
FUNC_RESTORE
|
||||
ret
|
||||
|
||||
.return_fail:
|
||||
mov return, 1
|
||||
FUNC_RESTORE
|
||||
ret
|
||||
|
||||
endproc_frame
|
||||
|
||||
section .data
|
||||
|
||||
align 16
|
||||
mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f
|
||||
|
||||
%macro slversion 4
|
||||
global %1_slver_%2%3%4
|
||||
global %1_slver
|
||||
%1_slver:
|
||||
%1_slver_%2%3%4:
|
||||
dw 0x%4
|
||||
db 0x%3, 0x%2
|
||||
%endmacro
|
||||
;;; func core, ver, snum
|
||||
slversion gf_2vect_dot_prod_sse, 00, 03, 0062
|
||||
@@ -1,258 +0,0 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Copyright(c) 2011-2015 Intel Corporation All rights reserved.
|
||||
;
|
||||
; Redistribution and use in source and binary forms, with or without
|
||||
; modification, are permitted provided that the following conditions
|
||||
; are met:
|
||||
; * Redistributions of source code must retain the above copyright
|
||||
; notice, this list of conditions and the following disclaimer.
|
||||
; * Redistributions in binary form must reproduce the above copyright
|
||||
; notice, this list of conditions and the following disclaimer in
|
||||
; the documentation and/or other materials provided with the
|
||||
; distribution.
|
||||
; * Neither the name of Intel Corporation nor the names of its
|
||||
; contributors may be used to endorse or promote products derived
|
||||
; from this software without specific prior written permission.
|
||||
;
|
||||
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;;;
|
||||
;;; gf_2vect_mad_avx(len, vec, vec_i, mul_array, src, dest);
|
||||
;;;
|
||||
|
||||
%define PS 8
|
||||
|
||||
%ifidn __OUTPUT_FORMAT__, win64
|
||||
%define arg0 rcx
|
||||
%define arg0.w ecx
|
||||
%define arg1 rdx
|
||||
%define arg2 r8
|
||||
%define arg3 r9
|
||||
%define arg4 r12
|
||||
%define arg5 r15
|
||||
%define tmp r11
|
||||
%define tmp2 r10
|
||||
%define return rax
|
||||
%define return.w eax
|
||||
%define stack_size 16*9 + 3*8
|
||||
%define arg(x) [rsp + stack_size + PS + PS*x]
|
||||
%define func(x) proc_frame x
|
||||
|
||||
%macro FUNC_SAVE 0
|
||||
sub rsp, stack_size
|
||||
movdqa [rsp+16*0],xmm6
|
||||
movdqa [rsp+16*1],xmm7
|
||||
movdqa [rsp+16*2],xmm8
|
||||
movdqa [rsp+16*3],xmm9
|
||||
movdqa [rsp+16*4],xmm10
|
||||
movdqa [rsp+16*5],xmm11
|
||||
movdqa [rsp+16*6],xmm12
|
||||
movdqa [rsp+16*7],xmm13
|
||||
movdqa [rsp+16*8],xmm14
|
||||
save_reg r12, 9*16 + 0*8
|
||||
save_reg r15, 9*16 + 1*8
|
||||
end_prolog
|
||||
mov arg4, arg(4)
|
||||
mov arg5, arg(5)
|
||||
%endmacro
|
||||
|
||||
%macro FUNC_RESTORE 0
|
||||
movdqa xmm6, [rsp+16*0]
|
||||
movdqa xmm7, [rsp+16*1]
|
||||
movdqa xmm8, [rsp+16*2]
|
||||
movdqa xmm9, [rsp+16*3]
|
||||
movdqa xmm10, [rsp+16*4]
|
||||
movdqa xmm11, [rsp+16*5]
|
||||
movdqa xmm12, [rsp+16*6]
|
||||
movdqa xmm13, [rsp+16*7]
|
||||
movdqa xmm14, [rsp+16*8]
|
||||
mov r12, [rsp + 9*16 + 0*8]
|
||||
mov r15, [rsp + 9*16 + 1*8]
|
||||
add rsp, stack_size
|
||||
%endmacro
|
||||
|
||||
%elifidn __OUTPUT_FORMAT__, elf64
|
||||
%define arg0 rdi
|
||||
%define arg0.w edi
|
||||
%define arg1 rsi
|
||||
%define arg2 rdx
|
||||
%define arg3 rcx
|
||||
%define arg4 r8
|
||||
%define arg5 r9
|
||||
%define tmp r11
|
||||
%define tmp2 r10
|
||||
%define return rax
|
||||
%define return.w eax
|
||||
|
||||
%define func(x) x:
|
||||
%define FUNC_SAVE
|
||||
%define FUNC_RESTORE
|
||||
|
||||
%elifidn __OUTPUT_FORMAT__, macho64
|
||||
%define arg0 rdi
|
||||
%define arg0.w edi
|
||||
%define arg1 rsi
|
||||
%define arg2 rdx
|
||||
%define arg3 rcx
|
||||
%define arg4 r8
|
||||
%define arg5 r9
|
||||
%define tmp r11
|
||||
%define tmp2 r10
|
||||
%define return rax
|
||||
%define return.w eax
|
||||
|
||||
%define func(x) x:
|
||||
%define FUNC_SAVE
|
||||
%define FUNC_RESTORE
|
||||
%endif
|
||||
|
||||
;;; gf_2vect_mad_avx(len, vec, vec_i, mul_array, src, dest)
|
||||
%define len arg0
|
||||
%define len.w arg0.w
|
||||
%define vec arg1
|
||||
%define vec_i arg2
|
||||
%define mul_array arg3
|
||||
%define src arg4
|
||||
%define dest1 arg5
|
||||
%define pos return
|
||||
%define pos.w return.w
|
||||
|
||||
%define dest2 tmp2
|
||||
|
||||
%ifndef EC_ALIGNED_ADDR
|
||||
;;; Use Un-aligned load/store
|
||||
%define XLDR vmovdqu
|
||||
%define XSTR vmovdqu
|
||||
%else
|
||||
;;; Use Non-temporal load/stor
|
||||
%ifdef NO_NT_LDST
|
||||
%define XLDR vmovdqa
|
||||
%define XSTR vmovdqa
|
||||
%else
|
||||
%define XLDR vmovntdqa
|
||||
%define XSTR vmovntdq
|
||||
%endif
|
||||
%endif
|
||||
|
||||
|
||||
default rel
|
||||
|
||||
[bits 64]
|
||||
section .text
|
||||
|
||||
%define xmask0f xmm14
|
||||
%define xgft1_lo xmm13
|
||||
%define xgft1_hi xmm12
|
||||
%define xgft2_lo xmm11
|
||||
%define xgft2_hi xmm10
|
||||
|
||||
%define x0 xmm0
|
||||
%define xtmpa xmm1
|
||||
%define xtmph1 xmm2
|
||||
%define xtmpl1 xmm3
|
||||
%define xtmph2 xmm4
|
||||
%define xtmpl2 xmm5
|
||||
%define xd1 xmm6
|
||||
%define xd2 xmm7
|
||||
%define xtmpd1 xmm8
|
||||
%define xtmpd2 xmm9
|
||||
|
||||
|
||||
align 16
|
||||
global gf_2vect_mad_avx:function
|
||||
func(gf_2vect_mad_avx)
|
||||
FUNC_SAVE
|
||||
sub len, 16
|
||||
jl .return_fail
|
||||
|
||||
xor pos, pos
|
||||
vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte
|
||||
sal vec_i, 5 ;Multiply by 32
|
||||
sal vec, 5
|
||||
lea tmp, [mul_array + vec_i]
|
||||
vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, Ax{02}, ...
|
||||
vmovdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0}
|
||||
vmovdqu xgft2_lo, [tmp+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ...
|
||||
vmovdqu xgft2_hi, [tmp+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0}
|
||||
|
||||
mov dest2, [dest1+PS]
|
||||
mov dest1, [dest1]
|
||||
|
||||
XLDR xtmpd1, [dest1+len] ;backup the last 16 bytes in dest
|
||||
XLDR xtmpd2, [dest2+len] ;backup the last 16 bytes in dest
|
||||
|
||||
.loop16
|
||||
XLDR xd1, [dest1+pos] ;Get next dest vector
|
||||
XLDR xd2, [dest2+pos] ;Get next dest vector
|
||||
.loop16_overlap:
|
||||
XLDR x0, [src+pos] ;Get next source vector
|
||||
|
||||
vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0
|
||||
vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0
|
||||
vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0
|
||||
|
||||
vpshufb xtmph1, xgft1_hi, x0 ;Lookup mul table of high nibble
|
||||
vpshufb xtmpl1, xgft1_lo, xtmpa ;Lookup mul table of low nibble
|
||||
vpxor xtmph1, xtmph1, xtmpl1 ;GF add high and low partials
|
||||
vpxor xd1, xd1, xtmph1 ;xd1 += partial
|
||||
|
||||
vpshufb xtmph2, xgft2_hi, x0 ;Lookup mul table of high nibble
|
||||
vpshufb xtmpl2, xgft2_lo, xtmpa ;Lookup mul table of low nibble
|
||||
vpxor xtmph2, xtmph2, xtmpl2 ;GF add high and low partials
|
||||
vpxor xd2, xd2, xtmph2 ;xd2 += partial
|
||||
|
||||
XSTR [dest1+pos], xd1
|
||||
XSTR [dest2+pos], xd2
|
||||
|
||||
add pos, 16 ;Loop on 16 bytes at a time
|
||||
cmp pos, len
|
||||
jle .loop16
|
||||
|
||||
lea tmp, [len + 16]
|
||||
cmp pos, tmp
|
||||
je .return_pass
|
||||
|
||||
;; Tail len
|
||||
mov pos, len ;Overlapped offset length-16
|
||||
vmovdqa xd1, xtmpd1 ;Restore xd1
|
||||
vmovdqa xd2, xtmpd2 ;Restore xd2
|
||||
jmp .loop16_overlap ;Do one more overlap pass
|
||||
|
||||
.return_pass:
|
||||
mov return, 0
|
||||
FUNC_RESTORE
|
||||
ret
|
||||
|
||||
.return_fail:
|
||||
mov return, 1
|
||||
FUNC_RESTORE
|
||||
ret
|
||||
|
||||
endproc_frame
|
||||
|
||||
section .data
|
||||
|
||||
align 16
|
||||
mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f
|
||||
|
||||
%macro slversion 4
|
||||
global %1_slver_%2%3%4
|
||||
global %1_slver
|
||||
%1_slver:
|
||||
%1_slver_%2%3%4:
|
||||
dw 0x%4
|
||||
db 0x%3, 0x%2
|
||||
%endmacro
|
||||
;;; func core, ver, snum
|
||||
slversion gf_2vect_mad_avx, 02, 00, 0204
|
||||
@@ -1,273 +0,0 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Copyright(c) 2011-2015 Intel Corporation All rights reserved.
|
||||
;
|
||||
; Redistribution and use in source and binary forms, with or without
|
||||
; modification, are permitted provided that the following conditions
|
||||
; are met:
|
||||
; * Redistributions of source code must retain the above copyright
|
||||
; notice, this list of conditions and the following disclaimer.
|
||||
; * Redistributions in binary form must reproduce the above copyright
|
||||
; notice, this list of conditions and the following disclaimer in
|
||||
; the documentation and/or other materials provided with the
|
||||
; distribution.
|
||||
; * Neither the name of Intel Corporation nor the names of its
|
||||
; contributors may be used to endorse or promote products derived
|
||||
; from this software without specific prior written permission.
|
||||
;
|
||||
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;;;
|
||||
;;; gf_2vect_mad_avx2(len, vec, vec_i, mul_array, src, dest);
|
||||
;;;
|
||||
|
||||
%define PS 8
|
||||
|
||||
%ifidn __OUTPUT_FORMAT__, win64
|
||||
%define arg0 rcx
|
||||
%define arg0.w ecx
|
||||
%define arg1 rdx
|
||||
%define arg2 r8
|
||||
%define arg3 r9
|
||||
%define arg4 r12
|
||||
%define arg5 r15
|
||||
|
||||
%define tmp r11
|
||||
%define tmp.w r11d
|
||||
%define tmp.b r11b
|
||||
%define tmp2 r10
|
||||
%define return rax
|
||||
%define return.w eax
|
||||
%define stack_size 16*9 + 3*8 ; must be an odd multiple of 8
|
||||
%define arg(x) [rsp + stack_size + PS + PS*x]
|
||||
|
||||
%define func(x) proc_frame x
|
||||
%macro FUNC_SAVE 0
|
||||
sub rsp, stack_size
|
||||
vmovdqa [rsp+16*0],xmm6
|
||||
vmovdqa [rsp+16*1],xmm7
|
||||
vmovdqa [rsp+16*2],xmm8
|
||||
vmovdqa [rsp+16*3],xmm9
|
||||
vmovdqa [rsp+16*4],xmm10
|
||||
vmovdqa [rsp+16*5],xmm11
|
||||
vmovdqa [rsp+16*6],xmm12
|
||||
vmovdqa [rsp+16*7],xmm13
|
||||
vmovdqa [rsp+16*8],xmm14
|
||||
save_reg r12, 9*16 + 0*8
|
||||
save_reg r15, 9*16 + 1*8
|
||||
end_prolog
|
||||
mov arg4, arg(4)
|
||||
mov arg5, arg(5)
|
||||
%endmacro
|
||||
|
||||
%macro FUNC_RESTORE 0
|
||||
vmovdqa xmm6, [rsp+16*0]
|
||||
vmovdqa xmm7, [rsp+16*1]
|
||||
vmovdqa xmm8, [rsp+16*2]
|
||||
vmovdqa xmm9, [rsp+16*3]
|
||||
vmovdqa xmm10, [rsp+16*4]
|
||||
vmovdqa xmm11, [rsp+16*5]
|
||||
vmovdqa xmm12, [rsp+16*6]
|
||||
vmovdqa xmm13, [rsp+16*7]
|
||||
vmovdqa xmm14, [rsp+16*8]
|
||||
mov r12, [rsp + 9*16 + 0*8]
|
||||
mov r15, [rsp + 9*16 + 1*8]
|
||||
add rsp, stack_size
|
||||
%endmacro
|
||||
%endif
|
||||
|
||||
%ifidn __OUTPUT_FORMAT__, elf64
|
||||
%define arg0 rdi
|
||||
%define arg0.w edi
|
||||
%define arg1 rsi
|
||||
%define arg2 rdx
|
||||
%define arg3 rcx
|
||||
%define arg4 r8
|
||||
%define arg5 r9
|
||||
|
||||
%define tmp r11
|
||||
%define tmp.w r11d
|
||||
%define tmp.b r11b
|
||||
%define tmp2 r10
|
||||
%define return rax
|
||||
%define return.w eax
|
||||
|
||||
%define func(x) x:
|
||||
%define FUNC_SAVE
|
||||
%define FUNC_RESTORE
|
||||
%endif
|
||||
|
||||
%ifidn __OUTPUT_FORMAT__, macho64
|
||||
%define arg0 rdi
|
||||
%define arg0.w edi
|
||||
%define arg1 rsi
|
||||
%define arg2 rdx
|
||||
%define arg3 rcx
|
||||
%define arg4 r8
|
||||
%define arg5 r9
|
||||
|
||||
%define tmp r11
|
||||
%define tmp.w r11d
|
||||
%define tmp.b r11b
|
||||
%define tmp2 r10
|
||||
%define return rax
|
||||
%define return.w eax
|
||||
|
||||
%define func(x) x:
|
||||
%define FUNC_SAVE
|
||||
%define FUNC_RESTORE
|
||||
%endif
|
||||
|
||||
;;; gf_2vect_mad_avx2(len, vec, vec_i, mul_array, src, dest)
|
||||
%define len arg0
|
||||
%define len.w arg0.w
|
||||
%define vec arg1
|
||||
%define vec_i arg2
|
||||
%define mul_array arg3
|
||||
%define src arg4
|
||||
%define dest1 arg5
|
||||
%define pos return
|
||||
%define pos.w return.w
|
||||
|
||||
%define dest2 tmp2
|
||||
|
||||
%ifndef EC_ALIGNED_ADDR
|
||||
;;; Use Un-aligned load/store
|
||||
%define XLDR vmovdqu
|
||||
%define XSTR vmovdqu
|
||||
%else
|
||||
|
||||
;;; Use Non-temporal load/stor
|
||||
%ifdef NO_NT_LDST
|
||||
%define XLDR vmovdqa
|
||||
%define XSTR vmovdqa
|
||||
%else
|
||||
%define XLDR vmovntdqa
|
||||
%define XSTR vmovntdq
|
||||
%endif
|
||||
%endif
|
||||
|
||||
|
||||
default rel
|
||||
|
||||
[bits 64]
|
||||
section .text
|
||||
|
||||
%define xmask0f ymm14
|
||||
%define xmask0fx xmm14
|
||||
%define xgft1_lo ymm13
|
||||
%define xgft1_hi ymm12
|
||||
%define xgft2_lo ymm11
|
||||
%define xgft2_hi ymm10
|
||||
|
||||
%define x0 ymm0
|
||||
%define xtmpa ymm1
|
||||
%define xtmph1 ymm2
|
||||
%define xtmpl1 ymm3
|
||||
%define xtmph2 ymm4
|
||||
%define xtmpl2 ymm5
|
||||
%define xd1 ymm6
|
||||
%define xd2 ymm7
|
||||
%define xtmpd1 ymm8
|
||||
%define xtmpd2 ymm9
|
||||
|
||||
align 16
|
||||
global gf_2vect_mad_avx2:function
|
||||
func(gf_2vect_mad_avx2)
|
||||
FUNC_SAVE
|
||||
sub len, 32
|
||||
jl .return_fail
|
||||
xor pos, pos
|
||||
mov tmp.b, 0x0f
|
||||
vpinsrb xmask0fx, xmask0fx, tmp.w, 0
|
||||
vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f...
|
||||
|
||||
sal vec_i, 5 ;Multiply by 32
|
||||
sal vec, 5
|
||||
lea tmp, [mul_array + vec_i]
|
||||
vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f}
|
||||
; " Ax{00}, Ax{10}, ..., Ax{f0}
|
||||
vmovdqu xgft2_lo, [tmp+vec] ;Load array Bx{00}, Bx{01}, ..., Bx{0f}
|
||||
; " Bx{00}, Bx{10}, ..., Bx{f0}
|
||||
|
||||
vperm2i128 xgft1_hi, xgft1_lo, xgft1_lo, 0x11 ; swapped to hi | hi
|
||||
vperm2i128 xgft1_lo, xgft1_lo, xgft1_lo, 0x00 ; swapped to lo | lo
|
||||
vperm2i128 xgft2_hi, xgft2_lo, xgft2_lo, 0x11 ; swapped to hi | hi
|
||||
vperm2i128 xgft2_lo, xgft2_lo, xgft2_lo, 0x00 ; swapped to lo | lo
|
||||
mov dest2, [dest1+PS] ; reuse mul_array
|
||||
mov dest1, [dest1]
|
||||
|
||||
XLDR xtmpd1, [dest1+len] ;backup the last 16 bytes in dest
|
||||
XLDR xtmpd2, [dest2+len] ;backup the last 16 bytes in dest
|
||||
|
||||
.loop32
|
||||
XLDR xd1, [dest1+pos] ;Get next dest vector
|
||||
XLDR xd2, [dest2+pos] ;Get next dest vector
|
||||
.loop32_overlap:
|
||||
XLDR x0, [src+pos] ;Get next source vector
|
||||
|
||||
vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0
|
||||
vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0
|
||||
vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0
|
||||
|
||||
vpshufb xtmph1, xgft1_hi, x0 ;Lookup mul table of high nibble
|
||||
vpshufb xtmpl1, xgft1_lo, xtmpa ;Lookup mul table of low nibble
|
||||
vpxor xtmph1, xtmph1, xtmpl1 ;GF add high and low partials
|
||||
vpxor xd1, xd1, xtmph1 ;xd1 += partial
|
||||
|
||||
vpshufb xtmph2, xgft2_hi, x0 ;Lookup mul table of high nibble
|
||||
vpshufb xtmpl2, xgft2_lo, xtmpa ;Lookup mul table of low nibble
|
||||
vpxor xtmph2, xtmph2, xtmpl2 ;GF add high and low partials
|
||||
vpxor xd2, xd2, xtmph2 ;xd2 += partial
|
||||
|
||||
XSTR [dest1+pos], xd1
|
||||
XSTR [dest2+pos], xd2
|
||||
|
||||
add pos, 32 ;Loop on 32 bytes at a time
|
||||
cmp pos, len
|
||||
jle .loop32
|
||||
|
||||
lea tmp, [len + 32]
|
||||
cmp pos, tmp
|
||||
je .return_pass
|
||||
|
||||
;; Tail len
|
||||
mov pos, len ;Overlapped offset length-32
|
||||
vmovdqa xd1, xtmpd1 ;Restore xd1
|
||||
vmovdqa xd2, xtmpd2 ;Restore xd2
|
||||
jmp .loop32_overlap ;Do one more overlap pass
|
||||
|
||||
.return_pass:
|
||||
mov return, 0
|
||||
FUNC_RESTORE
|
||||
ret
|
||||
|
||||
.return_fail:
|
||||
mov return, 1
|
||||
FUNC_RESTORE
|
||||
ret
|
||||
|
||||
endproc_frame
|
||||
|
||||
section .data
|
||||
|
||||
%macro slversion 4
|
||||
global %1_slver_%2%3%4
|
||||
global %1_slver
|
||||
%1_slver:
|
||||
%1_slver_%2%3%4:
|
||||
dw 0x%4
|
||||
db 0x%3, 0x%2
|
||||
%endmacro
|
||||
;;; func core, ver, snum
|
||||
slversion gf_2vect_mad_avx2, 04, 00, 0205
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user