From 9b0431dd51f4e0378a43881dcca5cce87660acc0 Mon Sep 17 00:00:00 2001 From: AlmAck Date: Sat, 29 Aug 2026 19:00:04 +0200 Subject: [PATCH 1/2] drivers/mtd/filemtd: open the backing file O_RDWR filemtd_initialize() opens its backing file with mode = O_RDONLY | O_WRONLY | O_CLOEXEC; Commit 6161c73639 introduced this when it replaced the non-standard O_RDOK | O_WROK pair, describing the change as a pure text substitution. That held while the access mode was a genuine bitmask: O_RDONLY was (1 << 0), O_WRONLY was (1 << 1), and O_RDWR was both bits, so the OR produced O_RDWR. O_ACCMODE was defined as an alias for O_RDWR. Commit 9e141acab3 then aligned the flags with Linux. The low two bits became an enumeration -- O_RDONLY 0, O_WRONLY 1, O_RDWR 2 -- and O_ACCMODE stopped being an alias for O_RDWR and became an independent mask of 3. OR-ing two members of that enumeration is no longer meaningful: O_RDONLY | O_WRONLY evaluates to 1, and masking it with O_ACCMODE yields O_WRONLY. The file is therefore opened write-only, and fs_read.c rejects every read on it with -EACCES. The failure does not name filemtd: on the simulator it surfaces as a LittleFS mount of a filemtd-backed partition returning -ENOSPC, after which nothing on that volume works. This appears to be an isolated miss rather than a pattern. Grepping the tree for the same construct -- two access-mode constants OR-ed together -- finds only this one call site. The one remaining place that bit-tests the mode, fs/xipfs/xipfs_vfs.c:606, happens to be correct under the new values (and would have been wrong under the old ones). The hostfs NUTTX_O_* mirror and host_oflags_convert() were updated in lockstep and switch on the masked value. Signed-off-by: AlmAck --- drivers/mtd/filemtd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/filemtd.c b/drivers/mtd/filemtd.c index 1ef36b84d6080..87c9e71022988 100644 --- a/drivers/mtd/filemtd.c +++ b/drivers/mtd/filemtd.c @@ -813,7 +813,7 @@ FAR struct mtd_dev_s *filemtd_initialize(FAR const char *path, off_t offset, /* Set the file open mode. */ - mode = O_RDONLY | O_WRONLY | O_CLOEXEC; + mode = O_RDWR | O_CLOEXEC; /* Try to open the file. NOTE that block devices will use a character * driver proxy. From 7b89917ea12c0baa46def266b26787ea81ff646f Mon Sep 17 00:00:00 2001 From: AlmAck Date: Wed, 2 Sep 2026 23:13:14 +0200 Subject: [PATCH 2/2] drivers/mtd/filemtd: fix nxstyle errors in filemtd.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pre-existing violations in this file, reported by checkpatch because the preceding commit touches it, and requested by a reviewer. Three "Missing blank line after declarations", in the BIOC_PARTINFO, MTDIOC_ERASESTATE and register-time-erase blocks. The rest were one problem: the whole mtd_loop_ioctl() switch body sits two columns short of NuttX style. With `switch` at 2 and its brace at 4, case labels belong at 6 — as they already are in filemtd_ioctl() earlier in this same file — but here the comments and cases sit at 4 and everything under them follows suit, which checkpatch reports as 21 separate comment, alignment and brace errors. Reindented the block to match, including the two stray closing lines that had drifted to seven and five columns. Whitespace only: `git diff -w` is empty apart from the three added blank lines, and the brace count is unchanged. checkpatch is clean against master. Signed-off-by: AlmAck --- drivers/mtd/filemtd.c | 107 ++++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 52 deletions(-) diff --git a/drivers/mtd/filemtd.c b/drivers/mtd/filemtd.c index 87c9e71022988..92c0102770d53 100644 --- a/drivers/mtd/filemtd.c +++ b/drivers/mtd/filemtd.c @@ -507,6 +507,7 @@ static int filemtd_ioctl(FAR struct mtd_dev_s *dev, int cmd, { FAR struct partition_info_s *info = (FAR struct partition_info_s *)arg; + if (info != NULL) { info->numsectors = priv->nblocks * @@ -530,6 +531,7 @@ static int filemtd_ioctl(FAR struct mtd_dev_s *dev, int cmd, case MTDIOC_ERASESTATE: { FAR uint8_t *result = (FAR uint8_t *)arg; + *result = CONFIG_FILEMTD_ERASESTATE; ret = OK; @@ -580,6 +582,7 @@ static int mtd_loop_setup(FAR const char *devname, FAR const char *filename, /* Try to erase the entire device, before register */ FAR struct file_dev_s *fdev = (FAR struct file_dev_s *)mtd; + mtd->erase(mtd, offset / erasesize, fdev->nblocks); } @@ -698,61 +701,61 @@ static int mtd_loop_ioctl(FAR struct file *filep, int cmd, switch (cmd) { - /* Command: LOOPIOC_SETUP - * Description: Setup the loop device - * Argument: A pointer to a read-only instance of struct losetup_s. - * Dependencies: The loop device must be enabled (CONFIG_MTD_LOOP=y) - */ - - case MTD_LOOPIOC_SETUP: - { - FAR struct mtd_losetup_s *setup = - (FAR struct mtd_losetup_s *)((uintptr_t)arg); - - if (setup == NULL) - { - ret = -EINVAL; - } - else - { + /* Command: LOOPIOC_SETUP + * Description: Setup the loop device + * Argument: A pointer to a read-only instance of struct losetup_s. + * Dependencies: The loop device must be enabled (CONFIG_MTD_LOOP=y) + */ + + case MTD_LOOPIOC_SETUP: + { + FAR struct mtd_losetup_s *setup = + (FAR struct mtd_losetup_s *)((uintptr_t)arg); + + if (setup == NULL) + { + ret = -EINVAL; + } + else + { # ifndef CONFIG_MTD_CONFIG_NONE - ret = mtd_loop_setup(setup->devname, setup->filename, - setup->sectsize, setup->erasesize, - setup->offset, setup->configdata); + ret = mtd_loop_setup(setup->devname, setup->filename, + setup->sectsize, setup->erasesize, + setup->offset, setup->configdata); # else - ret = mtd_loop_setup(setup->devname, setup->filename, - setup->sectsize, setup->erasesize, - setup->offset); + ret = mtd_loop_setup(setup->devname, setup->filename, + setup->sectsize, setup->erasesize, + setup->offset); # endif - } - } - break; - - /* Command: LOOPIOC_TEARDOWN - * Description: Teardown a loop device previously setup via - * LOOPIOC_SETUP - * Argument: A read-able pointer to the path of the device to be - * torn down - * Dependencies: The loop device must be enabled (CONFIG_MTD_LOOP=y) - */ - - case MTD_LOOPIOC_TEARDOWN: - { - FAR const char *devname = (FAR const char *)((uintptr_t)arg); - - if (devname == NULL) - { - ret = -EINVAL; - } - else - { - ret = mtd_loop_teardown(devname); - } - } - break; - - default: - ret = -ENOTTY; + } + } + break; + + /* Command: LOOPIOC_TEARDOWN + * Description: Teardown a loop device previously setup via + * LOOPIOC_SETUP + * Argument: A read-able pointer to the path of the device to be + * torn down + * Dependencies: The loop device must be enabled (CONFIG_MTD_LOOP=y) + */ + + case MTD_LOOPIOC_TEARDOWN: + { + FAR const char *devname = (FAR const char *)((uintptr_t)arg); + + if (devname == NULL) + { + ret = -EINVAL; + } + else + { + ret = mtd_loop_teardown(devname); + } + } + break; + + default: + ret = -ENOTTY; } return ret;