github.com/openebs/node-disk-manager@v1.9.1-0.20230225014141-4531f06ffa1e/pkg/mount/libmount/mount_table_diff.go (about) 1 /* 2 Copyright 2020 The OpenEBS Authors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package libmount 18 19 import "sort" 20 21 type MountAction uint8 22 23 const ( 24 MountActionMount MountAction = iota 25 MountActionUmount 26 MountActionMove 27 MountActionRemount 28 ) 29 30 // MountTabDiffEntry represents a single change entry in the MounTabDiff 31 type MountTabDiffEntry struct { 32 oldFs *Filesystem 33 newFs *Filesystem 34 action MountAction 35 } 36 37 // MountTabDiff is the list of all changes between two mount tabs. 38 type MountTabDiff []*MountTabDiffEntry 39 40 // NewMountTabDiff returns a new and empty MountTabDiff 41 func NewMountTabDiff() MountTabDiff { 42 tabDiff := make(MountTabDiff, 0) 43 return tabDiff 44 } 45 46 // AddDiffEntry returns a new MountTabDiff containing all the entries 47 // of the current MountTabDiff and a new entry appended based on the parametrs. 48 func (md MountTabDiff) AddDiffEntry(oldFs *Filesystem, newFs *Filesystem, action MountAction) MountTabDiff { 49 return append(md, &MountTabDiffEntry{oldFs, newFs, action}) 50 } 51 52 func (md MountTabDiff) getMountEntry(source string, id int) *MountTabDiffEntry { 53 for _, diffEntry := range md { 54 if diffEntry.action == MountActionMount && 55 diffEntry.newFs != nil && 56 diffEntry.newFs.GetID() == id && 57 diffEntry.newFs.GetSource() == source { 58 return diffEntry 59 } 60 } 61 return nil 62 } 63 64 // GenerateDiff returns a list of changes between the old mount tab 65 // and the new mount tab in the form of a MountTabDiff. A nil value 66 // for any of the parameters is valid and is treated as a mount tab 67 // with no entries. 68 func GenerateDiff(oldTab *MountTab, newTab *MountTab) MountTabDiff { 69 diffTable := NewMountTabDiff() 70 if oldTab == nil { 71 oldTab = &MountTab{} 72 } 73 if newTab == nil { 74 newTab = &MountTab{} 75 } 76 oldTabSize := oldTab.Size() 77 newTabSize := newTab.Size() 78 79 // Both tables empty 80 if newTabSize == 0 && oldTabSize == 0 { 81 return diffTable 82 } 83 // Old table empty => all entries in new table are new mounts 84 if oldTabSize == 0 { 85 for _, entry := range newTab.entries { 86 diffTable = diffTable.AddDiffEntry(nil, entry, MountActionMount) 87 } 88 return diffTable 89 } 90 // New table empty => all entries in old table were unmounted 91 if newTabSize == 0 { 92 for _, entry := range oldTab.entries { 93 diffTable = diffTable.AddDiffEntry(entry, nil, MountActionUmount) 94 } 95 return diffTable 96 } 97 98 // Search newly mounted or modified entries 99 for _, newFs := range newTab.entries { 100 oldFs := oldTab.Find(SourceFilter(newFs.GetSource()), TargetFilter(newFs.GetTarget())) 101 if oldFs == nil { 102 diffTable = diffTable.AddDiffEntry(nil, newFs, MountActionMount) 103 } else if oldFs.GetVFSOptions() != newFs.GetVFSOptions() || 104 oldFs.GetFSOptions() != newFs.GetFSOptions() { 105 diffTable = diffTable.AddDiffEntry(oldFs, newFs, MountActionRemount) 106 } 107 } 108 109 // Search umounted or moved entries 110 for _, oldFs := range oldTab.entries { 111 newFs := newTab.Find(SourceFilter(oldFs.GetSource()), TargetFilter(oldFs.GetTarget())) 112 if newFs == nil { 113 de := diffTable.getMountEntry(oldFs.GetSource(), oldFs.GetID()) 114 // fs umounted 115 if de == nil { 116 diffTable = diffTable.AddDiffEntry(oldFs, nil, MountActionUmount) 117 } else { 118 // else moved 119 de.oldFs = oldFs 120 de.action = MountActionMove 121 } 122 } 123 } 124 125 return diffTable 126 } 127 128 // GetAction returns the type of change - mount, umount, move, remount 129 func (mde *MountTabDiffEntry) GetAction() MountAction { 130 return mde.action 131 } 132 133 // GetOldFs returns a pointer to the old filesystem that changed 134 func (mde *MountTabDiffEntry) GetOldFs() *Filesystem { 135 if mde.oldFs == nil { 136 return nil 137 } 138 fs := *mde.oldFs 139 return &fs 140 } 141 142 // GetNewFs returns a pointer to the new filesystem that the old filesystem 143 // changed to. 144 func (mde *MountTabDiffEntry) GetNewFs() *Filesystem { 145 if mde.newFs == nil { 146 return nil 147 } 148 fs := *mde.newFs 149 return &fs 150 } 151 152 // ListSources lists all affected sources in the diff, i.e., all 153 // sources that were mounted/umounted/remounted/moved in the diff. 154 func (md MountTabDiff) ListSources() []string { 155 var src string 156 uniqueSources := make(map[string]struct{}) 157 sourcesList := make([]string, 0) 158 159 for _, diff := range md { 160 if diff.action == MountActionUmount { 161 src = diff.oldFs.GetSource() 162 } else { 163 src = diff.newFs.GetSource() 164 } 165 if _, ok := uniqueSources[src]; !ok { 166 uniqueSources[src] = struct{}{} 167 } 168 } 169 170 for src = range uniqueSources { 171 sourcesList = append(sourcesList, src) 172 } 173 sort.Strings(sourcesList) 174 175 return sourcesList 176 }