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

No clear way to use HandleID from Getattrer or Setattrer #225

Open
MikaelSmith opened this issue Dec 12, 2019 · 8 comments · May be fixed by #226
Open

No clear way to use HandleID from Getattrer or Setattrer #225

MikaelSmith opened this issue Dec 12, 2019 · 8 comments · May be fixed by #226

Comments

@MikaelSmith
Copy link

Most methods that are performed on a file handle resolve to functions implementing Handle* interfaces. NodeGetattrer and NodeSetattrer can be called with or without a handle (for example, from ftruncate vs truncate or fstat vs stat calls). However, there's no way to resolve the HandleID provided in GetattrRequest or SetattrRequest to a Handle so you can pass handling of those requests to the specific open handle.

I'd like to see HandleGetattrer and HandleSetattrer interfaces that are called when those requests are performed on an open handle. It makes sense to fall back to NodeGetattrer and NodeSetattrer if not implemented.

NodeFsyncer has a similar problem, since it's called on the node rather than a particular handle.

MikaelSmith added a commit to MikaelSmith/fuse that referenced this issue Dec 12, 2019
Getattr and Setattr requests can either happen on a fs.Node or an
fs.Handle (depending on the call that initiated it e.g. truncate vs
ftruncate or stat vs fstat). Add HandleGetattrer and HandleSetattrer so
implementations can provide handle-specific overrides when those
operations are performed on an open file descriptor.

Also create HandleFsyncer and deprecate NodeFsyncer to resolve the TODO.

Resolves bazil#225.
@MikaelSmith MikaelSmith linked a pull request Dec 12, 2019 that will close this issue
MikaelSmith added a commit to MikaelSmith/fuse that referenced this issue Dec 12, 2019
Getattr and Setattr requests can either happen on a fs.Node or an
fs.Handle (depending on the call that initiated it e.g. truncate vs
ftruncate or stat vs fstat). Add HandleGetattrer and HandleSetattrer so
implementations can provide handle-specific overrides when those
operations are performed on an open file descriptor.

Also create HandleFsyncer and deprecate NodeFsyncer to resolve the TODO.

Resolves bazil#225.
@tv42
Copy link
Member

tv42 commented Dec 13, 2019

Out of curiosity, how do you plan on using handle-specific attributes or fsync? All handles to a single node are supposed to view the same data, and as far as I know there's plenty of assumptions about that in the kernel (page cache).

If you want per-open content for a file, you're probably better off with uncacheable Lookup responses and giving each Lookup a new Node.

@MikaelSmith
Copy link
Author

I'm trying to model things behind an API as files that you can read and update. I was hoping that the way most editors worked when overwriting a file would be ftruncate, write, write, ..., flush. That way I could buffer updates, then do the actual change on flush, and I wouldn't have to worry about an intermediate state where the file supposedly has size 0 but the source behind it disagrees.

Unfortunately it seems that when they truncate (or maybe when you open with the truncate flag) it's truncate, which leaves me with a temporarily inconsistent state.

@tv42
Copy link
Member

tv42 commented Dec 13, 2019

bolt-mount is a filesystem interface to a transactional key-value database that stores file contents to the key-value store on Flush, which is the kernel operation triggered by fsync or final close of the file. That might give you some ideas: https://github.com/bazil/bolt-mount/blob/master/file.go

@MikaelSmith
Copy link
Author

I think the changes I made in the PR still make sense theoretically, but I think the way bolt-mount approaches it will probably solve the particular problems I was dealing with. Thanks.

@MikaelSmith
Copy link
Author

That example helped a bit. I guess you almost never get Setattr called without an open write handle? Also, I get problems with vim if I don't define Fsync (it gets the fuse.EIO error and says Fsync failed).

@tv42
Copy link
Member

tv42 commented Dec 16, 2019

I guess you almost never get Setattr called without an open write handle?

That'd happen with truncate syscall, chmod, etc.

Also, I get problems with vim if I don't define Fsync (it gets the fuse.EIO error and says Fsync failed).

I think returning an error to the caller (vim) is a lot better than lying about persistence guarantees. If your filesystem doesn't implement Fsync, we don't let callers think you do. Though reading fsync(2) it might make more sense to return EINVAL than EIO. I opened #227 for that.

@MikaelSmith
Copy link
Author

My point about truncate was that https://github.com/bazil/bolt-mount/blob/master/file.go doesn't seem to implement a way to handle that outside of a writable handle getting flushed. I guess it's up to my filesystem whether it wants to support raw truncate operations in that scenario.

P.S. Thanks for all the feedback.

@tv42
Copy link
Member

tv42 commented Dec 17, 2019

Based on my reading of bolt-mount it explicitly doesn't care whether incoming requests have a handle or not -- though that code is probably buggy if there are no writers concurrently open (f.data will be nil, changes to it will not be respected, nothing is persisted).

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 a pull request may close this issue.

2 participants