-
Notifications
You must be signed in to change notification settings - Fork 106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add notification messages framework #35
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -240,7 +240,19 @@ func (c *Connection) beginOp( | |
// should not record any state keyed on their ID. | ||
// | ||
// Cf. https://github.com/osxfuse/osxfuse/issues/208 | ||
if opCode != fusekernel.OpForget { | ||
|
||
// Special case: For notify ops ,it is issued by the userspace filesystem to | ||
// fuse kernel. The ops's kernel opCode is 0 in kernel' viewpoint or kernel not | ||
// care whether what the iopcode is .But the ops have the notifycode from 1 | ||
// to 6 now. For adapt the notfiy ops to the BeginOP ,we fake an opcode as | ||
// notfiycode + 100. Now opcode range of ops from kernel including origin | ||
// from userspace and just from kernel is < 100. The notify ops's opcode | ||
// range is [101-106]. | ||
// Then we can process all ops consistently. | ||
// Cf. func (c *Connection) SetNotifyContext(op interface{}) | ||
// (context.Context, error) { | ||
|
||
if opCode != fusekernel.OpForget && opCode < 100 { | ||
var cancel func() | ||
ctx, cancel = context.WithCancel(ctx) | ||
c.recordCancelFunc(fuseID, cancel) | ||
|
@@ -410,6 +422,42 @@ func (c *Connection) ReadOp() (ctx context.Context, op interface{}, err error) { | |
} | ||
} | ||
|
||
// The SetNotifyContext set context according with value of the notify op's | ||
// fuseops.Notify*Op. | ||
func (c *Connection) SetNotifyContext(op interface{}) (context.Context, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add documentation for all new exported symbols. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please remove the blank line here. (Please run gofmt if you haven't.) |
||
outMsg := c.getOutMessage() | ||
|
||
err := c.buildNotify(outMsg, op) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// var ctx context.Context | ||
|
||
ctx := context.Background() | ||
|
||
// maybe no need this switch | ||
// why ctx is nil from beginOp? | ||
switch op.(type) { | ||
case *fuseops.NotifyInvalInodeOp: | ||
ctx = c.beginOp(100+uint32(fusekernel.NotifyCodeInvalInode), 0) | ||
|
||
case *fuseops.NotifyInvalEntryOp: | ||
ctx = c.beginOp(100+uint32(fusekernel.NotifyCodeInvalEntry), 0) | ||
|
||
case *fuseops.NotifyDeleteOp: | ||
ctx = c.beginOp(100+uint32(fusekernel.NotifyCodeDelete), 0) | ||
|
||
default: | ||
panic(fmt.Sprintf("Unexpected op: %#v", op)) | ||
} | ||
|
||
ctx = context.WithValue(ctx, contextKey, opState{nil, outMsg, op}) | ||
return ctx, nil | ||
|
||
} | ||
|
||
// Skip errors that happen as a matter of course, since they spook users. | ||
func (c *Connection) shouldLogError( | ||
op interface{}, | ||
|
@@ -497,6 +545,25 @@ func (c *Connection) Reply(ctx context.Context, opErr error) { | |
} | ||
} | ||
|
||
// The NotifyKernel is same as Reply func of Connection.But the diff is | ||
// that the func only send to kernel. | ||
func (c *Connection) NotifyKernel(opstate *opState) { | ||
|
||
if opstate == nil { | ||
panic(fmt.Sprintf("must init notify op")) | ||
} | ||
|
||
outMsg := opstate.outMsg | ||
defer c.putOutMessage(outMsg) | ||
|
||
c.debugLogger.Println("dev fd is:unique:notifycode ", c.dev.Fd(), outMsg.OutHeader().Unique, outMsg.OutHeader().Error) | ||
err := c.writeMessage(outMsg.Bytes()) | ||
if err != nil && c.errorLogger != nil { | ||
c.errorLogger.Printf("writeMessage: %v %v", err, outMsg.Bytes()) | ||
} | ||
|
||
} | ||
|
||
// Close the connection. Must not be called until operations that were read | ||
// from the connection have been responded to. | ||
func (c *Connection) close() (err error) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -865,3 +865,62 @@ type SetXattrOp struct { | |
// simply replace the value if the attribute exists. | ||
Flags uint32 | ||
} | ||
|
||
// Notify IO readiness event | ||
type NotifyPollOp struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's especially important to have good documentation for the new Op structs. See the other ops in this package for an example of the kind of thing I'm looking for. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
} | ||
|
||
// Notify to invalidate cache for an inode. | ||
// Added in FUSE protocol version 7.12. If the kernel does not support this | ||
// (or a newer) version, the op will return -ENOSYS and do nothing | ||
type NotifyInvalInodeOp struct { | ||
// inode to invalidatej | ||
Ino InodeID | ||
|
||
// the offset in the inode where to start invalidating or negative to invalidate attributes only | ||
Off int64 | ||
|
||
// the amount of cache to invalidate or 0 for all | ||
Len int64 | ||
} | ||
|
||
// Notify to invalidate parent attributes and the dentry matching parent/name | ||
// Added in FUSE protocol version 7.12. If the kernel does not support this | ||
// (or a newer) version, the op will return -ENOSYS and do nothing | ||
type NotifyInvalEntryOp struct { | ||
// the inode number | ||
Parent InodeID | ||
|
||
// the child entry file name | ||
Name string | ||
} | ||
|
||
// Store data to the kernel buffers | ||
// Cf:http://libfuse.github.io/doxygen/fuse__lowlevel_8h.html#a9cb974af9745294ff446d11cba2422f1 | ||
type NotifyStoreOp struct { | ||
} | ||
|
||
// Retrieve data from the kernel buffers | ||
type NotifyRetrieveOp struct { | ||
} | ||
|
||
// This op behaves like NotifyInvalEntryOp with the following additional | ||
// effect (at least as of Linux kernel 4.8): | ||
|
||
// If the provided child inode matches the inode that is currently | ||
// associated with the cached dentry, and if there are any inotify | ||
// watches registered for the dentry, then the watchers are informed | ||
// that the dentry has been deleted. | ||
// Added in FUSE protocol version 7.18. If the kernel does not | ||
// support this (or a newer) version, op will return -ENOSYS and do nothing. | ||
|
||
type NotifyDeleteOp struct { | ||
// the inode number | ||
Parent InodeID | ||
|
||
// the child entry's inode | ||
Child InodeID | ||
|
||
// the child entry file name | ||
Name string | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -90,6 +90,8 @@ func NewFileSystemServer(fs FileSystem) fuse.Server { | |
type fileSystemServer struct { | ||
fs FileSystem | ||
opsInFlight sync.WaitGroup | ||
//use set/get to use mfs not Mfs | ||
Mfs *fuse.MountedFileSystem | ||
} | ||
|
||
func (s *fileSystemServer) ServeOps(c *fuse.Connection) { | ||
|
@@ -123,6 +125,77 @@ func (s *fileSystemServer) ServeOps(c *fuse.Connection) { | |
} | ||
} | ||
|
||
func (s *fileSystemServer) InvalidateEntry(parent fuseops.InodeID, name string) error { | ||
c := s.GetMfs().Conn.(*fuse.Connection) | ||
|
||
op := &fuseops.NotifyInvalEntryOp{ | ||
Parent: fuseops.InodeID(parent), | ||
Name: string(name), | ||
} | ||
ctx, _ := c.SetNotifyContext(op) | ||
var key interface{} = contextKey | ||
foo := ctx.Value(key) | ||
opstate, ok := foo.(opState) | ||
if !ok { | ||
panic(fmt.Sprintf("notify op have invalid context: %#v", ctx)) | ||
} | ||
s.opsInFlight.Add(1) | ||
go func(opstate *opState) { | ||
defer s.opsInFlight.Done() | ||
c.NotifyKernel(opstate) | ||
}(opstate) | ||
return nil | ||
} | ||
func (s *fileSystemServer) NotifyDelete( | ||
parent fuseops.InodeID, | ||
child fuseops.InodeID, | ||
name string) error { | ||
c := s.GetMfs().Conn.(*fuse.Connection) | ||
op := &fuseops.NotifyDeleteOp{ | ||
Parent: fuseops.InodeID(parent), | ||
Child: fuseops.InodeID(child), | ||
Name: string(name), | ||
} | ||
ctx, _ := c.SetNotifyContext(op) | ||
var key interface{} = contextKey | ||
foo := ctx.Value(key) | ||
opstate, ok := foo.(opState) | ||
if !ok { | ||
panic(fmt.Sprintf("notify op have invalid context: %#v", ctx)) | ||
} | ||
s.opsInFlight.Add(1) | ||
go func(opstate *opState) { | ||
defer s.opsInFlight.Done() | ||
c.NotifyKernel(opstate) | ||
}(opstate) | ||
return nil | ||
|
||
} | ||
func (s *fileSystemServer) InvalidateInode( | ||
ino fuseops.InodeID, | ||
off int64, | ||
len int64) error { | ||
c := s.GetMfs().Conn.(*fuse.Connection) | ||
op := &fuseops.NotifyInvalInodeOp{ | ||
Ino: fuseops.InodeID(ino), | ||
Off: off, | ||
Len: len, | ||
} | ||
ctx, _ := c.SetNotifyContext(op) | ||
var key interface{} = contextKey | ||
foo := ctx.Value(key) | ||
opstate, ok := foo.(opState) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The formatting here is a mess. |
||
if !ok { | ||
panic(fmt.Sprintf("notify op have invalid context: %#v", ctx)) | ||
} | ||
s.opsInFlight.Add(1) | ||
go func(opstate *opState) { | ||
defer s.opsInFlight.Done() | ||
c.NotifyKernel(opstate) | ||
}(opstate) | ||
return nil | ||
|
||
} | ||
func (s *fileSystemServer) handleOp( | ||
c *fuse.Connection, | ||
ctx context.Context, | ||
|
@@ -219,3 +292,12 @@ func (s *fileSystemServer) handleOp( | |
|
||
c.Reply(ctx, err) | ||
} | ||
|
||
func (s *fileSystemServer) GetMfs() *fuse.MountedFileSystem { | ||
return s.Mfs | ||
|
||
} | ||
func (s *fileSystemServer) SetMfs(mfs *fuse.MountedFileSystem) { | ||
s.Mfs = mfs | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For notify ops ,it is issued by the userspace filesystem to
fuse kernel. The ops's kernel opCode is 0 in kernel' viewpoint or kernel not
care whether what the opcode is .But the ops have the notifycode from 1
to 6 now. For adapt the notfiy ops to the BeginOP ,we fake an opcode as
notfiycode + 100. Now opcode range of ops from kernel including origin
from userspace and just from kernel is < 100. The notify ops's opcode
range is [101-106].
Then we can process all ops consistently.
Cf. func (c *Connection) SetNotifyContext(op interface{})
(context.Context, error) {
see pr code.