github.com/scaleoutsean/fusego@v0.0.0-20220224074057-4a6429e46bb8/internal/fusekernel/fuse_kernel.go (about)

     1  // See the file LICENSE for copyright and licensing information.
     2  
     3  // Derived from FUSE's fuse_kernel.h, which carries this notice:
     4  /*
     5     This file defines the kernel interface of FUSE
     6     Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
     7  
     8  
     9     This -- and only this -- header file may also be distributed under
    10     the terms of the BSD Licence as follows:
    11  
    12     Copyright (C) 2001-2007 Miklos Szeredi. All rights reserved.
    13  
    14     Redistribution and use in source and binary forms, with or without
    15     modification, are permitted provided that the following conditions
    16     are met:
    17     1. Redistributions of source code must retain the above copyright
    18        notice, this list of conditions and the following disclaimer.
    19     2. Redistributions in binary form must reproduce the above copyright
    20        notice, this list of conditions and the following disclaimer in the
    21        documentation and/or other materials provided with the distribution.
    22  
    23     THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
    24     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    25     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    26     ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
    27     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    28     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    29     OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    30     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    31     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    32     OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    33     SUCH DAMAGE.
    34  */
    35  
    36  package fusekernel
    37  
    38  import (
    39  	"fmt"
    40  	"syscall"
    41  	"unsafe"
    42  )
    43  
    44  // The FUSE version implemented by the package.
    45  const (
    46  	ProtoVersionMinMajor = 7
    47  	ProtoVersionMinMinor = 19
    48  	ProtoVersionMaxMajor = 7
    49  	ProtoVersionMaxMinor = 31
    50  )
    51  
    52  const (
    53  	RootID = 1
    54  )
    55  
    56  type Kstatfs struct {
    57  	Blocks  uint64
    58  	Bfree   uint64
    59  	Bavail  uint64
    60  	Files   uint64
    61  	Ffree   uint64
    62  	Bsize   uint32
    63  	Namelen uint32
    64  	Frsize  uint32
    65  	Padding uint32
    66  	Spare   [6]uint32
    67  }
    68  
    69  type fileLock struct {
    70  	Start uint64
    71  	End   uint64
    72  	Type  uint32
    73  	Pid   uint32
    74  }
    75  
    76  // GetattrFlags are bit flags that can be seen in GetattrRequest.
    77  type GetattrFlags uint32
    78  
    79  const (
    80  	// Indicates the handle is valid.
    81  	GetattrFh GetattrFlags = 1 << 0
    82  )
    83  
    84  var getattrFlagsNames = []flagName{
    85  	{uint32(GetattrFh), "GetattrFh"},
    86  }
    87  
    88  func (fl GetattrFlags) String() string {
    89  	return flagString(uint32(fl), getattrFlagsNames)
    90  }
    91  
    92  // The SetattrValid are bit flags describing which fields in the SetattrRequest
    93  // are included in the change.
    94  type SetattrValid uint32
    95  
    96  const (
    97  	SetattrMode   SetattrValid = 1 << 0
    98  	SetattrUid    SetattrValid = 1 << 1
    99  	SetattrGid    SetattrValid = 1 << 2
   100  	SetattrSize   SetattrValid = 1 << 3
   101  	SetattrAtime  SetattrValid = 1 << 4
   102  	SetattrMtime  SetattrValid = 1 << 5
   103  	SetattrHandle SetattrValid = 1 << 6
   104  
   105  	// Linux only(?)
   106  	SetattrAtimeNow  SetattrValid = 1 << 7
   107  	SetattrMtimeNow  SetattrValid = 1 << 8
   108  	SetattrLockOwner SetattrValid = 1 << 9 // http://www.mail-archive.com/git-commits-head@vger.kernel.org/msg27852.html
   109  
   110  	// OS X only
   111  	SetattrCrtime   SetattrValid = 1 << 28
   112  	SetattrChgtime  SetattrValid = 1 << 29
   113  	SetattrBkuptime SetattrValid = 1 << 30
   114  	SetattrFlags    SetattrValid = 1 << 31
   115  )
   116  
   117  func (fl SetattrValid) Mode() bool      { return fl&SetattrMode != 0 }
   118  func (fl SetattrValid) Uid() bool       { return fl&SetattrUid != 0 }
   119  func (fl SetattrValid) Gid() bool       { return fl&SetattrGid != 0 }
   120  func (fl SetattrValid) Size() bool      { return fl&SetattrSize != 0 }
   121  func (fl SetattrValid) Atime() bool     { return fl&SetattrAtime != 0 }
   122  func (fl SetattrValid) Mtime() bool     { return fl&SetattrMtime != 0 }
   123  func (fl SetattrValid) Handle() bool    { return fl&SetattrHandle != 0 }
   124  func (fl SetattrValid) AtimeNow() bool  { return fl&SetattrAtimeNow != 0 }
   125  func (fl SetattrValid) MtimeNow() bool  { return fl&SetattrMtimeNow != 0 }
   126  func (fl SetattrValid) LockOwner() bool { return fl&SetattrLockOwner != 0 }
   127  func (fl SetattrValid) Crtime() bool    { return fl&SetattrCrtime != 0 }
   128  func (fl SetattrValid) Chgtime() bool   { return fl&SetattrChgtime != 0 }
   129  func (fl SetattrValid) Bkuptime() bool  { return fl&SetattrBkuptime != 0 }
   130  func (fl SetattrValid) Flags() bool     { return fl&SetattrFlags != 0 }
   131  
   132  func (fl SetattrValid) String() string {
   133  	return flagString(uint32(fl), setattrValidNames)
   134  }
   135  
   136  var setattrValidNames = []flagName{
   137  	{uint32(SetattrMode), "SetattrMode"},
   138  	{uint32(SetattrUid), "SetattrUid"},
   139  	{uint32(SetattrGid), "SetattrGid"},
   140  	{uint32(SetattrSize), "SetattrSize"},
   141  	{uint32(SetattrAtime), "SetattrAtime"},
   142  	{uint32(SetattrMtime), "SetattrMtime"},
   143  	{uint32(SetattrHandle), "SetattrHandle"},
   144  	{uint32(SetattrAtimeNow), "SetattrAtimeNow"},
   145  	{uint32(SetattrMtimeNow), "SetattrMtimeNow"},
   146  	{uint32(SetattrLockOwner), "SetattrLockOwner"},
   147  	{uint32(SetattrCrtime), "SetattrCrtime"},
   148  	{uint32(SetattrChgtime), "SetattrChgtime"},
   149  	{uint32(SetattrBkuptime), "SetattrBkuptime"},
   150  	{uint32(SetattrFlags), "SetattrFlags"},
   151  }
   152  
   153  // Flags that can be seen in OpenRequest.Flags.
   154  const (
   155  	// Access modes. These are not 1-bit flags, but alternatives where
   156  	// only one can be chosen. See the IsReadOnly etc convenience
   157  	// methods.
   158  	OpenReadOnly  OpenFlags = syscall.O_RDONLY
   159  	OpenWriteOnly OpenFlags = syscall.O_WRONLY
   160  	OpenReadWrite OpenFlags = syscall.O_RDWR
   161  
   162  	OpenAppend    OpenFlags = syscall.O_APPEND
   163  	OpenCreate    OpenFlags = syscall.O_CREAT
   164  	OpenExclusive OpenFlags = syscall.O_EXCL
   165  	OpenSync      OpenFlags = syscall.O_SYNC
   166  	OpenTruncate  OpenFlags = syscall.O_TRUNC
   167  )
   168  
   169  // OpenAccessModeMask is a bitmask that separates the access mode
   170  // from the other flags in OpenFlags.
   171  const OpenAccessModeMask OpenFlags = syscall.O_ACCMODE
   172  
   173  // OpenFlags are the O_FOO flags passed to open/create/etc calls. For
   174  // example, os.O_WRONLY | os.O_APPEND.
   175  type OpenFlags uint32
   176  
   177  func (fl OpenFlags) String() string {
   178  	// O_RDONLY, O_RWONLY, O_RDWR are not flags
   179  	s := accModeName(fl & OpenAccessModeMask)
   180  	flags := uint32(fl &^ OpenAccessModeMask)
   181  	if flags != 0 {
   182  		s = s + "+" + flagString(flags, openFlagNames)
   183  	}
   184  	return s
   185  }
   186  
   187  // Return true if OpenReadOnly is set.
   188  func (fl OpenFlags) IsReadOnly() bool {
   189  	return fl&OpenAccessModeMask == OpenReadOnly
   190  }
   191  
   192  // Return true if OpenWriteOnly is set.
   193  func (fl OpenFlags) IsWriteOnly() bool {
   194  	return fl&OpenAccessModeMask == OpenWriteOnly
   195  }
   196  
   197  // Return true if OpenReadWrite is set.
   198  func (fl OpenFlags) IsReadWrite() bool {
   199  	return fl&OpenAccessModeMask == OpenReadWrite
   200  }
   201  
   202  func accModeName(flags OpenFlags) string {
   203  	switch flags {
   204  	case OpenReadOnly:
   205  		return "OpenReadOnly"
   206  	case OpenWriteOnly:
   207  		return "OpenWriteOnly"
   208  	case OpenReadWrite:
   209  		return "OpenReadWrite"
   210  	default:
   211  		return ""
   212  	}
   213  }
   214  
   215  var openFlagNames = []flagName{
   216  	{uint32(OpenCreate), "OpenCreate"},
   217  	{uint32(OpenExclusive), "OpenExclusive"},
   218  	{uint32(OpenTruncate), "OpenTruncate"},
   219  	{uint32(OpenAppend), "OpenAppend"},
   220  	{uint32(OpenSync), "OpenSync"},
   221  }
   222  
   223  // The OpenResponseFlags are returned in the OpenResponse.
   224  type OpenResponseFlags uint32
   225  
   226  const (
   227  	OpenDirectIO    OpenResponseFlags = 1 << 0 // bypass page cache for this open file
   228  	OpenKeepCache   OpenResponseFlags = 1 << 1 // don't invalidate the data cache on open
   229  	OpenNonSeekable OpenResponseFlags = 1 << 2 // mark the file as non-seekable (not supported on OS X)
   230  
   231  	OpenPurgeAttr OpenResponseFlags = 1 << 30 // OS X
   232  	OpenPurgeUBC  OpenResponseFlags = 1 << 31 // OS X
   233  )
   234  
   235  func (fl OpenResponseFlags) String() string {
   236  	return flagString(uint32(fl), openResponseFlagNames)
   237  }
   238  
   239  var openResponseFlagNames = []flagName{
   240  	{uint32(OpenDirectIO), "OpenDirectIO"},
   241  	{uint32(OpenKeepCache), "OpenKeepCache"},
   242  	{uint32(OpenNonSeekable), "OpenNonSeekable"},
   243  	{uint32(OpenPurgeAttr), "OpenPurgeAttr"},
   244  	{uint32(OpenPurgeUBC), "OpenPurgeUBC"},
   245  }
   246  
   247  // The InitFlags are used in the Init exchange.
   248  type InitFlags uint32
   249  
   250  const (
   251  	InitAsyncRead        InitFlags = 1 << 0
   252  	InitPosixLocks       InitFlags = 1 << 1
   253  	InitFileOps          InitFlags = 1 << 2
   254  	InitAtomicTrunc      InitFlags = 1 << 3
   255  	InitExportSupport    InitFlags = 1 << 4
   256  	InitBigWrites        InitFlags = 1 << 5
   257  	InitDontMask         InitFlags = 1 << 6
   258  	InitSpliceWrite      InitFlags = 1 << 7
   259  	InitSpliceMove       InitFlags = 1 << 8
   260  	InitSpliceRead       InitFlags = 1 << 9
   261  	InitFlockLocks       InitFlags = 1 << 10
   262  	InitHasIoctlDir      InitFlags = 1 << 11
   263  	InitAutoInvalData    InitFlags = 1 << 12
   264  	InitDoReaddirplus    InitFlags = 1 << 13
   265  	InitReaddirplusAuto  InitFlags = 1 << 14
   266  	InitAsyncDIO         InitFlags = 1 << 15
   267  	InitWritebackCache   InitFlags = 1 << 16
   268  	InitNoOpenSupport    InitFlags = 1 << 17
   269  	InitMaxPages         InitFlags = 1 << 22
   270  	InitCacheSymlinks    InitFlags = 1 << 23
   271  	InitNoOpendirSupport InitFlags = 1 << 24
   272  
   273  	InitCaseSensitive InitFlags = 1 << 29 // OS X only
   274  	InitVolRename     InitFlags = 1 << 30 // OS X only
   275  	InitXtimes        InitFlags = 1 << 31 // OS X only
   276  )
   277  
   278  type flagName struct {
   279  	bit  uint32
   280  	name string
   281  }
   282  
   283  var initFlagNames = []flagName{
   284  	{uint32(InitAsyncRead), "InitAsyncRead"},
   285  	{uint32(InitPosixLocks), "InitPosixLocks"},
   286  	{uint32(InitFileOps), "InitFileOps"},
   287  	{uint32(InitAtomicTrunc), "InitAtomicTrunc"},
   288  	{uint32(InitExportSupport), "InitExportSupport"},
   289  	{uint32(InitBigWrites), "InitBigWrites"},
   290  	{uint32(InitMaxPages), "InitMaxPages"},
   291  	{uint32(InitDontMask), "InitDontMask"},
   292  	{uint32(InitSpliceWrite), "InitSpliceWrite"},
   293  	{uint32(InitSpliceMove), "InitSpliceMove"},
   294  	{uint32(InitSpliceRead), "InitSpliceRead"},
   295  	{uint32(InitFlockLocks), "InitFlockLocks"},
   296  	{uint32(InitHasIoctlDir), "InitHasIoctlDir"},
   297  	{uint32(InitAutoInvalData), "InitAutoInvalData"},
   298  	{uint32(InitDoReaddirplus), "InitDoReaddirplus"},
   299  	{uint32(InitReaddirplusAuto), "InitReaddirplusAuto"},
   300  	{uint32(InitAsyncDIO), "InitAsyncDIO"},
   301  	{uint32(InitWritebackCache), "InitWritebackCache"},
   302  	{uint32(InitNoOpenSupport), "InitNoOpenSupport"},
   303  	{uint32(InitCacheSymlinks), "InitCacheSymlinks"},
   304  	{uint32(InitNoOpendirSupport), "InitNoOpendirSupport"},
   305  
   306  	{uint32(InitCaseSensitive), "InitCaseSensitive"},
   307  	{uint32(InitVolRename), "InitVolRename"},
   308  	{uint32(InitXtimes), "InitXtimes"},
   309  }
   310  
   311  func (fl InitFlags) String() string {
   312  	return flagString(uint32(fl), initFlagNames)
   313  }
   314  
   315  func flagString(f uint32, names []flagName) string {
   316  	var s string
   317  
   318  	if f == 0 {
   319  		return "0"
   320  	}
   321  
   322  	for _, n := range names {
   323  		if f&n.bit != 0 {
   324  			s += "+" + n.name
   325  			f &^= n.bit
   326  		}
   327  	}
   328  	if f != 0 {
   329  		s += fmt.Sprintf("%+#x", f)
   330  	}
   331  	return s[1:]
   332  }
   333  
   334  // The ReleaseFlags are used in the Release exchange.
   335  type ReleaseFlags uint32
   336  
   337  const (
   338  	ReleaseFlush ReleaseFlags = 1 << 0
   339  )
   340  
   341  func (fl ReleaseFlags) String() string {
   342  	return flagString(uint32(fl), releaseFlagNames)
   343  }
   344  
   345  var releaseFlagNames = []flagName{
   346  	{uint32(ReleaseFlush), "ReleaseFlush"},
   347  }
   348  
   349  // Opcodes
   350  const (
   351  	OpLookup      = 1
   352  	OpForget      = 2 // no reply
   353  	OpGetattr     = 3
   354  	OpSetattr     = 4
   355  	OpReadlink    = 5
   356  	OpSymlink     = 6
   357  	OpMknod       = 8
   358  	OpMkdir       = 9
   359  	OpUnlink      = 10
   360  	OpRmdir       = 11
   361  	OpRename      = 12
   362  	OpLink        = 13
   363  	OpOpen        = 14
   364  	OpRead        = 15
   365  	OpWrite       = 16
   366  	OpStatfs      = 17
   367  	OpRelease     = 18
   368  	OpFsync       = 20
   369  	OpSetxattr    = 21
   370  	OpGetxattr    = 22
   371  	OpListxattr   = 23
   372  	OpRemovexattr = 24
   373  	OpFlush       = 25
   374  	OpInit        = 26
   375  	OpOpendir     = 27
   376  	OpReaddir     = 28
   377  	OpReleasedir  = 29
   378  	OpFsyncdir    = 30
   379  	OpGetlk       = 31
   380  	OpSetlk       = 32
   381  	OpSetlkw      = 33
   382  	OpAccess      = 34
   383  	OpCreate      = 35
   384  	OpInterrupt   = 36
   385  	OpBmap        = 37
   386  	OpDestroy     = 38
   387  	OpIoctl       = 39 // Linux?
   388  	OpPoll        = 40 // Linux?
   389  	OpFallocate   = 43
   390  
   391  	// OS X
   392  	OpSetvolname = 61
   393  	OpGetxtimes  = 62
   394  	OpExchange   = 63
   395  )
   396  
   397  type EntryOut struct {
   398  	Nodeid         uint64 // Inode ID
   399  	Generation     uint64 // Inode generation
   400  	EntryValid     uint64 // Cache timeout for the name
   401  	AttrValid      uint64 // Cache timeout for the attributes
   402  	EntryValidNsec uint32
   403  	AttrValidNsec  uint32
   404  	Attr           Attr
   405  }
   406  
   407  func EntryOutSize(p Protocol) uintptr {
   408  	switch {
   409  	case p.LT(Protocol{7, 9}):
   410  		return unsafe.Offsetof(EntryOut{}.Attr) + unsafe.Offsetof(EntryOut{}.Attr.Blksize)
   411  	default:
   412  		return unsafe.Sizeof(EntryOut{})
   413  	}
   414  }
   415  
   416  type ForgetIn struct {
   417  	Nlookup uint64
   418  }
   419  
   420  type GetattrIn struct {
   421  	GetattrFlags uint32
   422  	dummy        uint32
   423  	Fh           uint64
   424  }
   425  
   426  type AttrOut struct {
   427  	AttrValid     uint64 // Cache timeout for the attributes
   428  	AttrValidNsec uint32
   429  	Dummy         uint32
   430  	Attr          Attr
   431  }
   432  
   433  func AttrOutSize(p Protocol) uintptr {
   434  	switch {
   435  	case p.LT(Protocol{7, 9}):
   436  		return unsafe.Offsetof(AttrOut{}.Attr) + unsafe.Offsetof(AttrOut{}.Attr.Blksize)
   437  	default:
   438  		return unsafe.Sizeof(AttrOut{})
   439  	}
   440  }
   441  
   442  // OS X
   443  type GetxtimesOut struct {
   444  	Bkuptime     uint64
   445  	Crtime       uint64
   446  	BkuptimeNsec uint32
   447  	CrtimeNsec   uint32
   448  }
   449  
   450  type MknodIn struct {
   451  	Mode    uint32
   452  	Rdev    uint32
   453  	Umask   uint32
   454  	padding uint32
   455  	// "filename\x00" follows.
   456  }
   457  
   458  func MknodInSize(p Protocol) uintptr {
   459  	switch {
   460  	case p.LT(Protocol{7, 12}):
   461  		return unsafe.Offsetof(MknodIn{}.Umask)
   462  	default:
   463  		return unsafe.Sizeof(MknodIn{})
   464  	}
   465  }
   466  
   467  type MkdirIn struct {
   468  	Mode  uint32
   469  	Umask uint32
   470  	// filename follows
   471  }
   472  
   473  func MkdirInSize(p Protocol) uintptr {
   474  	switch {
   475  	case p.LT(Protocol{7, 12}):
   476  		return unsafe.Offsetof(MkdirIn{}.Umask) + 4
   477  	default:
   478  		return unsafe.Sizeof(MkdirIn{})
   479  	}
   480  }
   481  
   482  type RenameIn struct {
   483  	Newdir uint64
   484  	// "oldname\x00newname\x00" follows
   485  }
   486  
   487  // OS X
   488  type ExchangeIn struct {
   489  	Olddir  uint64
   490  	Newdir  uint64
   491  	Options uint64
   492  }
   493  
   494  type LinkIn struct {
   495  	Oldnodeid uint64
   496  }
   497  
   498  type setattrInCommon struct {
   499  	Valid     uint32
   500  	Padding   uint32
   501  	Fh        uint64
   502  	Size      uint64
   503  	LockOwner uint64 // unused on OS X?
   504  	Atime     uint64
   505  	Mtime     uint64
   506  	Unused2   uint64
   507  	AtimeNsec uint32
   508  	MtimeNsec uint32
   509  	Unused3   uint32
   510  	Mode      uint32
   511  	Unused4   uint32
   512  	Uid       uint32
   513  	Gid       uint32
   514  	Unused5   uint32
   515  }
   516  
   517  type OpenIn struct {
   518  	Flags  uint32
   519  	Unused uint32
   520  }
   521  
   522  type OpenOut struct {
   523  	Fh        uint64
   524  	OpenFlags uint32
   525  	Padding   uint32
   526  }
   527  
   528  type CreateIn struct {
   529  	Flags   uint32
   530  	Mode    uint32
   531  	Umask   uint32
   532  	padding uint32
   533  }
   534  
   535  func CreateInSize(p Protocol) uintptr {
   536  	switch {
   537  	case p.LT(Protocol{7, 12}):
   538  		return unsafe.Offsetof(CreateIn{}.Umask)
   539  	default:
   540  		return unsafe.Sizeof(CreateIn{})
   541  	}
   542  }
   543  
   544  type ReleaseIn struct {
   545  	Fh           uint64
   546  	Flags        uint32
   547  	ReleaseFlags uint32
   548  	LockOwner    uint32
   549  }
   550  
   551  type FlushIn struct {
   552  	Fh         uint64
   553  	FlushFlags uint32
   554  	Padding    uint32
   555  	LockOwner  uint64
   556  }
   557  
   558  type ReadIn struct {
   559  	Fh        uint64
   560  	Offset    uint64
   561  	Size      uint32
   562  	ReadFlags uint32
   563  	LockOwner uint64
   564  	Flags     uint32
   565  	padding   uint32
   566  }
   567  
   568  func ReadInSize(p Protocol) uintptr {
   569  	switch {
   570  	case p.LT(Protocol{7, 9}):
   571  		return unsafe.Offsetof(ReadIn{}.ReadFlags) + 4
   572  	default:
   573  		return unsafe.Sizeof(ReadIn{})
   574  	}
   575  }
   576  
   577  // The ReadFlags are passed in ReadRequest.
   578  type ReadFlags uint32
   579  
   580  const (
   581  	// LockOwner field is valid.
   582  	ReadLockOwner ReadFlags = 1 << 1
   583  )
   584  
   585  var readFlagNames = []flagName{
   586  	{uint32(ReadLockOwner), "ReadLockOwner"},
   587  }
   588  
   589  func (fl ReadFlags) String() string {
   590  	return flagString(uint32(fl), readFlagNames)
   591  }
   592  
   593  type WriteIn struct {
   594  	Fh         uint64
   595  	Offset     uint64
   596  	Size       uint32
   597  	WriteFlags uint32
   598  	LockOwner  uint64
   599  	Flags      uint32
   600  	padding    uint32
   601  }
   602  
   603  func WriteInSize(p Protocol) uintptr {
   604  	switch {
   605  	case p.LT(Protocol{7, 9}):
   606  		return unsafe.Offsetof(WriteIn{}.LockOwner)
   607  	default:
   608  		return unsafe.Sizeof(WriteIn{})
   609  	}
   610  }
   611  
   612  type WriteOut struct {
   613  	Size    uint32
   614  	Padding uint32
   615  }
   616  
   617  // The WriteFlags are passed in WriteRequest.
   618  type WriteFlags uint32
   619  
   620  const (
   621  	WriteCache WriteFlags = 1 << 0
   622  	// LockOwner field is valid.
   623  	WriteLockOwner WriteFlags = 1 << 1
   624  )
   625  
   626  var writeFlagNames = []flagName{
   627  	{uint32(WriteCache), "WriteCache"},
   628  	{uint32(WriteLockOwner), "WriteLockOwner"},
   629  }
   630  
   631  func (fl WriteFlags) String() string {
   632  	return flagString(uint32(fl), writeFlagNames)
   633  }
   634  
   635  const compatStatfsSize = 48
   636  
   637  type StatfsOut struct {
   638  	St Kstatfs
   639  }
   640  
   641  type FsyncIn struct {
   642  	Fh         uint64
   643  	FsyncFlags uint32
   644  	Padding    uint32
   645  }
   646  
   647  type setxattrInCommon struct {
   648  	Size  uint32
   649  	Flags uint32
   650  }
   651  
   652  func (setxattrInCommon) GetPosition() uint32 {
   653  	return 0
   654  }
   655  
   656  type getxattrInCommon struct {
   657  	Size    uint32
   658  	Padding uint32
   659  }
   660  
   661  func (getxattrInCommon) GetPosition() uint32 {
   662  	return 0
   663  }
   664  
   665  type GetxattrOut struct {
   666  	Size    uint32
   667  	Padding uint32
   668  }
   669  
   670  type ListxattrIn struct {
   671  	Size    uint32
   672  	Padding uint32
   673  }
   674  
   675  type FallocateIn struct {
   676  	Fh      uint64
   677  	Offset  uint64
   678  	Length  uint64
   679  	Mode    uint32
   680  	Padding uint32
   681  }
   682  
   683  type LkIn struct {
   684  	Fh      uint64
   685  	Owner   uint64
   686  	Lk      fileLock
   687  	LkFlags uint32
   688  	padding uint32
   689  }
   690  
   691  func LkInSize(p Protocol) uintptr {
   692  	switch {
   693  	case p.LT(Protocol{7, 9}):
   694  		return unsafe.Offsetof(LkIn{}.LkFlags)
   695  	default:
   696  		return unsafe.Sizeof(LkIn{})
   697  	}
   698  }
   699  
   700  type LkOut struct {
   701  	Lk fileLock
   702  }
   703  
   704  type AccessIn struct {
   705  	Mask    uint32
   706  	Padding uint32
   707  }
   708  
   709  type InitIn struct {
   710  	Major        uint32
   711  	Minor        uint32
   712  	MaxReadahead uint32
   713  	Flags        uint32
   714  }
   715  
   716  const InitInSize = int(unsafe.Sizeof(InitIn{}))
   717  
   718  type InitOut struct {
   719  	Major               uint32
   720  	Minor               uint32
   721  	MaxReadahead        uint32
   722  	Flags               uint32
   723  	MaxBackground       uint16
   724  	CongestionThreshold uint16
   725  	MaxWrite            uint32
   726  	TimeGran            uint32
   727  	MaxPages            uint16
   728  	MapAlignment        uint16
   729  	Unused              [8]uint32
   730  }
   731  
   732  type InterruptIn struct {
   733  	Unique uint64
   734  }
   735  
   736  type BmapIn struct {
   737  	Block     uint64
   738  	BlockSize uint32
   739  	Padding   uint32
   740  }
   741  
   742  type BmapOut struct {
   743  	Block uint64
   744  }
   745  
   746  type InHeader struct {
   747  	Len     uint32
   748  	Opcode  uint32
   749  	Unique  uint64
   750  	Nodeid  uint64
   751  	Uid     uint32
   752  	Gid     uint32
   753  	Pid     uint32
   754  	Padding uint32
   755  }
   756  
   757  const InHeaderSize = int(unsafe.Sizeof(InHeader{}))
   758  
   759  type OutHeader struct {
   760  	Len    uint32
   761  	Error  int32
   762  	Unique uint64
   763  }
   764  
   765  type Dirent struct {
   766  	Ino     uint64
   767  	Off     uint64
   768  	Namelen uint32
   769  	Type    uint32
   770  	Name    [0]byte
   771  }
   772  
   773  const DirentSize = 8 + 8 + 4 + 4
   774  
   775  const (
   776  	NotifyCodePoll       int32 = 1
   777  	NotifyCodeInvalInode int32 = 2
   778  	NotifyCodeInvalEntry int32 = 3
   779  )
   780  
   781  type NotifyInvalInodeOut struct {
   782  	Ino uint64
   783  	Off int64
   784  	Len int64
   785  }
   786  
   787  type NotifyInvalEntryOut struct {
   788  	Parent  uint64
   789  	Namelen uint32
   790  	padding uint32
   791  }