diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2019-12-13 11:45:25 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2020-02-14 12:16:20 +0100 |
commit | 6a1daf5adcefad3d08f97dd85e2917eac12e7202 (patch) | |
tree | 06166f124096fef98b272687e9cc942f80aa39b4 | |
parent | ee6a508d2b1738c30d4e2eab06ce5732d172524d (diff) | |
download | barebox-6a1daf5adcefad3d08f97dd85e2917eac12e7202.tar.gz barebox-6a1daf5adcefad3d08f97dd85e2917eac12e7202.tar.xz |
fs: Introduce discard_range()
discard_range() is a way to tell the lower layers that we are no longer
interested in a data range of a file, so that the lower layers can
discard the underlying data if desired.
This is mainly designed to bypass the deficiencies of our block layer.
We cache the block data in chunks of multiple KiB (16 currently) if
we fall into the block layer with write requests smaller than that
we have to read/modify/write a chunk. With the help of discard_range()
code writing files to a raw block device can now discard the range the
file will be written to. The block layer then no longer has to read
the chunks first that are inside the discard range.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r-- | fs/fs.c | 25 | ||||
-rw-r--r-- | include/fs.h | 3 |
2 files changed, 28 insertions, 0 deletions
@@ -497,6 +497,31 @@ int protect(int fd, size_t count, loff_t offset, int prot) } EXPORT_SYMBOL(protect); +int discard_range(int fd, loff_t count, loff_t offset) +{ + struct fs_driver_d *fsdrv; + FILE *f = fd_to_file(fd); + int ret; + + if (IS_ERR(f)) + return -errno; + if (offset >= f->size) + return 0; + if (count > f->size - offset) + count = f->size - offset; + + fsdrv = f->fsdev->driver; + if (fsdrv->discard_range) + ret = fsdrv->discard_range(&f->fsdev->dev, f, count, offset); + else + ret = -ENOSYS; + + if (ret) + errno = -ret; + + return ret; +} + int protect_file(const char *file, int prot) { int fd, ret; diff --git a/include/fs.h b/include/fs.h index 38debfc41b..d9684c82b1 100644 --- a/include/fs.h +++ b/include/fs.h @@ -60,6 +60,8 @@ struct fs_driver_d { loff_t offset); int (*protect)(struct device_d *dev, FILE *f, size_t count, loff_t offset, int prot); + int (*discard_range)(struct device_d *dev, FILE *f, loff_t count, + loff_t offset); int (*memmap)(struct device_d *dev, FILE *f, void **map, int flags); @@ -127,6 +129,7 @@ int umount_by_cdev(struct cdev *cdev); #define ERASE_SIZE_ALL ((loff_t) - 1) int erase(int fd, loff_t count, loff_t offset); int protect(int fd, size_t count, loff_t offset, int prot); +int discard_range(int fd, loff_t count, loff_t offset); int protect_file(const char *file, int prot); void *memmap(int fd, int flags); |