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 /fs/fs.c | |
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>
Diffstat (limited to 'fs/fs.c')
-rw-r--r-- | fs/fs.c | 25 |
1 files changed, 25 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; |