-
Notifications
You must be signed in to change notification settings - Fork 18
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
Generation numbers should ensure inode uniqueness across remounts #19
Comments
PS. Maybe allow user to set it themselves, but I think there should be a reasonable default behavior. |
Interesting, I didn't know that about the generation numbers! It's unfortunate that A better behavior would be to monotonically increase the inode number for the next file, and only bump the generation number when it rolls over. Then on remount, the filesystem can use the same generation number and start with the last-allocated inode from last time. I'll look into making this change. Thanks for the report! |
(for reference to myself and others, the place in the documentation that actually says this is: https://github.com/libfuse/libfuse/blob/d92bf83c152ff88c2d92bd852752d4c326004400/include/fuse_lowlevel.h#L69-L81) |
Yeah, that's what I referred to, though reusing inodes is ok and happens with regular filesystems too. But the slight problem is that generation space is limited. Despite what it says on the tin (u64 in fuse reply struct), generation number is actually 32 bit in linux kernel, and is returned so to userspace via FS_IOC_GETVERSION ioctl. I'm not sure how FUSE kernel driver resolves this contradiction internally, maybe it just truncates to the lower half of the 64 bit value or keeps a u64<->self-generated-u32 map.
Which would be like extending 64 bit inode number to linearly traversed 32+64 bit. Which surely means it won't overflow within our lifetime, but I'm not sure then how you're going to manage inode allocations without a HashMap, and where you're going to preserve the last (generation, inode) pair. This is why I suggested giving user a method to set initial generation and leave the preservation matter to him. Maybe keep the current inode reuse behavior but provide them with just the maximum of all generations to preserve so you can remount starting with (max_generation+1, 0). Though the 32 bit limitation means max_generation could overflow in feasible time due to some quick inode reuse. But that would still be an improvement over the current generation behavior with minimal changes to inode code. Though it would be nice to provide for operation without having to preserve anything as that demands some side storage. But current inode reuse together with 32 bit generation limitation means that user probably shouldn't just set generation to 32-bit seconds-since-epoch timestamp, as current inode reuse code might increment generation of some inode much faster than once per second (quite unlikely actually, as fuse tends to keep inodes in Maybe some hybrid approach will be better, with splitting free nodes into actual generations, allowing to reuse them only after a second passed. Then user can reasonably safely use seconds since epoch for generation initial value. In fact then it can be provided for them as default behavior. |
PS. Even just initializing generation to seconds since epoch and doing nothing else would be already better than the current state. |
The title says it all. As per FUSE docs,
(generation, inode)
combination must not reoccur even after application restart, because there are things, like NFS, that rely on it being unique. Hence initializing generation numbers to zero like it happens now is bad. I suggest using something like a nanosecond-precision timestamp of current time at the moment ofInodeTable
creation, or a random value.The text was updated successfully, but these errors were encountered: