diff options
author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2009-03-26 06:51:21 -0400 |
---|---|---|
committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2009-03-26 10:36:20 -0400 |
commit | 963f0cf6d116d83c558a8efe9045c1c5ad7aed34 (patch) | |
tree | 43937f0d742bfac7dfc1a00bae8f72e98dc87425 | |
parent | fcabb3479e2b15abfd2d2ef5363295f16e98b2d7 (diff) |
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>
-rw-r--r-- | fs/ubifs/sb.c | 35 | ||||
-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, 72 insertions, 11 deletions
diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c index 0dec47c87c6d..57085e43320f 100644 --- a/fs/ubifs/sb.c +++ b/fs/ubifs/sb.c | |||
@@ -193,6 +193,7 @@ static int create_default_filesystem(struct ubifs_info *c) | |||
193 | if (tmp64 > DEFAULT_MAX_RP_SIZE) | 193 | if (tmp64 > DEFAULT_MAX_RP_SIZE) |
194 | tmp64 = DEFAULT_MAX_RP_SIZE; | 194 | tmp64 = DEFAULT_MAX_RP_SIZE; |
195 | sup->rp_size = cpu_to_le64(tmp64); | 195 | sup->rp_size = cpu_to_le64(tmp64); |
196 | sup->ro_compat_version = cpu_to_le32(UBIFS_RO_COMPAT_VERSION); | ||
196 | 197 | ||
197 | err = ubifs_write_node(c, sup, UBIFS_SB_NODE_SZ, 0, 0, UBI_LONGTERM); | 198 | err = ubifs_write_node(c, sup, UBIFS_SB_NODE_SZ, 0, 0, UBI_LONGTERM); |
198 | kfree(sup); | 199 | kfree(sup); |
@@ -532,17 +533,39 @@ int ubifs_read_superblock(struct ubifs_info *c) | |||
532 | if (IS_ERR(sup)) | 533 | if (IS_ERR(sup)) |
533 | return PTR_ERR(sup); | 534 | return PTR_ERR(sup); |
534 | 535 | ||
536 | c->fmt_version = le32_to_cpu(sup->fmt_version); | ||
537 | c->ro_compat_version = le32_to_cpu(sup->ro_compat_version); | ||
538 | |||
535 | /* | 539 | /* |
536 | * The software supports all previous versions but not future versions, | 540 | * The software supports all previous versions but not future versions, |
537 | * due to the unavailability of time-travelling equipment. | 541 | * due to the unavailability of time-travelling equipment. |
538 | */ | 542 | */ |
539 | c->fmt_version = le32_to_cpu(sup->fmt_version); | ||
540 | if (c->fmt_version > UBIFS_FORMAT_VERSION) { | 543 | if (c->fmt_version > UBIFS_FORMAT_VERSION) { |
541 | ubifs_err("on-flash format version is %d, but software only " | 544 | struct super_block *sb = c->vfs_sb; |
542 | "supports up to version %d", c->fmt_version, | 545 | int mounting_ro = sb->s_flags & MS_RDONLY; |
543 | UBIFS_FORMAT_VERSION); | 546 | |
544 | err = -EINVAL; | 547 | ubifs_assert(!c->ro_media || mounting_ro); |
545 | goto out; | 548 | if (!mounting_ro || |
549 | c->ro_compat_version > UBIFS_RO_COMPAT_VERSION) { | ||
550 | ubifs_err("on-flash format version is w%d/r%d, but " | ||
551 | "software only supports up to version " | ||
552 | "w%d/r%d", c->fmt_version, | ||
553 | c->ro_compat_version, UBIFS_FORMAT_VERSION, | ||
554 | UBIFS_RO_COMPAT_VERSION); | ||
555 | if (c->ro_compat_version <= UBIFS_RO_COMPAT_VERSION) { | ||
556 | ubifs_msg("only R/O mounting is possible"); | ||
557 | err = -EROFS; | ||
558 | } else | ||
559 | err = -EINVAL; | ||
560 | goto out; | ||
561 | } | ||
562 | |||
563 | /* | ||
564 | * The FS is mounted R/O, and the media format is | ||
565 | * R/O-compatible with the UBIFS implementation, so we can | ||
566 | * mount. | ||
567 | */ | ||
568 | c->rw_incompat = 1; | ||
546 | } | 569 | } |
547 | 570 | ||
548 | if (c->fmt_version < 3) { | 571 | if (c->fmt_version < 3) { |
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 372c7fb66531..302a2056422e 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
@@ -1351,8 +1351,9 @@ static int mount_ubifs(struct ubifs_info *c) | |||
1351 | x = (long long)c->log_lebs * c->leb_size + c->max_bud_bytes; | 1351 | x = (long long)c->log_lebs * c->leb_size + c->max_bud_bytes; |
1352 | ubifs_msg("journal size: %lld bytes (%lld KiB, %lld MiB, %d " | 1352 | ubifs_msg("journal size: %lld bytes (%lld KiB, %lld MiB, %d " |
1353 | "LEBs)", x, x >> 10, x >> 20, c->log_lebs + c->max_bud_cnt); | 1353 | "LEBs)", x, x >> 10, x >> 20, c->log_lebs + c->max_bud_cnt); |
1354 | ubifs_msg("media format: %d (latest is %d)", | 1354 | ubifs_msg("media format: w%d/r%d (latest is w%d/r%d)", |
1355 | c->fmt_version, UBIFS_FORMAT_VERSION); | 1355 | c->fmt_version, c->ro_compat_version, |
1356 | UBIFS_FORMAT_VERSION, UBIFS_RO_COMPAT_VERSION); | ||
1356 | ubifs_msg("default compressor: %s", ubifs_compr_name(c->default_compr)); | 1357 | ubifs_msg("default compressor: %s", ubifs_compr_name(c->default_compr)); |
1357 | ubifs_msg("reserved for root: %llu bytes (%llu KiB)", | 1358 | ubifs_msg("reserved for root: %llu bytes (%llu KiB)", |
1358 | c->report_rp_size, c->report_rp_size >> 10); | 1359 | c->report_rp_size, c->report_rp_size >> 10); |
@@ -1492,6 +1493,15 @@ static int ubifs_remount_rw(struct ubifs_info *c) | |||
1492 | { | 1493 | { |
1493 | int err, lnum; | 1494 | int err, lnum; |
1494 | 1495 | ||
1496 | if (c->rw_incompat) { | ||
1497 | ubifs_err("the file-system is not R/W-compatible"); | ||
1498 | ubifs_msg("on-flash format version is w%d/r%d, but software " | ||
1499 | "only supports up to version w%d/r%d", c->fmt_version, | ||
1500 | c->ro_compat_version, UBIFS_FORMAT_VERSION, | ||
1501 | UBIFS_RO_COMPAT_VERSION); | ||
1502 | return -EROFS; | ||
1503 | } | ||
1504 | |||
1495 | mutex_lock(&c->umount_mutex); | 1505 | mutex_lock(&c->umount_mutex); |
1496 | dbg_save_space_info(c); | 1506 | dbg_save_space_info(c); |
1497 | c->remounting_rw = 1; | 1507 | c->remounting_rw = 1; |
diff --git a/fs/ubifs/ubifs-media.h b/fs/ubifs/ubifs-media.h index b25fc36cf72f..3eee07e0c495 100644 --- a/fs/ubifs/ubifs-media.h +++ b/fs/ubifs/ubifs-media.h | |||
@@ -36,9 +36,31 @@ | |||
36 | /* UBIFS node magic number (must not have the padding byte first or last) */ | 36 | /* UBIFS node magic number (must not have the padding byte first or last) */ |
37 | #define UBIFS_NODE_MAGIC 0x06101831 | 37 | #define UBIFS_NODE_MAGIC 0x06101831 |
38 | 38 | ||
39 | /* UBIFS on-flash format version */ | 39 | /* |
40 | * UBIFS on-flash format version. This version is increased when the on-flash | ||
41 | * format is changing. If this happens, UBIFS is will support older versions as | ||
42 | * well. But older UBIFS code will not support newer formats. Format changes | ||
43 | * will be rare and only when absolutely necessary, e.g. to fix a bug or to add | ||
44 | * a new feature. | ||
45 | * | ||
46 | * UBIFS went into mainline kernel with format version 4. The older formats | ||
47 | * were development formats. | ||
48 | */ | ||
40 | #define UBIFS_FORMAT_VERSION 4 | 49 | #define UBIFS_FORMAT_VERSION 4 |
41 | 50 | ||
51 | /* | ||
52 | * Read-only compatibility version. If the UBIFS format is changed, older UBIFS | ||
53 | * implementations will not be able to mount newer formats in read-write mode. | ||
54 | * However, depending on the change, it may be possible to mount newer formats | ||
55 | * in R/O mode. This is indicated by the R/O compatibility version which is | ||
56 | * stored in the super-block. | ||
57 | * | ||
58 | * This is needed to support boot-loaders which only need R/O mounting. With | ||
59 | * this flag it is possible to do UBIFS format changes without a need to update | ||
60 | * boot-loaders. | ||
61 | */ | ||
62 | #define UBIFS_RO_COMPAT_VERSION 0 | ||
63 | |||
42 | /* Minimum logical eraseblock size in bytes */ | 64 | /* Minimum logical eraseblock size in bytes */ |
43 | #define UBIFS_MIN_LEB_SZ (15*1024) | 65 | #define UBIFS_MIN_LEB_SZ (15*1024) |
44 | 66 | ||
@@ -53,7 +75,7 @@ | |||
53 | 75 | ||
54 | /* | 76 | /* |
55 | * If compressed data length is less than %UBIFS_MIN_COMPRESS_DIFF bytes | 77 | * If compressed data length is less than %UBIFS_MIN_COMPRESS_DIFF bytes |
56 | * shorter than uncompressed data length, UBIFS preferes to leave this data | 78 | * shorter than uncompressed data length, UBIFS prefers to leave this data |
57 | * node uncompress, because it'll be read faster. | 79 | * node uncompress, because it'll be read faster. |
58 | */ | 80 | */ |
59 | #define UBIFS_MIN_COMPRESS_DIFF 64 | 81 | #define UBIFS_MIN_COMPRESS_DIFF 64 |
@@ -586,6 +608,7 @@ struct ubifs_pad_node { | |||
586 | * @padding2: reserved for future, zeroes | 608 | * @padding2: reserved for future, zeroes |
587 | * @time_gran: time granularity in nanoseconds | 609 | * @time_gran: time granularity in nanoseconds |
588 | * @uuid: UUID generated when the file system image was created | 610 | * @uuid: UUID generated when the file system image was created |
611 | * @ro_compat_version: UBIFS R/O compatibility version | ||
589 | */ | 612 | */ |
590 | struct ubifs_sb_node { | 613 | struct ubifs_sb_node { |
591 | struct ubifs_ch ch; | 614 | struct ubifs_ch ch; |
@@ -612,7 +635,8 @@ struct ubifs_sb_node { | |||
612 | __le64 rp_size; | 635 | __le64 rp_size; |
613 | __le32 time_gran; | 636 | __le32 time_gran; |
614 | __u8 uuid[16]; | 637 | __u8 uuid[16]; |
615 | __u8 padding2[3972]; | 638 | __le32 ro_compat_version; |
639 | __u8 padding2[3968]; | ||
616 | } __attribute__ ((packed)); | 640 | } __attribute__ ((packed)); |
617 | 641 | ||
618 | /** | 642 | /** |
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index a53b9a6df2be..0a8341e14088 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h | |||
@@ -934,6 +934,7 @@ struct ubifs_debug_info; | |||
934 | * by @commit_sem | 934 | * by @commit_sem |
935 | * @cnt_lock: protects @highest_inum and @max_sqnum counters | 935 | * @cnt_lock: protects @highest_inum and @max_sqnum counters |
936 | * @fmt_version: UBIFS on-flash format version | 936 | * @fmt_version: UBIFS on-flash format version |
937 | * @ro_compat_version: R/O compatibility version | ||
937 | * @uuid: UUID from super block | 938 | * @uuid: UUID from super block |
938 | * | 939 | * |
939 | * @lhead_lnum: log head logical eraseblock number | 940 | * @lhead_lnum: log head logical eraseblock number |
@@ -966,6 +967,7 @@ struct ubifs_debug_info; | |||
966 | * recovery) | 967 | * recovery) |
967 | * @bulk_read: enable bulk-reads | 968 | * @bulk_read: enable bulk-reads |
968 | * @default_compr: default compression algorithm (%UBIFS_COMPR_LZO, etc) | 969 | * @default_compr: default compression algorithm (%UBIFS_COMPR_LZO, etc) |
970 | * @rw_incompat: the media is not R/W compatible | ||
969 | * | 971 | * |
970 | * @tnc_mutex: protects the Tree Node Cache (TNC), @zroot, @cnext, @enext, and | 972 | * @tnc_mutex: protects the Tree Node Cache (TNC), @zroot, @cnext, @enext, and |
971 | * @calc_idx_sz | 973 | * @calc_idx_sz |
@@ -1179,6 +1181,7 @@ struct ubifs_info { | |||
1179 | unsigned long long cmt_no; | 1181 | unsigned long long cmt_no; |
1180 | spinlock_t cnt_lock; | 1182 | spinlock_t cnt_lock; |
1181 | int fmt_version; | 1183 | int fmt_version; |
1184 | int ro_compat_version; | ||
1182 | unsigned char uuid[16]; | 1185 | unsigned char uuid[16]; |
1183 | 1186 | ||
1184 | int lhead_lnum; | 1187 | int lhead_lnum; |
@@ -1207,6 +1210,7 @@ struct ubifs_info { | |||
1207 | unsigned int no_chk_data_crc:1; | 1210 | unsigned int no_chk_data_crc:1; |
1208 | unsigned int bulk_read:1; | 1211 | unsigned int bulk_read:1; |
1209 | unsigned int default_compr:2; | 1212 | unsigned int default_compr:2; |
1213 | unsigned int rw_incompat:1; | ||
1210 | 1214 | ||
1211 | struct mutex tnc_mutex; | 1215 | struct mutex tnc_mutex; |
1212 | struct ubifs_zbranch zroot; | 1216 | struct ubifs_zbranch zroot; |