diff --git a/weed/topology/data_node.go b/weed/topology/data_node.go index b3f2edda9..8c013f001 100644 --- a/weed/topology/data_node.go +++ b/weed/topology/data_node.go @@ -200,11 +200,15 @@ func (dn *DataNode) AdjustDiskUsageBytes(diskTotalBytes, diskFreeBytes map[strin func (dn *DataNode) GetVolumes() (ret []storage.VolumeInfo) { dn.RLock() + defer dn.RUnlock() + total := 0 for _, c := range dn.children { - disk := c.(*Disk) - ret = append(ret, disk.GetVolumes()...) + total += c.(*Disk).VolumeCount() + } + ret = make([]storage.VolumeInfo, 0, total) + for _, c := range dn.children { + ret = c.(*Disk).AppendVolumes(ret) } - dn.RUnlock() return ret } diff --git a/weed/topology/disk.go b/weed/topology/disk.go index cec5ffe28..3d42fa7e5 100644 --- a/weed/topology/disk.go +++ b/weed/topology/disk.go @@ -202,14 +202,19 @@ func (d *Disk) doAddOrUpdateVolume(v storage.VolumeInfo) (isNew, isChanged bool) return } -func (d *Disk) GetVolumes() (ret []storage.VolumeInfo) { +func (d *Disk) GetVolumes() []storage.VolumeInfo { + return d.AppendVolumes(make([]storage.VolumeInfo, 0, d.VolumeCount())) +} + +// AppendVolumes appends the disk's volumes to dst, so a caller gathering +// several disks fills one slice instead of concatenating a copy per disk. +func (d *Disk) AppendVolumes(dst []storage.VolumeInfo) []storage.VolumeInfo { d.RLock() - ret = make([]storage.VolumeInfo, 0, len(d.volumes)) + defer d.RUnlock() for _, v := range d.volumes { - ret = append(ret, v) + dst = append(dst, v) } - d.RUnlock() - return ret + return dst } func (d *Disk) VolumeCount() int {