drivers/mtd/ftl: bypass rwbuffer when O_DIRECT is set

ftl_write() unconditionally routes writes through rwb_write() when
FTL_HAVE_RWBUFFER is defined, ignoring the O_DIRECT flag stored in
dev->oflags. This means callers that open with O_DIRECT expecting
unbuffered writes still get their data buffered in RAM.

The O_DIRECT flag is already checked in ftl_flush() to select
between direct and read-modify-write paths, but the buffering
decision in ftl_write() never consults it.

Add O_DIRECT checks in both ftl_write() and ftl_read() to bypass
rwbuffer entirely when the flag is set. For writes, go directly to
ftl_flush() and normalize the return value to match the block
driver convention (nsectors on success). For reads, go directly to
ftl_reload(), bypassing any read-ahead cache.

This gives O_DIRECT callers a complete bypass of the rwbuffer layer
for both reads and writes, matching the documented contract.

Signed-off-by: Neil Berkman <neil@xuku.com>
This commit is contained in:
Neil Berkman
2026-03-17 15:26:15 -07:00
committed by Michal Lenc
parent 1630b483d2
commit c1c6e26395
+11
View File
@@ -455,6 +455,11 @@ static ssize_t ftl_read(FAR struct inode *inode, unsigned char *buffer,
dev = inode->i_private;
#ifdef FTL_HAVE_RWBUFFER
if (dev->oflags & O_DIRECT)
{
return ftl_reload(dev, buffer, start_sector, nsectors);
}
return rwb_read(&dev->rwb, start_sector, nsectors, buffer);
#else
return ftl_reload(dev, buffer, start_sector, nsectors);
@@ -759,6 +764,12 @@ static ssize_t ftl_write(FAR struct inode *inode,
DEBUGASSERT(inode->i_private);
dev = inode->i_private;
#ifdef FTL_HAVE_RWBUFFER
if (dev->oflags & O_DIRECT)
{
ssize_t ret = ftl_flush(dev, buffer, start_sector, nsectors);
return ret < 0 ? ret : nsectors;
}
return rwb_write(&dev->rwb, start_sector, nsectors, buffer);
#else
return ftl_flush(dev, buffer, start_sector, nsectors);