-
Notifications
You must be signed in to change notification settings - Fork 3k
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 special handling for "/default" filesystem #7924
Conversation
c048d92
to
6a2d56a
Compare
6a2d56a
to
da4ae15
Compare
The code is OK but, I do have a problem with doing things under the hood. This feature is actually aiming to cloak the system paths. It actually means that while an application assumes it writes to default/ path, it will go to different one and not exactly a predictable one. |
platform/FileBase.cpp
Outdated
|
||
if (_default == this) { | ||
_default == NULL; | ||
} | ||
|
||
if (getPathType() == FilePathType) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This part was not locked by _mutex in the original code. Is it locked now by ScopedLock ?
If so, then note that 'remove_filehandle()' uses a lock of its own: filehandle_mutex->lock();
Consider the risk of deadlock.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ta for pointing that out - hadn't considered it. It seems okay, as mbed_retarget.cpp does not call out to File
objects while holding its filehandle_mutex - it's lower-level.
This needs review and consideration, as its functionality change, might be considered for 5.11 rather? |
The cloaking is already happening manually in #7774 - a filing system is being designated as the default, and is responding to "/default", so someone requesting via that name already doesn't know what it will be. This improves the situation by allowing the device to still have a proper name. Without this, and just #7774, you might have this situation: Platform A:
Platform B:
Like that, a portable program wanting to explicitly write to SD is going to struggle, as there's no consistent name - the default concept has got in the way. With this change, we can do this, which seems better: Platform A:
Platform B:
Programs can now reasonably request "/sd", "/littlefs" or "/default". |
Would be nice to get it in, as I fear that without it I fear #7774 may somewhat distort the effective API. A default shouldn't get in the way of explicit selection. But on the other hand, we'd still need the extension to 7774 to do the renaming as per the previous comment, so maybe it's too late now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me.
@kjbracey-arm . Ok, I see your point and agreed. |
/morph build |
Build : SUCCESSBuild number : 2995 Triggering tests/morph test |
Test : FAILUREBuild number : 2758 |
Exporter Build : SUCCESSBuild number : 2606 |
/morph test |
Just been creating a PR to do that, but I've noticed that 7774 went in using "/fs", rather than "/default", My comment calling "/fs" a tautology got thumbs up so I assumed you went with that. Not sure what to do now. Here are the 3 possibilities I see, in my order of preference:
|
Sorry I missed the fs/ I have thought the big issue was to move back to the original naming pattern and use get_default_instance()
It very easy to change the default to default/. need to fix SystemStorage.cpp which I believe should be fixed anyway to include a call to set_as_default(). However, your solution does work even if it left "fs/" and "default/" will be an alias of "fs/". i thought this was the all idea? |
Just created #7977, which extends on this and flips everything to "/default". If you're okay with that, it would be awesome to try to get that into this release. I think the final result should make more sense to the end users. |
The idea was that we would use the mechanism maintain "physical" names like "/sd" or "/flash", in addition to supporting logical names. The initial only logical name is "/default", but we could have others in future with a general scheme. I want the devices' primary name - visible in config and errors - to be their physical one, so instantiate as "sd". We could maintain "/fs" as a duplicate logical name for backwards compatibility, but at this point it would be cleaner to quickly switch before release, if people are okay with "/default". If you look at 7977's final version, I think we have a great level of extra clarity on what's happening:
or
The default mechanism is, intentionally, an obfuscation, so we've got to take care we don't "over-obfuscate". We still need some real names backing the system - even if "good code" doesn't reference it directly, having standard conventions allowing people to re-use config files specifying "/sd/xxx" is worthwhile. |
Test : SUCCESSBuild number : 2766 |
@kjbracey-arm it sounds Ok to me. |
As soon as we get positive feedback, this will be ready for integration |
This is one of the APIs that needs a long-term change. My current thoughts are to split the FileBase out of the inheritance tree into it's own MountPoint class (the current FileBase class has already caused the duplication of all major file system interfaces, FileLike/FileHandle, FileSystemLike/FileSystemHandle). For the short term why not just add "/default" to the config system? "platform.default_mount_point" or something? I'm also not sure it's a big rush because moving "/default" to the config system should be a backwards-compatible change. But it's possible I'm missing something. |
platform/FileBase.cpp
Outdated
return NULL; | ||
} | ||
|
||
FileBase *FileBase::get(int n) | ||
{ | ||
_mutex->lock(); | ||
ScopedLock<PlatformMutex> lock(*_mutex); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the wrong PR to change these locking calls.
I'm not opposed to this change, but every change invites bugs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're not wrong - I certainly wouldn't do this in a patch/fix. Probably shouldn't be doing it in rc2 either.
I can undo this, but as the current test set has passed, and we might be accepting this version otherwise, is it worth restarting CI just to take it out? @0xc0170 ?
I'll prepare a removal anyway in case I do another spin, but won't push yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree not to block it now, it's just not a good habit to get into
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually another CI round is required anyway for part 2 - #7977, so we could still change it.
platform/SingletonPtr.h
Outdated
* @returns | ||
* A reference to the singleton | ||
*/ | ||
T &operator*() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this taken care of by the T *operator->()
operator?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No - the alternative here would be lock(*_mutex.get())
, which seemed unnecessarily awkward.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah you're right, I though operator-> was full magic, but it's only half magic 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That does cover the "I want a reference" case, but I wonder if we should also have a conversion operator to T *
for people who want the pointer. Does the get()
really have to be explicit? Is there any C++ trap there for the conversion operator?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested changes with mbed-os-5.10.
I agree that FileBase would be due for a significant rework - not clear how much a
So change the model "get_default_instance()" implementations to name them as "/sd" or "/flash", and make the JSON have a setting telling you what that name is? That would be possible, but it's not quite as flexible - "FileSystem::get_default_instance()" is a run-time call, so the default mount point can be a run-time decision (eg depending on if an SD card is present), or it can be based on conceptual #ifdefs like the default weak version in #7774. A config name specification couldn't mirror that. And I was trying to preserve the design choice of #7774 that the default mount point has a well-known name - I think it's a useful convenience. You could have a separate I'm imagining app config files like
That app can run on anything that's got some sort of general-purpose filing system, but for specific platforms it has specific set-up code and configuration. My view is that these two modes of operation - explicitly specified and "default" for the mount point should be able to co-exist, and 7774 as it stands makes that tricky - if you make the sdcard be the default you can't any longer explicitly refer to it as The somewhat app-specific boot-up code for platform_x to back that would contain
So all filing systems are present and named for config to refer to, and one of them is still marked as default so the basic |
Allow a FileBase (normally a FileSystemLike) to be set as the default, so it can be looked up as "/default" as well as its actual name.
Though note that choosing the name of the mount point is not a runtime call: FileSystem *fs = FileSystem::get_default_instance(); There's nothing there that specifies what the FS's name is. At the moment this is a compile time decision as far as I can tell.
I agree, but I don't think we're there yet. At the moment the underlying retarget code only supports 1 mount point per FS. Another short-term option, what if we add "/default" to the config system, and make the default "/default" NULL. This effectively does not mount the FS to the tree. That would leave things open to add multiple mount points and reintroduce "/default" properly next release. |
This came up during review, and the agreement was that as there was no way to pass a
So given that, that means that the sdcard is called "default" (or "fs"), not "sd", because without this PR there's no way to present "default" as an alias. I'm happy with the "default" name, but I'm regretting the loss of "sd". The other possibility here would be to junk the idea of a well-known name and make code extract it. I'm not sure this option was properly considered:
I'd be okay with that in code, but does preclude the short-cut of just doing "/default/foo" in the config file - using the default and using something explicit would actually be different code at each call site, not just flipping config between "/default/foo" and "/sd/foo". I do like the concept of it ultimately always just coming down to a string constant.
Sorry, you've lost me now. Can you be more specific?
Once something like that is in place, the set_as_default() call just becomes a wrapper around |
"/fs" is a tautology - not a good name for the default filing system, as whereever we use it, we know we're specifying a filing system. Rename to "/default".
Make the built-in FileSystem::get_default_instance() implementation instantiate storage as "flash" or "sd", with "default" as an alias. This will aid interworking between simple and advanced filesystem code on various platforms. The expectation is that the names "sd" or "flash" will be always available if the device is available and configured, regardless of what "default" represents.
Doesn't that still make this a compile time decision?
This is a new API, and it's provided at the target level. Unless this target is mounting the FS as both "default" and "sd" (which I don't believe it is?), we won't have "sd". Unless the user declares an FS as "sd", but then it won't be a part of the get_default_instance. Actually that raises a separate question. Does FileBase::set_as_default change what FileSystem::get_default_instance returns?
FileBase supports NULL, which FileSystem::get_default_instance() does not need to create a mount point. Though it sounds like from your comment this isn't what we're looking for.
True, I originally thought the cost was 1 mount point per filesystem, but after looking at it again we only need a global one. So it's a minor cost. |
I would say it's a design-time decision, if it's a decision at all - it's was intended to be an API invariant, not something that would change between programs, builds or platforms.
But why not? Why can't someone have 2 or 3 explicitly-mounted filing systems, and have one of them be the default? That's what I've shown in several of my examples, and that is the motivation for my wanting a change here. See this comment here: #7924 (comment) I don't want there to be this exclusion - either you have exactly 1 filing system which is accessible via the "get_default" or you have multiple, but there's no default. The very name "get_default" suggests it's 1 of potentially several. For the simple case there is this default weak instantiation of "get_default_instance" that spawns the (only?) FS on demand, but the intent is that you can override to point at something you've explicitly set-up yourself, as per this comment: #7924 (comment) But when you do that, the current API contract is that the thing you point the
No, the causality is in the other direction - whoever is providing The simple In the more complex examples I've given previously, the assumption is that you have some application knowledge so you know what filing systems are worth mounting and hence pulling into the image up-front. |
da4ae15
to
c0dbc49
Compare
I needed to correct an error in the string comparison, so redone. This time without the ScopedLock and SingletonPtr changes, and adding in the extra completion from #7977. |
/morph build |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, thanks for taking those out 👍
My comments are concerns but not blockers
Build : SUCCESSBuild number : 3014 Triggering tests/morph test |
Exporter Build : SUCCESSBuild number : 2625 |
Test : SUCCESSBuild number : 2780 |
Description
Allow a FileBase (normally a FileSystemLike) to be set as the default, so it can be looked up as "/default" as well as its actual name.
Intended to be used to extend the implementation in #7774. Once that is merged, we can add a commit to do that in this PR.
Expected pattern is
This will allow simple code using "/default" to interwork with custom-configured setups preferring to use explicit mount names.
Pull request type