github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/fs/gofer/context_file.go (about) 1 // Copyright 2018 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 ) 22 23 // contextFile is a wrapper around p9.File that notifies the context that 24 // it's about to sleep before calling the Gofer over P9. 25 type contextFile struct { 26 file p9.File 27 } 28 29 func (c *contextFile) walk(ctx context.Context, names []string) ([]p9.QID, contextFile, error) { 30 ctx.UninterruptibleSleepStart(false) 31 32 q, f, err := c.file.Walk(names) 33 if err != nil { 34 ctx.UninterruptibleSleepFinish(false) 35 return nil, contextFile{}, err 36 } 37 ctx.UninterruptibleSleepFinish(false) 38 return q, contextFile{file: f}, nil 39 } 40 41 func (c *contextFile) statFS(ctx context.Context) (p9.FSStat, error) { 42 ctx.UninterruptibleSleepStart(false) 43 s, err := c.file.StatFS() 44 ctx.UninterruptibleSleepFinish(false) 45 return s, err 46 } 47 48 func (c *contextFile) getAttr(ctx context.Context, req p9.AttrMask) (p9.QID, p9.AttrMask, p9.Attr, error) { 49 ctx.UninterruptibleSleepStart(false) 50 q, m, a, err := c.file.GetAttr(req) 51 ctx.UninterruptibleSleepFinish(false) 52 return q, m, a, err 53 } 54 55 func (c *contextFile) setAttr(ctx context.Context, valid p9.SetAttrMask, attr p9.SetAttr) error { 56 ctx.UninterruptibleSleepStart(false) 57 err := c.file.SetAttr(valid, attr) 58 ctx.UninterruptibleSleepFinish(false) 59 return err 60 } 61 62 func (c *contextFile) getXattr(ctx context.Context, name string, size uint64) (string, error) { 63 ctx.UninterruptibleSleepStart(false) 64 val, err := c.file.GetXattr(name, size) 65 ctx.UninterruptibleSleepFinish(false) 66 return val, err 67 } 68 69 func (c *contextFile) setXattr(ctx context.Context, name, value string, flags uint32) error { 70 ctx.UninterruptibleSleepStart(false) 71 err := c.file.SetXattr(name, value, flags) 72 ctx.UninterruptibleSleepFinish(false) 73 return err 74 } 75 76 func (c *contextFile) listXattr(ctx context.Context, size uint64) (map[string]struct{}, error) { 77 ctx.UninterruptibleSleepStart(false) 78 xattrs, err := c.file.ListXattr(size) 79 ctx.UninterruptibleSleepFinish(false) 80 return xattrs, err 81 } 82 83 func (c *contextFile) removeXattr(ctx context.Context, name string) error { 84 ctx.UninterruptibleSleepStart(false) 85 err := c.file.RemoveXattr(name) 86 ctx.UninterruptibleSleepFinish(false) 87 return err 88 } 89 90 func (c *contextFile) allocate(ctx context.Context, mode p9.AllocateMode, offset, length uint64) error { 91 ctx.UninterruptibleSleepStart(false) 92 err := c.file.Allocate(mode, offset, length) 93 ctx.UninterruptibleSleepFinish(false) 94 return err 95 } 96 97 func (c *contextFile) rename(ctx context.Context, directory contextFile, name string) error { 98 ctx.UninterruptibleSleepStart(false) 99 err := c.file.Rename(directory.file, name) 100 ctx.UninterruptibleSleepFinish(false) 101 return err 102 } 103 104 func (c *contextFile) close(ctx context.Context) error { 105 ctx.UninterruptibleSleepStart(false) 106 err := c.file.Close() 107 ctx.UninterruptibleSleepFinish(false) 108 return err 109 } 110 111 func (c *contextFile) open(ctx context.Context, mode p9.OpenFlags) (*fd.FD, p9.QID, uint32, error) { 112 ctx.UninterruptibleSleepStart(false) 113 f, q, u, err := c.file.Open(mode) 114 ctx.UninterruptibleSleepFinish(false) 115 return f, q, u, err 116 } 117 118 func (c *contextFile) readAt(ctx context.Context, p []byte, offset uint64) (int, error) { 119 ctx.UninterruptibleSleepStart(false) 120 n, err := c.file.ReadAt(p, offset) 121 ctx.UninterruptibleSleepFinish(false) 122 return n, err 123 } 124 125 func (c *contextFile) writeAt(ctx context.Context, p []byte, offset uint64) (int, error) { 126 ctx.UninterruptibleSleepStart(false) 127 n, err := c.file.WriteAt(p, offset) 128 ctx.UninterruptibleSleepFinish(false) 129 return n, err 130 } 131 132 func (c *contextFile) fsync(ctx context.Context) error { 133 ctx.UninterruptibleSleepStart(false) 134 err := c.file.FSync() 135 ctx.UninterruptibleSleepFinish(false) 136 return err 137 } 138 139 func (c *contextFile) create(ctx context.Context, name string, flags p9.OpenFlags, permissions p9.FileMode, uid p9.UID, gid p9.GID) (*fd.FD, error) { 140 ctx.UninterruptibleSleepStart(false) 141 fd, _, _, _, err := c.file.Create(name, flags, permissions, uid, gid) 142 ctx.UninterruptibleSleepFinish(false) 143 return fd, err 144 } 145 146 func (c *contextFile) mkdir(ctx context.Context, name string, permissions p9.FileMode, uid p9.UID, gid p9.GID) (p9.QID, error) { 147 ctx.UninterruptibleSleepStart(false) 148 q, err := c.file.Mkdir(name, permissions, uid, gid) 149 ctx.UninterruptibleSleepFinish(false) 150 return q, err 151 } 152 153 func (c *contextFile) symlink(ctx context.Context, oldName string, newName string, uid p9.UID, gid p9.GID) (p9.QID, error) { 154 ctx.UninterruptibleSleepStart(false) 155 q, err := c.file.Symlink(oldName, newName, uid, gid) 156 ctx.UninterruptibleSleepFinish(false) 157 return q, err 158 } 159 160 func (c *contextFile) link(ctx context.Context, target *contextFile, newName string) error { 161 ctx.UninterruptibleSleepStart(false) 162 err := c.file.Link(target.file, newName) 163 ctx.UninterruptibleSleepFinish(false) 164 return err 165 } 166 167 func (c *contextFile) mknod(ctx context.Context, name string, permissions p9.FileMode, major uint32, minor uint32, uid p9.UID, gid p9.GID) (p9.QID, error) { 168 ctx.UninterruptibleSleepStart(false) 169 q, err := c.file.Mknod(name, permissions, major, minor, uid, gid) 170 ctx.UninterruptibleSleepFinish(false) 171 return q, err 172 } 173 174 func (c *contextFile) unlinkAt(ctx context.Context, name string, flags uint32) error { 175 ctx.UninterruptibleSleepStart(false) 176 err := c.file.UnlinkAt(name, flags) 177 ctx.UninterruptibleSleepFinish(false) 178 return err 179 } 180 181 func (c *contextFile) readdir(ctx context.Context, offset uint64, count uint32) ([]p9.Dirent, error) { 182 ctx.UninterruptibleSleepStart(false) 183 d, err := c.file.Readdir(offset, count) 184 ctx.UninterruptibleSleepFinish(false) 185 return d, err 186 } 187 188 func (c *contextFile) readlink(ctx context.Context) (string, error) { 189 ctx.UninterruptibleSleepStart(false) 190 s, err := c.file.Readlink() 191 ctx.UninterruptibleSleepFinish(false) 192 return s, err 193 } 194 195 func (c *contextFile) flush(ctx context.Context) error { 196 ctx.UninterruptibleSleepStart(false) 197 err := c.file.Flush() 198 ctx.UninterruptibleSleepFinish(false) 199 return err 200 } 201 202 func (c *contextFile) walkGetAttr(ctx context.Context, names []string) ([]p9.QID, contextFile, p9.AttrMask, p9.Attr, error) { 203 ctx.UninterruptibleSleepStart(false) 204 q, f, m, a, err := c.file.WalkGetAttr(names) 205 if err != nil { 206 ctx.UninterruptibleSleepFinish(false) 207 return nil, contextFile{}, p9.AttrMask{}, p9.Attr{}, err 208 } 209 ctx.UninterruptibleSleepFinish(false) 210 return q, contextFile{file: f}, m, a, nil 211 } 212 213 func (c *contextFile) connect(ctx context.Context, flags p9.ConnectFlags) (*fd.FD, error) { 214 ctx.UninterruptibleSleepStart(false) 215 f, err := c.file.Connect(flags) 216 ctx.UninterruptibleSleepFinish(false) 217 return f, err 218 }