diff options
| -rw-r--r-- | internal/contentenc/bpool.go | 39 | ||||
| -rw-r--r-- | internal/contentenc/content.go | 40 | ||||
| -rw-r--r-- | internal/fusefrontend/file.go | 4 | 
3 files changed, 56 insertions, 27 deletions
| diff --git a/internal/contentenc/bpool.go b/internal/contentenc/bpool.go new file mode 100644 index 0000000..c4517d3 --- /dev/null +++ b/internal/contentenc/bpool.go @@ -0,0 +1,39 @@ +package contentenc + +import ( +	"log" +	"sync" +) + +// bPool is a byte slice pool +type bPool struct { +	sync.Pool +	sliceLen int +} + +func newBPool(sliceLen int) bPool { +	return bPool{ +		Pool: sync.Pool{ +			New: func() interface{} { return make([]byte, sliceLen) }, +		}, +		sliceLen: sliceLen, +	} +} + +// Put grows the slice "s" to its maximum capacity and puts it into the pool. +func (b *bPool) Put(s []byte) { +	s = s[:cap(s)] +	if len(s) != b.sliceLen { +		log.Panicf("wrong len=%d, want=%d", len(s), b.sliceLen) +	} +	b.Pool.Put(s) +} + +// Get returns a byte slice from the pool. +func (b *bPool) Get() (s []byte) { +	s = b.Pool.Get().([]byte) +	if len(s) != b.sliceLen { +		log.Panicf("wrong len=%d, want=%d", len(s), b.sliceLen) +	} +	return s +} diff --git a/internal/contentenc/content.go b/internal/contentenc/content.go index 9bc1c50..238683c 100644 --- a/internal/contentenc/content.go +++ b/internal/contentenc/content.go @@ -54,18 +54,19 @@ type ContentEnc struct {  	// Force decode even if integrity check fails (openSSL only)  	forceDecode bool  	// Ciphertext block pool. Always returns cipherBS-sized byte slices. -	cBlockPool sync.Pool -	// Ciphertext write pool. Always returns byte slices of size +	cBlockPool bPool +	// Ciphertext request data pool. Always returns byte slices of size  	// fuse.MAX_KERNEL_WRITE + overhead. -	cWritePool sync.Pool -	cWriteSize int +	CReqPool bPool +	// Plaintext block pool. Always returns plainBS-sized byte slices. +	pBlockPool bPool  }  // New returns an initialized ContentEnc instance.  func New(cc *cryptocore.CryptoCore, plainBS uint64, forceDecode bool) *ContentEnc {  	cipherBS := plainBS + uint64(cc.IVLen) + cryptocore.AuthTagLen  	// Take IV and GHASH overhead into account. -	cWriteSize := int(fuse.MAX_KERNEL_WRITE / plainBS * cipherBS) +	cReqSize := int(fuse.MAX_KERNEL_WRITE / plainBS * cipherBS)  	if fuse.MAX_KERNEL_WRITE%plainBS != 0 {  		log.Panicf("unaligned MAX_KERNEL_WRITE=%d", fuse.MAX_KERNEL_WRITE)  	} @@ -76,22 +77,13 @@ func New(cc *cryptocore.CryptoCore, plainBS uint64, forceDecode bool) *ContentEn  		allZeroBlock: make([]byte, cipherBS),  		allZeroNonce: make([]byte, cc.IVLen),  		forceDecode:  forceDecode, -		cWriteSize:   cWriteSize, +		cBlockPool:   newBPool(int(cipherBS)), +		CReqPool:     newBPool(cReqSize), +		pBlockPool:   newBPool(int(plainBS)),  	} -	c.cBlockPool.New = func() interface{} { return make([]byte, cipherBS) } -	c.cWritePool.New = func() interface{} { return make([]byte, cWriteSize) }  	return c  } -// CWritePut puts "buf" back into the cWritePool. -func (be *ContentEnc) CWritePut(buf []byte) { -	buf = buf[:cap(buf)] -	if len(buf) != be.cWriteSize { -		log.Panicf("wrong len=%d, want=%d", len(buf), be.cWriteSize) -	} -	be.cWritePool.Put(buf) -} -  // PlainBS returns the plaintext block size  func (be *ContentEnc) PlainBS() uint64 {  	return be.plainBS @@ -119,6 +111,7 @@ func (be *ContentEnc) DecryptBlocks(ciphertext []byte, firstBlockNo uint64, file  			}  		}  		pBuf.Write(pBlock) +		be.pBlockPool.Put(pBlock)  		firstBlockNo++  	}  	return pBuf.Bytes(), err @@ -158,7 +151,8 @@ func (be *ContentEnc) DecryptBlock(ciphertext []byte, blockNo uint64, fileID []b  	ciphertext = ciphertext[be.cryptoCore.IVLen:]  	// Decrypt -	var plaintext []byte +	plaintext := be.pBlockPool.Get() +	plaintext = plaintext[:0]  	aData := make([]byte, 8)  	aData = append(aData, fileID...)  	binary.BigEndian.PutUint64(aData, blockNo) @@ -210,16 +204,12 @@ func (be *ContentEnc) EncryptBlocks(plaintextBlocks [][]byte, firstBlockNo uint6  		be.doEncryptBlocks(plaintextBlocks, ciphertextBlocks, firstBlockNo, fileID)  	}  	// Concatenate ciphertext into a single byte array. -	tmp := be.cWritePool.Get().([]byte) +	tmp := be.CReqPool.Get()  	out := bytes.NewBuffer(tmp[:0])  	for _, v := range ciphertextBlocks {  		out.Write(v)  		// Return the memory to cBlockPool -		cBlock := v[:cap(v)] -		if len(cBlock) != int(be.cipherBS) { -			log.Panicf("unexpected cBlock length: len=%d cipherBS=%d", len(cBlock), be.cipherBS) -		} -		be.cBlockPool.Put(cBlock) +		be.cBlockPool.Put(v)  	}  	return out.Bytes()  } @@ -268,7 +258,7 @@ func (be *ContentEnc) doEncryptBlock(plaintext []byte, blockNo uint64, fileID []  	aData = append(aData, fileID...)  	// Get a cipherBS-sized block of memory, copy the nonce into it and truncate to  	// nonce length -	cBlock := be.cBlockPool.Get().([]byte) +	cBlock := be.cBlockPool.Get()  	copy(cBlock, nonce)  	cBlock = cBlock[0:len(nonce)]  	// Encrypt plaintext and append to nonce diff --git a/internal/fusefrontend/file.go b/internal/fusefrontend/file.go index f70c9a5..277a71e 100644 --- a/internal/fusefrontend/file.go +++ b/internal/fusefrontend/file.go @@ -311,8 +311,8 @@ func (f *file) doWrite(data []byte, off int64) (uint32, fuse.Status) {  	}  	// Write  	_, err = f.fd.WriteAt(ciphertext, cOff) -	// Return memory to cWritePool -	f.fs.contentEnc.CWritePut(ciphertext) +	// Return memory to CReqPool +	f.fs.contentEnc.CReqPool.Put(ciphertext)  	if err != nil {  		tlog.Warn.Printf("doWrite: Write failed: %s", err.Error())  		return 0, fuse.ToStatus(err) | 
