diff options
| author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2009-03-27 10:21:14 +0100 | 
|---|---|---|
| committer | Wolfgang Denk <wd@denx.de> | 2009-04-04 22:44:22 +0200 | 
| commit | febd7e4174e54579c9aa165c85c519fe5288f9d2 (patch) | |
| tree | 77824e8f6861c68b4151824d2e25cfb1216ee784 | |
| parent | 852dbfdd56f68eb67d138b306a64e4de58dabb91 (diff) | |
| download | olio-uboot-2014.01-febd7e4174e54579c9aa165c85c519fe5288f9d2.tar.xz olio-uboot-2014.01-febd7e4174e54579c9aa165c85c519fe5288f9d2.zip | |
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>
Signed-off-by: Stefan Roese <sr@denx.de>
| -rw-r--r-- | fs/ubifs/sb.c | 34 | ||||
| -rw-r--r-- | fs/ubifs/super.c | 14 | ||||
| -rw-r--r-- | fs/ubifs/ubifs-media.h | 30 | ||||
| -rw-r--r-- | fs/ubifs/ubifs.h | 4 | 
4 files changed, 71 insertions, 11 deletions
| diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c index 9708fda95..00c9cd31a 100644 --- a/fs/ubifs/sb.c +++ b/fs/ubifs/sb.c @@ -235,17 +235,39 @@ int ubifs_read_superblock(struct ubifs_info *c)  	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) { diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 95f2a4125..391dea425 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -727,8 +727,9 @@ static int mount_ubifs(struct ubifs_info *c)  	x = (long long)c->log_lebs * c->leb_size + c->max_bud_bytes;  	ubifs_msg("journal size:       %lld bytes (%lld KiB, %lld MiB, %d "  		  "LEBs)", x, x >> 10, x >> 20, c->log_lebs + c->max_bud_cnt); -	ubifs_msg("media format:       %d (latest is %d)", -		  c->fmt_version, UBIFS_FORMAT_VERSION); +	ubifs_msg("media format:       w%d/r%d (latest is w%d/r%d)", +		  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("reserved for root:  %llu bytes (%llu KiB)",  		c->report_rp_size, c->report_rp_size >> 10); @@ -967,6 +968,15 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)  	if (c->max_inode_sz > MAX_LFS_FILESIZE)  		sb->s_maxbytes = c->max_inode_sz = MAX_LFS_FILESIZE; +	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);  	err = mount_ubifs(c);  	if (err) { diff --git a/fs/ubifs/ubifs-media.h b/fs/ubifs/ubifs-media.h index b25fc36cf..3eee07e0c 100644 --- a/fs/ubifs/ubifs-media.h +++ b/fs/ubifs/ubifs-media.h @@ -36,9 +36,31 @@  /* UBIFS node magic number (must not have the padding byte first or last) */  #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 +/* + * 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 */  #define UBIFS_MIN_LEB_SZ (15*1024) @@ -53,7 +75,7 @@  /*   * 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.   */  #define UBIFS_MIN_COMPRESS_DIFF 64 @@ -586,6 +608,7 @@ struct ubifs_pad_node {   * @padding2: reserved for future, zeroes   * @time_gran: time granularity in nanoseconds   * @uuid: UUID generated when the file system image was created + * @ro_compat_version: UBIFS R/O compatibility version   */  struct ubifs_sb_node {  	struct ubifs_ch ch; @@ -612,7 +635,8 @@ struct ubifs_sb_node {  	__le64 rp_size;  	__le32 time_gran;  	__u8 uuid[16]; -	__u8 padding2[3972]; +	__le32 ro_compat_version; +	__u8 padding2[3968];  } __attribute__ ((packed));  /** diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index f342dd8bf..91351de75 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1386,6 +1386,7 @@ struct ubifs_debug_info;   *          by @commit_sem   * @cnt_lock: protects @highest_inum and @max_sqnum counters   * @fmt_version: UBIFS on-flash format version + * @ro_compat_version: R/O compatibility version   * @uuid: UUID from super block   *   * @lhead_lnum: log head logical eraseblock number @@ -1418,6 +1419,7 @@ struct ubifs_debug_info;   *                   recovery)   * @bulk_read: enable bulk-reads   * @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   *             @calc_idx_sz @@ -1628,6 +1630,7 @@ struct ubifs_info {  	unsigned long long cmt_no;  	spinlock_t cnt_lock;  	int fmt_version; +	int ro_compat_version;  	unsigned char uuid[16];  	int lhead_lnum; @@ -1656,6 +1659,7 @@ struct ubifs_info {  	unsigned int no_chk_data_crc:1;  	unsigned int bulk_read:1;  	unsigned int default_compr:2; +	unsigned int rw_incompat:1;  	struct mutex tnc_mutex;  	struct ubifs_zbranch zroot; |