diff options
-rw-r--r-- | Documentation/filesystems/ubifs.txt | 6 | ||||
-rw-r--r-- | fs/ubifs/io.c | 11 | ||||
-rw-r--r-- | fs/ubifs/scan.c | 2 | ||||
-rw-r--r-- | fs/ubifs/super.c | 34 | ||||
-rw-r--r-- | fs/ubifs/tnc.c | 6 | ||||
-rw-r--r-- | fs/ubifs/ubifs.h | 11 |
6 files changed, 61 insertions, 9 deletions
diff --git a/Documentation/filesystems/ubifs.txt b/Documentation/filesystems/ubifs.txt index 340512c32506..dd84ea3c10da 100644 --- a/Documentation/filesystems/ubifs.txt +++ b/Documentation/filesystems/ubifs.txt | |||
@@ -89,6 +89,12 @@ fast_unmount do not commit on unmount; this option makes | |||
89 | bulk_read read more in one go to take advantage of flash | 89 | bulk_read read more in one go to take advantage of flash |
90 | media that read faster sequentially | 90 | media that read faster sequentially |
91 | no_bulk_read (*) do not bulk-read | 91 | no_bulk_read (*) do not bulk-read |
92 | no_chk_data_crc skip checking of CRCs on data nodes in order to | ||
93 | improve read performance. Use this option only | ||
94 | if the flash media is highly reliable. The effect | ||
95 | of this option is that corruption of the contents | ||
96 | of a file can go unnoticed. | ||
97 | chk_data_crc (*) do not skip checking CRCs on data nodes | ||
92 | 98 | ||
93 | 99 | ||
94 | Quick usage instructions | 100 | Quick usage instructions |
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index 054363f2b207..40e2790b62ce 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c | |||
@@ -74,6 +74,7 @@ void ubifs_ro_mode(struct ubifs_info *c, int err) | |||
74 | * @lnum: logical eraseblock number | 74 | * @lnum: logical eraseblock number |
75 | * @offs: offset within the logical eraseblock | 75 | * @offs: offset within the logical eraseblock |
76 | * @quiet: print no messages | 76 | * @quiet: print no messages |
77 | * @chk_crc: indicates whether to always check the CRC | ||
77 | * | 78 | * |
78 | * This function checks node magic number and CRC checksum. This function also | 79 | * This function checks node magic number and CRC checksum. This function also |
79 | * validates node length to prevent UBIFS from becoming crazy when an attacker | 80 | * validates node length to prevent UBIFS from becoming crazy when an attacker |
@@ -85,7 +86,7 @@ void ubifs_ro_mode(struct ubifs_info *c, int err) | |||
85 | * or magic. | 86 | * or magic. |
86 | */ | 87 | */ |
87 | int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, | 88 | int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, |
88 | int offs, int quiet) | 89 | int offs, int quiet, int chk_crc) |
89 | { | 90 | { |
90 | int err = -EINVAL, type, node_len; | 91 | int err = -EINVAL, type, node_len; |
91 | uint32_t crc, node_crc, magic; | 92 | uint32_t crc, node_crc, magic; |
@@ -121,6 +122,10 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, | |||
121 | node_len > c->ranges[type].max_len) | 122 | node_len > c->ranges[type].max_len) |
122 | goto out_len; | 123 | goto out_len; |
123 | 124 | ||
125 | if (!chk_crc && type == UBIFS_DATA_NODE && !c->always_chk_crc) | ||
126 | if (c->no_chk_data_crc) | ||
127 | return 0; | ||
128 | |||
124 | crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8); | 129 | crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8); |
125 | node_crc = le32_to_cpu(ch->crc); | 130 | node_crc = le32_to_cpu(ch->crc); |
126 | if (crc != node_crc) { | 131 | if (crc != node_crc) { |
@@ -722,7 +727,7 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len, | |||
722 | goto out; | 727 | goto out; |
723 | } | 728 | } |
724 | 729 | ||
725 | err = ubifs_check_node(c, buf, lnum, offs, 0); | 730 | err = ubifs_check_node(c, buf, lnum, offs, 0, 0); |
726 | if (err) { | 731 | if (err) { |
727 | ubifs_err("expected node type %d", type); | 732 | ubifs_err("expected node type %d", type); |
728 | return err; | 733 | return err; |
@@ -781,7 +786,7 @@ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len, | |||
781 | goto out; | 786 | goto out; |
782 | } | 787 | } |
783 | 788 | ||
784 | err = ubifs_check_node(c, buf, lnum, offs, 0); | 789 | err = ubifs_check_node(c, buf, lnum, offs, 0, 0); |
785 | if (err) { | 790 | if (err) { |
786 | ubifs_err("expected node type %d", type); | 791 | ubifs_err("expected node type %d", type); |
787 | return err; | 792 | return err; |
diff --git a/fs/ubifs/scan.c b/fs/ubifs/scan.c index acf5c5fffc60..0ed82479b44b 100644 --- a/fs/ubifs/scan.c +++ b/fs/ubifs/scan.c | |||
@@ -87,7 +87,7 @@ int ubifs_scan_a_node(const struct ubifs_info *c, void *buf, int len, int lnum, | |||
87 | 87 | ||
88 | dbg_scan("scanning %s", dbg_ntype(ch->node_type)); | 88 | dbg_scan("scanning %s", dbg_ntype(ch->node_type)); |
89 | 89 | ||
90 | if (ubifs_check_node(c, buf, lnum, offs, quiet)) | 90 | if (ubifs_check_node(c, buf, lnum, offs, quiet, 1)) |
91 | return SCANNED_A_CORRUPT_NODE; | 91 | return SCANNED_A_CORRUPT_NODE; |
92 | 92 | ||
93 | if (ch->node_type == UBIFS_PAD_NODE) { | 93 | if (ch->node_type == UBIFS_PAD_NODE) { |
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index b1c57e8ee855..cf078b5cc88c 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
@@ -406,6 +406,11 @@ static int ubifs_show_options(struct seq_file *s, struct vfsmount *mnt) | |||
406 | else if (c->mount_opts.bulk_read == 1) | 406 | else if (c->mount_opts.bulk_read == 1) |
407 | seq_printf(s, ",no_bulk_read"); | 407 | seq_printf(s, ",no_bulk_read"); |
408 | 408 | ||
409 | if (c->mount_opts.chk_data_crc == 2) | ||
410 | seq_printf(s, ",chk_data_crc"); | ||
411 | else if (c->mount_opts.chk_data_crc == 1) | ||
412 | seq_printf(s, ",no_chk_data_crc"); | ||
413 | |||
409 | return 0; | 414 | return 0; |
410 | } | 415 | } |
411 | 416 | ||
@@ -859,6 +864,8 @@ static int check_volume_empty(struct ubifs_info *c) | |||
859 | * Opt_norm_unmount: run a journal commit before un-mounting | 864 | * Opt_norm_unmount: run a journal commit before un-mounting |
860 | * Opt_bulk_read: enable bulk-reads | 865 | * Opt_bulk_read: enable bulk-reads |
861 | * Opt_no_bulk_read: disable bulk-reads | 866 | * Opt_no_bulk_read: disable bulk-reads |
867 | * Opt_chk_data_crc: check CRCs when reading data nodes | ||
868 | * Opt_no_chk_data_crc: do not check CRCs when reading data nodes | ||
862 | * Opt_err: just end of array marker | 869 | * Opt_err: just end of array marker |
863 | */ | 870 | */ |
864 | enum { | 871 | enum { |
@@ -866,6 +873,8 @@ enum { | |||
866 | Opt_norm_unmount, | 873 | Opt_norm_unmount, |
867 | Opt_bulk_read, | 874 | Opt_bulk_read, |
868 | Opt_no_bulk_read, | 875 | Opt_no_bulk_read, |
876 | Opt_chk_data_crc, | ||
877 | Opt_no_chk_data_crc, | ||
869 | Opt_err, | 878 | Opt_err, |
870 | }; | 879 | }; |
871 | 880 | ||
@@ -874,6 +883,8 @@ static match_table_t tokens = { | |||
874 | {Opt_norm_unmount, "norm_unmount"}, | 883 | {Opt_norm_unmount, "norm_unmount"}, |
875 | {Opt_bulk_read, "bulk_read"}, | 884 | {Opt_bulk_read, "bulk_read"}, |
876 | {Opt_no_bulk_read, "no_bulk_read"}, | 885 | {Opt_no_bulk_read, "no_bulk_read"}, |
886 | {Opt_chk_data_crc, "chk_data_crc"}, | ||
887 | {Opt_no_chk_data_crc, "no_chk_data_crc"}, | ||
877 | {Opt_err, NULL}, | 888 | {Opt_err, NULL}, |
878 | }; | 889 | }; |
879 | 890 | ||
@@ -919,6 +930,14 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options, | |||
919 | c->mount_opts.bulk_read = 1; | 930 | c->mount_opts.bulk_read = 1; |
920 | c->bulk_read = 0; | 931 | c->bulk_read = 0; |
921 | break; | 932 | break; |
933 | case Opt_chk_data_crc: | ||
934 | c->mount_opts.chk_data_crc = 2; | ||
935 | c->no_chk_data_crc = 0; | ||
936 | break; | ||
937 | case Opt_no_chk_data_crc: | ||
938 | c->mount_opts.chk_data_crc = 1; | ||
939 | c->no_chk_data_crc = 1; | ||
940 | break; | ||
922 | default: | 941 | default: |
923 | ubifs_err("unrecognized mount option \"%s\" " | 942 | ubifs_err("unrecognized mount option \"%s\" " |
924 | "or missing value", p); | 943 | "or missing value", p); |
@@ -1027,6 +1046,8 @@ static int mount_ubifs(struct ubifs_info *c) | |||
1027 | goto out_free; | 1046 | goto out_free; |
1028 | } | 1047 | } |
1029 | 1048 | ||
1049 | c->always_chk_crc = 1; | ||
1050 | |||
1030 | err = ubifs_read_superblock(c); | 1051 | err = ubifs_read_superblock(c); |
1031 | if (err) | 1052 | if (err) |
1032 | goto out_free; | 1053 | goto out_free; |
@@ -1168,6 +1189,8 @@ static int mount_ubifs(struct ubifs_info *c) | |||
1168 | if (err) | 1189 | if (err) |
1169 | goto out_infos; | 1190 | goto out_infos; |
1170 | 1191 | ||
1192 | c->always_chk_crc = 0; | ||
1193 | |||
1171 | ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"", | 1194 | ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"", |
1172 | c->vi.ubi_num, c->vi.vol_id, c->vi.name); | 1195 | c->vi.ubi_num, c->vi.vol_id, c->vi.name); |
1173 | if (mounted_read_only) | 1196 | if (mounted_read_only) |
@@ -1313,6 +1336,7 @@ static int ubifs_remount_rw(struct ubifs_info *c) | |||
1313 | 1336 | ||
1314 | mutex_lock(&c->umount_mutex); | 1337 | mutex_lock(&c->umount_mutex); |
1315 | c->remounting_rw = 1; | 1338 | c->remounting_rw = 1; |
1339 | c->always_chk_crc = 1; | ||
1316 | 1340 | ||
1317 | /* Check for enough free space */ | 1341 | /* Check for enough free space */ |
1318 | if (ubifs_calc_available(c, c->min_idx_lebs) <= 0) { | 1342 | if (ubifs_calc_available(c, c->min_idx_lebs) <= 0) { |
@@ -1381,13 +1405,15 @@ static int ubifs_remount_rw(struct ubifs_info *c) | |||
1381 | c->bgt = NULL; | 1405 | c->bgt = NULL; |
1382 | ubifs_err("cannot spawn \"%s\", error %d", | 1406 | ubifs_err("cannot spawn \"%s\", error %d", |
1383 | c->bgt_name, err); | 1407 | c->bgt_name, err); |
1384 | return err; | 1408 | goto out; |
1385 | } | 1409 | } |
1386 | wake_up_process(c->bgt); | 1410 | wake_up_process(c->bgt); |
1387 | 1411 | ||
1388 | c->orph_buf = vmalloc(c->leb_size); | 1412 | c->orph_buf = vmalloc(c->leb_size); |
1389 | if (!c->orph_buf) | 1413 | if (!c->orph_buf) { |
1390 | return -ENOMEM; | 1414 | err = -ENOMEM; |
1415 | goto out; | ||
1416 | } | ||
1391 | 1417 | ||
1392 | /* Check for enough log space */ | 1418 | /* Check for enough log space */ |
1393 | lnum = c->lhead_lnum + 1; | 1419 | lnum = c->lhead_lnum + 1; |
@@ -1414,6 +1440,7 @@ static int ubifs_remount_rw(struct ubifs_info *c) | |||
1414 | dbg_gen("re-mounted read-write"); | 1440 | dbg_gen("re-mounted read-write"); |
1415 | c->vfs_sb->s_flags &= ~MS_RDONLY; | 1441 | c->vfs_sb->s_flags &= ~MS_RDONLY; |
1416 | c->remounting_rw = 0; | 1442 | c->remounting_rw = 0; |
1443 | c->always_chk_crc = 0; | ||
1417 | mutex_unlock(&c->umount_mutex); | 1444 | mutex_unlock(&c->umount_mutex); |
1418 | return 0; | 1445 | return 0; |
1419 | 1446 | ||
@@ -1429,6 +1456,7 @@ out: | |||
1429 | c->ileb_buf = NULL; | 1456 | c->ileb_buf = NULL; |
1430 | ubifs_lpt_free(c, 1); | 1457 | ubifs_lpt_free(c, 1); |
1431 | c->remounting_rw = 0; | 1458 | c->remounting_rw = 0; |
1459 | c->always_chk_crc = 0; | ||
1432 | mutex_unlock(&c->umount_mutex); | 1460 | mutex_unlock(&c->umount_mutex); |
1433 | return err; | 1461 | return err; |
1434 | } | 1462 | } |
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index d279012d8dd5..66dc57100bdf 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c | |||
@@ -470,6 +470,10 @@ static int try_read_node(const struct ubifs_info *c, void *buf, int type, | |||
470 | if (node_len != len) | 470 | if (node_len != len) |
471 | return 0; | 471 | return 0; |
472 | 472 | ||
473 | if (type == UBIFS_DATA_NODE && !c->always_chk_crc) | ||
474 | if (c->no_chk_data_crc) | ||
475 | return 0; | ||
476 | |||
473 | crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8); | 477 | crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8); |
474 | node_crc = le32_to_cpu(ch->crc); | 478 | node_crc = le32_to_cpu(ch->crc); |
475 | if (crc != node_crc) | 479 | if (crc != node_crc) |
@@ -1687,7 +1691,7 @@ static int validate_data_node(struct ubifs_info *c, void *buf, | |||
1687 | goto out_err; | 1691 | goto out_err; |
1688 | } | 1692 | } |
1689 | 1693 | ||
1690 | err = ubifs_check_node(c, buf, zbr->lnum, zbr->offs, 0); | 1694 | err = ubifs_check_node(c, buf, zbr->lnum, zbr->offs, 0, 0); |
1691 | if (err) { | 1695 | if (err) { |
1692 | ubifs_err("expected node type %d", UBIFS_DATA_NODE); | 1696 | ubifs_err("expected node type %d", UBIFS_DATA_NODE); |
1693 | goto out; | 1697 | goto out; |
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 8513239ea8a0..d6ae3f7b2b05 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h | |||
@@ -894,10 +894,12 @@ struct ubifs_orphan { | |||
894 | * struct ubifs_mount_opts - UBIFS-specific mount options information. | 894 | * struct ubifs_mount_opts - UBIFS-specific mount options information. |
895 | * @unmount_mode: selected unmount mode (%0 default, %1 normal, %2 fast) | 895 | * @unmount_mode: selected unmount mode (%0 default, %1 normal, %2 fast) |
896 | * @bulk_read: enable bulk-reads | 896 | * @bulk_read: enable bulk-reads |
897 | * @chk_data_crc: check CRCs when reading data nodes | ||
897 | */ | 898 | */ |
898 | struct ubifs_mount_opts { | 899 | struct ubifs_mount_opts { |
899 | unsigned int unmount_mode:2; | 900 | unsigned int unmount_mode:2; |
900 | unsigned int bulk_read:2; | 901 | unsigned int bulk_read:2; |
902 | unsigned int chk_data_crc:2; | ||
901 | }; | 903 | }; |
902 | 904 | ||
903 | /** | 905 | /** |
@@ -1001,6 +1003,9 @@ struct ubifs_mount_opts { | |||
1001 | * @bulk_read: enable bulk-reads | 1003 | * @bulk_read: enable bulk-reads |
1002 | * @bulk_read_buf_size: buffer size for bulk-reads | 1004 | * @bulk_read_buf_size: buffer size for bulk-reads |
1003 | * | 1005 | * |
1006 | * @no_chk_data_crc: do not check CRCs when reading data nodes (except during | ||
1007 | * recovery) | ||
1008 | * | ||
1004 | * @dirty_pg_cnt: number of dirty pages (not used) | 1009 | * @dirty_pg_cnt: number of dirty pages (not used) |
1005 | * @dirty_zn_cnt: number of dirty znodes | 1010 | * @dirty_zn_cnt: number of dirty znodes |
1006 | * @clean_zn_cnt: number of clean znodes | 1011 | * @clean_zn_cnt: number of clean znodes |
@@ -1138,6 +1143,7 @@ struct ubifs_mount_opts { | |||
1138 | * @rcvrd_mst_node: recovered master node to write when mounting ro to rw | 1143 | * @rcvrd_mst_node: recovered master node to write when mounting ro to rw |
1139 | * @size_tree: inode size information for recovery | 1144 | * @size_tree: inode size information for recovery |
1140 | * @remounting_rw: set while remounting from ro to rw (sb flags have MS_RDONLY) | 1145 | * @remounting_rw: set while remounting from ro to rw (sb flags have MS_RDONLY) |
1146 | * @always_chk_crc: always check CRCs (while mounting and remounting rw) | ||
1141 | * @mount_opts: UBIFS-specific mount options | 1147 | * @mount_opts: UBIFS-specific mount options |
1142 | * | 1148 | * |
1143 | * @dbg_buf: a buffer of LEB size used for debugging purposes | 1149 | * @dbg_buf: a buffer of LEB size used for debugging purposes |
@@ -1244,6 +1250,8 @@ struct ubifs_info { | |||
1244 | int bulk_read; | 1250 | int bulk_read; |
1245 | int bulk_read_buf_size; | 1251 | int bulk_read_buf_size; |
1246 | 1252 | ||
1253 | int no_chk_data_crc; | ||
1254 | |||
1247 | atomic_long_t dirty_pg_cnt; | 1255 | atomic_long_t dirty_pg_cnt; |
1248 | atomic_long_t dirty_zn_cnt; | 1256 | atomic_long_t dirty_zn_cnt; |
1249 | atomic_long_t clean_zn_cnt; | 1257 | atomic_long_t clean_zn_cnt; |
@@ -1374,6 +1382,7 @@ struct ubifs_info { | |||
1374 | struct ubifs_mst_node *rcvrd_mst_node; | 1382 | struct ubifs_mst_node *rcvrd_mst_node; |
1375 | struct rb_root size_tree; | 1383 | struct rb_root size_tree; |
1376 | int remounting_rw; | 1384 | int remounting_rw; |
1385 | int always_chk_crc; | ||
1377 | struct ubifs_mount_opts mount_opts; | 1386 | struct ubifs_mount_opts mount_opts; |
1378 | 1387 | ||
1379 | #ifdef CONFIG_UBIFS_FS_DEBUG | 1388 | #ifdef CONFIG_UBIFS_FS_DEBUG |
@@ -1416,7 +1425,7 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len, | |||
1416 | int ubifs_write_node(struct ubifs_info *c, void *node, int len, int lnum, | 1425 | int ubifs_write_node(struct ubifs_info *c, void *node, int len, int lnum, |
1417 | int offs, int dtype); | 1426 | int offs, int dtype); |
1418 | int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, | 1427 | int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, |
1419 | int offs, int quiet); | 1428 | int offs, int quiet, int chk_crc); |
1420 | void ubifs_prepare_node(struct ubifs_info *c, void *buf, int len, int pad); | 1429 | void ubifs_prepare_node(struct ubifs_info *c, void *buf, int len, int pad); |
1421 | void ubifs_prep_grp_node(struct ubifs_info *c, void *node, int len, int last); | 1430 | void ubifs_prep_grp_node(struct ubifs_info *c, void *node, int len, int last); |
1422 | int ubifs_io_init(struct ubifs_info *c); | 1431 | int ubifs_io_init(struct ubifs_info *c); |