From: Artem Bityutskiy <dedekind@infradead.org>
To: linux-fsdevel@vger.kernel.org
Cc: Adrian Hunter <ext-adrian.hunter@nokia.com>,
linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org
Subject: [PATCH] UBIFS: add no_chk_data_crc mount option
Date: Tue, 30 Sep 2008 12:19:02 +0300 [thread overview]
Message-ID: <1222766358-21886-7-git-send-email-dedekind@infradead.org> (raw)
In-Reply-To: <1222766358-21886-1-git-send-email-dedekind@infradead.org>
From: Adrian Hunter <ext-adrian.hunter@nokia.com>
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>
---
Documentation/filesystems/ubifs.txt | 6 ++++++
fs/ubifs/io.c | 11 ++++++++---
fs/ubifs/scan.c | 2 +-
fs/ubifs/super.c | 34 +++++++++++++++++++++++++++++++---
fs/ubifs/tnc.c | 6 +++++-
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 340512c..dd84ea3 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
bulk_read read more in one go to take advantage of flash
media that read faster sequentially
no_bulk_read (*) do not bulk-read
+no_chk_data_crc skip checking of CRCs on data nodes in order to
+ improve read performance. Use this option only
+ if the flash media is highly reliable. The effect
+ of this option is that corruption of the contents
+ of a file can go unnoticed.
+chk_data_crc (*) do not skip checking CRCs on data nodes
Quick usage instructions
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
index 054363f..40e2790 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)
* @lnum: logical eraseblock number
* @offs: offset within the logical eraseblock
* @quiet: print no messages
+ * @chk_crc: indicates whether to always check the CRC
*
* This function checks node magic number and CRC checksum. This function also
* 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)
* or magic.
*/
int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
- int offs, int quiet)
+ int offs, int quiet, int chk_crc)
{
int err = -EINVAL, type, node_len;
uint32_t crc, node_crc, magic;
@@ -121,6 +122,10 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
node_len > c->ranges[type].max_len)
goto out_len;
+ if (!chk_crc && type == UBIFS_DATA_NODE && !c->always_chk_crc)
+ if (c->no_chk_data_crc)
+ return 0;
+
crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8);
node_crc = le32_to_cpu(ch->crc);
if (crc != node_crc) {
@@ -722,7 +727,7 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
goto out;
}
- err = ubifs_check_node(c, buf, lnum, offs, 0);
+ err = ubifs_check_node(c, buf, lnum, offs, 0, 0);
if (err) {
ubifs_err("expected node type %d", type);
return err;
@@ -781,7 +786,7 @@ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
goto out;
}
- err = ubifs_check_node(c, buf, lnum, offs, 0);
+ err = ubifs_check_node(c, buf, lnum, offs, 0, 0);
if (err) {
ubifs_err("expected node type %d", type);
return err;
diff --git a/fs/ubifs/scan.c b/fs/ubifs/scan.c
index acf5c5f..0ed8247 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,
dbg_scan("scanning %s", dbg_ntype(ch->node_type));
- if (ubifs_check_node(c, buf, lnum, offs, quiet))
+ if (ubifs_check_node(c, buf, lnum, offs, quiet, 1))
return SCANNED_A_CORRUPT_NODE;
if (ch->node_type == UBIFS_PAD_NODE) {
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index b1c57e8..cf078b5 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)
else if (c->mount_opts.bulk_read == 1)
seq_printf(s, ",no_bulk_read");
+ if (c->mount_opts.chk_data_crc == 2)
+ seq_printf(s, ",chk_data_crc");
+ else if (c->mount_opts.chk_data_crc == 1)
+ seq_printf(s, ",no_chk_data_crc");
+
return 0;
}
@@ -859,6 +864,8 @@ static int check_volume_empty(struct ubifs_info *c)
* Opt_norm_unmount: run a journal commit before un-mounting
* Opt_bulk_read: enable bulk-reads
* Opt_no_bulk_read: disable bulk-reads
+ * Opt_chk_data_crc: check CRCs when reading data nodes
+ * Opt_no_chk_data_crc: do not check CRCs when reading data nodes
* Opt_err: just end of array marker
*/
enum {
@@ -866,6 +873,8 @@ enum {
Opt_norm_unmount,
Opt_bulk_read,
Opt_no_bulk_read,
+ Opt_chk_data_crc,
+ Opt_no_chk_data_crc,
Opt_err,
};
@@ -874,6 +883,8 @@ static match_table_t tokens = {
{Opt_norm_unmount, "norm_unmount"},
{Opt_bulk_read, "bulk_read"},
{Opt_no_bulk_read, "no_bulk_read"},
+ {Opt_chk_data_crc, "chk_data_crc"},
+ {Opt_no_chk_data_crc, "no_chk_data_crc"},
{Opt_err, NULL},
};
@@ -919,6 +930,14 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options,
c->mount_opts.bulk_read = 1;
c->bulk_read = 0;
break;
+ case Opt_chk_data_crc:
+ c->mount_opts.chk_data_crc = 2;
+ c->no_chk_data_crc = 0;
+ break;
+ case Opt_no_chk_data_crc:
+ c->mount_opts.chk_data_crc = 1;
+ c->no_chk_data_crc = 1;
+ break;
default:
ubifs_err("unrecognized mount option \"%s\" "
"or missing value", p);
@@ -1027,6 +1046,8 @@ static int mount_ubifs(struct ubifs_info *c)
goto out_free;
}
+ c->always_chk_crc = 1;
+
err = ubifs_read_superblock(c);
if (err)
goto out_free;
@@ -1168,6 +1189,8 @@ static int mount_ubifs(struct ubifs_info *c)
if (err)
goto out_infos;
+ c->always_chk_crc = 0;
+
ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"",
c->vi.ubi_num, c->vi.vol_id, c->vi.name);
if (mounted_read_only)
@@ -1313,6 +1336,7 @@ static int ubifs_remount_rw(struct ubifs_info *c)
mutex_lock(&c->umount_mutex);
c->remounting_rw = 1;
+ c->always_chk_crc = 1;
/* Check for enough free space */
if (ubifs_calc_available(c, c->min_idx_lebs) <= 0) {
@@ -1381,13 +1405,15 @@ static int ubifs_remount_rw(struct ubifs_info *c)
c->bgt = NULL;
ubifs_err("cannot spawn \"%s\", error %d",
c->bgt_name, err);
- return err;
+ goto out;
}
wake_up_process(c->bgt);
c->orph_buf = vmalloc(c->leb_size);
- if (!c->orph_buf)
- return -ENOMEM;
+ if (!c->orph_buf) {
+ err = -ENOMEM;
+ goto out;
+ }
/* Check for enough log space */
lnum = c->lhead_lnum + 1;
@@ -1414,6 +1440,7 @@ static int ubifs_remount_rw(struct ubifs_info *c)
dbg_gen("re-mounted read-write");
c->vfs_sb->s_flags &= ~MS_RDONLY;
c->remounting_rw = 0;
+ c->always_chk_crc = 0;
mutex_unlock(&c->umount_mutex);
return 0;
@@ -1429,6 +1456,7 @@ out:
c->ileb_buf = NULL;
ubifs_lpt_free(c, 1);
c->remounting_rw = 0;
+ c->always_chk_crc = 0;
mutex_unlock(&c->umount_mutex);
return err;
}
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
index d279012..66dc571 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,
if (node_len != len)
return 0;
+ if (type == UBIFS_DATA_NODE && !c->always_chk_crc)
+ if (c->no_chk_data_crc)
+ return 0;
+
crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8);
node_crc = le32_to_cpu(ch->crc);
if (crc != node_crc)
@@ -1687,7 +1691,7 @@ static int validate_data_node(struct ubifs_info *c, void *buf,
goto out_err;
}
- err = ubifs_check_node(c, buf, zbr->lnum, zbr->offs, 0);
+ err = ubifs_check_node(c, buf, zbr->lnum, zbr->offs, 0, 0);
if (err) {
ubifs_err("expected node type %d", UBIFS_DATA_NODE);
goto out;
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 8513239..d6ae3f7 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -894,10 +894,12 @@ struct ubifs_orphan {
* struct ubifs_mount_opts - UBIFS-specific mount options information.
* @unmount_mode: selected unmount mode (%0 default, %1 normal, %2 fast)
* @bulk_read: enable bulk-reads
+ * @chk_data_crc: check CRCs when reading data nodes
*/
struct ubifs_mount_opts {
unsigned int unmount_mode:2;
unsigned int bulk_read:2;
+ unsigned int chk_data_crc:2;
};
/**
@@ -1001,6 +1003,9 @@ struct ubifs_mount_opts {
* @bulk_read: enable bulk-reads
* @bulk_read_buf_size: buffer size for bulk-reads
*
+ * @no_chk_data_crc: do not check CRCs when reading data nodes (except during
+ * recovery)
+ *
* @dirty_pg_cnt: number of dirty pages (not used)
* @dirty_zn_cnt: number of dirty znodes
* @clean_zn_cnt: number of clean znodes
@@ -1138,6 +1143,7 @@ struct ubifs_mount_opts {
* @rcvrd_mst_node: recovered master node to write when mounting ro to rw
* @size_tree: inode size information for recovery
* @remounting_rw: set while remounting from ro to rw (sb flags have MS_RDONLY)
+ * @always_chk_crc: always check CRCs (while mounting and remounting rw)
* @mount_opts: UBIFS-specific mount options
*
* @dbg_buf: a buffer of LEB size used for debugging purposes
@@ -1244,6 +1250,8 @@ struct ubifs_info {
int bulk_read;
int bulk_read_buf_size;
+ int no_chk_data_crc;
+
atomic_long_t dirty_pg_cnt;
atomic_long_t dirty_zn_cnt;
atomic_long_t clean_zn_cnt;
@@ -1374,6 +1382,7 @@ struct ubifs_info {
struct ubifs_mst_node *rcvrd_mst_node;
struct rb_root size_tree;
int remounting_rw;
+ int always_chk_crc;
struct ubifs_mount_opts mount_opts;
#ifdef CONFIG_UBIFS_FS_DEBUG
@@ -1416,7 +1425,7 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
int ubifs_write_node(struct ubifs_info *c, void *node, int len, int lnum,
int offs, int dtype);
int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
- int offs, int quiet);
+ int offs, int quiet, int chk_crc);
void ubifs_prepare_node(struct ubifs_info *c, void *buf, int len, int pad);
void ubifs_prep_grp_node(struct ubifs_info *c, void *node, int len, int last);
int ubifs_io_init(struct ubifs_info *c);
--
1.5.4.1
next prev parent reply other threads:[~2008-09-30 7:44 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-09-30 9:18 What is in ubifs-2.6.git Artem Bityutskiy
2008-09-30 7:56 ` Artem Bityutskiy
2008-09-30 8:55 ` Amit Kumar Sharma
2008-09-30 9:02 ` Artem Bityutskiy
2008-09-30 9:18 ` [PATCH] UBIFS: add a print, fix comments and more minor stuff Artem Bityutskiy
2008-09-30 9:18 ` [PATCH] UBIFS: remove unneeded unlikely() Artem Bityutskiy
2008-09-30 9:18 ` [PATCH] UBIFS: inline one-line functions Artem Bityutskiy
2008-09-30 9:19 ` [PATCH] UBIFS: use an IS_ERR test rather than a NULL test Artem Bityutskiy
2008-09-30 9:19 ` [PATCH] UBIFS: add bulk-read facility Artem Bityutskiy
2008-09-30 9:19 ` Artem Bityutskiy [this message]
2008-09-30 9:19 ` [PATCH] UBIFS: improve znode splitting rules Artem Bityutskiy
2008-09-30 9:19 ` [PATCH] UBIFS: check data CRC when in error state Artem Bityutskiy
2008-09-30 9:19 ` [PATCH] UBIFS: use bit-fields when possible Artem Bityutskiy
2008-09-30 9:19 ` [PATCH] UBIFS: correct key comparison Artem Bityutskiy
2008-09-30 9:19 ` [PATCH] UBIFS: ensure data read beyond i_size is zeroed out correctly Artem Bityutskiy
2008-09-30 9:19 ` [PATCH] UBIFS: fix races in bit-fields Artem Bityutskiy
2008-09-30 9:19 ` [PATCH] UBIFS: fix commentary Artem Bityutskiy
2008-09-30 9:19 ` [PATCH] UBIFS: update dbg_dump_inode Artem Bityutskiy
2008-09-30 9:19 ` [PATCH] UBIFS: correct comment for commit_on_unmount Artem Bityutskiy
2008-09-30 9:19 ` [PATCH] UBIFS: commit on sync_fs Artem Bityutskiy
2008-09-30 9:19 ` [PATCH] UBIFS: allow for sync_fs when read-only Artem Bityutskiy
2008-09-30 9:19 ` [PATCH] UBIFS: improve garbage collection Artem Bityutskiy
2008-09-30 9:19 ` [PATCH] UBIFS: fix bulk-read handling uptodate pages Artem Bityutskiy
2008-09-30 9:19 ` [PATCH] UBIFS: add more debugging messages for LPT Artem Bityutskiy
2008-09-30 9:19 ` [PATCH] UBIFS: correct condition to eliminate unecessary assignment Artem Bityutskiy
2008-09-30 9:19 ` [PATCH] UBIFS: check buffer length when scanning for LPT nodes Artem Bityutskiy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1222766358-21886-7-git-send-email-dedekind@infradead.org \
--to=dedekind@infradead.org \
--cc=ext-adrian.hunter@nokia.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mtd@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®