Finished filling out the fuseops package, for #3.
commit
d44e63937d
|
@ -0,0 +1,264 @@
|
|||
// Copyright 2015 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package fuseops contains implementations of the fuse.Op interface that may
|
||||
// be returned by fuse.Connection.ReadOp. See documentation in that package for
|
||||
// more.
|
||||
package fuseops
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/jacobsa/bazilfuse"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// Convert the supplied bazilfuse request struct to an Op, returning nil if it
|
||||
// is unknown.
|
||||
//
|
||||
// This function is an implementation detail of the fuse package, and must not
|
||||
// be called by anyone else.
|
||||
func Convert(r bazilfuse.Request) (o Op) {
|
||||
var co *commonOp
|
||||
|
||||
switch typed := r.(type) {
|
||||
case *bazilfuse.InitRequest:
|
||||
to := &InitOp{}
|
||||
o = to
|
||||
co = &to.commonOp
|
||||
|
||||
case *bazilfuse.LookupRequest:
|
||||
to := &LookUpInodeOp{
|
||||
Parent: InodeID(typed.Header.Node),
|
||||
Name: typed.Name,
|
||||
}
|
||||
o = to
|
||||
co = &to.commonOp
|
||||
|
||||
case *bazilfuse.GetattrRequest:
|
||||
to := &GetInodeAttributesOp{
|
||||
Inode: InodeID(typed.Header.Node),
|
||||
}
|
||||
o = to
|
||||
co = &to.commonOp
|
||||
|
||||
case *bazilfuse.SetattrRequest:
|
||||
to := &SetInodeAttributesOp{
|
||||
Inode: InodeID(typed.Header.Node),
|
||||
}
|
||||
o = to
|
||||
co = &to.commonOp
|
||||
|
||||
case *bazilfuse.MkdirRequest:
|
||||
to := &MkDirOp{
|
||||
Parent: InodeID(typed.Header.Node),
|
||||
Name: typed.Name,
|
||||
Mode: typed.Mode,
|
||||
}
|
||||
o = to
|
||||
co = &to.commonOp
|
||||
|
||||
case *bazilfuse.CreateRequest:
|
||||
to := &CreateFileOp{
|
||||
Parent: InodeID(typed.Header.Node),
|
||||
Name: typed.Name,
|
||||
Mode: typed.Mode,
|
||||
Flags: typed.Flags,
|
||||
}
|
||||
o = to
|
||||
co = &to.commonOp
|
||||
|
||||
case *bazilfuse.RemoveRequest:
|
||||
if typed.Dir {
|
||||
to := &RmDirOp{
|
||||
Parent: InodeID(typed.Header.Node),
|
||||
Name: typed.Name,
|
||||
}
|
||||
o = to
|
||||
co = &to.commonOp
|
||||
} else {
|
||||
to := &UnlinkOp{
|
||||
Parent: InodeID(typed.Header.Node),
|
||||
Name: typed.Name,
|
||||
}
|
||||
o = to
|
||||
co = &to.commonOp
|
||||
}
|
||||
|
||||
case *bazilfuse.OpenRequest:
|
||||
if typed.Dir {
|
||||
to := &OpenDirOp{
|
||||
Inode: InodeID(typed.Header.Node),
|
||||
Flags: typed.Flags,
|
||||
}
|
||||
o = to
|
||||
co = &to.commonOp
|
||||
} else {
|
||||
to := &OpenFileOp{
|
||||
Inode: InodeID(typed.Header.Node),
|
||||
Flags: typed.Flags,
|
||||
}
|
||||
o = to
|
||||
co = &to.commonOp
|
||||
}
|
||||
|
||||
case *bazilfuse.ReadRequest:
|
||||
if typed.Dir {
|
||||
to := &ReadDirOp{
|
||||
Inode: InodeID(typed.Header.Node),
|
||||
Handle: HandleID(typed.Handle),
|
||||
Offset: DirOffset(typed.Offset),
|
||||
Size: typed.Size,
|
||||
}
|
||||
o = to
|
||||
co = &to.commonOp
|
||||
} else {
|
||||
to := &ReadFileOp{
|
||||
Inode: InodeID(typed.Header.Node),
|
||||
Handle: HandleID(typed.Handle),
|
||||
Offset: typed.Offset,
|
||||
Size: typed.Size,
|
||||
}
|
||||
o = to
|
||||
co = &to.commonOp
|
||||
}
|
||||
|
||||
case *bazilfuse.ReleaseRequest:
|
||||
if typed.Dir {
|
||||
to := &ReleaseDirHandleOp{
|
||||
Handle: HandleID(typed.Handle),
|
||||
}
|
||||
o = to
|
||||
co = &to.commonOp
|
||||
} else {
|
||||
to := &ReadFileOp{
|
||||
Handle: HandleID(typed.Handle),
|
||||
}
|
||||
o = to
|
||||
co = &to.commonOp
|
||||
}
|
||||
|
||||
case *bazilfuse.WriteRequest:
|
||||
to := &WriteFileOp{
|
||||
Inode: InodeID(typed.Header.Node),
|
||||
Handle: HandleID(typed.Handle),
|
||||
Data: typed.Data,
|
||||
Offset: typed.Offset,
|
||||
}
|
||||
o = to
|
||||
co = &to.commonOp
|
||||
|
||||
case *bazilfuse.FsyncRequest:
|
||||
// We don't currently support this for directories.
|
||||
if typed.Dir {
|
||||
return
|
||||
}
|
||||
|
||||
to := &SyncFileOp{
|
||||
Inode: InodeID(typed.Header.Node),
|
||||
Handle: HandleID(typed.Handle),
|
||||
}
|
||||
o = to
|
||||
co = &to.commonOp
|
||||
|
||||
case *bazilfuse.FlushRequest:
|
||||
to := &FlushFileOp{
|
||||
Inode: InodeID(typed.Header.Node),
|
||||
Handle: HandleID(typed.Handle),
|
||||
}
|
||||
o = to
|
||||
co = &to.commonOp
|
||||
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
co.init(r)
|
||||
return
|
||||
}
|
||||
|
||||
func convertAttributes(inode InodeID, attr InodeAttributes) bazilfuse.Attr {
|
||||
return bazilfuse.Attr{
|
||||
Inode: uint64(inode),
|
||||
Size: attr.Size,
|
||||
Mode: attr.Mode,
|
||||
Nlink: uint32(attr.Nlink),
|
||||
Atime: attr.Atime,
|
||||
Mtime: attr.Mtime,
|
||||
Ctime: attr.Ctime,
|
||||
Crtime: attr.Crtime,
|
||||
Uid: attr.Uid,
|
||||
Gid: attr.Gid,
|
||||
}
|
||||
}
|
||||
|
||||
// Convert an absolute cache expiration time to a relative time from now for
|
||||
// consumption by fuse.
|
||||
func convertExpirationTime(t time.Time) (d time.Duration) {
|
||||
// Fuse represents durations as unsigned 64-bit counts of seconds and 32-bit
|
||||
// counts of nanoseconds (cf. http://goo.gl/EJupJV). The bazil.org/fuse
|
||||
// package converts time.Duration values to this form in a straightforward
|
||||
// way (cf. http://goo.gl/FJhV8j).
|
||||
//
|
||||
// So negative durations are right out. There is no need to cap the positive
|
||||
// magnitude, because 2^64 seconds is well longer than the 2^63 ns range of
|
||||
// time.Duration.
|
||||
d = t.Sub(time.Now())
|
||||
if d < 0 {
|
||||
d = 0
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func convertChildInodeEntry(
|
||||
in *ChildInodeEntry,
|
||||
out *bazilfuse.LookupResponse) {
|
||||
out.Node = bazilfuse.NodeID(in.Child)
|
||||
out.Generation = uint64(in.Generation)
|
||||
out.Attr = convertAttributes(in.Child, in.Attributes)
|
||||
out.AttrValid = convertExpirationTime(in.AttributesExpiration)
|
||||
out.EntryValid = convertExpirationTime(in.EntryExpiration)
|
||||
}
|
||||
|
||||
// A helper for embedding common behavior.
|
||||
type commonOp struct {
|
||||
ctx context.Context
|
||||
r bazilfuse.Request
|
||||
}
|
||||
|
||||
func (o *commonOp) init(r bazilfuse.Request) {
|
||||
o.ctx = context.Background()
|
||||
o.r = r
|
||||
}
|
||||
|
||||
func (o *commonOp) Header() OpHeader {
|
||||
bh := o.r.Hdr()
|
||||
return OpHeader{
|
||||
Uid: bh.Uid,
|
||||
Gid: bh.Gid,
|
||||
}
|
||||
}
|
||||
|
||||
func (o *commonOp) Context() context.Context {
|
||||
return o.ctx
|
||||
}
|
||||
|
||||
func (o *commonOp) respondErr(err error) {
|
||||
if err != nil {
|
||||
panic("Expect non-nil here.")
|
||||
}
|
||||
|
||||
o.r.RespondError(err)
|
||||
}
|
255
fuseops/ops.go
255
fuseops/ops.go
|
@ -22,12 +22,38 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/jacobsa/bazilfuse"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type Op interface {
|
||||
// Return the fields common to all operations.
|
||||
Header() OpHeader
|
||||
|
||||
// A context that can be used for long-running operations.
|
||||
Context() context.Context
|
||||
|
||||
// Repond to the operation with the supplied error. If there is no error, set
|
||||
// any necessary output fields and then call Respond(nil).
|
||||
Respond(error)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Setup
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Sent once when mounting the file system. It must succeed in order for the
|
||||
// mount to succeed.
|
||||
type InitOp struct {
|
||||
Header OpHeader
|
||||
commonOp
|
||||
}
|
||||
|
||||
func (o *InitOp) Respond(err error) {
|
||||
if err != nil {
|
||||
o.commonOp.respondErr(err)
|
||||
return
|
||||
}
|
||||
|
||||
o.r.(*bazilfuse.InitRequest).Respond(&bazilfuse.InitResponse{})
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
@ -37,7 +63,7 @@ type InitOp struct {
|
|||
// Look up a child by name within a parent directory. The kernel sends this
|
||||
// when resolving user paths to dentry structs, which are then cached.
|
||||
type LookUpInodeOp struct {
|
||||
Header OpHeader
|
||||
commonOp
|
||||
|
||||
// The ID of the directory inode to which the child belongs.
|
||||
Parent InodeID
|
||||
|
@ -57,12 +83,23 @@ type LookUpInodeOp struct {
|
|||
Entry ChildInodeEntry
|
||||
}
|
||||
|
||||
func (o *LookUpInodeOp) Respond(err error) {
|
||||
if err != nil {
|
||||
o.commonOp.respondErr(err)
|
||||
return
|
||||
}
|
||||
|
||||
resp := bazilfuse.LookupResponse{}
|
||||
convertChildInodeEntry(&o.Entry, &resp)
|
||||
o.r.(*bazilfuse.LookupRequest).Respond(&resp)
|
||||
}
|
||||
|
||||
// Refresh the attributes for an inode whose ID was previously returned in a
|
||||
// LookUpInodeOp. The kernel sends this when the FUSE VFS layer's cache of
|
||||
// inode attributes is stale. This is controlled by the AttributesExpiration
|
||||
// field of ChildInodeEntry, etc.
|
||||
type GetInodeAttributesOp struct {
|
||||
Header OpHeader
|
||||
commonOp
|
||||
|
||||
// The inode of interest.
|
||||
Inode InodeID
|
||||
|
@ -74,12 +111,26 @@ type GetInodeAttributesOp struct {
|
|||
AttributesExpiration time.Time
|
||||
}
|
||||
|
||||
func (o *GetInodeAttributesOp) Respond(err error) {
|
||||
if err != nil {
|
||||
o.commonOp.respondErr(err)
|
||||
return
|
||||
}
|
||||
|
||||
resp := bazilfuse.GetattrResponse{
|
||||
Attr: convertAttributes(o.Inode, o.Attributes),
|
||||
AttrValid: convertExpirationTime(o.AttributesExpiration),
|
||||
}
|
||||
|
||||
o.r.(*bazilfuse.GetattrRequest).Respond(&resp)
|
||||
}
|
||||
|
||||
// Change attributes for an inode.
|
||||
//
|
||||
// The kernel sends this for obvious cases like chmod(2), and for less obvious
|
||||
// cases like ftrunctate(2).
|
||||
type SetInodeAttributesOp struct {
|
||||
Header OpHeader
|
||||
commonOp
|
||||
|
||||
// The inode of interest.
|
||||
Inode InodeID
|
||||
|
@ -97,10 +148,24 @@ type SetInodeAttributesOp struct {
|
|||
AttributesExpiration time.Time
|
||||
}
|
||||
|
||||
func (o *SetInodeAttributesOp) Respond(err error) {
|
||||
if err != nil {
|
||||
o.commonOp.respondErr(err)
|
||||
return
|
||||
}
|
||||
|
||||
resp := bazilfuse.SetattrResponse{
|
||||
Attr: convertAttributes(o.Inode, o.Attributes),
|
||||
AttrValid: convertExpirationTime(o.AttributesExpiration),
|
||||
}
|
||||
|
||||
o.r.(*bazilfuse.SetattrRequest).Respond(&resp)
|
||||
}
|
||||
|
||||
// Forget an inode ID previously issued (e.g. by LookUpInode or MkDir). The
|
||||
// kernel sends this when removing an inode from its internal caches.
|
||||
type ForgetInodeOp struct {
|
||||
Header OpHeader
|
||||
commonOp
|
||||
|
||||
// The inode to be forgotten. The kernel guarantees that the node ID will not
|
||||
// be used in further calls to the file system (unless it is reissued by the
|
||||
|
@ -108,6 +173,15 @@ type ForgetInodeOp struct {
|
|||
ID InodeID
|
||||
}
|
||||
|
||||
func (o *ForgetInodeOp) Respond(err error) {
|
||||
if err != nil {
|
||||
o.commonOp.respondErr(err)
|
||||
return
|
||||
}
|
||||
|
||||
o.r.(*bazilfuse.ForgetRequest).Respond()
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Inode creation
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
@ -120,7 +194,7 @@ type ForgetInodeOp struct {
|
|||
// http://goo.gl/FZpLu5). But volatile file systems and paranoid non-volatile
|
||||
// file systems should check for the reasons described below on CreateFile.
|
||||
type MkDirOp struct {
|
||||
Header OpHeader
|
||||
commonOp
|
||||
|
||||
// The ID of parent directory inode within which to create the child.
|
||||
Parent InodeID
|
||||
|
@ -133,6 +207,16 @@ type MkDirOp struct {
|
|||
Entry ChildInodeEntry
|
||||
}
|
||||
|
||||
func (o *MkDirOp) Respond(err error) {
|
||||
if err != nil {
|
||||
o.commonOp.respondErr(err)
|
||||
return
|
||||
}
|
||||
|
||||
resp := bazilfuse.MkdirResponse{}
|
||||
o.r.(*bazilfuse.MkdirRequest).Respond(&resp)
|
||||
}
|
||||
|
||||
// Create a file inode and open it.
|
||||
//
|
||||
// The kernel sends this when the user asks to open a file with the O_CREAT
|
||||
|
@ -147,7 +231,7 @@ type MkDirOp struct {
|
|||
// course particularly applies to file systems that are volatile from the
|
||||
// kernel's point of view.
|
||||
type CreateFileOp struct {
|
||||
Header OpHeader
|
||||
commonOp
|
||||
|
||||
// The ID of parent directory inode within which to create the child file.
|
||||
Parent InodeID
|
||||
|
@ -173,6 +257,22 @@ type CreateFileOp struct {
|
|||
Handle HandleID
|
||||
}
|
||||
|
||||
func (o *CreateFileOp) Respond(err error) {
|
||||
if err != nil {
|
||||
o.commonOp.respondErr(err)
|
||||
return
|
||||
}
|
||||
|
||||
resp := bazilfuse.CreateResponse{
|
||||
OpenResponse: bazilfuse.OpenResponse{
|
||||
Handle: bazilfuse.HandleID(o.Handle),
|
||||
},
|
||||
}
|
||||
convertChildInodeEntry(&o.Entry, &resp.LookupResponse)
|
||||
|
||||
o.r.(*bazilfuse.CreateRequest).Respond(&resp)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Unlinking
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
@ -185,7 +285,7 @@ type CreateFileOp struct {
|
|||
//
|
||||
// Sample implementation in ext2: ext2_rmdir (http://goo.gl/B9QmFf)
|
||||
type RmDirOp struct {
|
||||
Header OpHeader
|
||||
commonOp
|
||||
|
||||
// The ID of parent directory inode, and the name of the directory being
|
||||
// removed within it.
|
||||
|
@ -193,13 +293,22 @@ type RmDirOp struct {
|
|||
Name string
|
||||
}
|
||||
|
||||
func (o *RmDirOp) Respond(err error) {
|
||||
if err != nil {
|
||||
o.commonOp.respondErr(err)
|
||||
return
|
||||
}
|
||||
|
||||
o.r.(*bazilfuse.RemoveRequest).Respond()
|
||||
}
|
||||
|
||||
// Unlink a file from its parent. If this brings the inode's link count to
|
||||
// zero, the inode should be deleted once the kernel sends ForgetInodeOp. It
|
||||
// may still be referenced before then if a user still has the file open.
|
||||
//
|
||||
// Sample implementation in ext2: ext2_unlink (http://goo.gl/hY6r6C)
|
||||
type UnlinkOp struct {
|
||||
Header OpHeader
|
||||
commonOp
|
||||
|
||||
// The ID of parent directory inode, and the name of the file being removed
|
||||
// within it.
|
||||
|
@ -207,6 +316,15 @@ type UnlinkOp struct {
|
|||
Name string
|
||||
}
|
||||
|
||||
func (o *UnlinkOp) Respond(err error) {
|
||||
if err != nil {
|
||||
o.commonOp.respondErr(err)
|
||||
return
|
||||
}
|
||||
|
||||
o.r.(*bazilfuse.RemoveRequest).Respond()
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Directory handles
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
@ -218,7 +336,7 @@ type UnlinkOp struct {
|
|||
// user-space process. On OS X it may not be sent for every open(2) (cf.
|
||||
// https://github.com/osxfuse/osxfuse/issues/199).
|
||||
type OpenDirOp struct {
|
||||
Header OpHeader
|
||||
commonOp
|
||||
|
||||
// The ID of the inode to be opened.
|
||||
Inode InodeID
|
||||
|
@ -237,9 +355,22 @@ type OpenDirOp struct {
|
|||
Handle HandleID
|
||||
}
|
||||
|
||||
func (o *OpenDirOp) Respond(err error) {
|
||||
if err != nil {
|
||||
o.commonOp.respondErr(err)
|
||||
return
|
||||
}
|
||||
|
||||
resp := bazilfuse.OpenResponse{
|
||||
Handle: bazilfuse.HandleID(o.Handle),
|
||||
}
|
||||
|
||||
o.r.(*bazilfuse.OpenRequest).Respond(&resp)
|
||||
}
|
||||
|
||||
// Read entries from a directory previously opened with OpenDir.
|
||||
type ReadDirOp struct {
|
||||
Header OpHeader
|
||||
commonOp
|
||||
|
||||
// The directory inode that we are reading, and the handle previously
|
||||
// returned by OpenDir when opening that inode.
|
||||
|
@ -327,6 +458,19 @@ type ReadDirOp struct {
|
|||
Data []byte
|
||||
}
|
||||
|
||||
func (o *ReadDirOp) Respond(err error) {
|
||||
if err != nil {
|
||||
o.commonOp.respondErr(err)
|
||||
return
|
||||
}
|
||||
|
||||
resp := bazilfuse.ReadResponse{
|
||||
Data: o.Data,
|
||||
}
|
||||
|
||||
o.r.(*bazilfuse.ReadRequest).Respond(&resp)
|
||||
}
|
||||
|
||||
// Release a previously-minted directory handle. The kernel sends this when
|
||||
// there are no more references to an open directory: all file descriptors are
|
||||
// closed and all memory mappings are unmapped.
|
||||
|
@ -334,7 +478,7 @@ type ReadDirOp struct {
|
|||
// The kernel guarantees that the handle ID will not be used in further ops
|
||||
// sent to the file system (unless it is reissued by the file system).
|
||||
type ReleaseDirHandleOp struct {
|
||||
Header OpHeader
|
||||
commonOp
|
||||
|
||||
// The handle ID to be released. The kernel guarantees that this ID will not
|
||||
// be used in further calls to the file system (unless it is reissued by the
|
||||
|
@ -342,6 +486,15 @@ type ReleaseDirHandleOp struct {
|
|||
Handle HandleID
|
||||
}
|
||||
|
||||
func (o *ReleaseDirHandleOp) Respond(err error) {
|
||||
if err != nil {
|
||||
o.commonOp.respondErr(err)
|
||||
return
|
||||
}
|
||||
|
||||
o.r.(*bazilfuse.ReleaseRequest).Respond()
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// File handles
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
@ -353,7 +506,7 @@ type ReleaseDirHandleOp struct {
|
|||
// process. On OS X it may not be sent for every open(2)
|
||||
// (cf.https://github.com/osxfuse/osxfuse/issues/199).
|
||||
type OpenFileOp struct {
|
||||
Header OpHeader
|
||||
commonOp
|
||||
|
||||
// The ID of the inode to be opened.
|
||||
Inode InodeID
|
||||
|
@ -371,13 +524,26 @@ type OpenFileOp struct {
|
|||
Handle HandleID
|
||||
}
|
||||
|
||||
func (o *OpenFileOp) Respond(err error) {
|
||||
if err != nil {
|
||||
o.commonOp.respondErr(err)
|
||||
return
|
||||
}
|
||||
|
||||
resp := bazilfuse.OpenResponse{
|
||||
Handle: bazilfuse.HandleID(o.Handle),
|
||||
}
|
||||
|
||||
o.r.(*bazilfuse.OpenRequest).Respond(&resp)
|
||||
}
|
||||
|
||||
// Read data from a file previously opened with CreateFile or OpenFile.
|
||||
//
|
||||
// Note that this op is not sent for every call to read(2) by the end user;
|
||||
// some reads may be served by the page cache. See notes on WriteFileOp for
|
||||
// more.
|
||||
type ReadFileOp struct {
|
||||
Header OpHeader
|
||||
commonOp
|
||||
|
||||
// The file inode that we are reading, and the handle previously returned by
|
||||
// CreateFile or OpenFile when opening that inode.
|
||||
|
@ -400,6 +566,19 @@ type ReadFileOp struct {
|
|||
Data []byte
|
||||
}
|
||||
|
||||
func (o *ReadFileOp) Respond(err error) {
|
||||
if err != nil {
|
||||
o.commonOp.respondErr(err)
|
||||
return
|
||||
}
|
||||
|
||||
resp := bazilfuse.ReadResponse{
|
||||
Data: o.Data,
|
||||
}
|
||||
|
||||
o.r.(*bazilfuse.ReadRequest).Respond(&resp)
|
||||
}
|
||||
|
||||
// Write data to a file previously opened with CreateFile or OpenFile.
|
||||
//
|
||||
// When the user writes data using write(2), the write goes into the page
|
||||
|
@ -429,7 +608,7 @@ type ReadFileOp struct {
|
|||
// flush request.
|
||||
//
|
||||
type WriteFileOp struct {
|
||||
Header OpHeader
|
||||
commonOp
|
||||
|
||||
// The file inode that we are modifying, and the handle previously returned
|
||||
// by CreateFile or OpenFile when opening that inode.
|
||||
|
@ -467,6 +646,19 @@ type WriteFileOp struct {
|
|||
Data []byte
|
||||
}
|
||||
|
||||
func (o *WriteFileOp) Respond(err error) {
|
||||
if err != nil {
|
||||
o.commonOp.respondErr(err)
|
||||
return
|
||||
}
|
||||
|
||||
resp := bazilfuse.WriteResponse{
|
||||
Size: len(o.Data),
|
||||
}
|
||||
|
||||
o.r.(*bazilfuse.WriteRequest).Respond(&resp)
|
||||
}
|
||||
|
||||
// Synchronize the current contents of an open file to storage.
|
||||
//
|
||||
// vfs.txt documents this as being called for by the fsync(2) system call
|
||||
|
@ -484,13 +676,22 @@ type WriteFileOp struct {
|
|||
// See also: FlushFileOp, which may perform a similar function when closing a
|
||||
// file (but which is not used in "real" file systems).
|
||||
type SyncFileOp struct {
|
||||
Header OpHeader
|
||||
commonOp
|
||||
|
||||
// The file and handle being sync'd.
|
||||
Inode InodeID
|
||||
Handle HandleID
|
||||
}
|
||||
|
||||
func (o *SyncFileOp) Respond(err error) {
|
||||
if err != nil {
|
||||
o.commonOp.respondErr(err)
|
||||
return
|
||||
}
|
||||
|
||||
o.r.(*bazilfuse.FsyncRequest).Respond()
|
||||
}
|
||||
|
||||
// Flush the current state of an open file to storage upon closing a file
|
||||
// descriptor.
|
||||
//
|
||||
|
@ -539,13 +740,22 @@ type SyncFileOp struct {
|
|||
// to at least schedule a real flush, and maybe do it immediately in order to
|
||||
// return any errors that occur.
|
||||
type FlushFileOp struct {
|
||||
Header OpHeader
|
||||
commonOp
|
||||
|
||||
// The file and handle being flushed.
|
||||
Inode InodeID
|
||||
Handle HandleID
|
||||
}
|
||||
|
||||
func (o *FlushFileOp) Respond(err error) {
|
||||
if err != nil {
|
||||
o.commonOp.respondErr(err)
|
||||
return
|
||||
}
|
||||
|
||||
o.r.(*bazilfuse.FlushRequest).Respond()
|
||||
}
|
||||
|
||||
// Release a previously-minted file handle. The kernel calls this when there
|
||||
// are no more references to an open file: all file descriptors are closed
|
||||
// and all memory mappings are unmapped.
|
||||
|
@ -553,10 +763,19 @@ type FlushFileOp struct {
|
|||
// The kernel guarantees that the handle ID will not be used in further calls
|
||||
// to the file system (unless it is reissued by the file system).
|
||||
type ReleaseFileHandleOp struct {
|
||||
Header OpHeader
|
||||
commonOp
|
||||
|
||||
// The handle ID to be released. The kernel guarantees that this ID will not
|
||||
// be used in further calls to the file system (unless it is reissued by the
|
||||
// file system).
|
||||
Handle HandleID
|
||||
}
|
||||
|
||||
func (o *ReleaseFileHandleOp) Respond(err error) {
|
||||
if err != nil {
|
||||
o.commonOp.respondErr(err)
|
||||
return
|
||||
}
|
||||
|
||||
o.r.(*bazilfuse.ReleaseRequest).Respond()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue