summaryrefslogtreecommitdiff
path: root/src/storage
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2020-07-06 18:00:57 +0200
committerMax Kellermann <max@musicpd.org>2020-07-06 18:02:47 +0200
commitd7744d2b8e8219e6f9a9fad7eff63c8e5f3a000d (patch)
treedd326468aab434f59461aecb54c2cd070da747d9 /src/storage
parent33ee35ab928fab752aa7f533e6a9a2b46de6528a (diff)
command/storage: check if storage is already mounted
Mounting one storage URI twice on different mount points can lead to conflicts with the database cache file, and it doesn't make a lot of sense. But most importantly, our udisks storage plugin will unmount the disk from the kernel VFS, and if two exist, they will compete with each others. We could (and should) fix this in the udisks storage plugin, but for now, this workaround is good enough (and useful).
Diffstat (limited to 'src/storage')
-rw-r--r--src/storage/CompositeStorage.hxx25
-rw-r--r--src/storage/StorageState.cxx5
2 files changed, 30 insertions, 0 deletions
diff --git a/src/storage/CompositeStorage.hxx b/src/storage/CompositeStorage.hxx
index d6c424d54..c06240403 100644
--- a/src/storage/CompositeStorage.hxx
+++ b/src/storage/CompositeStorage.hxx
@@ -121,6 +121,15 @@ public:
VisitMounts(uri, root, t);
}
+ /**
+ * Is a storage with the given URI already mounted?
+ */
+ gcc_pure gcc_nonnull_all
+ bool IsMounted(const char *storage_uri) const noexcept {
+ const std::lock_guard<Mutex> protect(mutex);
+ return IsMounted(root, storage_uri);
+ }
+
void Mount(const char *uri, std::unique_ptr<Storage> storage);
bool Unmount(const char *uri);
@@ -155,6 +164,22 @@ private:
}
}
+ gcc_pure gcc_nonnull_all
+ static bool IsMounted(const Directory &directory,
+ const char *storage_uri) noexcept {
+ if (directory.storage) {
+ const auto uri = directory.storage->MapUTF8("");
+ if (uri == storage_uri)
+ return true;
+ }
+
+ for (const auto &i : directory.children)
+ if (IsMounted(i.second, storage_uri))
+ return true;
+
+ return false;
+ }
+
/**
* Follow the given URI path, and find the outermost directory
* which is a #Storage mount point. If there are no mounts,
diff --git a/src/storage/StorageState.cxx b/src/storage/StorageState.cxx
index 34e669787..404dfeeb3 100644
--- a/src/storage/StorageState.cxx
+++ b/src/storage/StorageState.cxx
@@ -112,6 +112,11 @@ storage_state_restore(const char *line, TextFile &file, Instance &instance)
return true;
}
+ if (composite_storage.IsMounted(url.c_str())) {
+ LogError(storage_domain, "This storage is already mounted");
+ return true;
+ }
+
auto &event_loop = instance.io_thread.GetEventLoop();
auto storage = CreateStorageURI(event_loop, url.c_str());
if (storage == nullptr) {