From 18d1d7fbcc260e67d249bf90b454d8cf34288453 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 17 Jan 2011 22:27:56 +0200 Subject: UBIFS: introduce mounting flag This is a preparational patch which removes the 'c->always_chk_crc' which was set during mounting and remounting to R/W mode and introduces 'c->mounting' flag which is set when mounting. Now the 'c->always_chk_crc' flag is the same as 'c->remounting_rw && c->mounting'. This patch is a preparation for the next one which will need to know when we are mounting and remounting to R/W mode, which is exactly what 'c->always_chk_crc' effectively is, but its name does not suite the next patch. The other possibility would be to just re-name it, but then we'd end up with less logical flags coverage. Signed-off-by: Artem Bityutskiy --- fs/ubifs/super.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'fs/ubifs/super.c') diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 91fac54c70e3..703a62109cf2 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1194,11 +1194,7 @@ static int mount_ubifs(struct ubifs_info *c) if (c->bulk_read == 1) bu_init(c); - /* - * We have to check all CRCs, even for data nodes, when we mount the FS - * (specifically, when we are replaying). - */ - c->always_chk_crc = 1; + c->mounting = 1; err = ubifs_read_superblock(c); if (err) @@ -1374,7 +1370,7 @@ static int mount_ubifs(struct ubifs_info *c) if (err) goto out_infos; - c->always_chk_crc = 0; + c->mounting = 0; ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"", c->vi.ubi_num, c->vi.vol_id, c->vi.name); @@ -1535,7 +1531,6 @@ static int ubifs_remount_rw(struct ubifs_info *c) mutex_lock(&c->umount_mutex); dbg_save_space_info(c); c->remounting_rw = 1; - c->always_chk_crc = 1; err = check_free_space(c); if (err) @@ -1642,7 +1637,6 @@ static int ubifs_remount_rw(struct ubifs_info *c) dbg_gen("re-mounted read-write"); c->ro_mount = 0; c->remounting_rw = 0; - c->always_chk_crc = 0; err = dbg_check_space_info(c); mutex_unlock(&c->umount_mutex); return err; @@ -1659,7 +1653,6 @@ 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; } -- cgit v1.2.1 From 3e8e2e0c8da1f1701a8014543c951c41751791cc Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sun, 30 Jan 2011 18:58:32 +0200 Subject: UBIFS: incorporate maximum write size Incorporate maximum write size into the UBIFS description data structure. This patch just introduces new 'c->max_write_size' and 'c->max_write_shift' fields as a preparation for the following patches. Signed-off-by: Artem Bityutskiy --- fs/ubifs/super.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'fs/ubifs/super.c') diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 703a62109cf2..efc327b92f98 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -507,6 +507,8 @@ static int init_constants_early(struct ubifs_info *c) c->half_leb_size = c->leb_size / 2; c->min_io_size = c->di.min_io_size; c->min_io_shift = fls(c->min_io_size) - 1; + c->max_write_size = c->di.max_write_size; + c->max_write_shift = fls(c->max_write_size) - 1; if (c->leb_size < UBIFS_MIN_LEB_SZ) { ubifs_err("too small LEBs (%d bytes), min. is %d bytes", @@ -525,6 +527,18 @@ static int init_constants_early(struct ubifs_info *c) return -EINVAL; } + /* + * Maximum write size has to be greater or equivalent to min. I/O + * size, and be multiple of min. I/O size. + */ + if (c->max_write_size < c->min_io_size || + c->max_write_size % c->min_io_size || + !is_power_of_2(c->max_write_size)) { + ubifs_err("bad write buffer size %d for %d min. I/O unit", + c->max_write_size, c->min_io_size); + return -EINVAL; + } + /* * UBIFS aligns all node to 8-byte boundary, so to make function in * io.c simpler, assume minimum I/O unit size to be 8 bytes if it is @@ -533,6 +547,10 @@ static int init_constants_early(struct ubifs_info *c) if (c->min_io_size < 8) { c->min_io_size = 8; c->min_io_shift = 3; + if (c->max_write_size < c->min_io_size) { + c->max_write_size = c->min_io_size; + c->max_write_shift = c->min_io_shift; + } } c->ref_node_alsz = ALIGN(UBIFS_REF_NODE_SZ, c->min_io_size); @@ -1391,6 +1409,7 @@ static int mount_ubifs(struct ubifs_info *c) dbg_msg("compiled on: " __DATE__ " at " __TIME__); dbg_msg("min. I/O unit size: %d bytes", c->min_io_size); + dbg_msg("max. write size: %d bytes", c->max_write_size); dbg_msg("LEB size: %d bytes (%d KiB)", c->leb_size, c->leb_size >> 10); dbg_msg("data journal heads: %d", -- cgit v1.2.1 From ca2ec61d157f23ec24aaa200f8016ea0a8aeb617 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 14 Feb 2011 15:17:55 +0200 Subject: UBI: incorporate LEB offset information Incorporate the LEB offset information into UBIFS. We'll use this information in one of the next patches to figure out what are the max. write size offsets relative to the PEB. So this patch is just a preparation. Signed-off-by: Artem Bityutskiy --- fs/ubifs/super.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/ubifs/super.c') diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index efc327b92f98..d4b4cb4596e2 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -504,6 +504,7 @@ static int init_constants_early(struct ubifs_info *c) c->leb_cnt = c->vi.size; c->leb_size = c->vi.usable_leb_size; + c->leb_start = c->di.leb_start; c->half_leb_size = c->leb_size / 2; c->min_io_size = c->di.min_io_size; c->min_io_shift = fls(c->min_io_size) - 1; -- cgit v1.2.1 From d882962f6af2b484b62a7fb05ef959e1bf355fc4 Mon Sep 17 00:00:00 2001 From: "Matthew L. Creech" Date: Fri, 4 Mar 2011 17:55:02 -0500 Subject: UBIFS: handle allocation failures in UBIFS write path Running kernel 2.6.37, my PPC-based device occasionally gets an order-2 allocation failure in UBIFS, which causes the root FS to become unwritable: kswapd0: page allocation failure. order:2, mode:0x4050 Call Trace: [c787dc30] [c00085b8] show_stack+0x7c/0x194 (unreliable) [c787dc70] [c0061aec] __alloc_pages_nodemask+0x4f0/0x57c [c787dd00] [c0061b98] __get_free_pages+0x20/0x50 [c787dd10] [c00e4f88] ubifs_jnl_write_data+0x54/0x200 [c787dd50] [c00e82d4] do_writepage+0x94/0x198 [c787dd90] [c00675e4] shrink_page_list+0x40c/0x77c [c787de40] [c0067de0] shrink_inactive_list+0x1e0/0x370 [c787de90] [c0068224] shrink_zone+0x2b4/0x2b8 [c787df00] [c0068854] kswapd+0x408/0x5d4 [c787dfb0] [c0037bcc] kthread+0x80/0x84 [c787dff0] [c000ef44] kernel_thread+0x4c/0x68 Similar problems were encountered last April by Tomasz Stanislawski: http://patchwork.ozlabs.org/patch/50965/ This patch implements Artem's suggested fix: fall back to a mutex-protected static buffer, allocated at mount time. I tested it by forcing execution down the failure path, and didn't see any ill effects. Artem: massaged the patch a little, improved it so that we'd not allocate the write reserve buffer when we are in R/O mode. Signed-off-by: Matthew L. Creech Signed-off-by: Artem Bityutskiy --- fs/ubifs/super.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'fs/ubifs/super.c') diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index d4b4cb4596e2..e360c7a71f9e 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1213,6 +1213,13 @@ static int mount_ubifs(struct ubifs_info *c) if (c->bulk_read == 1) bu_init(c); + if (!c->ro_mount) { + c->write_reserve_buf = kmalloc(COMPRESSED_DATA_NODE_BUF_SZ, + GFP_KERNEL); + if (!c->write_reserve_buf) + goto out_free; + } + c->mounting = 1; err = ubifs_read_superblock(c); @@ -1482,6 +1489,7 @@ out_wbufs: out_cbuf: kfree(c->cbuf); out_free: + kfree(c->write_reserve_buf); kfree(c->bu.buf); vfree(c->ileb_buf); vfree(c->sbuf); @@ -1520,6 +1528,7 @@ static void ubifs_umount(struct ubifs_info *c) kfree(c->cbuf); kfree(c->rcvrd_mst_node); kfree(c->mst_node); + kfree(c->write_reserve_buf); kfree(c->bu.buf); vfree(c->ileb_buf); vfree(c->sbuf); @@ -1605,6 +1614,10 @@ static int ubifs_remount_rw(struct ubifs_info *c) goto out; } + c->write_reserve_buf = kmalloc(COMPRESSED_DATA_NODE_BUF_SZ, GFP_KERNEL); + if (!c->write_reserve_buf) + goto out; + err = ubifs_lpt_init(c, 0, 1); if (err) goto out; @@ -1669,6 +1682,8 @@ out: c->bgt = NULL; } free_wbufs(c); + kfree(c->write_reserve_buf); + c->write_reserve_buf = NULL; vfree(c->ileb_buf); c->ileb_buf = NULL; ubifs_lpt_free(c, 1); @@ -1712,6 +1727,8 @@ static void ubifs_remount_ro(struct ubifs_info *c) free_wbufs(c); vfree(c->orph_buf); c->orph_buf = NULL; + kfree(c->write_reserve_buf); + c->write_reserve_buf = NULL; vfree(c->ileb_buf); c->ileb_buf = NULL; ubifs_lpt_free(c, 1); @@ -1942,6 +1959,7 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent) mutex_init(&c->mst_mutex); mutex_init(&c->umount_mutex); mutex_init(&c->bu_mutex); + mutex_init(&c->write_reserve_mutex); init_waitqueue_head(&c->cmt_wq); c->buds = RB_ROOT; c->old_idx = RB_ROOT; -- cgit v1.2.1 From 6342aaebda9b94e3cd101ba13eee690ac6577124 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 8 Mar 2011 14:26:47 +0200 Subject: UBIFS: print max. index node size Improve debugging messages by printing the maximum index node size on mount. Signed-off-by: Artem Bityutskiy --- fs/ubifs/super.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/ubifs/super.c') diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index e360c7a71f9e..e9585ad90f5e 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1447,9 +1447,9 @@ static int mount_ubifs(struct ubifs_info *c) UBIFS_TRUN_NODE_SZ, UBIFS_SB_NODE_SZ, UBIFS_MST_NODE_SZ); dbg_msg("node sizes: ref %zu, cmt. start %zu, orph %zu", UBIFS_REF_NODE_SZ, UBIFS_CS_NODE_SZ, UBIFS_ORPH_NODE_SZ); - dbg_msg("max. node sizes: data %zu, inode %zu dentry %zu", + dbg_msg("max. node sizes: data %zu, inode %zu dentry %zu, idx %d", UBIFS_MAX_DATA_NODE_SZ, UBIFS_MAX_INO_NODE_SZ, - UBIFS_MAX_DENT_NODE_SZ); + UBIFS_MAX_DENT_NODE_SZ, ubifs_idx_node_sz(c, c->fanout)); dbg_msg("dead watermark: %d", c->dead_wm); dbg_msg("dark watermark: %d", c->dark_wm); dbg_msg("LEB overhead: %d", c->leb_overhead); -- cgit v1.2.1 From 2bcf002159c2aedd5c0ab5a21c3ea73fec87ff8d Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Thu, 10 Mar 2011 16:26:32 +0200 Subject: UBIFS: do not check data crc by default Change the default UBIFS behavior WRT data CRC checking. Currently, UBIFS checks data CRC when reading, which slows it down quite a bit, and this is the default option. However, it looks like in average user does not need this feature and would prefer faster read speed over extra reliability. And this seems to be de-facto standard that file-systems do not check data CRC every time they read from the media. Thus, make UBIFS default behavior so that it does not check data CRC. This corresponds to the no_chk_data_crc mount option. Those users who need extra protection can always enable it using the chk_data_crc option. Please, read more information about this feature here: http://www.linux-mtd.infradead.org/doc/ubifs.html#L_checksumming Signed-off-by: Artem Bityutskiy --- fs/ubifs/super.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/ubifs/super.c') diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index e9585ad90f5e..1da5155a1bea 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1977,6 +1977,7 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent) INIT_LIST_HEAD(&c->old_buds); INIT_LIST_HEAD(&c->orph_list); INIT_LIST_HEAD(&c->orph_new); + c->no_chk_data_crc = 1; c->vfs_sb = sb; c->highest_inum = UBIFS_FIRST_INO; -- cgit v1.2.1