github.com/rohankumardubey/proxyfs@v0.0.0-20210108201508-653efa9ab00e/inode/volume.go (about) 1 package inode 2 3 import ( 4 "fmt" 5 6 "github.com/swiftstack/ProxyFS/logger" 7 "github.com/swiftstack/ProxyFS/stats" 8 "github.com/swiftstack/sortedmap" 9 ) 10 11 func (vS *volumeStruct) GetFSID() (fsid uint64) { 12 fsid = vS.fsid 13 return 14 } 15 16 func (vS *volumeStruct) SnapShotCreate(name string) (id uint64, err error) { 17 err = enforceRWMode(false) 18 if nil != err { 19 return 20 } 21 22 if ("." == name) || (".." == name) { 23 err = fmt.Errorf("SnapShot cannot be named either '.' or '..'") 24 return 25 } 26 27 vS.Lock() 28 id, err = vS.headhunterVolumeHandle.SnapShotCreateByInodeLayer(name) 29 vS.Unlock() 30 return 31 } 32 33 func (vS *volumeStruct) SnapShotDelete(id uint64) (err error) { 34 var ( 35 found bool 36 keyAsInodeNumber InodeNumber 37 keyAsKey sortedmap.Key 38 indexWherePurgesAreToHappen int 39 maxInodeNumberToPurgeFromInodeCache InodeNumber 40 minInodeNumberToPurgeFromInodeCache InodeNumber 41 ok bool 42 valueAsValue sortedmap.Value 43 valueAsInodeStructPtr *inMemoryInodeStruct 44 ) 45 46 err = enforceRWMode(false) 47 if nil != err { 48 return 49 } 50 51 vS.Lock() 52 err = vS.headhunterVolumeHandle.SnapShotDeleteByInodeLayer(id) 53 if nil == err { 54 // Purge elements in inodeCache to avoid aliasing if/when SnapShotID is reused 55 56 minInodeNumberToPurgeFromInodeCache = InodeNumber(vS.headhunterVolumeHandle.SnapShotIDAndNonceEncode(id, uint64(0))) 57 maxInodeNumberToPurgeFromInodeCache = InodeNumber(vS.headhunterVolumeHandle.SnapShotIDAndNonceEncode(id+1, uint64(0))) 58 59 indexWherePurgesAreToHappen, found, err = vS.inodeCache.BisectRight(minInodeNumberToPurgeFromInodeCache) 60 if nil != err { 61 vS.Unlock() 62 err = fmt.Errorf("Volume %v InodeCache BisectRight() failed: %v", vS.volumeName, err) 63 logger.Error(err) 64 return 65 } 66 67 // If there is some InodeNumber at or beyond minInodeNumberToPurgeFromInodeCache, found == TRUE 68 69 for found { 70 keyAsKey, valueAsValue, ok, err = vS.inodeCache.GetByIndex(indexWherePurgesAreToHappen) 71 if nil != err { 72 vS.Unlock() 73 err = fmt.Errorf("Volume %v InodeCache GetByIndex() failed: %v", vS.volumeName, err) 74 logger.Error(err) 75 return 76 } 77 78 if !ok { 79 vS.Unlock() 80 return 81 } 82 83 keyAsInodeNumber, ok = keyAsKey.(InodeNumber) 84 if !ok { 85 vS.Unlock() 86 err = fmt.Errorf("Volume %v InodeCache GetByIndex() returned non-InodeNumber", vS.volumeName) 87 return 88 } 89 90 // Redefine found to indicate we've found an InodeCache entry to evict (used next iteration) 91 92 found = (keyAsInodeNumber < maxInodeNumberToPurgeFromInodeCache) 93 94 // func (vS *volumeStruct) inodeCacheDropWhileLocked(inode *inMemoryInodeStruct) (ok bool, err error) 95 if found { 96 valueAsInodeStructPtr, ok = valueAsValue.(*inMemoryInodeStruct) 97 if !ok { 98 vS.Unlock() 99 err = fmt.Errorf("Volume %v InodeCache GetByIndex() returned non-inMemoryInodeStructPtr", vS.volumeName) 100 return 101 } 102 ok, err = vS.inodeCacheDropWhileLocked(valueAsInodeStructPtr) 103 if nil != err { 104 vS.Unlock() 105 err = fmt.Errorf("Volume %v inodeCacheDropWhileLocked() failed: %v", vS.volumeName, err) 106 return 107 } 108 if !ok { 109 vS.Unlock() 110 err = fmt.Errorf("Volume %v inodeCacheDropWhileLocked() returned !ok", vS.volumeName) 111 return 112 } 113 } 114 } 115 } 116 vS.Unlock() 117 return 118 } 119 120 func (vS *volumeStruct) CheckpointCompleted() { 121 var ( 122 dirEntryCacheHitsDelta uint64 123 dirEntryCacheMissesDelta uint64 124 dirEntryCacheStats *sortedmap.BPlusTreeCacheStats 125 fileExtentMapCacheHitsDelta uint64 126 fileExtentMapCacheMissesDelta uint64 127 fileExtentMapCacheStats *sortedmap.BPlusTreeCacheStats 128 ) 129 130 dirEntryCacheStats = globals.dirEntryCache.Stats() 131 fileExtentMapCacheStats = globals.fileExtentMapCache.Stats() 132 133 globals.Lock() 134 135 dirEntryCacheHitsDelta = dirEntryCacheStats.CacheHits - globals.dirEntryCachePriorCacheHits 136 dirEntryCacheMissesDelta = dirEntryCacheStats.CacheMisses - globals.dirEntryCachePriorCacheMisses 137 138 fileExtentMapCacheHitsDelta = fileExtentMapCacheStats.CacheHits - globals.fileExtentMapCachePriorCacheHits 139 fileExtentMapCacheMissesDelta = fileExtentMapCacheStats.CacheMisses - globals.fileExtentMapCachePriorCacheMisses 140 141 if 0 != dirEntryCacheHitsDelta { 142 stats.IncrementOperationsBy(&stats.DirEntryCacheHits, dirEntryCacheHitsDelta) 143 globals.dirEntryCachePriorCacheHits = dirEntryCacheStats.CacheHits 144 } 145 if 0 != dirEntryCacheMissesDelta { 146 stats.IncrementOperationsBy(&stats.DirEntryCacheMisses, dirEntryCacheMissesDelta) 147 globals.dirEntryCachePriorCacheMisses = dirEntryCacheStats.CacheMisses 148 } 149 150 if 0 != fileExtentMapCacheHitsDelta { 151 stats.IncrementOperationsBy(&stats.FileExtentMapCacheHits, fileExtentMapCacheHitsDelta) 152 globals.fileExtentMapCachePriorCacheHits = fileExtentMapCacheStats.CacheHits 153 } 154 if 0 != fileExtentMapCacheMissesDelta { 155 stats.IncrementOperationsBy(&stats.FileExtentMapCacheMisses, fileExtentMapCacheMissesDelta) 156 globals.fileExtentMapCachePriorCacheMisses = fileExtentMapCacheStats.CacheMisses 157 } 158 159 globals.Unlock() 160 }