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

Allow overriding RUNTIME_DIR with a cli flag. #621

Closed
wants to merge 0 commits into from
Closed

Conversation

sdab
Copy link
Contributor

@sdab sdab commented Dec 1, 2023

This adds a --runtime-dir flag which can override the RUNTIME_PATH (renamed RUNTIME_DEFAULT_PATH). This ended up being kind of tricky because of how lxcfslib can be reloaded and its use of a library constructor which mounts paths under the runtime path. In order read the cli flag and then set a variable in the library before it starts mounting things, I removed the constructor attribute and made it an explicit init call in order to override the runtime dir in between loading the library and initializing lxcfslib.

This allows me to run multiple instances of lxcfs without them sharing mounts/paths. Unfortunately, I think this a breaking lib change so it will require a restart.

@stgraber
Copy link
Member

stgraber commented Dec 1, 2023

Commits don't appear to be correctly signed off.

@sdab
Copy link
Contributor Author

sdab commented Dec 1, 2023

They are signed off with my personal email, but I guess it compares it to my git config:
Expected "sdabdoub [email protected]", but got "Sebastien Dabdoub [email protected]".

Ive updated them, please re-run the checks.

src/bindings.c Outdated Show resolved Hide resolved
src/lxcfs.c Outdated Show resolved Hide resolved
@sdab
Copy link
Contributor Author

sdab commented Dec 11, 2023

@stgraber, friendly ping.

@stgraber
Copy link
Member

@sdab not sure what's up with Github Actions on this one. Could you do a quick rebase or pointless amend of your last commit so you can force push and re-trigger the Github stuff?

@sdab
Copy link
Contributor Author

sdab commented Feb 20, 2024

I did a blank amend + force push. It looks like it needs approval to run the tests/checks.

@sdab
Copy link
Contributor Author

sdab commented Feb 21, 2024

Looks like my amend undid the sign-off? Should be good now

@stgraber
Copy link
Member

@mihalicyn can you review this please?

src/bindings.c Outdated Show resolved Hide resolved
src/lxcfs.c Outdated Show resolved Hide resolved
src/lxcfs.c Outdated
else
lxcfs_debug("Opened %s", lxcfs_lib_path);

good:
if (strlen(runtime_path) > 0 && !do_set_runtime_path(runtime_path)) {
Copy link
Member

@mihalicyn mihalicyn Mar 1, 2024

Choose a reason for hiding this comment

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

Do we really have to introduce two new exported symbols set_runtime_path and lxcfslib_init in there?

If you changing existing constructor to be a normal exported function you can also add an argument to it like this:

void lxcfslib_init(const char *new_path)
{
//... handle new_path here

As far as I understand you can't call set_runtime_path anywhere except before the lxcfslib_init anyways. Which is a good sign that this function should be a part of lxcfslib_init.

==

Second thing is that we are trying to maintain compatibility, which means that old LXCFS daemon should be able to load and use a new LXCFS library gracefully. With this change old LXCFS daemon will try to reload LXCFS library, constructor is missing, and it's fine and no error will be generated. But LXCFS will remain uninitialized and then it will crash or at least give fuse request failures to the user.
My idea is to move lxcfs_init (constructor) call to the lxcfs_fuse_init(struct fuse_conn_info *conn, void *data), because it's always called almost at the same time as constructor should be called. In this case you don't need to add a new exported symbol lxcfslib_init. Just remove a __attribute__((constructor)) from the lxcfs_init and then add an explicit lxcfs_init call in the lxcfs_fuse_init.
Please, correct me if I'm wrong ;-)

Copy link
Member

Choose a reason for hiding this comment

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

This solution is also not ideal because lxcfs_fuse_init is also relatively new (3 years, see 285aea4) exported symbol, which means that LXCFS daemons older than 3 years will still fail to properly load new LXCFS library. But it's better than nothing.

cc @brauner

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 looked at this for a bit, but dont see a way around breaking backwards compatibility. Essentially the problem is that we need to send a new parameter (runtime_path) between the binary and the library.

I did however merge set_runtime_path into lxcfslib_init, so there is only one new symbol.

Copy link
Member

Choose a reason for hiding this comment

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

I guess your current solution is correct and does not break compatibility against the recent LXCFS version.

@mihalicyn
Copy link
Member

@sdab
Hi, Sebastien!

Sorry for the delay with review. I have left some comments regarding a compatibility issue.

In general, this looks good to me. But I would improve this a bit otherwise it will make troubles for existing Incus/LXD installations as they will have to restart all the container instances after the upgrade.

@stgraber
Copy link
Member

I'll let @mihalicyn provided a more detailed answer here but speaking of backward compat, a normal upgrade path on most distros will be that the library will be updated to 6.0 with a daemon running 5.0, that daemon will be asked to reload the library.

Doing so should not result in a crash as that would instantly break all containers :)

So we basically need the new lib to be fine with not being provided the extra data and behave as it currently would. But then if the extra data is provided, operate with the custom runtime dir.

Also, the new symbol you're introducing here is very specific to providing the runtime path, would it make sense to have it provide some kind of init struct so we don't need to add another symbol the next time we need something like this?

@sdab
Copy link
Contributor Author

sdab commented Mar 26, 2024

ack, I wasnt sure how strict the backwards compatibility requirement was (I thought maybe on a major version, it was ok to break).

I have removed the runtime_path only export, unless you mean you want an more generic option struct as the function argument.

Ill have to think of a backwards compatible way to do this. A separate symbol might be helpful in that case and make it only called by a newer binary (is backwards compatibility only required for old binaries and not old libs? or is it both ways)

@stgraber
Copy link
Member

Ill have to think of a backwards compatible way to do this. A separate symbol might be helpful in that case and make it only called by a newer binary (is backwards compatibility only required for old binaries and not old libs? or is it both ways)

We only care about the case where an old binary (already running) needs to talk to a new library, the other way around shouldn't be possible.

@stgraber
Copy link
Member

I have removed the runtime_path only export, unless you mean you want an more generic option struct as the function argument.

Yeah, that. Having an init function which only takes a single string argument is a recipe for needing an initv2 function down the line when we need to pass something else, using a struct from the start saves us from having to keep adding new functions.

@sdab
Copy link
Contributor Author

sdab commented Apr 3, 2024

Ok I reworked the code a bit to make it backwards compatible.

@stgraber I made use of the existing (and versioned) lxcfs_opts struct and bumped the version value to 2. Thus if an old binary loads this new lib then the version will be set to 1 and we will not attempt to read the new field. PTAL

@sdab
Copy link
Contributor Author

sdab commented Apr 19, 2024

@mihalicyn let me know if I need to do anything else

@stgraber
Copy link
Member

stgraber commented Jun 3, 2024

@sdab looks like you have a small conflict and Github Actions failed to run the tests because of that. Can you rebase on main?

@sdab
Copy link
Contributor Author

sdab commented Jun 3, 2024

Rebased

src/bindings.c Outdated Show resolved Hide resolved
src/bindings.h Outdated Show resolved Hide resolved
@mihalicyn
Copy link
Member

LGTM except small issue with a new field placement in the struct lxcfs_opts

Once this fixed I'll test this change locally and check that I can update LXCFS from the version in the main branch to the version in the sdab:main branch without crashes and issues.

@sdab
Copy link
Contributor Author

sdab commented Jun 5, 2024

Addressed the comments, thanks @mihalicyn

@mihalicyn
Copy link
Member

LGTM, thanks for your work on this, Sebastien!

I'll make some small adjustments:

  • squash 2 last commits into one
  • small changes in the commit messages format to align with our current standards

@mihalicyn
Copy link
Member

Updated version #645

@sdab
Copy link
Contributor Author

sdab commented Jun 6, 2024

btw @mihalicyn it would be useful to update the README or CONTRIBUTING files with:

  • instructions on how to run the tests and a backwards compatibility test
  • the requirement to be backwards compatible across the lib and binary

@mihalicyn
Copy link
Member

  • instructions on how to run the tests and a backwards compatibility test

That's a good point. Today, I started to work on adding a new CI test to check forward-compatibility.
Hopefully, it will be ready for review tomorrow. ;-)

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

Successfully merging this pull request may close these issues.

4 participants