Repository: petermattis/pebble
Pull request #114 (2019-05-04 02:59:04)

Rename "storage" package to "vfs"
This avoids awkwardness with the cockroach "storage" package.

petermattis: 

<!-- Reviewable:start -->
This change is [<img src="https://reviewable.io/review_button.png" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/petermattis/pebble/114)
<!-- Reviewable:end -->


Patch:
diff --git a/compaction.go b/compaction.go
index c3ce8d1..4a9ad18 100644
--- a/compaction.go
+++ b/compaction.go
@@ -16,7 +16,7 @@ import (
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/internal/rangedel"
 	"github.com/petermattis/pebble/sstable"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 )
 
 var errEmptyTable = errors.New("pebble: empty table")
@@ -479,7 +479,7 @@ func (d *DB) flush1() error {
 		})
 	}
 
-	meta, err := d.writeLevel0Table(d.opts.Storage, iter,
+	meta, err := d.writeLevel0Table(d.opts.VFS, iter,
 		true /* allowRangeTombstoneElision */)
 
 	if d.opts.EventListener != nil && d.opts.EventListener.FlushEnd != nil {
@@ -539,7 +539,7 @@ func (d *DB) flush1() error {
 // d.mu must be held when calling this, but the mutex may be dropped and
 // re-acquired during the course of this method.
 func (d *DB) writeLevel0Table(
-	fs storage.Storage, iiter internalIterator, allowRangeTombstoneElision bool,
+	fs vfs.FS, iiter internalIterator, allowRangeTombstoneElision bool,
 ) (meta fileMetadata, err error) {
 	meta.fileNum = d.mu.versions.nextFileNum()
 	filename := dbFilename(d.dirname, fileTypeTable, meta.fileNum)
@@ -599,7 +599,7 @@ func (d *DB) writeLevel0Table(
 		elideRangeTombstone,
 	)
 	var (
-		file storage.File
+		file vfs.File
 		tw   *sstable.Writer
 	)
 	defer func() {
@@ -838,7 +838,7 @@ func (d *DB) compactDiskTables(c *compaction) (ve *versionEdit, pendingOutputs [
 		}
 		if retErr != nil {
 			for _, filename := range filenames {
-				d.opts.Storage.Remove(filename)
+				d.opts.VFS.Remove(filename)
 			}
 		}
 	}()
@@ -855,7 +855,7 @@ func (d *DB) compactDiskTables(c *compaction) (ve *versionEdit, pendingOutputs [
 		d.mu.Unlock()
 
 		filename := dbFilename(d.dirname, fileTypeTable, fileNum)
-		file, err := d.opts.Storage.Create(filename)
+		file, err := d.opts.VFS.Create(filename)
 		if err != nil {
 			return err
 		}
@@ -984,7 +984,7 @@ func (d *DB) deleteObsoleteFiles(jobID int) {
 		d.mu.cleaner.cond.Signal()
 	}()
 
-	fs := d.opts.Storage
+	fs := d.opts.VFS
 	list, err := fs.List(d.dirname)
 	if err != nil {
 		// Ignore any filesystem errors.
diff --git a/db.go b/db.go
index d447f11..e8d0b43 100644
--- a/db.go
+++ b/db.go
@@ -16,7 +16,7 @@ import (
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/internal/arenaskl"
 	"github.com/petermattis/pebble/internal/record"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 )
 
 const (
@@ -769,7 +769,7 @@ func (d *DB) makeRoomForWrite(b *Batch) error {
 		}
 
 		var newLogNumber uint64
-		var newLogFile storage.File
+		var newLogFile vfs.File
 		var err error
 
 		if !d.opts.DisableWAL {
@@ -790,11 +790,11 @@ func (d *DB) makeRoomForWrite(b *Batch) error {
 			recycleLogNumber := d.logRecycler.peek()
 			if recycleLogNumber > 0 {
 				recycleLogName := dbFilename(d.dirname, fileTypeLog, recycleLogNumber)
-				err = d.opts.Storage.Rename(recycleLogName, newLogName)
+				err = d.opts.VFS.Rename(recycleLogName, newLogName)
 			}
 
 			if err == nil {
-				newLogFile, err = d.opts.Storage.Create(newLogName)
+				newLogFile, err = d.opts.VFS.Create(newLogName)
 			}
 
 			if err == nil {
@@ -802,7 +802,7 @@ func (d *DB) makeRoomForWrite(b *Batch) error {
 				if err != nil {
 					newLogFile.Close()
 				} else {
-					newLogFile = storage.NewSyncingFile(newLogFile, storage.SyncingFileOptions{
+					newLogFile = vfs.NewSyncingFile(newLogFile, vfs.SyncingFileOptions{
 						BytesPerSync:    d.opts.BytesPerSync,
 						PreallocateSize: d.walPreallocateSize(),
 					})
diff --git a/db/options.go b/db/options.go
index 49c17fd..f2ed1de 100644
--- a/db/options.go
+++ b/db/options.go
@@ -10,7 +10,7 @@ import (
 	"strings"
 
 	"github.com/petermattis/pebble/cache"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 )
 
 // Compression is the per-block compression algorithm to use.
@@ -267,16 +267,16 @@ type Options struct {
 	// The default merger concatenates values.
 	Merger *Merger
 
-	// Storage maps file names to byte storage.
-	//
-	// The default value uses the underlying operating system's file system.
-	Storage storage.Storage
-
 	// TableFormat specifies the format version for sstables. The default is
 	// TableFormatRocksDBv2 which creates RocksDB compatible sstables. Use
 	// TableFormatLevelDB to create LevelDB compatible sstable which can be used
 	// by a wider range of tools and libraries.
 	TableFormat TableFormat
+
+	// VFS provides the interface for persistent file storage.
+	//
+	// The default value uses the underlying operating system's file system.
+	VFS vfs.FS
 }
 
 // EnsureDefaults ensures that the default values for all options are set if a
@@ -334,8 +334,8 @@ func (o *Options) EnsureDefaults() *Options {
 	if o.Merger == nil {
 		o.Merger = DefaultMerger
 	}
-	if o.Storage == nil {
-		o.Storage = storage.Default
+	if o.VFS == nil {
+		o.VFS = vfs.Default
 	}
 	return o
 }
diff --git a/filenames.go b/filenames.go
index b1a5bcc..e3bba61 100644
--- a/filenames.go
+++ b/filenames.go
@@ -11,7 +11,7 @@ import (
 	"strconv"
 	"strings"
 
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 )
 
 type fileType int
@@ -84,7 +84,7 @@ func parseDBFilename(filename string) (fileType fileType, fileNum uint64, ok boo
 	return 0, 0, false
 }
 
-func setCurrentFile(dirname string, fs storage.Storage, fileNum uint64) error {
+func setCurrentFile(dirname string, fs vfs.FS, fileNum uint64) error {
 	newFilename := dbFilename(dirname, fileTypeCurrent, fileNum)
 	oldFilename := fmt.Sprintf("%s.%06d.dbtmp", newFilename, fileNum)
 	fs.Remove(oldFilename)
diff --git a/ingest.go b/ingest.go
index b4cac31..b75dcfe 100644
--- a/ingest.go
+++ b/ingest.go
@@ -10,16 +10,16 @@ import (
 
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/sstable"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 )
 
 func ingestLoad1(opts *db.Options, path string, fileNum uint64) (*fileMetadata, error) {
-	stat, err := opts.Storage.Stat(path)
+	stat, err := opts.VFS.Stat(path)
 	if err != nil {
 		return nil, err
 	}
 
-	f, err := opts.Storage.Open(path)
+	f, err := opts.VFS.Open(path)
 	if err != nil {
 		return nil, err
 	}
@@ -100,7 +100,7 @@ func ingestSortAndVerify(cmp db.Compare, meta []*fileMetadata) error {
 }
 
 func ingestCleanup(
-	fs storage.Storage, dirname string, meta []*fileMetadata,
+	fs vfs.FS, dirname string, meta []*fileMetadata,
 ) error {
 	var firstErr error
 	for i := range meta {
@@ -119,9 +119,9 @@ func ingestLink(
 ) error {
 	for i := range paths {
 		target := dbFilename(dirname, fileTypeTable, meta[i].fileNum)
-		err := opts.Storage.Link(paths[i], target)
+		err := opts.VFS.Link(paths[i], target)
 		if err != nil {
-			if err2 := ingestCleanup(opts.Storage, dirname, meta[:i]); err2 != nil {
+			if err2 := ingestCleanup(opts.VFS, dirname, meta[:i]); err2 != nil {
 				opts.Logger.Infof("ingest cleanup failed: %v", err2)
 			}
 			return err
@@ -339,7 +339,7 @@ func (d *DB) Ingest(paths []string) error {
 	d.commit.AllocateSeqNum(prepare, apply)
 
 	if err != nil {
-		if err2 := ingestCleanup(d.opts.Storage, d.dirname, meta); err2 != nil {
+		if err2 := ingestCleanup(d.opts.VFS, d.dirname, meta); err2 != nil {
 			d.opts.Logger.Infof("ingest cleanup failed: %v", err2)
 		}
 	}
diff --git a/open.go b/open.go
index 34aac0f..72f12c0 100644
--- a/open.go
+++ b/open.go
@@ -16,7 +16,7 @@ import (
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/internal/arenaskl"
 	"github.com/petermattis/pebble/internal/record"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 )
 
 func createDB(dirname string, opts *db.Options) (retErr error) {
@@ -26,13 +26,13 @@ func createDB(dirname string, opts *db.Options) (retErr error) {
 		nextFileNumber: manifestFileNum + 1,
 	}
 	manifestFilename := dbFilename(dirname, fileTypeManifest, manifestFileNum)
-	f, err := opts.Storage.Create(manifestFilename)
+	f, err := opts.VFS.Create(manifestFilename)
 	if err != nil {
 		return fmt.Errorf("pebble: could not create %q: %v", manifestFilename, err)
 	}
 	defer func() {
 		if retErr != nil {
-			opts.Storage.Remove(manifestFilename)
+			opts.VFS.Remove(manifestFilename)
 		}
 	}()
 	defer f.Close()
@@ -50,7 +50,7 @@ func createDB(dirname string, opts *db.Options) (retErr error) {
 	if err != nil {
 		return err
 	}
-	return setCurrentFile(dirname, opts.Storage, manifestFileNum)
+	return setCurrentFile(dirname, opts.VFS, manifestFileNum)
 }
 
 // Open opens a LevelDB whose files live in the given directory.
@@ -72,7 +72,7 @@ func Open(dirname string, opts *db.Options) (*DB, error) {
 	if tableCacheSize < minTableCacheSize {
 		tableCacheSize = minTableCacheSize
 	}
-	d.tableCache.init(dirname, opts.Storage, d.opts, tableCacheSize)
+	d.tableCache.init(dirname, opts.VFS, d.opts, tableCacheSize)
 	d.newIters = d.tableCache.newIters
 	d.commit = newCommitPipeline(commitEnv{
 		logSeqNum:     &d.mu.versions.logSeqNum,
@@ -95,12 +95,11 @@ func Open(dirname string, opts *db.Options) (*DB, error) {
 	defer d.mu.Unlock()
 
 	// Lock the database directory.
-	fs := opts.Storage
-	err := fs.MkdirAll(dirname, 0755)
+	err := opts.VFS.MkdirAll(dirname, 0755)
 	if err != nil {
 		return nil, err
 	}
-	fileLock, err := fs.Lock(dbFilename(dirname, fileTypeLock, 0))
+	fileLock, err := opts.VFS.Lock(dbFilename(dirname, fileTypeLock, 0))
 	if err != nil {
 		return nil, err
 	}
@@ -110,7 +109,7 @@ func Open(dirname string, opts *db.Options) (*DB, error) {
 		}
 	}()
 
-	if _, err := fs.Stat(dbFilename(dirname, fileTypeCurrent, 0)); os.IsNotExist(err) {
+	if _, err := opts.VFS.Stat(dbFilename(dirname, fileTypeCurrent, 0)); os.IsNotExist(err) {
 		// Create the DB if it did not already exist.
 		if err := createDB(dirname, opts); err != nil {
 			return nil, err
@@ -127,7 +126,7 @@ func Open(dirname string, opts *db.Options) (*DB, error) {
 		return nil, err
 	}
 
-	ls, err := fs.List(dirname)
+	ls, err := opts.VFS.List(dirname)
 	if err != nil {
 		return nil, err
 	}
@@ -159,7 +158,7 @@ func Open(dirname string, opts *db.Options) (*DB, error) {
 	})
 	var ve versionEdit
 	for _, lf := range logFiles {
-		maxSeqNum, err := d.replayWAL(&ve, fs, filepath.Join(dirname, lf.name), lf.num)
+		maxSeqNum, err := d.replayWAL(&ve, opts.VFS, filepath.Join(dirname, lf.name), lf.num)
 		if err != nil {
 			return nil, err
 		}
@@ -173,11 +172,11 @@ func Open(dirname string, opts *db.Options) (*DB, error) {
 	// Create an empty .log file.
 	ve.logNumber = d.mu.versions.nextFileNum()
 	d.mu.log.number = ve.logNumber
-	logFile, err := fs.Create(dbFilename(dirname, fileTypeLog, ve.logNumber))
+	logFile, err := opts.VFS.Create(dbFilename(dirname, fileTypeLog, ve.logNumber))
 	if err != nil {
 		return nil, err
 	}
-	logFile = storage.NewSyncingFile(logFile, storage.SyncingFileOptions{
+	logFile = vfs.NewSyncingFile(logFile, vfs.SyncingFileOptions{
 		BytesPerSync:    d.opts.BytesPerSync,
 		PreallocateSize: d.walPreallocateSize(),
 	})
@@ -191,7 +190,7 @@ func Open(dirname string, opts *db.Options) (*DB, error) {
 
 	// Write the current options to disk.
 	d.optionsFileNum = d.mu.versions.nextFileNum()
-	optionsFile, err := fs.Create(dbFilename(dirname, fileTypeOptions, d.optionsFileNum))
+	optionsFile, err := opts.VFS.Create(dbFilename(dirname, fileTypeOptions, d.optionsFileNum))
 	if err != nil {
 		return nil, err
 	}
@@ -216,7 +215,7 @@ func Open(dirname string, opts *db.Options) (*DB, error) {
 // re-acquired during the course of this method.
 func (d *DB) replayWAL(
 	ve *versionEdit,
-	fs storage.Storage,
+	fs vfs.FS,
 	filename string,
 	logNum uint64,
 ) (maxSeqNum uint64, err error) {
@@ -300,7 +299,7 @@ func (d *DB) replayWAL(
 }
 
 func checkOptions(opts *db.Options, path string) error {
-	f, err := opts.Storage.Open(path)
+	f, err := opts.VFS.Open(path)
 	if err != nil {
 		return err
 	}
diff --git a/ptable/reader.go b/ptable/reader.go
index 34eba5e..49aa0a1 100644
--- a/ptable/reader.go
+++ b/ptable/reader.go
@@ -15,7 +15,7 @@ import (
 	"github.com/petermattis/pebble/cache"
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/internal/crc"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 )
 
 // Iter ...
@@ -123,7 +123,7 @@ func (i *Iter) loadBlock() {
 
 // Reader ...
 type Reader struct {
-	file    storage.File
+	file    vfs.File
 	fileNum uint64 // TODO(peter): needed for block cache
 	err     error
 	index   []byte
@@ -132,7 +132,7 @@ type Reader struct {
 }
 
 // NewReader ...
-func NewReader(f storage.File, fileNum uint64, o *db.Options) *Reader {
+func NewReader(f vfs.File, fileNum uint64, o *db.Options) *Reader {
 	o = o.EnsureDefaults()
 	r := &Reader{
 		file:    f,
diff --git a/ptable/writer.go b/ptable/writer.go
index c2a134d..8dd1807 100644
--- a/ptable/writer.go
+++ b/ptable/writer.go
@@ -13,7 +13,7 @@ import (
 	"github.com/golang/snappy"
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/internal/crc"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 )
 
 const (
@@ -93,7 +93,7 @@ type Writer struct {
 var indexColTypes = []ColumnType{ColumnTypeBytes, ColumnTypeInt64}
 
 // NewWriter ...
-func NewWriter(f storage.File, env *Env, _ *db.Options, lo *db.LevelOptions) *Writer {
+func NewWriter(f vfs.File, env *Env, _ *db.Options, lo *db.LevelOptions) *Writer {
 	lo = lo.EnsureDefaults()
 	w := &Writer{
 		env:         env,
diff --git a/sstable/reader.go b/sstable/reader.go
index 1efc693..7bd315a 100644
--- a/sstable/reader.go
+++ b/sstable/reader.go
@@ -15,7 +15,7 @@ import (
 	"github.com/petermattis/pebble/cache"
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/internal/crc"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 )
 
 // blockHandle is the file offset and length of a block.
@@ -430,7 +430,7 @@ type weakCachedBlock struct {
 
 // Reader is a table reader.
 type Reader struct {
-	file        storage.File
+	file        vfs.File
 	fileNum     uint64
 	err         error
 	index       weakCachedBlock
@@ -704,7 +704,7 @@ func (r *Reader) readMetaindex(metaindexBH blockHandle, o *db.Options) error {
 
 // NewReader returns a new table reader for the file. Closing the reader will
 // close the file.
-func NewReader(f storage.File, fileNum uint64, o *db.Options) *Reader {
+func NewReader(f vfs.File, fileNum uint64, o *db.Options) *Reader {
 	o = o.EnsureDefaults()
 	r := &Reader{
 		file:    f,
diff --git a/sstable/table.go b/sstable/table.go
index dac606a..3f2a6d2 100644
--- a/sstable/table.go
+++ b/sstable/table.go
@@ -68,7 +68,7 @@ import (
 	"io"
 
 	"github.com/petermattis/pebble/db"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 )
 
 /*
@@ -179,7 +179,7 @@ type footer struct {
 	indexBH     blockHandle
 }
 
-func readFooter(f storage.File) (footer, error) {
+func readFooter(f vfs.File) (footer, error) {
 	var footer footer
 	stat, err := f.Stat()
 	if err != nil {
diff --git a/sstable/writer.go b/sstable/writer.go
index b432ce4..013126e 100644
--- a/sstable/writer.go
+++ b/sstable/writer.go
@@ -16,7 +16,7 @@ import (
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/internal/crc"
 	"github.com/petermattis/pebble/internal/rangedel"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 )
 
 // WriterMetadata holds info about a finished sstable.
@@ -78,7 +78,7 @@ func (m *WriterMetadata) Largest(cmp db.Compare) db.InternalKey {
 type Writer struct {
 	writer    io.Writer
 	bufWriter *bufio.Writer
-	file      storage.File
+	file      vfs.File
 	meta      WriterMetadata
 	err       error
 	// The following fields are copied from db.Options.
@@ -532,12 +532,12 @@ func (w *Writer) Metadata() (*WriterMetadata, error) {
 
 // NewWriter returns a new table writer for the file. Closing the writer will
 // close the file.
-func NewWriter(f storage.File, o *db.Options, lo db.LevelOptions) *Writer {
+func NewWriter(f vfs.File, o *db.Options, lo db.LevelOptions) *Writer {
 	o = o.EnsureDefaults()
 	lo = *lo.EnsureDefaults()
 
 	if f != nil {
-		f = storage.NewSyncingFile(f, storage.SyncingFileOptions{
+		f = vfs.NewSyncingFile(f, vfs.SyncingFileOptions{
 			BytesPerSync: o.BytesPerSync,
 		})
 	}
diff --git a/table_cache.go b/table_cache.go
index 1e182fd..3dbffbc 100644
--- a/table_cache.go
+++ b/table_cache.go
@@ -14,12 +14,12 @@ import (
 
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/sstable"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 )
 
 type tableCache struct {
 	dirname string
-	fs      storage.Storage
+	fs      vfs.FS
 	opts    *db.Options
 	size    int
 
@@ -34,7 +34,7 @@ type tableCache struct {
 	}
 }
 
-func (c *tableCache) init(dirname string, fs storage.Storage, opts *db.Options, size int) {
+func (c *tableCache) init(dirname string, fs vfs.FS, opts *db.Options, size int) {
 	c.dirname = dirname
 	c.fs = fs
 	c.opts = opts
diff --git a/version_set.go b/version_set.go
index c18262a..17bc48a 100644
--- a/version_set.go
+++ b/version_set.go
@@ -13,7 +13,7 @@ import (
 
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/internal/record"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 )
 
 // versionSet manages a collection of immutable versions, and manages the
@@ -26,7 +26,7 @@ type versionSet struct {
 	dirname string
 	mu      *sync.Mutex
 	opts    *db.Options
-	fs      storage.Storage
+	fs      vfs.FS
 	cmp     db.Compare
 	cmpName string
 
@@ -41,7 +41,7 @@ type versionSet struct {
 	visibleSeqNum      uint64 // visible seqNum (<= logSeqNum)
 	manifestFileNumber uint64
 
-	manifestFile storage.File
+	manifestFile vfs.File
 	manifest     *record.Writer
 
 	writing    bool
@@ -55,7 +55,7 @@ func (vs *versionSet) load(dirname string, opts *db.Options, mu *sync.Mutex) err
 	vs.versions.mu = mu
 	vs.writerCond.L = mu
 	vs.opts = opts
-	vs.fs = opts.Storage
+	vs.fs = opts.VFS
 	vs.cmp = opts.Comparer.Compare
 	vs.cmpName = opts.Comparer.Name
 	vs.versions.init()
@@ -231,7 +231,7 @@ func (vs *versionSet) logAndApply(ve *versionEdit) error {
 func (vs *versionSet) createManifest(dirname string) (err error) {
 	var (
 		filename     = dbFilename(dirname, fileTypeManifest, vs.manifestFileNumber)
-		manifestFile storage.File
+		manifestFile vfs.File
 		manifest     *record.Writer
 	)
 	defer func() {
diff --git a/storage/file_lock_generic.go b/vfs/file_lock_generic.go
similarity index 96%
rename from storage/file_lock_generic.go
rename to vfs/file_lock_generic.go
index fb6c8cc..4b0e01a 100644
--- a/storage/file_lock_generic.go
+++ b/vfs/file_lock_generic.go
@@ -4,7 +4,7 @@
 
 // +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
 
-package storage
+package vfs
 
 import (
 	"fmt"
diff --git a/storage/file_lock_unix.go b/vfs/file_lock_unix.go
similarity index 98%
rename from storage/file_lock_unix.go
rename to vfs/file_lock_unix.go
index 5c9e7d9..211ed64 100644
--- a/storage/file_lock_unix.go
+++ b/vfs/file_lock_unix.go
@@ -4,7 +4,7 @@
 
 // +build darwin dragonfly freebsd linux netbsd openbsd solaris
 
-package storage
+package vfs
 
 import (
 	"io"
diff --git a/storage/file_lock_windows.go b/vfs/file_lock_windows.go
similarity index 97%
rename from storage/file_lock_windows.go
rename to vfs/file_lock_windows.go
index 8faa5b9..b53ec49 100644
--- a/storage/file_lock_windows.go
+++ b/vfs/file_lock_windows.go
@@ -2,7 +2,7 @@
 // of this source code is governed by a BSD-style license that can be found in
 // the LICENSE file.
 
-package storage
+package vfs
 
 import (
 	"io"
diff --git a/storage/mem_storage.go b/vfs/mem_fs.go
similarity index 73%
rename from storage/mem_storage.go
rename to vfs/mem_fs.go
index 739b791..203451b 100644
--- a/storage/mem_storage.go
+++ b/vfs/mem_fs.go
@@ -2,11 +2,7 @@
 // of this source code is governed by a BSD-style license that can be found in
 // the LICENSE file.
 
-// Package storage provides a memory-backed storage.FileSystem implementation.
-//
-// It can be useful for tests, and also for LevelDB instances that should not
-// ever touch persistent storage, such as a web browser's private browsing mode.
-package storage // import "github.com/petermattis/pebble/storage"
+package vfs // import "github.com/petermattis/pebble/vfs"
 
 import (
 	"bytes"
@@ -28,9 +24,9 @@ func (nopCloser) Close() error {
 	return nil
 }
 
-// NewMem returns a new memory-backed Storage implementation.
-func NewMem() Storage {
-	return &memStorage{
+// NewMem returns a new memory-backed FS implementation.
+func NewMem() FS {
+	return &memFS{
 		root: &node{
 			children: make(map[string]*node),
 			isDir:    true,
@@ -38,13 +34,13 @@ func NewMem() Storage {
 	}
 }
 
-// memStorage implements Storage
-type memStorage struct {
+// memFS implements FS.
+type memFS struct {
 	mu   sync.Mutex
 	root *node
 }
 
-func (y *memStorage) String() string {
+func (y *memFS) String() string {
 	y.mu.Lock()
 	defer y.mu.Unlock()
 
@@ -69,7 +65,7 @@ func (y *memStorage) String() string {
 //   - "/", "y", false
 //   - "/y/", "z", false
 //   - "/y/z/", "", true
-func (y *memStorage) walk(fullname string, f func(dir *node, frag string, final bool) error) error {
+func (y *memFS) walk(fullname string, f func(dir *node, frag string, final bool) error) error {
 	y.mu.Lock()
 	defer y.mu.Unlock()
 
@@ -99,22 +95,22 @@ func (y *memStorage) walk(fullname string, f func(dir *node, frag string, final
 		}
 		child := dir.children[frag]
 		if child == nil {
-			return errors.New("pebble/storage: no such directory")
+			return errors.New("pebble/vfs: no such directory")
 		}
 		if !child.isDir {
-			return errors.New("pebble/storage: not a directory")
+			return errors.New("pebble/vfs: not a directory")
 		}
 		dir, fullname = child, remaining
 	}
 	return nil
 }
 
-func (y *memStorage) Create(fullname string) (File, error) {
+func (y *memFS) Create(fullname string) (File, error) {
 	var ret *file
 	err := y.walk(fullname, func(dir *node, frag string, final bool) error {
 		if final {
 			if frag == "" {
-				return errors.New("pebble/storage: empty file name")
+				return errors.New("pebble/vfs: empty file name")
 			}
 			n := &node{name: frag}
 			dir.children[frag] = n
@@ -131,12 +127,12 @@ func (y *memStorage) Create(fullname string) (File, error) {
 	return ret, nil
 }
 
-func (y *memStorage) Link(oldname, newname string) error {
+func (y *memFS) Link(oldname, newname string) error {
 	var n *node
 	err := y.walk(oldname, func(dir *node, frag string, final bool) error {
 		if final {
 			if frag == "" {
-				return errors.New("pebble/storage: empty file name")
+				return errors.New("pebble/vfs: empty file name")
 			}
 			n = dir.children[frag]
 		}
@@ -146,12 +142,12 @@ func (y *memStorage) Link(oldname, newname string) error {
 		return err
 	}
 	if n == nil {
-		return errors.New("pebble/storage: no such file or directory")
+		return errors.New("pebble/vfs: no such file or directory")
 	}
 	return y.walk(newname, func(dir *node, frag string, final bool) error {
 		if final {
 			if frag == "" {
-				return errors.New("pebble/storage: empty file name")
+				return errors.New("pebble/vfs: empty file name")
 			}
 			dir.children[frag] = n
 		}
@@ -159,12 +155,12 @@ func (y *memStorage) Link(oldname, newname string) error {
 	})
 }
 
-func (y *memStorage) Open(fullname string) (File, error) {
+func (y *memFS) Open(fullname string) (File, error) {
 	var ret *file
 	err := y.walk(fullname, func(dir *node, frag string, final bool) error {
 		if final {
 			if frag == "" {
-				return errors.New("pebble/storage: empty file name")
+				return errors.New("pebble/vfs: empty file name")
 			}
 			if n := dir.children[frag]; n != nil {
 				ret = &file{
@@ -188,11 +184,11 @@ func (y *memStorage) Open(fullname string) (File, error) {
 	return ret, nil
 }
 
-func (y *memStorage) Remove(fullname string) error {
+func (y *memFS) Remove(fullname string) error {
 	return y.walk(fullname, func(dir *node, frag string, final bool) error {
 		if final {
 			if frag == "" {
-				return errors.New("pebble/storage: empty file name")
+				return errors.New("pebble/vfs: empty file name")
 			}
 			_, ok := dir.children[frag]
 			if !ok {
@@ -204,12 +200,12 @@ func (y *memStorage) Remove(fullname string) error {
 	})
 }
 
-func (y *memStorage) Rename(oldname, newname string) error {
+func (y *memFS) Rename(oldname, newname string) error {
 	var n *node
 	err := y.walk(oldname, func(dir *node, frag string, final bool) error {
 		if final {
 			if frag == "" {
-				return errors.New("pebble/storage: empty file name")
+				return errors.New("pebble/vfs: empty file name")
 			}
 			n = dir.children[frag]
 			delete(dir.children, frag)
@@ -220,12 +216,12 @@ func (y *memStorage) Rename(oldname, newname string) error {
 		return err
 	}
 	if n == nil {
-		return errors.New("pebble/storage: no such file or directory")
+		return errors.New("pebble/vfs: no such file or directory")
 	}
 	return y.walk(newname, func(dir *node, frag string, final bool) error {
 		if final {
 			if frag == "" {
-				return errors.New("pebble/storage: empty file name")
+				return errors.New("pebble/vfs: empty file name")
 			}
 			dir.children[frag] = n
 		}
@@ -233,13 +229,13 @@ func (y *memStorage) Rename(oldname, newname string) error {
 	})
 }
 
-func (y *memStorage) MkdirAll(dirname string, perm os.FileMode) error {
+func (y *memFS) MkdirAll(dirname string, perm os.FileMode) error {
 	return y.walk(dirname, func(dir *node, frag string, final bool) error {
 		if frag == "" {
 			if final {
 				return nil
 			}
-			return errors.New("pebble/storage: empty file name")
+			return errors.New("pebble/vfs: empty file name")
 		}
 		child := dir.children[frag]
 		if child == nil {
@@ -251,19 +247,19 @@ func (y *memStorage) MkdirAll(dirname string, perm os.FileMode) error {
 			return nil
 		}
 		if !child.isDir {
-			return errors.New("pebble/storage: not a directory")
+			return errors.New("pebble/vfs: not a directory")
 		}
 		return nil
 	})
 }
 
-func (y *memStorage) Lock(fullname string) (io.Closer, error) {
-	// FileSystem.Lock excludes other processes, but other processes cannot
-	// see this process' memory, so Lock is a no-op.
+func (y *memFS) Lock(fullname string) (io.Closer, error) {
+	// FS.Lock excludes other processes, but other processes cannot see this
+	// process' memory, so Lock is a no-op.
 	return nopCloser{}, nil
 }
 
-func (y *memStorage) List(dirname string) ([]string, error) {
+func (y *memFS) List(dirname string) ([]string, error) {
 	if !strings.HasSuffix(dirname, sep) {
 		dirname += sep
 	}
@@ -283,7 +279,7 @@ func (y *memStorage) List(dirname string) ([]string, error) {
 	return ret, err
 }
 
-func (y *memStorage) Stat(name string) (os.FileInfo, error) {
+func (y *memFS) Stat(name string) (os.FileInfo, error) {
 	f, err := y.Open(name)
 	if err != nil {
 		if pe, ok := err.(*os.PathError); ok {
@@ -370,10 +366,10 @@ func (f *file) Close() error {
 
 func (f *file) Read(p []byte) (int, error) {
 	if !f.read {
-		return 0, errors.New("pebble/storage: file was not opened for reading")
+		return 0, errors.New("pebble/vfs: file was not opened for reading")
 	}
 	if f.n.isDir {
-		return 0, errors.New("pebble/storage: cannot read a directory")
+		return 0, errors.New("pebble/vfs: cannot read a directory")
 	}
 	if f.rpos >= len(f.n.data) {
 		return 0, io.EOF
@@ -385,10 +381,10 @@ func (f *file) Read(p []byte) (int, error) {
 
 func (f *file) ReadAt(p []byte, off int64) (int, error) {
 	if !f.read {
-		return 0, errors.New("pebble/storage: file was not opened for reading")
+		return 0, errors.New("pebble/vfs: file was not opened for reading")
 	}
 	if f.n.isDir {
-		return 0, errors.New("pebble/storage: cannot read a directory")
+		return 0, errors.New("pebble/vfs: cannot read a directory")
 	}
 	if off >= int64(len(f.n.data)) {
 		return 0, io.EOF
@@ -398,10 +394,10 @@ func (f *file) ReadAt(p []byte, off int64) (int, error) {
 
 func (f *file) Write(p []byte) (int, error) {
 	if !f.write {
-		return 0, errors.New("pebble/storage: file was not created for writing")
+		return 0, errors.New("pebble/vfs: file was not created for writing")
 	}
 	if f.n.isDir {
-		return 0, errors.New("pebble/storage: cannot write a directory")
+		return 0, errors.New("pebble/vfs: cannot write a directory")
 	}
 	f.n.modTime = time.Now()
 	f.n.data = append(f.n.data, p...)
diff --git a/storage/preallocate_darwin.go b/vfs/preallocate_darwin.go
similarity index 99%
rename from storage/preallocate_darwin.go
rename to vfs/preallocate_darwin.go
index 946ab56..cdaee8d 100644
--- a/storage/preallocate_darwin.go
+++ b/vfs/preallocate_darwin.go
@@ -14,7 +14,7 @@
 
 // +build darwin
 
-package storage
+package vfs
 
 import (
 	"syscall"
diff --git a/storage/preallocate_linux.go b/vfs/preallocate_linux.go
similarity index 98%
rename from storage/preallocate_linux.go
rename to vfs/preallocate_linux.go
index d93018c..f83c2b4 100644
--- a/storage/preallocate_linux.go
+++ b/vfs/preallocate_linux.go
@@ -14,7 +14,7 @@
 
 // +build linux
 
-package storage
+package vfs
 
 import (
 	"syscall"
diff --git a/storage/syncing_file.go b/vfs/syncing_file.go
similarity index 99%
rename from storage/syncing_file.go
rename to vfs/syncing_file.go
index 5a88e22..1947cd5 100644
--- a/storage/syncing_file.go
+++ b/vfs/syncing_file.go
@@ -2,7 +2,7 @@
 // of this source code is governed by a BSD-style license that can be found in
 // the LICENSE file.
 
-package storage
+package vfs
 
 import (
 	"sync/atomic"
diff --git a/storage/syncing_file_generic.go b/vfs/syncing_file_generic.go
similarity index 96%
rename from storage/syncing_file_generic.go
rename to vfs/syncing_file_generic.go
index d5debde..fd8691b 100644
--- a/storage/syncing_file_generic.go
+++ b/vfs/syncing_file_generic.go
@@ -4,7 +4,7 @@
 
 // +build !linux
 
-package storage
+package vfs
 
 func (f *syncingFile) init() {
 	f.syncTo = f.syncToGeneric
diff --git a/storage/syncing_file_linux.go b/vfs/syncing_file_linux.go
similarity index 98%
rename from storage/syncing_file_linux.go
rename to vfs/syncing_file_linux.go
index 06984a0..cf724f5 100644
--- a/storage/syncing_file_linux.go
+++ b/vfs/syncing_file_linux.go
@@ -4,7 +4,7 @@
 
 // +build linux
 
-package storage
+package vfs
 
 import (
 	"sync/atomic"
diff --git a/storage/storage.go b/vfs/vfs.go
similarity index 94%
rename from storage/storage.go
rename to vfs/vfs.go
index fbf7517..e1b744e 100644
--- a/storage/storage.go
+++ b/vfs/vfs.go
@@ -2,7 +2,7 @@
 // of this source code is governed by a BSD-style license that can be found in
 // the LICENSE file.
 
-package storage
+package vfs
 
 import (
 	"io"
@@ -22,11 +22,11 @@ type File interface {
 	Sync() error
 }
 
-// Storage is a namespace for files.
+// FS is a namespace for files.
 //
 // The names are filepath names: they may be / separated or \ separated,
 // depending on the underlying operating system.
-type Storage interface {
+type FS interface {
 	// Create creates the named file for writing, truncating it if it already
 	// exists.
 	Create(name string) (File, error)
@@ -77,9 +77,9 @@ type Storage interface {
 	Stat(name string) (os.FileInfo, error)
 }
 
-// Default is a Storage implementation backed by the underlying operating
-// system's file system.
-var Default Storage = defaultFS{}
+// Default is a FS implementation backed by the underlying operating system's
+// file system.
+var Default FS = defaultFS{}
 
 type defaultFS struct{}
 


Test patch:
diff --git a/batch_test.go b/batch_test.go
index 64b9333..09fe9a3 100644
--- a/batch_test.go
+++ b/batch_test.go
@@ -14,7 +14,7 @@ import (
 
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/internal/datadriven"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 )
 
 func TestBatch(t *testing.T) {
@@ -115,7 +115,7 @@ func TestBatchGet(t *testing.T) {
 	for _, method := range []string{"build", "apply"} {
 		t.Run(method, func(t *testing.T) {
 			d, err := Open("", &db.Options{
-				Storage: storage.NewMem(),
+				VFS: vfs.NewMem(),
 			})
 			if err != nil {
 				t.Fatalf("Open: %v", err)
diff --git a/compaction_test.go b/compaction_test.go
index f4ea8dc..3c9858a 100644
--- a/compaction_test.go
+++ b/compaction_test.go
@@ -17,7 +17,7 @@ import (
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/internal/datadriven"
 	"github.com/petermattis/pebble/sstable"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 )
 
 func TestPickCompaction(t *testing.T) {
@@ -579,9 +579,9 @@ func TestCompaction(t *testing.T) {
 	// size.
 	const valueSize = 3500
 
-	fs := storage.NewMem()
+	mem := vfs.NewMem()
 	d, err := Open("", &db.Options{
-		Storage:      fs,
+		VFS:          mem,
 		MemTableSize: memTableSize,
 	})
 	if err != nil {
@@ -609,7 +609,7 @@ func TestCompaction(t *testing.T) {
 		v := d.mu.versions.currentVersion()
 		for _, files := range v.files {
 			for _, meta := range files {
-				f, err := fs.Open(dbFilename("", fileTypeTable, meta.fileNum))
+				f, err := mem.Open(dbFilename("", fileTypeTable, meta.fileNum))
 				if err != nil {
 					return "", "", fmt.Errorf("Open: %v", err)
 				}
@@ -687,14 +687,14 @@ func TestCompaction(t *testing.T) {
 }
 
 func TestManualCompaction(t *testing.T) {
-	fs := storage.NewMem()
-	err := fs.MkdirAll("ext", 0755)
+	mem := vfs.NewMem()
+	err := mem.MkdirAll("ext", 0755)
 	if err != nil {
 		t.Fatal(err)
 	}
 
 	d, err := Open("", &db.Options{
-		Storage: fs,
+		VFS: mem,
 	})
 	if err != nil {
 		t.Fatal(err)
diff --git a/data_test.go b/data_test.go
index da48407..c2500f3 100644
--- a/data_test.go
+++ b/data_test.go
@@ -12,7 +12,7 @@ import (
 
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/internal/datadriven"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 )
 
 type iterCmdOpt int
@@ -191,9 +191,8 @@ func runDBDefineCmd(td *datadriven.TestData) (*DB, error) {
 		return nil, fmt.Errorf("empty test input")
 	}
 
-	fs := storage.NewMem()
 	opts := db.Options{
-		Storage: fs,
+		VFS: vfs.NewMem(),
 	}
 	var snapshots []uint64
 	for _, arg := range td.CmdArgs {
@@ -248,7 +247,7 @@ func runDBDefineCmd(td *datadriven.TestData) (*DB, error) {
 		if rangeDelIter := mem.newRangeDelIter(nil); rangeDelIter != nil {
 			iter = newMergingIter(d.cmp, iter, rangeDelIter)
 		}
-		meta, err := d.writeLevel0Table(d.opts.Storage, iter,
+		meta, err := d.writeLevel0Table(d.opts.VFS, iter,
 			false /* allowRangeTombstoneElision */)
 		if err != nil {
 			return nil
diff --git a/db_test.go b/db_test.go
index 35e53f5..9d24f39 100644
--- a/db_test.go
+++ b/db_test.go
@@ -18,7 +18,7 @@ import (
 
 	"github.com/petermattis/pebble/cache"
 	"github.com/petermattis/pebble/db"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 	"golang.org/x/exp/rand"
 )
 
@@ -88,12 +88,12 @@ func TestTry(t *testing.T) {
 // containing:
 //   - /x
 //   - /y
-func cloneFileSystem(srcFS storage.Storage, dirname string) (storage.Storage, error) {
+func cloneFileSystem(srcFS vfs.FS, dirname string) (vfs.FS, error) {
 	if len(dirname) == 0 || dirname[len(dirname)-1] != os.PathSeparator {
 		dirname += string(os.PathSeparator)
 	}
 
-	dstFS := storage.NewMem()
+	dstFS := vfs.NewMem()
 	list, err := srcFS.List(dirname)
 	if err != nil {
 		return nil, err
@@ -190,13 +190,13 @@ func TestBasicReads(t *testing.T) {
 		},
 	}
 	for _, tc := range testCases {
-		fs, err := cloneFileSystem(storage.Default, "testdata/"+tc.dirname)
+		fs, err := cloneFileSystem(vfs.Default, "testdata/"+tc.dirname)
 		if err != nil {
 			t.Errorf("%s: cloneFileSystem failed: %v", tc.dirname, err)
 			continue
 		}
 		d, err := Open("", &db.Options{
-			Storage: fs,
+			VFS: fs,
 		})
 		if err != nil {
 			t.Errorf("%s: Open failed: %v", tc.dirname, err)
@@ -223,7 +223,7 @@ func TestBasicReads(t *testing.T) {
 
 func TestBasicWrites(t *testing.T) {
 	d, err := Open("", &db.Options{
-		Storage: storage.NewMem(),
+		VFS: vfs.NewMem(),
 	})
 	if err != nil {
 		t.Fatal(err)
@@ -362,7 +362,7 @@ func TestBasicWrites(t *testing.T) {
 
 func TestRandomWrites(t *testing.T) {
 	d, err := Open("", &db.Options{
-		Storage:      storage.NewMem(),
+		VFS:          vfs.NewMem(),
 		MemTableSize: 8 * 1024,
 	})
 	if err != nil {
@@ -418,7 +418,7 @@ func TestRandomWrites(t *testing.T) {
 
 func TestLargeBatch(t *testing.T) {
 	d, err := Open("", &db.Options{
-		Storage:                     storage.NewMem(),
+		VFS:                         vfs.NewMem(),
 		MemTableSize:                1400,
 		MemTableStopWritesThreshold: 100,
 	})
@@ -469,7 +469,7 @@ func TestLargeBatch(t *testing.T) {
 
 func TestGetMerge(t *testing.T) {
 	d, err := Open("", &db.Options{
-		Storage: storage.NewMem(),
+		VFS: vfs.NewMem(),
 	})
 	if err != nil {
 		t.Fatal(err)
@@ -511,7 +511,7 @@ func TestIterLeak(t *testing.T) {
 			for _, flush := range []bool{true, false} {
 				t.Run(fmt.Sprintf("flush=%t", flush), func(t *testing.T) {
 					d, err := Open("", &db.Options{
-						Storage: storage.NewMem(),
+						VFS: vfs.NewMem(),
 					})
 					if err != nil {
 						t.Fatal(err)
@@ -552,8 +552,8 @@ func TestIterLeak(t *testing.T) {
 func TestCacheEvict(t *testing.T) {
 	cache := cache.New(10 << 20)
 	d, err := Open("", &db.Options{
-		Cache:   cache,
-		Storage: storage.NewMem(),
+		Cache: cache,
+		VFS:   vfs.NewMem(),
 	})
 	if err != nil {
 		t.Fatal(err)
@@ -601,7 +601,7 @@ func TestCacheEvict(t *testing.T) {
 
 func TestFlushEmpty(t *testing.T) {
 	d, err := Open("", &db.Options{
-		Storage: storage.NewMem(),
+		VFS: vfs.NewMem(),
 	})
 	if err != nil {
 		t.Fatal(err)
diff --git a/event_listener_test.go b/event_listener_test.go
index 4837ad0..9017d80 100644
--- a/event_listener_test.go
+++ b/event_listener_test.go
@@ -11,7 +11,7 @@ import (
 	"testing"
 
 	"github.com/petermattis/pebble/db"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 )
 
 type syncedBuffer struct {
@@ -35,7 +35,7 @@ func TestEventListener(t *testing.T) {
 	var buf syncedBuffer
 
 	d, err := Open("", &db.Options{
-		Storage: storage.NewMem(),
+		VFS: vfs.NewMem(),
 		EventListener: &db.EventListener{
 			CompactionBegin: func(info db.CompactionInfo) {
 				fmt.Fprintf(&buf, "#%d: compaction begin: L%d -> L%d\n", info.JobID,
diff --git a/flush_test.go b/flush_test.go
index 3d5b7fc..034799e 100644
--- a/flush_test.go
+++ b/flush_test.go
@@ -11,12 +11,12 @@ import (
 
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/internal/datadriven"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 )
 
 func TestManualFlush(t *testing.T) {
 	d, err := Open("", &db.Options{
-		Storage: storage.NewMem(),
+		VFS: vfs.NewMem(),
 	})
 	if err != nil {
 		t.Fatal(err)
@@ -70,7 +70,7 @@ func TestManualFlush(t *testing.T) {
 
 		case "reset":
 			d, err = Open("", &db.Options{
-				Storage: storage.NewMem(),
+				VFS: vfs.NewMem(),
 			})
 			if err != nil {
 				return err.Error()
diff --git a/ingest_test.go b/ingest_test.go
index c99cb4b..a787333 100644
--- a/ingest_test.go
+++ b/ingest_test.go
@@ -19,17 +19,17 @@ import (
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/internal/datadriven"
 	"github.com/petermattis/pebble/sstable"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 	"golang.org/x/exp/rand"
 )
 
 func TestIngestLoad(t *testing.T) {
-	fs := storage.NewMem()
+	mem := vfs.NewMem()
 
 	datadriven.RunTest(t, "testdata/ingest_load", func(td *datadriven.TestData) string {
 		switch td.Cmd {
 		case "load":
-			f, err := fs.Create("ext")
+			f, err := mem.Create("ext")
 			if err != nil {
 				return err.Error()
 			}
@@ -49,7 +49,7 @@ func TestIngestLoad(t *testing.T) {
 
 			opts := &db.Options{
 				Comparer: db.DefaultComparer,
-				Storage:  fs,
+				VFS:      mem,
 			}
 			meta, err := ingestLoad(opts, []string{"ext"}, []uint64{1})
 			if err != nil {
@@ -68,7 +68,7 @@ func TestIngestLoad(t *testing.T) {
 }
 
 func TestIngestLoadRand(t *testing.T) {
-	mem := storage.NewMem()
+	mem := vfs.NewMem()
 	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 	cmp := db.DefaultComparer.Compare
 
@@ -129,7 +129,7 @@ func TestIngestLoadRand(t *testing.T) {
 
 	opts := &db.Options{
 		Comparer: db.DefaultComparer,
-		Storage:  mem,
+		VFS:      mem,
 	}
 	meta, err := ingestLoad(opts, paths, pending)
 	if err != nil {
@@ -143,7 +143,7 @@ func TestIngestLoadRand(t *testing.T) {
 func TestIngestLoadNonExistent(t *testing.T) {
 	opts := &db.Options{
 		Comparer: db.DefaultComparer,
-		Storage:  storage.NewMem(),
+		VFS:      vfs.NewMem(),
 	}
 	if _, err := ingestLoad(opts, []string{"non-existent"}, []uint64{1}); err == nil {
 		t.Fatalf("expected error, but found success")
@@ -151,7 +151,7 @@ func TestIngestLoadNonExistent(t *testing.T) {
 }
 
 func TestIngestLoadEmpty(t *testing.T) {
-	mem := storage.NewMem()
+	mem := vfs.NewMem()
 	f, err := mem.Create("empty")
 	if err != nil {
 		t.Fatal(err)
@@ -160,7 +160,7 @@ func TestIngestLoadEmpty(t *testing.T) {
 
 	opts := &db.Options{
 		Comparer: db.DefaultComparer,
-		Storage:  mem,
+		VFS:      mem,
 	}
 	if _, err := ingestLoad(opts, []string{"empty"}, []uint64{1}); err == nil {
 		t.Fatalf("expected error, but found success")
@@ -244,8 +244,8 @@ func TestIngestLink(t *testing.T) {
 	const count = 10
 	for i := 0; i <= count; i++ {
 		t.Run("", func(t *testing.T) {
-			mem := storage.NewMem()
-			opts := &db.Options{Storage: mem}
+			mem := vfs.NewMem()
+			opts := &db.Options{VFS: mem}
 			opts.EnsureDefaults()
 			if err := mem.MkdirAll(dir, 0755); err != nil {
 				t.Fatal(err)
@@ -466,14 +466,14 @@ func TestIngestTargetLevel(t *testing.T) {
 }
 
 func TestIngest(t *testing.T) {
-	fs := storage.NewMem()
-	err := fs.MkdirAll("ext", 0755)
+	mem := vfs.NewMem()
+	err := mem.MkdirAll("ext", 0755)
 	if err != nil {
 		t.Fatal(err)
 	}
 
 	d, err := Open("", &db.Options{
-		Storage:               fs,
+		VFS:                   mem,
 		L0CompactionThreshold: 100,
 	})
 	if err != nil {
@@ -490,7 +490,7 @@ func TestIngest(t *testing.T) {
 
 			switch td.Cmd {
 			case "ingest":
-				f, err := fs.Create("ext/0")
+				f, err := mem.Create("ext/0")
 				if err != nil {
 					return err.Error()
 				}
@@ -521,7 +521,7 @@ func TestIngest(t *testing.T) {
 				if err := d.Ingest([]string{"ext/0"}); err != nil {
 					return err.Error()
 				}
-				if err := fs.Remove("ext/0"); err != nil {
+				if err := mem.Remove("ext/0"); err != nil {
 					return err.Error()
 				}
 
diff --git a/level_iter_test.go b/level_iter_test.go
index 645b8e5..b063f68 100644
--- a/level_iter_test.go
+++ b/level_iter_test.go
@@ -16,7 +16,7 @@ import (
 	"github.com/petermattis/pebble/internal/datadriven"
 	"github.com/petermattis/pebble/internal/rangedel"
 	"github.com/petermattis/pebble/sstable"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 	"golang.org/x/exp/rand"
 )
 
@@ -122,7 +122,7 @@ func TestLevelIter(t *testing.T) {
 
 func TestLevelIterBoundaries(t *testing.T) {
 	cmp := db.DefaultComparer.Compare
-	fs := storage.NewMem()
+	mem := vfs.NewMem()
 	var readers []*sstable.Reader
 	var files []fileMetadata
 
@@ -135,7 +135,7 @@ func TestLevelIterBoundaries(t *testing.T) {
 	datadriven.RunTest(t, "testdata/level_iter_boundaries", func(d *datadriven.TestData) string {
 		switch d.Cmd {
 		case "clear":
-			fs = storage.NewMem()
+			mem = vfs.NewMem()
 			readers = nil
 			files = nil
 			return ""
@@ -143,7 +143,7 @@ func TestLevelIterBoundaries(t *testing.T) {
 		case "build":
 			fileNum := uint64(len(readers))
 			name := fmt.Sprint(fileNum)
-			f0, err := fs.Create(name)
+			f0, err := mem.Create(name)
 			if err != nil {
 				return err.Error()
 			}
@@ -183,7 +183,7 @@ func TestLevelIterBoundaries(t *testing.T) {
 				return err.Error()
 			}
 
-			f1, err := fs.Open(name)
+			f1, err := mem.Open(name)
 			if err != nil {
 				return err.Error()
 			}
@@ -216,8 +216,8 @@ func TestLevelIterBoundaries(t *testing.T) {
 func buildLevelIterTables(
 	b *testing.B, blockSize, restartInterval, count int,
 ) ([]*sstable.Reader, []fileMetadata, [][]byte) {
-	mem := storage.NewMem()
-	files := make([]storage.File, count)
+	mem := vfs.NewMem()
+	files := make([]vfs.File, count)
 	for i := range files {
 		f, err := mem.Create(fmt.Sprintf("bench%d", i))
 		if err != nil {
diff --git a/log_recycler_test.go b/log_recycler_test.go
index 8e2a6ed..01e746b 100644
--- a/log_recycler_test.go
+++ b/log_recycler_test.go
@@ -8,7 +8,7 @@ import (
 	"testing"
 
 	"github.com/petermattis/pebble/db"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 	"github.com/stretchr/testify/require"
 )
 
@@ -76,7 +76,7 @@ func TestLogRecycler(t *testing.T) {
 
 func TestRecycleLogs(t *testing.T) {
 	d, err := Open("", &db.Options{
-		Storage: storage.NewMem(),
+		VFS: vfs.NewMem(),
 	})
 	if err != nil {
 		t.Fatal(err)
diff --git a/merging_iter_test.go b/merging_iter_test.go
index 5034ac7..9204336 100644
--- a/merging_iter_test.go
+++ b/merging_iter_test.go
@@ -14,7 +14,7 @@ import (
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/internal/datadriven"
 	"github.com/petermattis/pebble/sstable"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 	"golang.org/x/exp/rand"
 )
 
@@ -127,8 +127,8 @@ func TestMergingIterNextPrev(t *testing.T) {
 func buildMergingIterTables(
 	b *testing.B, blockSize, restartInterval, count int,
 ) ([]*sstable.Reader, [][]byte) {
-	mem := storage.NewMem()
-	files := make([]storage.File, count)
+	mem := vfs.NewMem()
+	files := make([]vfs.File, count)
 	for i := range files {
 		f, err := mem.Create(fmt.Sprintf("bench%d", i))
 		if err != nil {
diff --git a/open_test.go b/open_test.go
index ee11c24..06246cc 100644
--- a/open_test.go
+++ b/open_test.go
@@ -15,15 +15,15 @@ import (
 	"testing"
 
 	"github.com/petermattis/pebble/db"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 	"github.com/stretchr/testify/require"
 )
 
 func TestErrorIfDBExists(t *testing.T) {
 	for _, b := range [...]bool{false, true} {
-		fs := storage.NewMem()
+		mem := vfs.NewMem()
 		d0, err := Open("", &db.Options{
-			Storage: fs,
+			VFS: mem,
 		})
 		if err != nil {
 			t.Errorf("b=%v: d0 Open: %v", b, err)
@@ -35,7 +35,7 @@ func TestErrorIfDBExists(t *testing.T) {
 		}
 
 		d1, err := Open("", &db.Options{
-			Storage:         fs,
+			VFS:             mem,
 			ErrorIfDBExists: b,
 		})
 		if d1 != nil {
@@ -50,9 +50,9 @@ func TestErrorIfDBExists(t *testing.T) {
 
 func TestNewDBFilenames(t *testing.T) {
 	fooBar := filepath.Join("foo", "bar")
-	fs := storage.NewMem()
+	mem := vfs.NewMem()
 	d, err := Open(fooBar, &db.Options{
-		Storage: fs,
+		VFS: mem,
 	})
 	if err != nil {
 		t.Fatalf("Open: %v", err)
@@ -60,7 +60,7 @@ func TestNewDBFilenames(t *testing.T) {
 	if err := d.Close(); err != nil {
 		t.Fatalf("Close: %v", err)
 	}
-	got, err := fs.List(fooBar)
+	got, err := mem.List(fooBar)
 	if err != nil {
 		t.Fatalf("List: %v", err)
 	}
@@ -77,9 +77,9 @@ func TestNewDBFilenames(t *testing.T) {
 	}
 }
 
-func testOpenCloseOpenClose(t *testing.T, fs storage.Storage, root string) {
+func testOpenCloseOpenClose(t *testing.T, fs vfs.FS, root string) {
 	opts := &db.Options{
-		Storage: fs,
+		VFS: fs,
 	}
 
 	for _, startFromEmpty := range []bool{false, true} {
@@ -144,7 +144,7 @@ func testOpenCloseOpenClose(t *testing.T, fs storage.Storage, root string) {
 			}
 
 			{
-				got, err := opts.Storage.List(dirname)
+				got, err := opts.VFS.List(dirname)
 				if err != nil {
 					t.Fatalf("List: %v", err)
 				}
@@ -165,7 +165,7 @@ func testOpenCloseOpenClose(t *testing.T, fs storage.Storage, root string) {
 func TestOpenCloseOpenClose(t *testing.T) {
 	for _, fstype := range []string{"disk", "mem"} {
 		t.Run(fstype, func(t *testing.T) {
-			var fs storage.Storage
+			var fs vfs.FS
 			var dir string
 			switch fstype {
 			case "disk":
@@ -177,10 +177,10 @@ func TestOpenCloseOpenClose(t *testing.T) {
 				defer func() {
 					_ = os.RemoveAll(dir)
 				}()
-				fs = storage.Default
+				fs = vfs.Default
 			case "mem":
 				dir = ""
-				fs = storage.NewMem()
+				fs = vfs.NewMem()
 			}
 			testOpenCloseOpenClose(t, fs, dir)
 		})
@@ -188,8 +188,8 @@ func TestOpenCloseOpenClose(t *testing.T) {
 }
 
 func TestOpenOptionsCheck(t *testing.T) {
-	mem := storage.NewMem()
-	opts := &db.Options{Storage: mem}
+	mem := vfs.NewMem()
+	opts := &db.Options{VFS: mem}
 
 	d, err := Open("", opts)
 	if err != nil {
@@ -201,14 +201,14 @@ func TestOpenOptionsCheck(t *testing.T) {
 
 	opts = &db.Options{
 		Comparer: &db.Comparer{Name: "foo"},
-		Storage:  mem,
+		VFS:      mem,
 	}
 	_, err = Open("", opts)
 	require.Regexp(t, `comparer name from file.*!=.*`, err)
 
 	opts = &db.Options{
-		Merger:  &db.Merger{Name: "bar"},
-		Storage: mem,
+		Merger: &db.Merger{Name: "bar"},
+		VFS:    mem,
 	}
 	_, err = Open("", opts)
 	require.Regexp(t, `merger name from file.*!=.*`, err)
diff --git a/ptable/table_test.go b/ptable/table_test.go
index 71e4c3b..922bdbc 100644
--- a/ptable/table_test.go
+++ b/ptable/table_test.go
@@ -12,7 +12,7 @@ import (
 
 	"github.com/petermattis/pebble/cache"
 	"github.com/petermattis/pebble/db"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 	"golang.org/x/exp/rand"
 )
 
@@ -97,7 +97,7 @@ func (r testRow) Bytes(col int) []byte {
 
 func TestTable(t *testing.T) {
 	const count int64 = 1000
-	mem := storage.NewMem()
+	mem := vfs.NewMem()
 	env := newEnv(ColumnDef{Type: ColumnTypeInt64})
 
 	{
@@ -162,7 +162,7 @@ func TestTable(t *testing.T) {
 }
 
 func buildBenchmarkTable(b *testing.B, blockSize int, nullValues bool) (*Reader, [][]byte) {
-	mem := storage.NewMem()
+	mem := vfs.NewMem()
 	f0, err := mem.Create("bench")
 	if err != nil {
 		b.Fatal(err)
diff --git a/range_del_test.go b/range_del_test.go
index d86ce61..bc983c1 100644
--- a/range_del_test.go
+++ b/range_del_test.go
@@ -15,7 +15,7 @@ import (
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/internal/datadriven"
 	"github.com/petermattis/pebble/sstable"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 )
 
 func TestRangeDel(t *testing.T) {
@@ -115,7 +115,7 @@ func TestRangeDel(t *testing.T) {
 func TestRangeDelCompactionTruncation(t *testing.T) {
 	// Use a small target file size so that there is a single key per sstable.
 	d, err := Open("", &db.Options{
-		Storage: storage.NewMem(),
+		VFS: vfs.NewMem(),
 		Levels: []db.LevelOptions{
 			{TargetFileSize: 100},
 			{TargetFileSize: 100},
@@ -246,10 +246,10 @@ func BenchmarkRangeDelIterate(b *testing.B) {
 		b.Run(fmt.Sprintf("entries=%d", entries), func(b *testing.B) {
 			for _, deleted := range []int{entries, entries - 1} {
 				b.Run(fmt.Sprintf("deleted=%d", deleted), func(b *testing.B) {
-					fs := storage.NewMem()
+					mem := vfs.NewMem()
 					d, err := Open("", &db.Options{
-						Cache:   cache.New(128 << 20), // 128 MB
-						Storage: fs,
+						Cache: cache.New(128 << 20), // 128 MB
+						VFS:   mem,
 					})
 					if err != nil {
 						b.Fatal(err)
@@ -262,7 +262,7 @@ func BenchmarkRangeDelIterate(b *testing.B) {
 
 					// Create an sstable with N entries and ingest it. This is a fast way
 					// to get a lot of entries into pebble.
-					f, err := fs.Create("ext")
+					f, err := mem.Create("ext")
 					if err != nil {
 						b.Fatal(err)
 					}
@@ -281,7 +281,7 @@ func BenchmarkRangeDelIterate(b *testing.B) {
 					if err := d.Ingest([]string{"ext"}); err != nil {
 						b.Fatal(err)
 					}
-					if err := fs.Remove("ext"); err != nil {
+					if err := mem.Remove("ext"); err != nil {
 						b.Fatal(err)
 					}
 
diff --git a/read_state_test.go b/read_state_test.go
index d3409fb..0dd9480 100644
--- a/read_state_test.go
+++ b/read_state_test.go
@@ -10,13 +10,13 @@ import (
 	"time"
 
 	"github.com/petermattis/pebble/db"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 	"golang.org/x/exp/rand"
 )
 
 func BenchmarkReadState(b *testing.B) {
 	d, err := Open("", &db.Options{
-		Storage: storage.NewMem(),
+		VFS: vfs.NewMem(),
 	})
 	if err != nil {
 		b.Fatal(err)
diff --git a/snapshot_test.go b/snapshot_test.go
index 0331ce0..8b5f012 100644
--- a/snapshot_test.go
+++ b/snapshot_test.go
@@ -13,7 +13,7 @@ import (
 
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/internal/datadriven"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 )
 
 func TestSnapshotListToSlice(t *testing.T) {
@@ -49,7 +49,7 @@ func TestSnapshot(t *testing.T) {
 		case "define":
 			var err error
 			d, err = Open("", &db.Options{
-				Storage: storage.NewMem(),
+				VFS: vfs.NewMem(),
 			})
 			if err != nil {
 				return err.Error()
diff --git a/sstable/reader_test.go b/sstable/reader_test.go
index 216542a..2f5326e 100644
--- a/sstable/reader_test.go
+++ b/sstable/reader_test.go
@@ -18,7 +18,7 @@ import (
 	"github.com/petermattis/pebble/cache"
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/internal/datadriven"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 	"golang.org/x/exp/rand"
 )
 
@@ -126,7 +126,7 @@ func runTestReader(t *testing.T, o db.Options) {
 		return db.MakeInternalKey([]byte(s[:j]), uint64(seqNum), db.InternalKeyKindSet), []byte(s[k+1:])
 	}
 
-	fs := storage.NewMem()
+	mem := vfs.NewMem()
 	var r *Reader
 
 	datadriven.Walk(t, "testdata/reader", func(t *testing.T, path string) {
@@ -135,10 +135,10 @@ func runTestReader(t *testing.T, o db.Options) {
 			case "build":
 				if r != nil {
 					r.Close()
-					fs.Remove("sstable")
+					mem.Remove("sstable")
 				}
 
-				f, err := fs.Create("sstable")
+				f, err := mem.Create("sstable")
 				if err != nil {
 					return err.Error()
 				}
@@ -149,7 +149,7 @@ func runTestReader(t *testing.T, o db.Options) {
 				}
 				w.Close()
 
-				f, err = fs.Open("sstable")
+				f, err = mem.Open("sstable")
 				if err != nil {
 					return err.Error()
 				}
@@ -234,7 +234,7 @@ func runTestReader(t *testing.T, o db.Options) {
 }
 
 func buildBenchmarkTable(b *testing.B, blockSize, restartInterval int) (*Reader, [][]byte) {
-	mem := storage.NewMem()
+	mem := vfs.NewMem()
 	f0, err := mem.Create("bench")
 	if err != nil {
 		b.Fatal(err)
diff --git a/sstable/table_test.go b/sstable/table_test.go
index d08b3db..7eb212a 100644
--- a/sstable/table_test.go
+++ b/sstable/table_test.go
@@ -20,7 +20,7 @@ import (
 	"github.com/kr/pretty"
 	"github.com/petermattis/pebble/bloom"
 	"github.com/petermattis/pebble/db"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 	"golang.org/x/exp/rand"
 )
 
@@ -112,7 +112,7 @@ func init() {
 	}
 }
 
-func check(f storage.File, comparer *db.Comparer, fp db.FilterPolicy) error {
+func check(f vfs.File, comparer *db.Comparer, fp db.FilterPolicy) error {
 	r := NewReader(f, 0, &db.Options{
 		Comparer: comparer,
 		Levels: []db.LevelOptions{{
@@ -308,7 +308,7 @@ func check(f storage.File, comparer *db.Comparer, fp db.FilterPolicy) error {
 }
 
 var (
-	memFileSystem = storage.NewMem()
+	memFileSystem = vfs.NewMem()
 	tmpFileCount  int
 )
 
@@ -317,7 +317,7 @@ func build(
 	fp db.FilterPolicy,
 	ftype db.FilterType,
 	comparer *db.Comparer,
-) (storage.File, error) {
+) (vfs.File, error) {
 	// Create a sorted list of wordCount's keys.
 	keys := make([]string, len(wordCount))
 	i := 0
@@ -555,7 +555,7 @@ func TestFinalBlockIsWritten(t *testing.T) {
 	for nk := 0; nk <= len(keys); nk++ {
 	loop:
 		for _, vLen := range valueLengths {
-			got, memFS := 0, storage.NewMem()
+			got, memFS := 0, vfs.NewMem()
 
 			wf, err := memFS.Create("foo")
 			if err != nil {
@@ -639,8 +639,8 @@ func TestFooterRoundTrip(t *testing.T) {
 					}
 					for offset := range []int64{0, 1, 100} {
 						t.Run(fmt.Sprintf("offset=%d", offset), func(t *testing.T) {
-							fs := storage.NewMem()
-							f, err := fs.Create("test")
+							mem := vfs.NewMem()
+							f, err := mem.Create("test")
 							if err != nil {
 								t.Fatal(err)
 							}
@@ -654,7 +654,7 @@ func TestFooterRoundTrip(t *testing.T) {
 								t.Fatal(err)
 							}
 
-							f, err = fs.Open("test")
+							f, err = mem.Open("test")
 							if err != nil {
 								t.Fatal(err)
 							}
@@ -701,8 +701,8 @@ func TestReadFooter(t *testing.T) {
 	}
 	for _, c := range testCases {
 		t.Run("", func(t *testing.T) {
-			fs := storage.NewMem()
-			f, err := fs.Create("test")
+			mem := vfs.NewMem()
+			f, err := mem.Create("test")
 			if err != nil {
 				t.Fatal(err)
 			}
@@ -713,7 +713,7 @@ func TestReadFooter(t *testing.T) {
 				t.Fatal(err)
 			}
 
-			f, err = fs.Open("test")
+			f, err = mem.Open("test")
 			if err != nil {
 				t.Fatal(err)
 			}
diff --git a/sstable/writer_test.go b/sstable/writer_test.go
index 2781f07..380876b 100644
--- a/sstable/writer_test.go
+++ b/sstable/writer_test.go
@@ -14,7 +14,7 @@ import (
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/internal/datadriven"
 	"github.com/petermattis/pebble/internal/rangedel"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 )
 
 func TestWriter(t *testing.T) {
@@ -27,8 +27,8 @@ func TestWriter(t *testing.T) {
 				r = nil
 			}
 
-			fs := storage.NewMem()
-			f0, err := fs.Create("test")
+			mem := vfs.NewMem()
+			f0, err := mem.Create("test")
 			if err != nil {
 				return err.Error()
 			}
@@ -79,7 +79,7 @@ func TestWriter(t *testing.T) {
 				return err.Error()
 			}
 
-			f1, err := fs.Open("test")
+			f1, err := mem.Open("test")
 			if err != nil {
 				return err.Error()
 			}
@@ -95,8 +95,8 @@ func TestWriter(t *testing.T) {
 				r = nil
 			}
 
-			fs := storage.NewMem()
-			f0, err := fs.Create("test")
+			mem := vfs.NewMem()
+			f0, err := mem.Create("test")
 			if err != nil {
 				return err.Error()
 			}
@@ -118,7 +118,7 @@ func TestWriter(t *testing.T) {
 				return err.Error()
 			}
 
-			f1, err := fs.Open("test")
+			f1, err := mem.Open("test")
 			if err != nil {
 				return err.Error()
 			}
diff --git a/table_cache_test.go b/table_cache_test.go
index b3475dc..3ae27b3 100644
--- a/table_cache_test.go
+++ b/table_cache_test.go
@@ -14,12 +14,12 @@ import (
 
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/sstable"
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 	"golang.org/x/exp/rand"
 )
 
 type tableCacheTestFile struct {
-	storage.File
+	vfs.File
 	fs   *tableCacheTestFS
 	name string
 }
@@ -34,20 +34,20 @@ func (f *tableCacheTestFile) Close() error {
 }
 
 type tableCacheTestFS struct {
-	storage.Storage
+	vfs.FS
 
 	mu          sync.Mutex
 	openCounts  map[string]int
 	closeCounts map[string]int
 }
 
-func (fs *tableCacheTestFS) Open(name string) (storage.File, error) {
+func (fs *tableCacheTestFS) Open(name string) (vfs.File, error) {
 	fs.mu.Lock()
 	if fs.openCounts != nil {
 		fs.openCounts[name]++
 	}
 	fs.mu.Unlock()
-	f, err := fs.Storage.Open(name)
+	f, err := fs.FS.Open(name)
 	if err != nil {
 		return nil, err
 	}
@@ -124,7 +124,7 @@ const (
 func newTableCache() (*tableCache, *tableCacheTestFS, error) {
 	xxx := bytes.Repeat([]byte("x"), tableCacheTestNumTables)
 	fs := &tableCacheTestFS{
-		Storage: storage.NewMem(),
+		FS: vfs.NewMem(),
 	}
 	for i := 0; i < tableCacheTestNumTables; i++ {
 		f, err := fs.Create(dbFilename("", fileTypeTable, uint64(i)))
diff --git a/storage/file_lock_test.go b/vfs/file_lock_test.go
similarity index 94%
rename from storage/file_lock_test.go
rename to vfs/file_lock_test.go
index 891144f..6220222 100644
--- a/storage/file_lock_test.go
+++ b/vfs/file_lock_test.go
@@ -2,7 +2,7 @@
 // of this source code is governed by a BSD-style license that can be found in
 // the LICENSE file.
 
-package storage_test
+package vfs_test
 
 import (
 	"bytes"
@@ -12,7 +12,7 @@ import (
 	"os/exec"
 	"testing"
 
-	"github.com/petermattis/pebble/storage"
+	"github.com/petermattis/pebble/vfs"
 )
 
 var lockFilename = flag.String("lockfile", "", "File to lock. A non-empty value implies a child process.")
@@ -47,7 +47,7 @@ func TestLock(t *testing.T) {
 	}
 
 	t.Logf("Locking %s\n", filename)
-	lock, err := storage.Default.Lock(filename)
+	lock, err := vfs.Default.Lock(filename)
 	if err != nil {
 		t.Fatalf("Could not lock %s: %v", filename, err)
 	}
diff --git a/storage/mem_storage_test.go b/vfs/mem_fs_test.go
similarity index 99%
rename from storage/mem_storage_test.go
rename to vfs/mem_fs_test.go
index a3f9ab9..2b94e86 100644
--- a/storage/mem_storage_test.go
+++ b/vfs/mem_fs_test.go
@@ -2,7 +2,7 @@
 // of this source code is governed by a BSD-style license that can be found in
 // the LICENSE file.
 
-package storage
+package vfs
 
 import (
 	"io"
@@ -193,7 +193,7 @@ func TestList(t *testing.T) {
 	}
 
 	{
-		got := fs.(*memStorage).String()
+		got := fs.(*memFS).String()
 		want := normalize(`          /
        0    a
             bar/
diff --git a/storage/syncing_file_linux_test.go b/vfs/syncing_file_linux_test.go
similarity index 99%
rename from storage/syncing_file_linux_test.go
rename to vfs/syncing_file_linux_test.go
index 18a30c5..142d618 100644
--- a/storage/syncing_file_linux_test.go
+++ b/vfs/syncing_file_linux_test.go
@@ -4,7 +4,7 @@
 
 // +build linux
 
-package storage
+package vfs
 
 import (
 	"fmt"
diff --git a/storage/syncing_file_test.go b/vfs/syncing_file_test.go
similarity index 99%
rename from storage/syncing_file_test.go
rename to vfs/syncing_file_test.go
index e694160..22b5eac 100644
--- a/storage/syncing_file_test.go
+++ b/vfs/syncing_file_test.go
@@ -2,7 +2,7 @@
 // of this source code is governed by a BSD-style license that can be found in
 // the LICENSE file.
 
-package storage
+package vfs
 
 import (
 	"fmt"