diff --git a/cpukit/libfs/src/jffs2/include/linux/mtd/mtd.h b/cpukit/libfs/src/jffs2/include/linux/mtd/mtd.h index 548201483f..541992535e 100644 --- a/cpukit/libfs/src/jffs2/include/linux/mtd/mtd.h +++ b/cpukit/libfs/src/jffs2/include/linux/mtd/mtd.h @@ -52,8 +52,33 @@ static inline int mtd_is_bitflip(int err) { return (err == -EUCLEAN); } }) #define mtd_block_markbad(mtd_sp, offset) \ jffs2_flash_block_mark_bad(RTEMS_CONTAINER_OF(&(mtd_sp), struct jffs2_sb_info, mtd), offset) -#define mtd_write(mtd_sp, ofs, len, retlen, buf) \ - jffs2_flash_direct_write(RTEMS_CONTAINER_OF(&(mtd_sp), struct jffs2_sb_info, mtd), ofs, len, retlen, buf) +#define mtd_write(mtd_sp, write_buffer_offset, size, return_size, write_buffer) \ +({ \ + struct jffs2_sb_info *_c = RTEMS_CONTAINER_OF(&(mtd_sp), struct jffs2_sb_info, mtd); \ + const struct super_block *_sb = OFNI_BS_2SFFJ(_c); \ + rtems_jffs2_flash_control *_fc = _sb->s_flash_control; \ + *return_size = size; \ + (*_fc->write)(_fc, write_buffer_offset, write_buffer, size); \ +}) +#define mtd_writev(mtd_sp, vecs, count, to, retlen) \ +({ \ + size_t _totlen = 0; \ + size_t _thislen; \ + int _ret = 0; \ + for (int _i = 0; _i < count; _i++) { \ + _ret = mtd_write(c->mtd, to, vecs[_i].iov_len, &_thislen, \ + vecs[_i].iov_base); \ + _totlen += _thislen; \ + if (_ret || _thislen != vecs[_i].iov_len) { \ + break; \ + } \ + to += vecs[_i].iov_len; \ + } \ + if (retlen) { \ + *retlen = _totlen; \ + } \ + _ret; \ +}) #define mtd_read(mtd_sp, ofs, len, retlen, buf) \ jffs2_flash_direct_read(RTEMS_CONTAINER_OF(&(mtd_sp), struct jffs2_sb_info, mtd), ofs, len, retlen, buf) diff --git a/cpukit/libfs/src/jffs2/include/linux/types.h b/cpukit/libfs/src/jffs2/include/linux/types.h index a85b85647d..b9dc54711a 100644 --- a/cpukit/libfs/src/jffs2/include/linux/types.h +++ b/cpukit/libfs/src/jffs2/include/linux/types.h @@ -1,6 +1,10 @@ #ifndef __LINUX_TYPES_H__ #define __LINUX_TYPES_H__ +#ifdef CONFIG_JFFS2_SUMMARY +#include +#define __must_hold(a) +#endif #include #include diff --git a/cpukit/libfs/src/jffs2/src/flashio.c b/cpukit/libfs/src/jffs2/src/flashio.c index 6b0a9433fa..31d79330a6 100644 --- a/cpukit/libfs/src/jffs2/src/flashio.c +++ b/cpukit/libfs/src/jffs2/src/flashio.c @@ -15,6 +15,7 @@ */ #include +#include #include "nodelist.h" #ifndef CONFIG_JFFS2_FS_WRITEBUFFER @@ -44,101 +45,6 @@ int jffs2_flash_direct_read(struct jffs2_sb_info * c, return (*fc->read)(fc, read_buffer_offset, write_buffer, size); } -int jffs2_flash_direct_write(struct jffs2_sb_info * c, - loff_t write_buffer_offset, const size_t size, - size_t * return_size, const unsigned char *read_buffer) -{ - const struct super_block *sb = OFNI_BS_2SFFJ(c); - rtems_jffs2_flash_control *fc = sb->s_flash_control; - - *return_size = size; - - return (*fc->write)(fc, write_buffer_offset, read_buffer, size); -} - -int -jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct iovec *vecs, - unsigned long count, loff_t to, size_t * retlen) -{ - unsigned long i; - size_t totlen = 0, thislen; - int ret = 0; - - for (i = 0; i < count; i++) { - // writes need to be aligned but the data we're passed may not be - // Observation suggests most unaligned writes are small, so we - // optimize for that case. - - if (((vecs[i].iov_len & (sizeof (int) - 1))) || - (((unsigned long) vecs[i]. - iov_base & (sizeof (unsigned long) - 1)))) { - // are there iov's after this one? Or is it so much we'd need - // to do multiple writes anyway? - if ((i + 1) < count || vecs[i].iov_len > 256) { - // cop out and malloc - unsigned long j; - ssize_t sizetomalloc = 0, totvecsize = 0; - char *cbuf, *cbufptr; - - for (j = i; j < count; j++) - totvecsize += vecs[j].iov_len; - - // pad up in case unaligned - sizetomalloc = totvecsize + sizeof (int) - 1; - sizetomalloc &= ~(sizeof (int) - 1); - cbuf = (char *) malloc(sizetomalloc); - // malloc returns aligned memory - if (!cbuf) { - ret = -ENOMEM; - goto writev_out; - } - cbufptr = cbuf; - for (j = i; j < count; j++) { - memcpy(cbufptr, vecs[j].iov_base, - vecs[j].iov_len); - cbufptr += vecs[j].iov_len; - } - ret = - jffs2_flash_write(c, to, sizetomalloc, - &thislen, cbuf); - if (thislen > totvecsize) // in case it was aligned up - thislen = totvecsize; - totlen += thislen; - free(cbuf); - goto writev_out; - } else { - // otherwise optimize for the common case - int buf[256 / sizeof (int)]; // int, so int aligned - size_t lentowrite; - - lentowrite = vecs[i].iov_len; - // pad up in case its unaligned - lentowrite += sizeof (int) - 1; - lentowrite &= ~(sizeof (int) - 1); - memcpy(buf, vecs[i].iov_base, lentowrite); - - ret = - jffs2_flash_write(c, to, lentowrite, - &thislen, (char *) &buf); - if (thislen > vecs[i].iov_len) - thislen = vecs[i].iov_len; - } // else - } else - ret = - jffs2_flash_write(c, to, vecs[i].iov_len, &thislen, - vecs[i].iov_base); - totlen += thislen; - if (ret || thislen != vecs[i].iov_len) - break; - to += vecs[i].iov_len; - } - writev_out: - if (retlen) - *retlen = totlen; - - return ret; -} - int jffs2_flash_erase(struct jffs2_sb_info * c, struct jffs2_eraseblock * jeb) { diff --git a/cpukit/libfs/src/jffs2/src/os-rtems.h b/cpukit/libfs/src/jffs2/src/os-rtems.h index 4bc6f5df13..a460fdd839 100644 --- a/cpukit/libfs/src/jffs2/src/os-rtems.h +++ b/cpukit/libfs/src/jffs2/src/os-rtems.h @@ -182,7 +182,11 @@ static inline void jffs2_erase_pending_trigger(struct jffs2_sb_info *c) #define SECTOR_ADDR(x) ( ((unsigned long)(x) & ~(c->sector_size-1)) ) #ifndef CONFIG_JFFS2_FS_WRITEBUFFER +#ifdef CONFIG_JFFS2_SUMMARY +#define jffs2_can_mark_obsolete(c) (0) +#else #define jffs2_can_mark_obsolete(c) (1) +#endif #define jffs2_is_writebuffered(c) (0) #define jffs2_cleanmarker_oob(c) (0) #define jffs2_write_nand_cleanmarker(c,jeb) (-EIO) @@ -204,7 +208,11 @@ static inline void jffs2_erase_pending_trigger(struct jffs2_sb_info *c) #define MTD_BIT_WRITEABLE 0x800 #define jffs2_is_writebuffered(c) (c->wbuf != NULL) +#ifdef CONFIG_JFFS2_SUMMARY +#define jffs2_can_mark_obsolete(c) (0) +#else #define jffs2_can_mark_obsolete(c) (OFNI_BS_2SFFJ(c)->s_flash_control->block_is_bad == NULL) +#endif #define jffs2_cleanmarker_oob(c) (OFNI_BS_2SFFJ(c)->s_flash_control->block_is_bad != NULL) diff --git a/cpukit/libfs/src/jffs2/src/summary.c b/cpukit/libfs/src/jffs2/src/summary.c index 4fe6451987..3f68de1d2e 100644 --- a/cpukit/libfs/src/jffs2/src/summary.c +++ b/cpukit/libfs/src/jffs2/src/summary.c @@ -127,7 +127,27 @@ int jffs2_sum_add_inode_mem(struct jffs2_summary *s, struct jffs2_raw_inode *ri, temp->totlen = ri->totlen; temp->next = NULL; +#ifdef __rtems__ + /* cast through void* for type warnings */ + void *alignment_temp = temp; + /* + * logic copied from jffs2_sum_add_mem above to avoid array bounds + * issues caused by unions + */ + if (!s->sum_list_head) + s->sum_list_head = alignment_temp; + if (s->sum_list_tail) + s->sum_list_tail->u.next = alignment_temp; + s->sum_list_tail = alignment_temp; + + s->sum_size += JFFS2_SUMMARY_INODE_SIZE; + s->sum_num++; + dbg_summary("inode (%u) added to summary\n", + je32_to_cpu(temp->inode)); + return 0; +#else return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp); +#endif } int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *rd, @@ -151,7 +171,12 @@ int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *r memcpy(temp->name, rd->name, rd->nsize); +#ifdef __rtems__ + void *alignment_cast = temp; + return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)alignment_cast); +#else return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp); +#endif } #ifdef CONFIG_JFFS2_FS_XATTR @@ -275,7 +300,12 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs, temp->totlen = node->i.totlen; temp->next = NULL; +#ifdef __rtems__ + void *alignment_cast = temp; + return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)alignment_cast); +#else return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp); +#endif } case JFFS2_NODETYPE_DIRENT: { @@ -309,7 +339,12 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs, break; } +#ifdef __rtems__ + void *alignment_cast = temp; + return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)alignment_cast); +#else return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp); +#endif } #ifdef CONFIG_JFFS2_FS_XATTR case JFFS2_NODETYPE_XATTR: { diff --git a/cpukit/libfs/src/jffs2/src/summary.h b/cpukit/libfs/src/jffs2/src/summary.h index 36d9a12807..e323e10219 100644 --- a/cpukit/libfs/src/jffs2/src/summary.h +++ b/cpukit/libfs/src/jffs2/src/summary.h @@ -13,11 +13,20 @@ #ifndef JFFS2_SUMMARY_H #define JFFS2_SUMMARY_H +#ifndef __rtems__ /* Limit summary size to 64KiB so that we can kmalloc it. If the summary is larger than that, we have to just ditch it and avoid using summary for the eraseblock in question... and it probably doesn't hurt us much anyway. */ #define MAX_SUMMARY_SIZE 65536 +#else /* __rtems__ */ +/* + * RTEMS uses a flat memory space with no virtual addressing, so allocation for + * DMA purposes does not require the special consideration that the Linux kernel + * requires. Allow summary nodes to consume up to a sector. + */ +#define MAX_SUMMARY_SIZE c->sector_size +#endif /* __rtems__ */ #include #include @@ -198,7 +207,18 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb #define jffs2_sum_disable_collecting(a) #define jffs2_sum_is_disabled(a) (0) #define jffs2_sum_reset_collected(a) do { } while (0) +#ifndef __rtems__ #define jffs2_sum_add_kvec(a,b,c,d) (0) +#else +#define jffs2_sum_add_kvec(a,b,c,d) \ + ({ \ + (void)a; \ + (void)b; \ + (void)c; \ + (void)d; \ + 0; \ + }) +#endif #define jffs2_sum_move_collected(a,b) do { } while (0) #define jffs2_sum_write_sumnode(a) (0) #define jffs2_sum_add_padding_mem(a,b) do { } while (0) diff --git a/spec/build/cpukit/cpuopts.yml b/spec/build/cpukit/cpuopts.yml index 1d28ace552..17a3856bb4 100644 --- a/spec/build/cpukit/cpuopts.yml +++ b/spec/build/cpukit/cpuopts.yml @@ -77,5 +77,7 @@ links: uid: optnocoverageldflags - role: build-dependency uid: optversion +- role: build-dependency + uid: optjffs2summary target: cpukit/include/rtems/score/cpuopts.h type: build diff --git a/spec/build/cpukit/libjffs2.yml b/spec/build/cpukit/libjffs2.yml index 26765adcf8..eb080c15ec 100644 --- a/spec/build/cpukit/libjffs2.yml +++ b/spec/build/cpukit/libjffs2.yml @@ -16,7 +16,9 @@ install: source: - cpukit/include/rtems/jffs2.h install-path: ${BSP_LIBDIR} -links: [] +links: +- role: build-dependency + uid: objjffs2summary source: - cpukit/libfs/src/jffs2/src/build.c - cpukit/libfs/src/jffs2/src/compr.c @@ -36,5 +38,6 @@ source: - cpukit/libfs/src/jffs2/src/scan.c - cpukit/libfs/src/jffs2/src/wbuf.c - cpukit/libfs/src/jffs2/src/write.c +- cpukit/libfs/src/jffs2/src/writev.c target: jffs2 type: build diff --git a/spec/build/cpukit/objjffs2summary.yml b/spec/build/cpukit/objjffs2summary.yml new file mode 100644 index 0000000000..46f7a04ceb --- /dev/null +++ b/spec/build/cpukit/objjffs2summary.yml @@ -0,0 +1,15 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +build-type: objects +cflags: [] +copyrights: +- Copyright (C) 2025 On-Line Applications Research (OAR) Corporation +cppflags: [] +cxxflags: [] +enabled-by: +- CONFIG_JFFS2_SUMMARY +includes: [] +install: [] +links: [] +source: +- cpukit/libfs/src/jffs2/src/summary.c +type: build diff --git a/spec/build/cpukit/optjffs2summary.yml b/spec/build/cpukit/optjffs2summary.yml new file mode 100644 index 0000000000..e9af603ce5 --- /dev/null +++ b/spec/build/cpukit/optjffs2summary.yml @@ -0,0 +1,17 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +actions: +- get-boolean: null +- env-enable: null +- define-condition: null +build-type: option +copyrights: +- Copyright (C) 2025 On-Line Applications Research (OAR) Corporation +default: +- enabled-by: true + value: false +description: | + Enable support for JFFS2 Erase Block Summary (EBS) +enabled-by: true +links: [] +name: CONFIG_JFFS2_SUMMARY +type: build