github.com/rohankumardubey/proxyfs@v0.0.0-20210108201508-653efa9ab00e/inode/api.go (about) 1 // Package inode provides inode-management functionality for ProxyFS. 2 package inode 3 4 import ( 5 "time" 6 "unsafe" 7 8 "golang.org/x/sys/unix" 9 10 "github.com/swiftstack/sortedmap" 11 12 "github.com/swiftstack/ProxyFS/dlm" 13 "github.com/swiftstack/ProxyFS/utils" 14 ) 15 16 type InodeNumber uint64 17 type InodeType uint16 18 type InodeMode uint32 19 type InodeUserID uint32 20 type InodeGroupID uint32 21 type InodeDirLocation int64 22 23 const ( 24 InodeRootUserID = InodeUserID(0) 25 ) 26 27 // NOTE: Using unix.DT_* constants for these types makes it easier 28 // to expose this information in a standardized way with our RPC APIs. 29 const ( 30 DirType InodeType = unix.DT_DIR 31 FileType InodeType = unix.DT_REG 32 SymlinkType InodeType = unix.DT_LNK 33 ) 34 35 // NOTE: Would have liked to use os.FileMode bitmask definitions here instead of creating our own, 36 // but unfortunately the bitmasks used by os.ModeDir and os.ModeSymlink (0x80000000 and 0x8000000) 37 // are not the same values as what is expected on the linux side (0x4000 and 0xa000). 38 const ( 39 PosixModeType InodeMode = 0xE000 40 PosixModeDir InodeMode = 0x4000 41 PosixModeFile InodeMode = 0x8000 42 PosixModeSymlink InodeMode = 0xa000 43 PosixModePerm InodeMode = 0777 44 ) 45 46 // The following are used in calls to Access()... either F_OK or bitwise or of R_OK, W_OK, and X_OK 47 const ( 48 F_OK = InodeMode(unix.F_OK) // check for existence 49 R_OK = InodeMode(unix.R_OK) // UID:GID check for read permission 50 W_OK = InodeMode(unix.W_OK) // UID:GID check for write permission 51 X_OK = InodeMode(unix.X_OK) // UID:GID check for execute permission 52 P_OK = InodeMode((unix.R_OK | unix.W_OK | unix.X_OK) + 1) // check for ownership permissions 53 ) 54 55 // AccessOverride.Owner means Access() grants permission to the owner of the 56 // file even if the permission bits disallow it. 57 type AccessOverride uint32 58 59 const ( 60 NoOverride AccessOverride = iota 61 OwnerOverride 62 ) 63 64 // The following line of code is a directive to go generate that tells it to create a 65 // file called inodetype_string.go that implements the .String() method for InodeType. 66 //go:generate stringer -type=InodeType 67 68 type MetadataStruct struct { 69 InodeType 70 LinkCount uint64 71 Size uint64 72 CreationTime time.Time 73 ModificationTime time.Time 74 AccessTime time.Time 75 AttrChangeTime time.Time // aka ctime; This field is intended to be changed by writing or by setting inode information (i.e., owner, group, link count, mode, etc.). 76 NumWrites uint64 // only maintained for FileType inodes 77 InodeStreamNameSlice []string 78 Mode InodeMode 79 UserID InodeUserID 80 GroupID InodeGroupID 81 } 82 83 type FragmentationReport struct { 84 NumberOfFragments uint64 // used with BytesInFragments to compute average fragment size 85 BytesInFragments uint64 // equivalent to size of file for FileInode that is not sparse 86 BytesTrapped uint64 // unreferenced bytes trapped in referenced log segments 87 } 88 89 type DirEntry struct { 90 InodeNumber 91 Basename string 92 Type InodeType 93 NextDirLocation InodeDirLocation 94 } 95 96 type CoalesceElement struct { 97 ContainingDirectoryInodeNumber InodeNumber 98 ElementInodeNumber InodeNumber 99 ElementName string 100 } 101 102 type ReadPlanStep struct { 103 LogSegmentNumber uint64 // If == 0, Length specifies zero-fill size 104 Offset uint64 // If zero-fill case, == 0 105 Length uint64 // Must != 0 106 AccountName string // If == "", Length specifies a zero-fill size 107 ContainerName string // If == "", Length specifies a zero-fill size 108 ObjectName string // If == "", Length specifies a zero-fill size 109 ObjectPath string // If == "", Length specifies a zero-fill size 110 } 111 112 type ExtentMapEntryStruct struct { 113 FileOffset uint64 114 LogSegmentOffset uint64 115 Length uint64 116 ContainerName string // While "read-as-zero" entries in ExtentMapShunkStruct 117 ObjectName string // are not present, {Container|Object}Name would be == "" 118 } 119 120 type ExtentMapChunkStruct struct { 121 FileOffsetRangeStart uint64 // Holes in [FileOffsetRangeStart:FileOffsetRangeEnd) 122 FileOffsetRangeEnd uint64 // not covered in ExtentMapEntry slice should "read-as-zero" 123 FileSize uint64 // up to the end-of-file as indicated by FileSize 124 ExtentMapEntry []ExtentMapEntryStruct // All will be in [FileOffsetRangeStart:FileOffsetRangeEnd) 125 } 126 127 const ( 128 RootDirInodeNumber = InodeNumber(1) 129 ) 130 131 const ( 132 SnapShotDirName = ".snapshot" 133 ) 134 135 type RWModeType uint8 136 137 const ( 138 RWModeNormal RWModeType = iota // All reads, writes, etc... should be allowed 139 RWModeNoWrite // Same as modeNormal except Write() & ProvisionObject() should fail 140 RWModeReadOnly // No operations that modify state (data or metadata) should be allowed 141 ) 142 143 func (de *DirEntry) Size() int { 144 // sizeof(InodeNumber) + sizeof(InodeType) + sizeof(DirLocation) + string data + null byte delimiter 145 return int(unsafe.Sizeof(de.InodeNumber)) + int(unsafe.Sizeof(de.Type)) + int(unsafe.Sizeof(de.NextDirLocation)) + len(de.Basename) + 1 146 } 147 148 // AccountNameToVolumeName returns the corresponding volumeName for the supplied accountName (if any). 149 func AccountNameToVolumeName(accountName string) (volumeName string, ok bool) { 150 volumeName, ok = accountNameToVolumeName(accountName) 151 return 152 } 153 154 // VolumeNameToAccountName returns the corresponding accountName for the supplied volumeName (if any). 155 func VolumeNameToAccountName(volumeName string) (accountName string, ok bool) { 156 accountName, ok = volumeNameToAccountName(volumeName) 157 return 158 } 159 160 // VolumeNameToActivePeerPrivateIPAddr returns the Peer IP Address serving the specified VolumeName. 161 func VolumeNameToActivePeerPrivateIPAddr(volumeName string) (activePeerPrivateIPAddr string, ok bool) { 162 activePeerPrivateIPAddr, ok = volumeNameToActivePeerPrivateIPAddr(volumeName) 163 return 164 } 165 166 // FetchVolumeHandle returns a the VolumeHandle corresponding to the name VolumeName. 167 // 168 // Note: The method should be considered a write operation on the RoodDirInodeNumber. 169 // As such, an exclusive lock should be held around a call to FetchVolumeHandle(). 170 func FetchVolumeHandle(volumeName string) (volumeHandle VolumeHandle, err error) { 171 volumeHandle, err = fetchVolumeHandle(volumeName) 172 return 173 } 174 175 type VolumeHandle interface { 176 // Generic methods, implemented volume.go 177 178 GetFSID() (fsid uint64) 179 SnapShotCreate(name string) (id uint64, err error) 180 SnapShotDelete(id uint64) (err error) 181 182 // Wrapper methods around DLM locks. Implemented in locker.go 183 184 MakeLockID(inodeNumber InodeNumber) (lockID string, err error) 185 InitInodeLock(inodeNumber InodeNumber, callerID dlm.CallerID) (lock *dlm.RWLockStruct, err error) 186 GetReadLock(inodeNumber InodeNumber, callerID dlm.CallerID) (*dlm.RWLockStruct, error) 187 GetWriteLock(inodeNumber InodeNumber, callerID dlm.CallerID) (*dlm.RWLockStruct, error) 188 AttemptReadLock(inodeNumber InodeNumber, callerID dlm.CallerID) (*dlm.RWLockStruct, error) 189 AttemptWriteLock(inodeNumber InodeNumber, callerID dlm.CallerID) (*dlm.RWLockStruct, error) 190 EnsureReadLock(inodeNumber InodeNumber, callerID dlm.CallerID) (*dlm.RWLockStruct, error) 191 EnsureWriteLock(inodeNumber InodeNumber, callerID dlm.CallerID) (*dlm.RWLockStruct, error) 192 193 // Common Inode methods, implemented in inode.go 194 195 Access(inodeNumber InodeNumber, userID InodeUserID, groupID InodeGroupID, otherGroupIDs []InodeGroupID, accessMode InodeMode, override AccessOverride) (accessReturn bool) 196 Purge(inodeNumber InodeNumber) (err error) 197 Destroy(inodeNumber InodeNumber) (err error) 198 GetMetadata(inodeNumber InodeNumber) (metadata *MetadataStruct, err error) 199 GetType(inodeNumber InodeNumber) (inodeType InodeType, err error) 200 GetLinkCount(inodeNumber InodeNumber) (linkCount uint64, err error) 201 SetLinkCount(inodeNumber InodeNumber, linkCount uint64) (err error) 202 SetCreationTime(inodeNumber InodeNumber, creationTime time.Time) (err error) 203 SetModificationTime(inodeNumber InodeNumber, modificationTime time.Time) (err error) 204 SetAccessTime(inodeNumber InodeNumber, accessTime time.Time) (err error) 205 SetPermMode(inodeNumber InodeNumber, filePerm InodeMode) (err error) 206 SetOwnerUserID(inodeNumber InodeNumber, userID InodeUserID) (err error) 207 SetOwnerUserIDGroupID(inodeNumber InodeNumber, userID InodeUserID, groupID InodeGroupID) (err error) 208 SetOwnerGroupID(inodeNumber InodeNumber, groupID InodeGroupID) (err error) 209 GetStream(inodeNumber InodeNumber, inodeStreamName string) (buf []byte, err error) 210 PutStream(inodeNumber InodeNumber, inodeStreamName string, buf []byte) (err error) 211 DeleteStream(inodeNumber InodeNumber, inodeStreamName string) (err error) 212 FetchOnDiskInode(inodeNumber InodeNumber) (corruptionDetected CorruptionDetected, version Version, onDiskInode []byte, err error) 213 PatchInode(inodeNumber InodeNumber, inodeType InodeType, linkCount uint64, mode InodeMode, userID InodeUserID, groupID InodeGroupID, parentInodeNumber InodeNumber, symlinkTarget string) (err error) 214 FetchLayoutReport(inodeNumber InodeNumber) (layoutReport sortedmap.LayoutReport, err error) 215 FetchFragmentationReport(inodeNumber InodeNumber) (fragmentationReport FragmentationReport, err error) 216 Optimize(inodeNumber InodeNumber, maxDuration time.Duration) (err error) 217 Validate(inodeNumber InodeNumber, deeply bool) (err error) 218 219 // Directory Inode specific methods, implemented in dir.go 220 221 CreateDir(filePerm InodeMode, userID InodeUserID, groupID InodeGroupID) (dirInodeNumber InodeNumber, err error) 222 Link(dirInodeNumber InodeNumber, basename string, targetInodeNumber InodeNumber, insertOnly bool) (err error) 223 Unlink(dirInodeNumber InodeNumber, basename string, removeOnly bool) (err error) 224 Move(srcDirInodeNumber InodeNumber, srcBasename string, dstDirInodeNumber InodeNumber, dstBasename string) (err error) 225 Lookup(dirInodeNumber InodeNumber, basename string) (targetInodeNumber InodeNumber, err error) 226 NumDirEntries(dirInodeNumber InodeNumber) (numEntries uint64, err error) 227 ReadDir(dirInodeNumber InodeNumber, maxEntries uint64, maxBufSize uint64, prevReturned ...interface{}) (dirEntrySlice []DirEntry, moreEntries bool, err error) 228 ReplaceDirEntries(parentDirInodeNumber InodeNumber, parentDirEntryBasename string, dirInodeNumber InodeNumber, dirEntryInodeNumbers []InodeNumber) (err error) 229 230 // File Inode specific methods, implemented in file.go 231 232 CreateFile(filePerm InodeMode, userID InodeUserID, groupID InodeGroupID) (fileInodeNumber InodeNumber, err error) 233 Read(inodeNumber InodeNumber, offset uint64, length uint64, profiler *utils.Profiler) (buf []byte, err error) 234 GetReadPlan(fileInodeNumber InodeNumber, offset *uint64, length *uint64) (readPlan []ReadPlanStep, err error) 235 FetchExtentMapChunk(fileInodeNumber InodeNumber, fileOffset uint64, maxEntriesFromFileOffset int64, maxEntriesBeforeFileOffset int64) (extentMapChunk *ExtentMapChunkStruct, err error) 236 Write(fileInodeNumber InodeNumber, offset uint64, buf []byte, profiler *utils.Profiler) (err error) 237 ProvisionObject() (objectPath string, err error) 238 Wrote(fileInodeNumber InodeNumber, containerName string, objectName string, fileOffset []uint64, objectOffset []uint64, length []uint64, patchOnly bool) (err error) 239 SetSize(fileInodeNumber InodeNumber, Size uint64) (err error) 240 Flush(fileInodeNumber InodeNumber, andPurge bool) (err error) 241 Coalesce(destInodeNumber InodeNumber, metaDataName string, metaData []byte, elements []*CoalesceElement) (attrChangeTime time.Time, modificationTime time.Time, numWrites uint64, fileSize uint64, err error) 242 DefragmentFile(fileInodeNumber InodeNumber, startingFileOffset uint64, chunkSize uint64) (nextFileOffset uint64, eofReached bool, err error) 243 244 // Symlink Inode specific methods, implemented in symlink.go 245 246 CreateSymlink(target string, filePerm InodeMode, userID InodeUserID, groupID InodeGroupID) (symlinkInodeNumber InodeNumber, err error) 247 GetSymlink(symlinkInodeNumber InodeNumber) (target string, err error) 248 } 249 250 // SetRWMode sets the package to either allow all read/write operations (RWModeNormal), 251 // allow all except Write() and ProvisionObject() operations (RWModeNoWrite), or 252 // disallow any data or metadata operations (RWModeReadOnly). 253 func SetRWMode(rwMode RWModeType) (err error) { 254 err = setRWMode(rwMode) 255 return 256 }