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

NodeReleaser not triggered #434

Closed
buzzy opened this issue Jul 12, 2022 · 14 comments
Closed

NodeReleaser not triggered #434

buzzy opened this issue Jul 12, 2022 · 14 comments

Comments

@buzzy
Copy link

buzzy commented Jul 12, 2022

My Release function is never triggered. Other events works fine, like GetAttr, Lookup etc.
I have debug enabled and see that FUSE triggers the Release event, but my function is never run

var _ = (fs.NodeReleaser)((*inode)(nil))
func (n *inode) Release(ctx context.Context, f fs.FileHandle) syscall.Errno {
	log.Println("RELEASE FILE")	
	n.data.Body.Close()

	return 0
}

@hanwen
Copy link
Owner

hanwen commented Jul 12, 2022

is the FS user closing the files? Can you see RELEASE opcodes in the debug output?

@buzzy
Copy link
Author

buzzy commented Jul 12, 2022

Yes, when debug is set to true for the mount-options, I see the RELEASE being triggered, but it never runs my function.

@buzzy
Copy link
Author

buzzy commented Jul 12, 2022

2022/07/12 18:00:45 rx 78: READ n2 {Fh 0 [3538944 +131072) L 0 RDONLY,0x8000}
2022/07/12 18:00:45 WROTE BYTES 131072
2022/07/12 18:00:45 tx 78: OK, 131072b data "\xe8\x13\x81[\xdd\xfa\x88q"...
2022/07/12 18:00:45 rx 82: READ n2 {Fh 0 [3801088 +20480) L 0 RDONLY,0x8000}
2022/07/12 18:00:45 Last chunk is small
2022/07/12 18:00:45 WROTE BYTES 16662
2022/07/12 18:00:45 tx 82: OK, 20480b data "\x16B\xd4\xf9\xf6\xdes\x80"...
2022/07/12 18:00:45 rx 84: GETATTR n2 {Fh 0}
2022/07/12 18:00:45 GETATTR
2022/07/12 18:00:45 tx 84: OK, {tA=0s {M0100666 SZ=3817750 L=0 0:0 B7457512 i0:1300 A 12345678.000000 M 12345678.000000 C 12345678.000000}}
2022/07/12 18:00:45 rx 86: GETATTR n2 {Fh 0}
2022/07/12 18:00:45 GETATTR
2022/07/12 18:00:45 tx 86: OK, {tA=0s {M0100666 SZ=3817750 L=0 0:0 B7457
512 i0:1300 A 12345678.000000 M 12345678.000000 C 12345678.000000}}
2022/07/12 18:00:45 rx 88: FLUSH n2 {Fh 0}
2022/07/12 18:00:45 tx 88: OK
2022/07/12 18:00:45 rx 90: RELEASE n2 {Fh 0 0x8000 L0}
2022/07/12 18:00:45 tx 90: OK

@hanwen
Copy link
Owner

hanwen commented Jul 12, 2022

the code is pretty straightforward, see

if r, ok := n.ops.(NodeReleaser); ok {

are you sure the inode implementation (n.ops) is actually the one you want it to be?

@buzzy
Copy link
Author

buzzy commented Jul 12, 2022

Well, I created it the same way as the GETATTR and that one works fine. READDIR and LOOKUP also works fine.

//WORKS
var _ = (fs.NodeGetattrer)((*inode)(nil))
func (n *inode) Getattr(ctx context.Context, fh fs.FileHandle, out *fuse.AttrOut) syscall.Errno {}

//DOES NOT WORK
var _ = (fs.NodeReleaser)((*inode)(nil))
func (n *inode) Release(ctx context.Context, f fs.FileHandle) syscall.Errno {}

@hanwen
Copy link
Owner

hanwen commented Jul 12, 2022

if you have no file handler, there is nothing to release. You can hook on Forget instead, but if your internals are tied a HTTP body that is read-once, you should use file handles, or things will get weird with concurrent access to the same file.

@hanwen hanwen closed this as completed Jul 12, 2022
@buzzy
Copy link
Author

buzzy commented Jul 12, 2022

Do you have any example how to use OPEN and READ with a http request? I tried, but can't get it to work correctly with file handlers. Exactly as you described, by READs happens in random order :(

@buzzy
Copy link
Author

buzzy commented Jul 12, 2022

I have this, and it's working 90% of the time. But 10% of the time, the md5sum of the resulting file does not match the original one. Obviously I am not understanding it correctly :)

The Read function is not always being executed in the "correct" order even though I have set SingleThreaded: true
I guess there is some simple fix to this that I am just not seeing?

var _ = (fs.NodeOpener)((*inode)(nil))
func (n *inode) Open(ctx context.Context, flags uint32) (fh fs.FileHandle, fuseFlags uint32, errno syscall.Errno) {
    
    resp, err := http.Get("https://ftp.sunet.se/mirror/almalinux.org/9/BaseOS/aarch64/os/Packages/cracklib-dicts-2.9.6-27.el9.aarch64.rpm")
    if err != nil {
	    return nil, 0, 1
    }
    //DONT FORGET TO CLOSE THIS SOMEWHERE! BROBABLY AT RELEASE EVENT
    //defer resp.Body.Close()

    return resp.Body, 0, 0
}

var _ = (fs.NodeReader)((*inode)(nil))
func (n *inode) Read(ctx context.Context, fh fs.FileHandle, dest []byte, off int64) (fuse.ReadResult, syscall.Errno) {

    howmany, err := io.ReadFull(fh.(io.Reader), dest)
    if err != nil {
	    log.Println("Last chunk is small")
    }

    //log.Println("PART", int(off) / len(dest))
    log.Println("WROTE BYTES", howmany)

    return fuse.ReadResultData(dest), fs.OK
}

@buzzy
Copy link
Author

buzzy commented Jul 12, 2022

I don't understand why the READ is called in almost random order over the file even though it's like one single read.
The "off" parameter is all over the place trying to read back and forth over the "file", which of course I can't do since it's a read-once.

Is there a way to force it to READ in "order" or do I need to rely on the HTTP server to accept "range" requests?

2022/07/13 04:49:23 OFF 0 PART 0
2022/07/13 04:49:23 OFF 131072 PART 1
2022/07/13 04:49:23 OFF 655360 PART 5
2022/07/13 04:49:23 OFF 524288 PART 4
2022/07/13 04:49:23 OFF 393216 PART 3
2022/07/13 04:49:23 OFF 262144 PART 2
2022/07/13 04:49:23 OFF 786432 PART 6
2022/07/13 04:49:23 OFF 1048576 PART 8
2022/07/13 04:49:23 OFF 1179648 PART 9
2022/07/13 04:49:23 OFF 917504 PART 7
2022/07/13 04:49:23 OFF 1310720 PART 10
2022/07/13 04:49:23 OFF 1572864 PART 12
2022/07/13 04:49:24 OFF 1703936 PART 13
2022/07/13 04:49:24 OFF 1441792 PART 11
2022/07/13 04:49:24 OFF 2097152 PART 16
2022/07/13 04:49:24 OFF 1966080 PART 15
2022/07/13 04:49:24 OFF 1835008 PART 14
2022/07/13 04:49:24 OFF 2228224 PART 17
2022/07/13 04:49:24 OFF 2359296 PART 18
2022/07/13 04:49:24 OFF 2490368 PART 19
2022/07/13 04:49:24 OFF 2621440 PART 20
2022/07/13 04:49:24 OFF 2752512 PART 21
2022/07/13 04:49:24 OFF 2883584 PART 22
2022/07/13 04:49:24 OFF 3014656 PART 23
2022/07/13 04:49:24 OFF 3145728 PART 24
2022/07/13 04:49:24 OFF 3538944 PART 27
2022/07/13 04:49:24 OFF 3276800 PART 25
2022/07/13 04:49:24 OFF 3407872 PART 26

@hanwen
Copy link
Owner

hanwen commented Jul 13, 2022

The kernel has caching and read-ahead, so it sometimes tries to be clever and read ahead of what is requested.
Have a look at the directio example for a way around this. Or, dump the HTTP stream to a file on Open, and read from there. Then delete the file on RELEASE.

@rfjakob
Copy link
Contributor

rfjakob commented Jul 13, 2022

Yes, that's kernel read-ahead. Used to be a tricky problem (rfjakob/gocryptfs#92), but, now we have the SyncRead flag.

Set it to true like here:
https://github.com/rfjakob/gocryptfs/blob/e9ecff7f07aeb1efe0edec7b4b050ce3c0ef75f8/mount.go#L398

@buzzy
Copy link
Author

buzzy commented Jul 13, 2022

Yes, that's kernel read-ahead. Used to be a tricky problem (rfjakob/gocryptfs#92), but, now we have the SyncRead flag.

Set it to true like here: https://github.com/rfjakob/gocryptfs/blob/e9ecff7f07aeb1efe0edec7b4b050ce3c0ef75f8/mount.go#L398

That would be awesome! Unfortunately, that flag does not seem to exist? Was this added in some other branch?

Also can't find it in the documentation for MountOptions:
https://pkg.go.dev/github.com/hanwen/go-fuse/v2@v2.1.0/fuse#MountOptions

server, err := fs.Mount(mntDir, root, &fs.Options{
	MountOptions: fuse.MountOptions{
		Debug: false,
		SyncRead: true,
	},
})

# command-line-arguments
./test.go:243:4: unknown field 'SyncRead' in struct literal of type fuse.MountOptions

@buzzy
Copy link
Author

buzzy commented Jul 13, 2022

Ah! I see now, this was added in late 2021 and was never included in any release.

@buzzy
Copy link
Author

buzzy commented Jul 13, 2022

@rfjakob Thanks!! Now it's working the way it should! Even works with multi-threading enabled.

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

No branches or pull requests

3 participants