github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/fsimpl/gofer/p9file.go (about) 1 // Copyright 2019 The gVisor Authors. 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 gofer 16 17 import ( 18 "github.com/SagerNet/gvisor/pkg/context" 19 "github.com/SagerNet/gvisor/pkg/fd" 20 "github.com/SagerNet/gvisor/pkg/p9" 21 "github.com/SagerNet/gvisor/pkg/syserror" 22 ) 23 24 // p9file is a wrapper around p9.File that provides methods that are 25 // Context-aware. 26 type p9file struct { 27 file p9.File 28 } 29 30 func (f p9file) isNil() bool { 31 return f.file == nil 32 } 33 34 func (f p9file) walk(ctx context.Context, names []string) ([]p9.QID, p9file, error) { 35 ctx.UninterruptibleSleepStart(false) 36 qids, newfile, err := f.file.Walk(names) 37 ctx.UninterruptibleSleepFinish(false) 38 return qids, p9file{newfile}, err 39 } 40 41 func (f p9file) walkGetAttr(ctx context.Context, names []string) ([]p9.QID, p9file, p9.AttrMask, p9.Attr, error) { 42 ctx.UninterruptibleSleepStart(false) 43 qids, newfile, attrMask, attr, err := f.file.WalkGetAttr(names) 44 ctx.UninterruptibleSleepFinish(false) 45 return qids, p9file{newfile}, attrMask, attr, err 46 } 47 48 // walkGetAttrOne is a wrapper around p9.File.WalkGetAttr that takes a single 49 // path component and returns a single qid. 50 func (f p9file) walkGetAttrOne(ctx context.Context, name string) (p9.QID, p9file, p9.AttrMask, p9.Attr, error) { 51 ctx.UninterruptibleSleepStart(false) 52 qids, newfile, attrMask, attr, err := f.file.WalkGetAttr([]string{name}) 53 ctx.UninterruptibleSleepFinish(false) 54 if err != nil { 55 return p9.QID{}, p9file{}, p9.AttrMask{}, p9.Attr{}, err 56 } 57 if len(qids) != 1 { 58 ctx.Warningf("p9.File.WalkGetAttr returned %d qids (%v), wanted 1", len(qids), qids) 59 if newfile != nil { 60 p9file{newfile}.close(ctx) 61 } 62 return p9.QID{}, p9file{}, p9.AttrMask{}, p9.Attr{}, syserror.EIO 63 } 64 return qids[0], p9file{newfile}, attrMask, attr, nil 65 } 66 67 func (f p9file) statFS(ctx context.Context) (p9.FSStat, error) { 68 ctx.UninterruptibleSleepStart(false) 69 fsstat, err := f.file.StatFS() 70 ctx.UninterruptibleSleepFinish(false) 71 return fsstat, err 72 } 73 74 func (f p9file) getAttr(ctx context.Context, req p9.AttrMask) (p9.QID, p9.AttrMask, p9.Attr, error) { 75 ctx.UninterruptibleSleepStart(false) 76 qid, attrMask, attr, err := f.file.GetAttr(req) 77 ctx.UninterruptibleSleepFinish(false) 78 return qid, attrMask, attr, err 79 } 80 81 func (f p9file) setAttr(ctx context.Context, valid p9.SetAttrMask, attr p9.SetAttr) error { 82 ctx.UninterruptibleSleepStart(false) 83 err := f.file.SetAttr(valid, attr) 84 ctx.UninterruptibleSleepFinish(false) 85 return err 86 } 87 88 func (f p9file) listXattr(ctx context.Context, size uint64) (map[string]struct{}, error) { 89 ctx.UninterruptibleSleepStart(false) 90 xattrs, err := f.file.ListXattr(size) 91 ctx.UninterruptibleSleepFinish(false) 92 return xattrs, err 93 } 94 95 func (f p9file) getXattr(ctx context.Context, name string, size uint64) (string, error) { 96 ctx.UninterruptibleSleepStart(false) 97 val, err := f.file.GetXattr(name, size) 98 ctx.UninterruptibleSleepFinish(false) 99 return val, err 100 } 101 102 func (f p9file) setXattr(ctx context.Context, name, value string, flags uint32) error { 103 ctx.UninterruptibleSleepStart(false) 104 err := f.file.SetXattr(name, value, flags) 105 ctx.UninterruptibleSleepFinish(false) 106 return err 107 } 108 109 func (f p9file) removeXattr(ctx context.Context, name string) error { 110 ctx.UninterruptibleSleepStart(false) 111 err := f.file.RemoveXattr(name) 112 ctx.UninterruptibleSleepFinish(false) 113 return err 114 } 115 116 func (f p9file) allocate(ctx context.Context, mode p9.AllocateMode, offset, length uint64) error { 117 ctx.UninterruptibleSleepStart(false) 118 err := f.file.Allocate(mode, offset, length) 119 ctx.UninterruptibleSleepFinish(false) 120 return err 121 } 122 123 func (f p9file) close(ctx context.Context) error { 124 ctx.UninterruptibleSleepStart(false) 125 err := f.file.Close() 126 ctx.UninterruptibleSleepFinish(false) 127 return err 128 } 129 130 func (f p9file) setAttrClose(ctx context.Context, valid p9.SetAttrMask, attr p9.SetAttr) error { 131 ctx.UninterruptibleSleepStart(false) 132 err := f.file.SetAttrClose(valid, attr) 133 ctx.UninterruptibleSleepFinish(false) 134 return err 135 } 136 137 func (f p9file) open(ctx context.Context, flags p9.OpenFlags) (*fd.FD, p9.QID, uint32, error) { 138 ctx.UninterruptibleSleepStart(false) 139 fdobj, qid, iounit, err := f.file.Open(flags) 140 ctx.UninterruptibleSleepFinish(false) 141 return fdobj, qid, iounit, err 142 } 143 144 func (f p9file) readAt(ctx context.Context, p []byte, offset uint64) (int, error) { 145 ctx.UninterruptibleSleepStart(false) 146 n, err := f.file.ReadAt(p, offset) 147 ctx.UninterruptibleSleepFinish(false) 148 return n, err 149 } 150 151 func (f p9file) writeAt(ctx context.Context, p []byte, offset uint64) (int, error) { 152 ctx.UninterruptibleSleepStart(false) 153 n, err := f.file.WriteAt(p, offset) 154 ctx.UninterruptibleSleepFinish(false) 155 return n, err 156 } 157 158 func (f p9file) fsync(ctx context.Context) error { 159 ctx.UninterruptibleSleepStart(false) 160 err := f.file.FSync() 161 ctx.UninterruptibleSleepFinish(false) 162 return err 163 } 164 165 func (f p9file) create(ctx context.Context, name string, flags p9.OpenFlags, permissions p9.FileMode, uid p9.UID, gid p9.GID) (*fd.FD, p9file, p9.QID, uint32, error) { 166 ctx.UninterruptibleSleepStart(false) 167 fdobj, newfile, qid, iounit, err := f.file.Create(name, flags, permissions, uid, gid) 168 ctx.UninterruptibleSleepFinish(false) 169 return fdobj, p9file{newfile}, qid, iounit, err 170 } 171 172 func (f p9file) mkdir(ctx context.Context, name string, permissions p9.FileMode, uid p9.UID, gid p9.GID) (p9.QID, error) { 173 ctx.UninterruptibleSleepStart(false) 174 qid, err := f.file.Mkdir(name, permissions, uid, gid) 175 ctx.UninterruptibleSleepFinish(false) 176 return qid, err 177 } 178 179 func (f p9file) symlink(ctx context.Context, oldName string, newName string, uid p9.UID, gid p9.GID) (p9.QID, error) { 180 ctx.UninterruptibleSleepStart(false) 181 qid, err := f.file.Symlink(oldName, newName, uid, gid) 182 ctx.UninterruptibleSleepFinish(false) 183 return qid, err 184 } 185 186 func (f p9file) link(ctx context.Context, target p9file, newName string) error { 187 ctx.UninterruptibleSleepStart(false) 188 err := f.file.Link(target.file, newName) 189 ctx.UninterruptibleSleepFinish(false) 190 return err 191 } 192 193 func (f p9file) mknod(ctx context.Context, name string, mode p9.FileMode, major uint32, minor uint32, uid p9.UID, gid p9.GID) (p9.QID, error) { 194 ctx.UninterruptibleSleepStart(false) 195 qid, err := f.file.Mknod(name, mode, major, minor, uid, gid) 196 ctx.UninterruptibleSleepFinish(false) 197 return qid, err 198 } 199 200 func (f p9file) rename(ctx context.Context, newDir p9file, newName string) error { 201 ctx.UninterruptibleSleepStart(false) 202 err := f.file.Rename(newDir.file, newName) 203 ctx.UninterruptibleSleepFinish(false) 204 return err 205 } 206 207 func (f p9file) unlinkAt(ctx context.Context, name string, flags uint32) error { 208 ctx.UninterruptibleSleepStart(false) 209 err := f.file.UnlinkAt(name, flags) 210 ctx.UninterruptibleSleepFinish(false) 211 return err 212 } 213 214 func (f p9file) readdir(ctx context.Context, offset uint64, count uint32) ([]p9.Dirent, error) { 215 ctx.UninterruptibleSleepStart(false) 216 dirents, err := f.file.Readdir(offset, count) 217 ctx.UninterruptibleSleepFinish(false) 218 return dirents, err 219 } 220 221 func (f p9file) readlink(ctx context.Context) (string, error) { 222 ctx.UninterruptibleSleepStart(false) 223 target, err := f.file.Readlink() 224 ctx.UninterruptibleSleepFinish(false) 225 return target, err 226 } 227 228 func (f p9file) flush(ctx context.Context) error { 229 ctx.UninterruptibleSleepStart(false) 230 err := f.file.Flush() 231 ctx.UninterruptibleSleepFinish(false) 232 return err 233 } 234 235 func (f p9file) connect(ctx context.Context, flags p9.ConnectFlags) (*fd.FD, error) { 236 ctx.UninterruptibleSleepStart(false) 237 fdobj, err := f.file.Connect(flags) 238 ctx.UninterruptibleSleepFinish(false) 239 return fdobj, err 240 } 241 242 func (f p9file) multiGetAttr(ctx context.Context, names []string) ([]p9.FullStat, error) { 243 ctx.UninterruptibleSleepStart(false) 244 stats, err := f.file.MultiGetAttr(names) 245 ctx.UninterruptibleSleepFinish(false) 246 return stats, err 247 }