diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2020-06-15 10:18:51 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2020-08-19 07:36:15 +0200 |
commit | 6583918059a1b0bac0ad776c06eeae4a7887fdab (patch) | |
tree | bc514e05b09fdde5c024c0f7db40d021a3daca7e | |
parent | 0dc2fbcea236a1d610f28f7fb17cd6aee49885f7 (diff) | |
download | barebox-6583918059a1b0bac0ad776c06eeae4a7887fdab.tar.gz barebox-6583918059a1b0bac0ad776c06eeae4a7887fdab.tar.xz |
fs: Warn when filesystem operations are called from a poller
Filesystem operations possibly call into arbitrary devices, so shouldn't
be used from a poller. This patch sprinkles some WARN_ONCE() when this
happens. One exception is when the file which is accessed is on ramfs
which doesn't have any dependencies to devices.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r-- | common/poller.c | 2 | ||||
-rw-r--r-- | fs/fs.c | 34 | ||||
-rw-r--r-- | include/slice.h | 10 |
3 files changed, 45 insertions, 1 deletions
diff --git a/common/poller.c b/common/poller.c index 7b1b92714c..50c518697b 100644 --- a/common/poller.c +++ b/common/poller.c @@ -16,7 +16,7 @@ #include <slice.h> static LIST_HEAD(poller_list); -static int poller_active; +int poller_active; int poller_register(struct poller_struct *poller, const char *name) { @@ -31,6 +31,7 @@ #include <environment.h> #include <libgen.h> #include <block.h> +#include <slice.h> #include <libfile.h> #include <parseopt.h> #include <linux/namei.h> @@ -74,6 +75,8 @@ static FILE *files; static struct dentry *d_root; static struct vfsmount *mnt_root; +static struct fs_driver_d *ramfs_driver; + static int init_fs(void) { cwd = xzalloc(PATH_MAX); @@ -257,6 +260,9 @@ static ssize_t __read(FILE *f, void *buf, size_t count) fsdrv = f->fsdev->driver; + if (fsdrv != ramfs_driver) + assert_command_context(); + if (f->size != FILE_SIZE_STREAM && f->pos + count > f->size) count = f->size - f->pos; @@ -315,6 +321,10 @@ static ssize_t __write(FILE *f, const void *buf, size_t count) } fsdrv = f->fsdev->driver; + + if (fsdrv != ramfs_driver) + assert_command_context(); + if (f->size != FILE_SIZE_STREAM && f->pos + count > f->size) { ret = fsdrv->truncate(&f->fsdev->dev, f, f->pos + count); if (ret) { @@ -402,6 +412,9 @@ loff_t lseek(int fd, loff_t offset, int whence) fsdrv = f->fsdev->driver; + if (fsdrv != ramfs_driver) + assert_command_context(); + ret = -EINVAL; switch (whence) { @@ -457,6 +470,10 @@ int erase(int fd, loff_t count, loff_t offset) return -EINVAL; fsdrv = f->fsdev->driver; + + if (fsdrv != ramfs_driver) + assert_command_context(); + if (fsdrv->erase) ret = fsdrv->erase(&f->fsdev->dev, f, count, offset); else @@ -483,6 +500,10 @@ int protect(int fd, size_t count, loff_t offset, int prot) count = f->size - offset; fsdrv = f->fsdev->driver; + + if (fsdrv != ramfs_driver) + assert_command_context(); + if (fsdrv->protect) ret = fsdrv->protect(&f->fsdev->dev, f, count, offset, prot); else @@ -509,6 +530,10 @@ int discard_range(int fd, loff_t count, loff_t offset) count = f->size - offset; fsdrv = f->fsdev->driver; + + if (fsdrv != ramfs_driver) + assert_command_context(); + if (fsdrv->discard_range) ret = fsdrv->discard_range(&f->fsdev->dev, f, count, offset); else @@ -547,6 +572,9 @@ void *memmap(int fd, int flags) fsdrv = f->fsdev->driver; + if (fsdrv != ramfs_driver) + assert_command_context(); + if (fsdrv->memmap) ret = fsdrv->memmap(&f->fsdev->dev, f, &retp, flags); else @@ -570,6 +598,9 @@ int close(int fd) fsdrv = f->fsdev->driver; + if (fsdrv != ramfs_driver) + assert_command_context(); + if (fsdrv->close) ret = fsdrv->close(&f->fsdev->dev, f); @@ -700,6 +731,9 @@ int register_fs_driver(struct fs_driver_d *fsdrv) fsdrv->drv.bus = &fs_bus; register_driver(&fsdrv->drv); + if (!strcmp(fsdrv->drv.name, "ramfs")) + ramfs_driver = fsdrv; + return 0; } EXPORT_SYMBOL(register_fs_driver); diff --git a/include/slice.h b/include/slice.h index fd753e194b..b2d65b80cd 100644 --- a/include/slice.h +++ b/include/slice.h @@ -33,4 +33,14 @@ extern struct slice command_slice; void command_slice_acquire(void); void command_slice_release(void); +extern int poller_active; + +#ifdef CONFIG_POLLER +#define assert_command_context() ({ \ + WARN_ONCE(poller_active, "%s called in poller\n", __func__); \ +}) +#else +#define assert_command_context() do { } while (0) +#endif + #endif /* __SLICE_H */ |