func (d *driver) Mount(volumeID string, mountpath string) error { v, err := d.GetVol(volumeID) if err != nil { return fmt.Errorf("Failed to locate volume %q", volumeID) } if err := syscall.Mount(v.DevicePath, mountpath, v.Spec.Format.SimpleString(), 0, ""); err != nil { // TODO(pedge): same string for log message and error? dlog.Errorf("Mounting %s on %s failed because of %v", v.DevicePath, mountpath, err) return fmt.Errorf("Failed to mount %v at %v: %v", v.DevicePath, mountpath, err) } dlog.Infof("BUSE mounted NBD device %s at %s", v.DevicePath, mountpath) v.AttachPath = mountpath // TODO(pedge): why ignoring the error? err = d.UpdateVol(v) return nil }
// Handle block requests. func (nbd *NBD) handle() { buf := make([]byte, 2<<19) var x request for { bytes, err := syscall.Read(nbd.socket, buf[0:28]) if nbd.deviceFile == nil { dlog.Infof("Disconnecting device %s", nbd.devicePath) return } if bytes < 0 || err != nil { dlog.Errorf("Error reading from device %s", nbd.devicePath) nbd.Disconnect() return } x.magic = binary.BigEndian.Uint32(buf) x.typus = binary.BigEndian.Uint32(buf[4:8]) x.handle = binary.BigEndian.Uint64(buf[8:16]) x.from = binary.BigEndian.Uint64(buf[16:24]) x.len = binary.BigEndian.Uint32(buf[24:28]) switch x.magic { case NBD_REPLY_MAGIC: fallthrough case NBD_REQUEST_MAGIC: switch x.typus { case NBD_CMD_READ: nbd.device.ReadAt(buf[16:16+x.len], int64(x.from)) binary.BigEndian.PutUint32(buf[0:4], NBD_REPLY_MAGIC) binary.BigEndian.PutUint32(buf[4:8], 0) syscall.Write(nbd.socket, buf[0:16+x.len]) case NBD_CMD_WRITE: n, _ := syscall.Read(nbd.socket, buf[28:28+x.len]) for uint32(n) < x.len { m, _ := syscall.Read(nbd.socket, buf[28+n:28+x.len]) n += m } nbd.device.WriteAt(buf[28:28+x.len], int64(x.from)) binary.BigEndian.PutUint32(buf[0:4], NBD_REPLY_MAGIC) binary.BigEndian.PutUint32(buf[4:8], 0) syscall.Write(nbd.socket, buf[0:16]) case NBD_CMD_DISC: dlog.Infof("Disconnecting device %s", nbd.devicePath) nbd.Disconnect() return case NBD_CMD_FLUSH: fallthrough case NBD_CMD_TRIM: binary.BigEndian.PutUint32(buf[0:4], NBD_REPLY_MAGIC) binary.BigEndian.PutUint32(buf[4:8], 1) syscall.Write(nbd.socket, buf[0:16]) default: dlog.Errorf("Unknown command recieved on device %s", nbd.devicePath) nbd.Disconnect() return } default: dlog.Errorf("Invalid packet command recieved on device %s", nbd.devicePath) nbd.Disconnect() return } } }
func (l *Layer0) create(id, parent string) (string, *Layer0Vol, error) { l.Lock() defer l.Unlock() // If this is the parent of the Layer0, add an entry for it. baseID, l0 := l.isLayer0Parent(id) if l0 { l.volumes[baseID] = &Layer0Vol{id: baseID, parent: parent} return id, nil, nil } // Don't do anything if this is not layer 0 if !l.isLayer0(id) { return id, nil, nil } vol, ok := l.volumes[id] if !ok { dlog.Warnf("Failed to find layer0 volume for id %v", id) return id, nil, nil } // Query volume for Layer 0 vols, err := l.volDriver.Enumerate(&api.VolumeLocator{Name: vol.parent}, nil) // If we don't find a volume configured for this image, // then don't track layer0 if err != nil || vols == nil { dlog.Infof("Failed to find configured volume for id %v", vol.parent) delete(l.volumes, id) return id, nil, nil } // Find a volume that is available. index := -1 for i, v := range vols { if len(v.AttachPath) == 0 { index = i break } } if index == -1 { dlog.Infof("Failed to find free volume for id %v", vol.parent) delete(l.volumes, id) return id, nil, nil } mountPath := path.Join(l.home, l.loID(id)) os.MkdirAll(mountPath, 0755) // If this is a block driver, first attach the volume. if l.volDriver.Type() == api.DriverType_DRIVER_TYPE_BLOCK { _, err := l.volDriver.Attach(vols[index].Id) if err != nil { dlog.Errorf("Failed to attach volume %v", vols[index].Id) delete(l.volumes, id) return id, nil, nil } } err = l.volDriver.Mount(vols[index].Id, mountPath) if err != nil { dlog.Errorf("Failed to mount volume %v at path %v", vols[index].Id, mountPath) delete(l.volumes, id) return id, nil, nil } vol.path = mountPath vol.volumeID = vols[index].Id vol.ref = 1 return l.realID(id), vol, nil }