#include "ubifs.h"
#include <linux/random.h>
+#include <linux/math64.h>
/*
* Default journal size in logical eraseblocks as a percent of total
int err, tmp, jnl_lebs, log_lebs, max_buds, main_lebs, main_first;
int lpt_lebs, lpt_first, orph_lebs, big_lpt, ino_waste, sup_flags = 0;
int min_leb_cnt = UBIFS_MIN_LEB_CNT;
- uint64_t tmp64, main_bytes;
+ long long tmp64, main_bytes;
__le64 tmp_le64;
/* Some functions called from here depend on the @c->key_len filed */
if (!sup)
return -ENOMEM;
- tmp64 = (uint64_t)max_buds * c->leb_size;
+ tmp64 = (long long)max_buds * c->leb_size;
if (big_lpt)
sup_flags |= UBIFS_FLG_BIGLPT;
generate_random_uuid(sup->uuid);
- main_bytes = (uint64_t)main_lebs * c->leb_size;
- tmp64 = main_bytes * DEFAULT_RP_PERCENT;
- do_div(tmp64, 100);
+ main_bytes = (long long)main_lebs * c->leb_size;
+ tmp64 = div_u64(main_bytes * DEFAULT_RP_PERCENT, 100);
if (tmp64 > DEFAULT_MAX_RP_SIZE)
tmp64 = DEFAULT_MAX_RP_SIZE;
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);
kfree(sup);
if (IS_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,
* due to the unavailability of time-travelling equipment.
*/
- c->fmt_version = le32_to_cpu(sup->fmt_version);
if (c->fmt_version > UBIFS_FORMAT_VERSION) {
- ubifs_err("on-flash format version is %d, but software only "
- "supports up to version %d", c->fmt_version,
- UBIFS_FORMAT_VERSION);
- err = -EINVAL;
- goto out;
+ struct super_block *sb = c->vfs_sb;
+ int mounting_ro = sb->s_flags & MS_RDONLY;
+
+ ubifs_assert(!c->ro_media || mounting_ro);
+ 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) {
c->main_lebs = c->leb_cnt - UBIFS_SB_LEBS - UBIFS_MST_LEBS;
c->main_lebs -= c->log_lebs + c->lpt_lebs + c->orph_lebs;
c->main_first = c->leb_cnt - c->main_lebs;
- c->report_rp_size = ubifs_reported_space(c, c->rp_size);
err = validate_sb(c, sup);
out: