github.com/scaleoutsean/fusego@v0.0.0-20220224074057-4a6429e46bb8/samples/statfs/statfs.go (about) 1 // Copyright 2015 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package statfs 16 17 import ( 18 "context" 19 "os" 20 "sync" 21 22 "github.com/scaleoutsean/fusego" 23 "github.com/scaleoutsean/fusego/fuseops" 24 "github.com/scaleoutsean/fusego/fuseutil" 25 ) 26 27 // A file system that allows orchestrating canned responses to statfs ops, for 28 // testng out OS-specific statfs behavior. 29 // 30 // The file system allows opening and writing to any name that is a child of 31 // the root inode, and keeps track of the most recent write size delivered by 32 // the kernel (in order to test statfs response block size effects on write 33 // size, if any). 34 // 35 // Safe for concurrent access. 36 type FS interface { 37 fuseutil.FileSystem 38 39 // Set the canned response to be used for future statfs ops. 40 SetStatFSResponse(r fuseops.StatFSOp) 41 42 // Set the canned response to be used for future stat ops. 43 SetStatResponse(r fuseops.InodeAttributes) 44 45 // Return the size of the most recent write delivered by the kernel, or -1 if 46 // none. 47 MostRecentWriteSize() int 48 } 49 50 func New() FS { 51 return &statFS{ 52 cannedStatResponse: fuseops.InodeAttributes{ 53 Mode: 0666, 54 }, 55 mostRecentWriteSize: -1, 56 } 57 } 58 59 const childInodeID = fuseops.RootInodeID + 1 60 61 type statFS struct { 62 fuseutil.NotImplementedFileSystem 63 64 mu sync.Mutex 65 cannedResponse fuseops.StatFSOp // GUARDED_BY(mu) 66 cannedStatResponse fuseops.InodeAttributes // GUARDED_BY(mu) 67 mostRecentWriteSize int // GUARDED_BY(mu) 68 } 69 70 //////////////////////////////////////////////////////////////////////// 71 // Helpers 72 //////////////////////////////////////////////////////////////////////// 73 74 func dirAttrs() fuseops.InodeAttributes { 75 return fuseops.InodeAttributes{ 76 Mode: os.ModeDir | 0777, 77 } 78 } 79 80 func (fs *statFS) fileAttrs() fuseops.InodeAttributes { 81 return fs.cannedStatResponse 82 } 83 84 //////////////////////////////////////////////////////////////////////// 85 // Public interface 86 //////////////////////////////////////////////////////////////////////// 87 88 // LOCKS_EXCLUDED(fs.mu) 89 func (fs *statFS) SetStatFSResponse(r fuseops.StatFSOp) { 90 fs.mu.Lock() 91 defer fs.mu.Unlock() 92 93 fs.cannedResponse = r 94 } 95 96 // LOCKS_EXCLUDED(fs.mu) 97 func (fs *statFS) SetStatResponse(r fuseops.InodeAttributes) { 98 fs.mu.Lock() 99 defer fs.mu.Unlock() 100 101 fs.cannedStatResponse = r 102 } 103 104 // LOCKS_EXCLUDED(fs.mu) 105 func (fs *statFS) MostRecentWriteSize() int { 106 fs.mu.Lock() 107 defer fs.mu.Unlock() 108 109 return fs.mostRecentWriteSize 110 } 111 112 //////////////////////////////////////////////////////////////////////// 113 // FileSystem methods 114 //////////////////////////////////////////////////////////////////////// 115 116 // LOCKS_EXCLUDED(fs.mu) 117 func (fs *statFS) StatFS( 118 ctx context.Context, 119 op *fuseops.StatFSOp) error { 120 fs.mu.Lock() 121 defer fs.mu.Unlock() 122 123 *op = fs.cannedResponse 124 return nil 125 } 126 127 func (fs *statFS) LookUpInode( 128 ctx context.Context, 129 op *fuseops.LookUpInodeOp) error { 130 // Only the root has children. 131 if op.Parent != fuseops.RootInodeID { 132 return fuse.ENOENT 133 } 134 135 op.Entry.Child = childInodeID 136 op.Entry.Attributes = fs.fileAttrs() 137 138 return nil 139 } 140 141 func (fs *statFS) GetInodeAttributes( 142 ctx context.Context, 143 op *fuseops.GetInodeAttributesOp) error { 144 switch op.Inode { 145 case fuseops.RootInodeID: 146 op.Attributes = dirAttrs() 147 148 case childInodeID: 149 op.Attributes = fs.fileAttrs() 150 151 default: 152 return fuse.ENOENT 153 } 154 155 return nil 156 } 157 158 func (fs *statFS) SetInodeAttributes( 159 ctx context.Context, 160 op *fuseops.SetInodeAttributesOp) error { 161 // Ignore calls to truncate existing files when opening. 162 return nil 163 } 164 165 func (fs *statFS) OpenFile( 166 ctx context.Context, 167 op *fuseops.OpenFileOp) error { 168 return nil 169 } 170 171 // LOCKS_EXCLUDED(fs.mu) 172 func (fs *statFS) WriteFile( 173 ctx context.Context, 174 op *fuseops.WriteFileOp) error { 175 fs.mu.Lock() 176 defer fs.mu.Unlock() 177 178 fs.mostRecentWriteSize = len(op.Data) 179 return nil 180 }