UBIFS: add R/O compatibility
Now UBIFS is supported by u-boot. If we ever decide to change the media format, then people will have to upgrade their u-boots to mount new format images. However, very often it is possible to preserve R/O forward-compatibility, even though the write forward-compatibility is not preserved. This patch introduces a new super-block field which stores the R/O compatibility version. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Acked-by: Adrian Hunter <Adrian.Hunter@nokia.com>
This commit is contained in:
parent
fcabb3479e
commit
963f0cf6d1
|
@ -193,6 +193,7 @@ static int create_default_filesystem(struct ubifs_info *c)
|
||||||
if (tmp64 > DEFAULT_MAX_RP_SIZE)
|
if (tmp64 > DEFAULT_MAX_RP_SIZE)
|
||||||
tmp64 = DEFAULT_MAX_RP_SIZE;
|
tmp64 = DEFAULT_MAX_RP_SIZE;
|
||||||
sup->rp_size = cpu_to_le64(tmp64);
|
sup->rp_size = cpu_to_le64(tmp64);
|
||||||
|
sup->ro_compat_version = cpu_to_le32(UBIFS_RO_COMPAT_VERSION);
|
||||||
|
|
||||||
err = ubifs_write_node(c, sup, UBIFS_SB_NODE_SZ, 0, 0, UBI_LONGTERM);
|
err = ubifs_write_node(c, sup, UBIFS_SB_NODE_SZ, 0, 0, UBI_LONGTERM);
|
||||||
kfree(sup);
|
kfree(sup);
|
||||||
|
@ -532,17 +533,39 @@ int ubifs_read_superblock(struct ubifs_info *c)
|
||||||
if (IS_ERR(sup))
|
if (IS_ERR(sup))
|
||||||
return PTR_ERR(sup);
|
return PTR_ERR(sup);
|
||||||
|
|
||||||
|
c->fmt_version = le32_to_cpu(sup->fmt_version);
|
||||||
|
c->ro_compat_version = le32_to_cpu(sup->ro_compat_version);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The software supports all previous versions but not future versions,
|
* The software supports all previous versions but not future versions,
|
||||||
* due to the unavailability of time-travelling equipment.
|
* due to the unavailability of time-travelling equipment.
|
||||||
*/
|
*/
|
||||||
c->fmt_version = le32_to_cpu(sup->fmt_version);
|
|
||||||
if (c->fmt_version > UBIFS_FORMAT_VERSION) {
|
if (c->fmt_version > UBIFS_FORMAT_VERSION) {
|
||||||
ubifs_err("on-flash format version is %d, but software only "
|
struct super_block *sb = c->vfs_sb;
|
||||||
"supports up to version %d", c->fmt_version,
|
int mounting_ro = sb->s_flags & MS_RDONLY;
|
||||||
UBIFS_FORMAT_VERSION);
|
|
||||||
err = -EINVAL;
|
ubifs_assert(!c->ro_media || mounting_ro);
|
||||||
goto out;
|
if (!mounting_ro ||
|
||||||
|
c->ro_compat_version > UBIFS_RO_COMPAT_VERSION) {
|
||||||
|
ubifs_err("on-flash format version is w%d/r%d, but "
|
||||||
|
"software only supports up to version "
|
||||||
|
"w%d/r%d", c->fmt_version,
|
||||||
|
c->ro_compat_version, UBIFS_FORMAT_VERSION,
|
||||||
|
UBIFS_RO_COMPAT_VERSION);
|
||||||
|
if (c->ro_compat_version <= UBIFS_RO_COMPAT_VERSION) {
|
||||||
|
ubifs_msg("only R/O mounting is possible");
|
||||||
|
err = -EROFS;
|
||||||
|
} else
|
||||||
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The FS is mounted R/O, and the media format is
|
||||||
|
* R/O-compatible with the UBIFS implementation, so we can
|
||||||
|
* mount.
|
||||||
|
*/
|
||||||
|
c->rw_incompat = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->fmt_version < 3) {
|
if (c->fmt_version < 3) {
|
||||||
|
|
|
@ -1351,8 +1351,9 @@ static int mount_ubifs(struct ubifs_info *c)
|
||||||
x = (long long)c->log_lebs * c->leb_size + c->max_bud_bytes;
|
x = (long long)c->log_lebs * c->leb_size + c->max_bud_bytes;
|
||||||
ubifs_msg("journal size: %lld bytes (%lld KiB, %lld MiB, %d "
|
ubifs_msg("journal size: %lld bytes (%lld KiB, %lld MiB, %d "
|
||||||
"LEBs)", x, x >> 10, x >> 20, c->log_lebs + c->max_bud_cnt);
|
"LEBs)", x, x >> 10, x >> 20, c->log_lebs + c->max_bud_cnt);
|
||||||
ubifs_msg("media format: %d (latest is %d)",
|
ubifs_msg("media format: w%d/r%d (latest is w%d/r%d)",
|
||||||
c->fmt_version, UBIFS_FORMAT_VERSION);
|
c->fmt_version, c->ro_compat_version,
|
||||||
|
UBIFS_FORMAT_VERSION, UBIFS_RO_COMPAT_VERSION);
|
||||||
ubifs_msg("default compressor: %s", ubifs_compr_name(c->default_compr));
|
ubifs_msg("default compressor: %s", ubifs_compr_name(c->default_compr));
|
||||||
ubifs_msg("reserved for root: %llu bytes (%llu KiB)",
|
ubifs_msg("reserved for root: %llu bytes (%llu KiB)",
|
||||||
c->report_rp_size, c->report_rp_size >> 10);
|
c->report_rp_size, c->report_rp_size >> 10);
|
||||||
|
@ -1492,6 +1493,15 @@ static int ubifs_remount_rw(struct ubifs_info *c)
|
||||||
{
|
{
|
||||||
int err, lnum;
|
int err, lnum;
|
||||||
|
|
||||||
|
if (c->rw_incompat) {
|
||||||
|
ubifs_err("the file-system is not R/W-compatible");
|
||||||
|
ubifs_msg("on-flash format version is w%d/r%d, but software "
|
||||||
|
"only supports up to version w%d/r%d", c->fmt_version,
|
||||||
|
c->ro_compat_version, UBIFS_FORMAT_VERSION,
|
||||||
|
UBIFS_RO_COMPAT_VERSION);
|
||||||
|
return -EROFS;
|
||||||
|
}
|
||||||
|
|
||||||
mutex_lock(&c->umount_mutex);
|
mutex_lock(&c->umount_mutex);
|
||||||
dbg_save_space_info(c);
|
dbg_save_space_info(c);
|
||||||
c->remounting_rw = 1;
|
c->remounting_rw = 1;
|
||||||
|
|
|
@ -36,9 +36,31 @@
|
||||||
/* UBIFS node magic number (must not have the padding byte first or last) */
|
/* UBIFS node magic number (must not have the padding byte first or last) */
|
||||||
#define UBIFS_NODE_MAGIC 0x06101831
|
#define UBIFS_NODE_MAGIC 0x06101831
|
||||||
|
|
||||||
/* UBIFS on-flash format version */
|
/*
|
||||||
|
* UBIFS on-flash format version. This version is increased when the on-flash
|
||||||
|
* format is changing. If this happens, UBIFS is will support older versions as
|
||||||
|
* well. But older UBIFS code will not support newer formats. Format changes
|
||||||
|
* will be rare and only when absolutely necessary, e.g. to fix a bug or to add
|
||||||
|
* a new feature.
|
||||||
|
*
|
||||||
|
* UBIFS went into mainline kernel with format version 4. The older formats
|
||||||
|
* were development formats.
|
||||||
|
*/
|
||||||
#define UBIFS_FORMAT_VERSION 4
|
#define UBIFS_FORMAT_VERSION 4
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read-only compatibility version. If the UBIFS format is changed, older UBIFS
|
||||||
|
* implementations will not be able to mount newer formats in read-write mode.
|
||||||
|
* However, depending on the change, it may be possible to mount newer formats
|
||||||
|
* in R/O mode. This is indicated by the R/O compatibility version which is
|
||||||
|
* stored in the super-block.
|
||||||
|
*
|
||||||
|
* This is needed to support boot-loaders which only need R/O mounting. With
|
||||||
|
* this flag it is possible to do UBIFS format changes without a need to update
|
||||||
|
* boot-loaders.
|
||||||
|
*/
|
||||||
|
#define UBIFS_RO_COMPAT_VERSION 0
|
||||||
|
|
||||||
/* Minimum logical eraseblock size in bytes */
|
/* Minimum logical eraseblock size in bytes */
|
||||||
#define UBIFS_MIN_LEB_SZ (15*1024)
|
#define UBIFS_MIN_LEB_SZ (15*1024)
|
||||||
|
|
||||||
|
@ -53,7 +75,7 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If compressed data length is less than %UBIFS_MIN_COMPRESS_DIFF bytes
|
* If compressed data length is less than %UBIFS_MIN_COMPRESS_DIFF bytes
|
||||||
* shorter than uncompressed data length, UBIFS preferes to leave this data
|
* shorter than uncompressed data length, UBIFS prefers to leave this data
|
||||||
* node uncompress, because it'll be read faster.
|
* node uncompress, because it'll be read faster.
|
||||||
*/
|
*/
|
||||||
#define UBIFS_MIN_COMPRESS_DIFF 64
|
#define UBIFS_MIN_COMPRESS_DIFF 64
|
||||||
|
@ -586,6 +608,7 @@ struct ubifs_pad_node {
|
||||||
* @padding2: reserved for future, zeroes
|
* @padding2: reserved for future, zeroes
|
||||||
* @time_gran: time granularity in nanoseconds
|
* @time_gran: time granularity in nanoseconds
|
||||||
* @uuid: UUID generated when the file system image was created
|
* @uuid: UUID generated when the file system image was created
|
||||||
|
* @ro_compat_version: UBIFS R/O compatibility version
|
||||||
*/
|
*/
|
||||||
struct ubifs_sb_node {
|
struct ubifs_sb_node {
|
||||||
struct ubifs_ch ch;
|
struct ubifs_ch ch;
|
||||||
|
@ -612,7 +635,8 @@ struct ubifs_sb_node {
|
||||||
__le64 rp_size;
|
__le64 rp_size;
|
||||||
__le32 time_gran;
|
__le32 time_gran;
|
||||||
__u8 uuid[16];
|
__u8 uuid[16];
|
||||||
__u8 padding2[3972];
|
__le32 ro_compat_version;
|
||||||
|
__u8 padding2[3968];
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -934,6 +934,7 @@ struct ubifs_debug_info;
|
||||||
* by @commit_sem
|
* by @commit_sem
|
||||||
* @cnt_lock: protects @highest_inum and @max_sqnum counters
|
* @cnt_lock: protects @highest_inum and @max_sqnum counters
|
||||||
* @fmt_version: UBIFS on-flash format version
|
* @fmt_version: UBIFS on-flash format version
|
||||||
|
* @ro_compat_version: R/O compatibility version
|
||||||
* @uuid: UUID from super block
|
* @uuid: UUID from super block
|
||||||
*
|
*
|
||||||
* @lhead_lnum: log head logical eraseblock number
|
* @lhead_lnum: log head logical eraseblock number
|
||||||
|
@ -966,6 +967,7 @@ struct ubifs_debug_info;
|
||||||
* recovery)
|
* recovery)
|
||||||
* @bulk_read: enable bulk-reads
|
* @bulk_read: enable bulk-reads
|
||||||
* @default_compr: default compression algorithm (%UBIFS_COMPR_LZO, etc)
|
* @default_compr: default compression algorithm (%UBIFS_COMPR_LZO, etc)
|
||||||
|
* @rw_incompat: the media is not R/W compatible
|
||||||
*
|
*
|
||||||
* @tnc_mutex: protects the Tree Node Cache (TNC), @zroot, @cnext, @enext, and
|
* @tnc_mutex: protects the Tree Node Cache (TNC), @zroot, @cnext, @enext, and
|
||||||
* @calc_idx_sz
|
* @calc_idx_sz
|
||||||
|
@ -1179,6 +1181,7 @@ struct ubifs_info {
|
||||||
unsigned long long cmt_no;
|
unsigned long long cmt_no;
|
||||||
spinlock_t cnt_lock;
|
spinlock_t cnt_lock;
|
||||||
int fmt_version;
|
int fmt_version;
|
||||||
|
int ro_compat_version;
|
||||||
unsigned char uuid[16];
|
unsigned char uuid[16];
|
||||||
|
|
||||||
int lhead_lnum;
|
int lhead_lnum;
|
||||||
|
@ -1207,6 +1210,7 @@ struct ubifs_info {
|
||||||
unsigned int no_chk_data_crc:1;
|
unsigned int no_chk_data_crc:1;
|
||||||
unsigned int bulk_read:1;
|
unsigned int bulk_read:1;
|
||||||
unsigned int default_compr:2;
|
unsigned int default_compr:2;
|
||||||
|
unsigned int rw_incompat:1;
|
||||||
|
|
||||||
struct mutex tnc_mutex;
|
struct mutex tnc_mutex;
|
||||||
struct ubifs_zbranch zroot;
|
struct ubifs_zbranch zroot;
|
||||||
|
|
Loading…
Reference in New Issue