// Mount makes the contents of the volume visible at the given // mountpoint. If Mount returns with a nil error, the mount has // occurred. func (app *App) Mount(volumeName string, mountpoint string) (*MountInfo, error) { // TODO obey `bazil -debug server run` var vol *fs.Volume var volumeID *fs.VolumeID var ready = make(chan error, 1) app.mounts.Lock() err := app.DB.View(func(tx *bolt.Tx) error { bucket := tx.Bucket([]byte(tokens.BucketVolName)) val := bucket.Get([]byte(volumeName)) if val == nil { return errors.New("volume not found") } var volConf wire.VolumeConfig if err := proto.Unmarshal(val, &volConf); err != nil { return err } var err error volumeID, err = fs.NewVolumeID(volConf.VolumeID) if err != nil { return err } if _, ok := app.mounts.open[*volumeID]; ok { return errors.New("volume already mounted") } kvstore, err := app.openKV(&volConf.Storage) if err != nil { return err } chunkStore := kvchunks.New(kvstore) vol, err = fs.Open(app.DB, chunkStore, volumeID) if err != nil { return err } mnt := &mountState{ unmounted: make(chan struct{}), } go func() { defer close(mnt.unmounted) ready <- app.serveMount(vol, volumeID, mountpoint) }() app.mounts.open[*volumeID] = mnt return nil }) app.mounts.Unlock() if err != nil { return nil, err } err = <-ready if err != nil { return nil, err } info := &MountInfo{ VolumeID: *volumeID, } return info, nil }
// caller must hold App.volumes.Mutex func (app *App) openVolume(tx *db.Tx, id *db.VolumeID) (*fs.Volume, error) { v, err := tx.Volumes().GetByVolumeID(id) if err != nil { return nil, err } kvstore, err := app.OpenKV(tx, v.Storage()) if err != nil { return nil, err } chunkStore := kvchunks.New(kvstore) vol, err := fs.Open(app.DB, chunkStore, id, (*peer.PublicKey)(app.Keys.Sign.Pub)) if err != nil { return nil, err } return vol, nil }