From: Simon Glass <sjg@chromium.org>
fs_lookup_dir() iterates all children of an FS device looking for a
cached directory but does not filter by uclass. With the addition of
the MOUNT uclass, a non-directory child whose uclass-private data is
misinterpreted as struct dir_uc_priv can cause a false path match.
Add a UCLASS_DIR check to skip non-directory children.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
fs/fs-uclass.c | 2 ++
fs/vfs.c | 7 +++++++
fs/vfs_dir.c | 10 ++++++++++
include/vfs.h | 8 ++++++++
4 files changed, 27 insertions(+)
@@ -61,6 +61,8 @@ int fs_lookup_dir(struct udevice *dev, const char *path, struct udevice **dirp)
if (!device_active(dir))
continue;
+ if (device_get_uclass_id(dir) != UCLASS_DIR)
+ continue;
priv = dev_get_uclass_priv(dir);
log_debug("dir %s '%s' '%s'\n", dir->name, path, priv->path);
@@ -311,6 +311,13 @@ int vfs_umount_path(struct udevice *vfs, const char *path)
return vfs_umount(mnt_dev);
}
+bool vfs_is_mount_point(struct udevice *dir)
+{
+ struct udevice *mnt;
+
+ return !find_mount(dir, &mnt);
+}
+
void vfs_print_mounts(void)
{
struct vfsmount *mnt;
@@ -13,6 +13,7 @@
#include <dir.h>
#include <dm.h>
#include <fs.h>
+#include <vfs.h>
#include <fs_common.h>
static int vfs_rootfs_dir_open(struct udevice *dev,
@@ -81,8 +82,17 @@ static struct dir_ops vfs_rootfs_dir_ops = {
.close = vfs_rootfs_dir_close,
};
+static int vfs_rootfs_dir_remove(struct udevice *dev)
+{
+ if (vfs_is_mount_point(dev))
+ return log_msg_ret("drm", -EBUSY);
+
+ return 0;
+}
+
U_BOOT_DRIVER(vfs_rootfs_dir) = {
.name = "vfs_rootfs_dir",
.id = UCLASS_DIR,
.ops = &vfs_rootfs_dir_ops,
+ .remove = vfs_rootfs_dir_remove,
};
@@ -112,6 +112,14 @@ int vfs_umount_path(struct udevice *vfs, const char *path);
int vfs_find_mount(struct udevice *vfs, const char *path,
struct udevice **mntp, const char **subpathp);
+/**
+ * vfs_is_mount_point() - Check whether a directory is a mount point
+ *
+ * @dir: UCLASS_DIR device to check
+ * Return: true if this directory has an active mount, false otherwise
+ */
+bool vfs_is_mount_point(struct udevice *dir);
+
/**
* vfs_print_mounts() - Print all current mounts
*/