[PATCH 1/4] fs: Introduce discard_range()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxxx>
---
 fs/fs.c      | 25 +++++++++++++++++++++++++
 include/fs.h |  3 +++
 2 files changed, 28 insertions(+)

diff --git a/fs/fs.c b/fs/fs.c
index 12faaebc27..e00bbcd223 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -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);
 
-- 
2.24.0


_______________________________________________
barebox mailing list
barebox@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/barebox



[Index of Archives]     [Linux Embedded]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux