aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Hunter <ext-adrian.hunter@nokia.com>2008-09-04 09:26:00 -0400
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2008-09-30 04:12:56 -0400
commit2953e73f1ce4b3284b409aefb9d46bbde6515c37 (patch)
tree56126c6a589bd0450eb288db6a93946e50e5bc29
parent4793e7c5e1c88382ead18db5ca072bac54467318 (diff)
UBIFS: add no_chk_data_crc mount option
UBIFS read performance can be improved by skipping the CRC check when data nodes are read. This option can be used if the underlying media is considered to be highly reliable. Note that CRCs are always checked for metadata. Read speed on Arm platform with OneNAND goes from 19 MiB/s to 27 MiB/s with data CRC checking disabled. Signed-off-by: Adrian Hunter <ext-adrian.hunter@nokia.com>
-rw-r--r--Documentation/filesystems/ubifs.txt6
-rw-r--r--fs/ubifs/io.c11
-rw-r--r--fs/ubifs/scan.c2
-rw-r--r--fs/ubifs/super.c34
-rw-r--r--fs/ubifs/tnc.c6
-rw-r--r--fs/ubifs/ubifs.h11
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
89bulk_read read more in one go to take advantage of flash 89bulk_read read more in one go to take advantage of flash
90 media that read faster sequentially 90 media that read faster sequentially
91no_bulk_read (*) do not bulk-read 91no_bulk_read (*) do not bulk-read
92no_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.
97chk_data_crc (*) do not skip checking CRCs on data nodes
92 98
93 99
94Quick usage instructions 100Quick 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 */
87int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, 88int 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 */
864enum { 871enum {
@@ -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 */
898struct ubifs_mount_opts { 899struct 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,
1416int ubifs_write_node(struct ubifs_info *c, void *node, int len, int lnum, 1425int ubifs_write_node(struct ubifs_info *c, void *node, int len, int lnum,
1417 int offs, int dtype); 1426 int offs, int dtype);
1418int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, 1427int 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);
1420void ubifs_prepare_node(struct ubifs_info *c, void *buf, int len, int pad); 1429void ubifs_prepare_node(struct ubifs_info *c, void *buf, int len, int pad);
1421void ubifs_prep_grp_node(struct ubifs_info *c, void *node, int len, int last); 1430void ubifs_prep_grp_node(struct ubifs_info *c, void *node, int len, int last);
1422int ubifs_io_init(struct ubifs_info *c); 1431int ubifs_io_init(struct ubifs_info *c);