umount_by_cdev() unmounts the filesystems mounted from one cdev. For a partitioned device that is not enough: the filesystems are mounted from the partitions, not from the disk itself, so unmounting the disk leaves them behind.
Add a variant that walks the partitions as well. This is what a driver needs when the medium it handed out is gone and the mounts on it have become useless. Signed-off-by: Sascha Hauer <[email protected]> Assisted-by: Claude:claude-opus-5 --- fs/fs.c | 31 +++++++++++++++++++++++++++++++ include/fs.h | 1 + 2 files changed, 32 insertions(+) diff --git a/fs/fs.c b/fs/fs.c index ce41f23f88..f0d3d9fa0a 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -1033,6 +1033,37 @@ int umount_by_cdev(struct cdev *cdev) } EXPORT_SYMBOL(umount_by_cdev); +/** + * cdev_umount_all - unmount everything mounted from a cdev + * @cdev: cdev to unmount + * + * Unmounts the filesystems mounted from @cdev and from its partitions. + * Useful for a medium that is gone, where the mounts cannot be used + * anymore anyway. + * + * Return: 0 on success or if nothing was mounted, the first error + * otherwise + */ +int cdev_umount_all(struct cdev *cdev) +{ + struct cdev *partcdev; + int first_error = 0; + int ret; + + for_each_cdev_partition(partcdev, cdev) { + ret = cdev_umount_all(partcdev); + if (ret && !first_error) + first_error = ret; + } + + ret = umount_by_cdev(cdev); + if (ret && !first_error) + first_error = ret; + + return first_error; +} +EXPORT_SYMBOL(cdev_umount_all); + struct readdir_entry { struct dirent d; struct list_head list; diff --git a/include/fs.h b/include/fs.h index 9c3c8d9512..0cc58d73c2 100644 --- a/include/fs.h +++ b/include/fs.h @@ -112,6 +112,7 @@ static inline bool is_tftp_fs(const char *path) int flush(int fd); int umount_by_cdev(struct cdev *cdev); +int cdev_umount_all(struct cdev *cdev); /* not-so-standard functions */ #define ERASE_SIZE_ALL ((loff_t) - 1) -- 2.47.3
