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  }