cpukit/jffs2,spec: Add summary support to the build

This adds summary support to the build with a global option to enable
this support and necessary changes to the imported summary support
source to integrate it into the build system and resolve errors.

Closes #5398
This commit is contained in:
Kinsey Moore
2024-03-29 17:05:39 -05:00
committed by Kinsey Moore
parent d0974e6bae
commit fa6c222bdc
10 changed files with 133 additions and 98 deletions

View File

@@ -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)

View File

@@ -1,6 +1,10 @@
#ifndef __LINUX_TYPES_H__
#define __LINUX_TYPES_H__
#ifdef CONFIG_JFFS2_SUMMARY
#include <sys/socket.h>
#define __must_hold(a)
#endif
#include <sys/types.h>
#include <stdint.h>

View File

@@ -15,6 +15,7 @@
*/
#include <linux/kernel.h>
#include <linux/mtd/mtd.h>
#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)
{

View File

@@ -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)

View File

@@ -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: {

View File

@@ -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 <linux/uio.h>
#include <linux/jffs2.h>
@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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