Skip to content
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

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

inevity
Copy link
Contributor

@inevity inevity commented Nov 3, 2017

Now we only impl the NotifyInvalInode,NotifyInvalEntry,
NotifyDelete.

Notify funcs allow the filesystem to invalidate VFS caches.

The statement that 'In a networked fuse file-system, the local
fuse instance may receive changes from a remote system that do not
pass through the local kernel vfs.
When those changes are made the local fuse instance must notify the
local kernel of the change so as to keep the local kernel's cache
in sync. This is accomplished via notify delete or notify
invalidate.
In other words, these notifications only apply if fuse file-system
makes changes to the file-system that are not initiated by the
local kernel: changes initiated by the local kernel must not
involve notify delete or notify invalidate (will deadlock), and
are not required.' is quoted from Jhon Muir.

About fuse notify func history ,please ref link
http://lkml.iu.edu/hypermail/linux/kernel/0906.0/01120.html

Copy link
Owner

@jacobsa jacobsa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the context, I understand what this is for now I think.

@@ -241,7 +241,7 @@ 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 {
if opCode != fusekernel.OpForget && opCode < 100 {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change?

Copy link
Contributor Author

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.

@@ -411,6 +411,36 @@ func (c *Connection) ReadOp() (ctx context.Context, op interface{}, err error) {
}
}

func (c *Connection) SetNotifyContext(op interface{}) (context.Context, error) {

Copy link
Owner

Choose a reason for hiding this comment

The 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.)

@@ -411,6 +411,36 @@ func (c *Connection) ReadOp() (ctx context.Context, op interface{}, err error) {
}
}

func (c *Connection) SetNotifyContext(op interface{}) (context.Context, error) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add documentation for all new exported symbols.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -845,3 +845,24 @@ type SetXattrOp struct {
// simply replace the value if the attribute exists.
Flags uint32
}
type NotifyPollOp struct {
Copy link
Owner

Choose a reason for hiding this comment

The 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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@inevity
Copy link
Contributor Author

inevity commented Nov 5, 2017

Have added documentation.

@fishpadak
Copy link

fishpadak commented Nov 1, 2018

Hello :D Any progress on this PR?

@inevity
Copy link
Contributor Author

inevity commented Jan 13, 2019

Hello :D Any progress on this PR?

Dont know why jacobsa not to merge or give some advice.

@stapelberg
Copy link
Collaborator

Would you mind rebasing this on the current master branch please? We fixed the travis config in the meantime.

Now we  only impl the NotifyInvalInode,NotifyInvalEntry,
NotifyDelete.

Notify funcs allow the filesystem to invalidate VFS caches.

The statement that 'In a networked fuse file-system, the local
fuse instance may receive changes from a remote system that do not
pass through the local kernel vfs.
When those changes are made the local fuse instance must notify the
local kernel of the change so as to keep the local kernel's cache
in sync. This is accomplished via notify delete or notify
invalidate.
In other words, these notifications only apply if fuse file-system
makes changes to the file-system that are not initiated by the
local kernel: changes initiated by the local kernel must not
involve notify delete or notify invalidate (will deadlock), and
are not required.' is quoted from Jhon Muir.

About fuse  notify func history ,please ref link
http://lkml.iu.edu/hypermail/linux/kernel/0906.0/01120.html .
@inevity
Copy link
Contributor Author

inevity commented Sep 20, 2019

Just have rebased on master branch.

Copy link
Collaborator

@stapelberg stapelberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This looks like a good feature addition to have (I should probably try using this once it landed).

Aside from the question about the context, I have a few minor comments, but can also just make the changes if that’s okay with you?

connection.go Outdated

// we should get outmsg from context
var key interface{} = contextKey
foo := ctx.Value(key)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain why we need to pull this value out of the context instead of just passing it as a parameter to NotifyKernel?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just do like the reply func. Of course you can also just pass the value of the context as a parameter to NotifyKernel.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. The reply mechanism needs to use a context because it passes a value (

ctx = context.WithValue(ctx, contextKey, opState{inMsg, outMsg, op})
) across API boundaries (to the file system implementation and back).

This is not the case here AIUI, so please change the function signature to not take a context, but just take the opState parameter directly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I rethink this case, even the notify func is diff with the normal op which need reply function. But the context use in notify func is same as the reply func. Just the context is created by our func (s *fileSystemServer) Invalidateentry/inode. And now we call unity all notify op and the normal op.
For the correct context use, we should alway use the context for notify case. see func (s *fileSystemServer) InvalidateInode for opsInFlight.Done.

Maybe i am not understandering the issue on detail.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I rethink this case, even the notify func is diff with the normal op which need reply function. But the context use in notify func is same as the reply func. Just the context is created by our func (s *fileSystemServer) Invalidateentry/inode. And now we call unity all notify op and the normal op.

If I understand correctly, you’re saying having both functions (NotifyKernel and Reply) take arguments via a context is good because they are similar, yes?

While similarity is good, I would argue that in this case, it’s clearer if a context is not used unless absolutely necessary. Since we’re creating a context but then immediately call the function (instead of passing the context somewhere else), I don’t think we need to use a context.

Contexts are used (aside from deadlines and cancellation) to propagate data across API boundaries. In this case, we don’t need to cross API boundaries, so we shouldn’t use a context if we can use a simple variable instead.

@inevity
Copy link
Contributor Author

inevity commented Sep 27, 2019

Can you give some comments about the context commit?
I use context in SetNotifyContext,so this func SetNotifyContext have nothing to modify, only one bug to fix.

Then change NotifyKernel(opstate opState) as this signature.

And the funcs which calling notifykernel in fuseutil/file_system.go Where have some dup code, you can give some detail advice.

@inevity inevity force-pushed the notifyfuncv1 branch 2 times, most recently from 42473bf to 0f2c8eb Compare September 27, 2019 10:22
@inevity
Copy link
Contributor Author

inevity commented Sep 28, 2019

Wait...

Copy link
Collaborator

@stapelberg stapelberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you still interested in working on this PR? It’s been open for a while. Perhaps the author of issue #64 would want to carry on?

Here are my design recommendations for this pull request:

  1. Add the InvalidateEntry, InvalidateInode and NotifyDelete functions to the fuse.Connection type.
  2. Directly fill in the corresponding data structure (e.g. fusekernel.NotifyCodeInvalEntryOut) and call c.writeMessage

I thought a bit about whether we need additional locking with a mutex, but I think the individual syscall.Write calls that fuse.Connection.writeMessage makes should already be atomic? Sanity-checks welcome.

@@ -24,6 +24,7 @@ type MountedFileSystem struct {
// The result to return from Join. Not valid until the channel is closed.
joinStatus error
joinStatusAvailable chan struct{}
Conn interface{}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does the Conn field use type interface{} instead of *fuse.Connection?

ctx, _ := c.SetNotifyContext(op)
var key interface{} = contextKey
foo := ctx.Value(key)
opstate, ok := foo.(opState)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The formatting here is a mess.

InvalidateInode(fuseops.InodeID, int64, int64) error
NotifyDelete(fuseops.InodeID, fuseops.InodeID, string) error
SetMfs(*MountedFileSystem)
GetMfs() *MountedFileSystem
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a lot of extra methods to be adding to the very simple Server interface, which could plausibly have been proxied in client code..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants