diff options
Diffstat (limited to 'fs/ubifs/tnc.c')
| -rw-r--r-- | fs/ubifs/tnc.c | 164 | 
1 files changed, 74 insertions, 90 deletions
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index ad9cf013362..8a40cf9c02d 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c @@ -178,27 +178,11 @@ static int ins_clr_old_idx_znode(struct ubifs_info *c,   */  void destroy_old_idx(struct ubifs_info *c)  { -	struct rb_node *this = c->old_idx.rb_node; -	struct ubifs_old_idx *old_idx; +	struct ubifs_old_idx *old_idx, *n; -	while (this) { -		if (this->rb_left) { -			this = this->rb_left; -			continue; -		} else if (this->rb_right) { -			this = this->rb_right; -			continue; -		} -		old_idx = rb_entry(this, struct ubifs_old_idx, rb); -		this = rb_parent(this); -		if (this) { -			if (this->rb_left == &old_idx->rb) -				this->rb_left = NULL; -			else -				this->rb_right = NULL; -		} +	rbtree_postorder_for_each_entry_safe(old_idx, n, &c->old_idx, rb)  		kfree(old_idx); -	} +  	c->old_idx = RB_ROOT;  } @@ -223,7 +207,7 @@ static struct ubifs_znode *copy_znode(struct ubifs_info *c,  	__set_bit(DIRTY_ZNODE, &zn->flags);  	__clear_bit(COW_ZNODE, &zn->flags); -	ubifs_assert(!test_bit(OBSOLETE_ZNODE, &znode->flags)); +	ubifs_assert(!ubifs_zn_obsolete(znode));  	__set_bit(OBSOLETE_ZNODE, &znode->flags);  	if (znode->level != 0) { @@ -271,7 +255,7 @@ static struct ubifs_znode *dirty_cow_znode(struct ubifs_info *c,  	struct ubifs_znode *zn;  	int err; -	if (!test_bit(COW_ZNODE, &znode->flags)) { +	if (!ubifs_zn_cow(znode)) {  		/* znode is not being committed */  		if (!test_and_set_bit(DIRTY_ZNODE, &znode->flags)) {  			atomic_long_inc(&c->dirty_zn_cnt); @@ -339,17 +323,16 @@ static int lnc_add(struct ubifs_info *c, struct ubifs_zbranch *zbr,  	err = ubifs_validate_entry(c, dent);  	if (err) { -		dbg_dump_stack(); -		dbg_dump_node(c, dent); +		dump_stack(); +		ubifs_dump_node(c, dent);  		return err;  	} -	lnc_node = kmalloc(zbr->len, GFP_NOFS); +	lnc_node = kmemdup(node, zbr->len, GFP_NOFS);  	if (!lnc_node)  		/* We don't have to have the cache, so no error */  		return 0; -	memcpy(lnc_node, node, zbr->len);  	zbr->leaf = lnc_node;  	return 0;  } @@ -373,8 +356,8 @@ static int lnc_add_directly(struct ubifs_info *c, struct ubifs_zbranch *zbr,  	err = ubifs_validate_entry(c, node);  	if (err) { -		dbg_dump_stack(); -		dbg_dump_node(c, node); +		dump_stack(); +		ubifs_dump_node(c, node);  		return err;  	} @@ -447,8 +430,11 @@ static int tnc_read_node_nm(struct ubifs_info *c, struct ubifs_zbranch *zbr,   *   * Note, this function does not check CRC of data nodes if @c->no_chk_data_crc   * is true (it is controlled by corresponding mount option). However, if - * @c->always_chk_crc is true, @c->no_chk_data_crc is ignored and CRC is always - * checked. + * @c->mounting or @c->remounting_rw is true (we are mounting or re-mounting to + * R/W mode), @c->no_chk_data_crc is ignored and CRC is checked. This is + * because during mounting or re-mounting from R/O mode to R/W mode we may read + * journal nodes (when replying the journal or doing the recovery) and the + * journal nodes may potentially be corrupted, so checking is required.   */  static int try_read_node(const struct ubifs_info *c, void *buf, int type,  			 int len, int lnum, int offs) @@ -459,7 +445,7 @@ static int try_read_node(const struct ubifs_info *c, void *buf, int type,  	dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len); -	err = ubi_read(c->ubi, lnum, buf, offs, len); +	err = ubifs_leb_read(c, lnum, buf, offs, len, 1);  	if (err) {  		ubifs_err("cannot read node type %d from LEB %d:%d, error %d",  			  type, lnum, offs, err); @@ -476,7 +462,8 @@ 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 && c->no_chk_data_crc) +	if (type == UBIFS_DATA_NODE && c->no_chk_data_crc && !c->mounting && +	    !c->remounting_rw)  		return 1;  	crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8); @@ -502,7 +489,7 @@ static int fallible_read_node(struct ubifs_info *c, const union ubifs_key *key,  {  	int ret; -	dbg_tnc("LEB %d:%d, key %s", zbr->lnum, zbr->offs, DBGKEY(key)); +	dbg_tnck(key, "LEB %d:%d, key ", zbr->lnum, zbr->offs);  	ret = try_read_node(c, node, key_type(c, key), zbr->len, zbr->lnum,  			    zbr->offs); @@ -516,8 +503,8 @@ static int fallible_read_node(struct ubifs_info *c, const union ubifs_key *key,  			ret = 0;  	}  	if (ret == 0 && c->replaying) -		dbg_mnt("dangling branch LEB %d:%d len %d, key %s", -			zbr->lnum, zbr->offs, zbr->len, DBGKEY(key)); +		dbg_mntk(key, "dangling branch LEB %d:%d len %d, key ", +			zbr->lnum, zbr->offs, zbr->len);  	return ret;  } @@ -992,9 +979,9 @@ static int fallible_resolve_collision(struct ubifs_info *c,  	if (adding || !o_znode)  		return 0; -	dbg_mnt("dangling match LEB %d:%d len %d %s", +	dbg_mntk(key, "dangling match LEB %d:%d len %d key ",  		o_znode->zbranch[o_n].lnum, o_znode->zbranch[o_n].offs, -		o_znode->zbranch[o_n].len, DBGKEY(key)); +		o_znode->zbranch[o_n].len);  	*zn = o_znode;  	*n = o_n;  	return 1; @@ -1176,7 +1163,7 @@ int ubifs_lookup_level0(struct ubifs_info *c, const union ubifs_key *key,  	struct ubifs_znode *znode;  	unsigned long time = get_seconds(); -	dbg_tnc("search key %s", DBGKEY(key)); +	dbg_tnck(key, "search key ");  	ubifs_assert(key_type(c, key) < UBIFS_INVALID_KEY);  	znode = c->zroot.znode; @@ -1312,7 +1299,7 @@ static int lookup_level0_dirty(struct ubifs_info *c, const union ubifs_key *key,  	struct ubifs_znode *znode;  	unsigned long time = get_seconds(); -	dbg_tnc("search and dirty key %s", DBGKEY(key)); +	dbg_tnck(key, "search and dirty key ");  	znode = c->zroot.znode;  	if (unlikely(!znode)) { @@ -1662,7 +1649,7 @@ static int read_wbuf(struct ubifs_wbuf *wbuf, void *buf, int len, int lnum,  	if (!overlap) {  		/* We may safely unlock the write-buffer and read the data */  		spin_unlock(&wbuf->lock); -		return ubi_read(c->ubi, lnum, buf, offs, len); +		return ubifs_leb_read(c, lnum, buf, offs, len, 0);  	}  	/* Don't read under wbuf */ @@ -1676,7 +1663,7 @@ static int read_wbuf(struct ubifs_wbuf *wbuf, void *buf, int len, int lnum,  	if (rlen > 0)  		/* Read everything that goes before write-buffer */ -		return ubi_read(c->ubi, lnum, buf, offs, rlen); +		return ubifs_leb_read(c, lnum, buf, offs, rlen, 0);  	return 0;  } @@ -1719,8 +1706,8 @@ static int validate_data_node(struct ubifs_info *c, void *buf,  	if (!keys_eq(c, &zbr->key, &key1)) {  		ubifs_err("bad key in node at LEB %d:%d",  			  zbr->lnum, zbr->offs); -		dbg_tnc("looked for key %s found node's key %s", -			DBGKEY(&zbr->key), DBGKEY1(&key1)); +		dbg_tnck(&zbr->key, "looked for key "); +		dbg_tnck(&key1, "found node's key ");  		goto out_err;  	} @@ -1730,8 +1717,8 @@ out_err:  	err = -EINVAL;  out:  	ubifs_err("bad node at LEB %d:%d", zbr->lnum, zbr->offs); -	dbg_dump_node(c, buf); -	dbg_dump_stack(); +	ubifs_dump_node(c, buf); +	dump_stack();  	return err;  } @@ -1763,7 +1750,7 @@ int ubifs_tnc_bulk_read(struct ubifs_info *c, struct bu_info *bu)  	if (wbuf)  		err = read_wbuf(wbuf, bu->buf, len, lnum, offs);  	else -		err = ubi_read(c->ubi, lnum, bu->buf, offs, len); +		err = ubifs_leb_read(c, lnum, bu->buf, offs, len, 0);  	/* Check for a race with GC */  	if (maybe_leb_gced(c, lnum, bu->gc_seq)) @@ -1772,8 +1759,8 @@ int ubifs_tnc_bulk_read(struct ubifs_info *c, struct bu_info *bu)  	if (err && err != -EBADMSG) {  		ubifs_err("failed to read from LEB %d:%d, error %d",  			  lnum, offs, err); -		dbg_dump_stack(); -		dbg_tnc("key %s", DBGKEY(&bu->key)); +		dump_stack(); +		dbg_tnck(&bu->key, "key ");  		return err;  	} @@ -1808,7 +1795,7 @@ static int do_lookup_nm(struct ubifs_info *c, const union ubifs_key *key,  	int found, n, err;  	struct ubifs_znode *znode; -	dbg_tnc("name '%.*s' key %s", nm->len, nm->name, DBGKEY(key)); +	dbg_tnck(key, "name '%.*s' key ", nm->len, nm->name);  	mutex_lock(&c->tnc_mutex);  	found = ubifs_lookup_level0(c, key, &znode, &n);  	if (!found) { @@ -1982,8 +1969,7 @@ again:  	zp = znode->parent;  	if (znode->child_cnt < c->fanout) {  		ubifs_assert(n != c->fanout); -		dbg_tnc("inserted at %d level %d, key %s", n, znode->level, -			DBGKEY(key)); +		dbg_tnck(key, "inserted at %d level %d, key ", n, znode->level);  		insert_zbranch(znode, zbr, n); @@ -1998,7 +1984,7 @@ again:  	 * Unfortunately, @znode does not have more empty slots and we have to  	 * split it.  	 */ -	dbg_tnc("splitting level %d, key %s", znode->level, DBGKEY(key)); +	dbg_tnck(key, "splitting level %d, key ", znode->level);  	if (znode->alt)  		/* @@ -2092,7 +2078,7 @@ do_split:  	}  	/* Insert new key and branch */ -	dbg_tnc("inserting at %d level %d, key %s", n, zn->level, DBGKEY(key)); +	dbg_tnck(key, "inserting at %d level %d, key ", n, zn->level);  	insert_zbranch(zi, zbr, n); @@ -2168,7 +2154,7 @@ int ubifs_tnc_add(struct ubifs_info *c, const union ubifs_key *key, int lnum,  	struct ubifs_znode *znode;  	mutex_lock(&c->tnc_mutex); -	dbg_tnc("%d:%d, len %d, key %s", lnum, offs, len, DBGKEY(key)); +	dbg_tnck(key, "%d:%d, len %d, key ", lnum, offs, len);  	found = lookup_level0_dirty(c, key, &znode, &n);  	if (!found) {  		struct ubifs_zbranch zbr; @@ -2217,8 +2203,8 @@ int ubifs_tnc_replace(struct ubifs_info *c, const union ubifs_key *key,  	struct ubifs_znode *znode;  	mutex_lock(&c->tnc_mutex); -	dbg_tnc("old LEB %d:%d, new LEB %d:%d, len %d, key %s", old_lnum, -		old_offs, lnum, offs, len, DBGKEY(key)); +	dbg_tnck(key, "old LEB %d:%d, new LEB %d:%d, len %d, key ", old_lnum, +		 old_offs, lnum, offs, len);  	found = lookup_level0_dirty(c, key, &znode, &n);  	if (found < 0) {  		err = found; @@ -2300,8 +2286,8 @@ int ubifs_tnc_add_nm(struct ubifs_info *c, const union ubifs_key *key,  	struct ubifs_znode *znode;  	mutex_lock(&c->tnc_mutex); -	dbg_tnc("LEB %d:%d, name '%.*s', key %s", lnum, offs, nm->len, nm->name, -		DBGKEY(key)); +	dbg_tnck(key, "LEB %d:%d, name '%.*s', key ", +		 lnum, offs, nm->len, nm->name);  	found = lookup_level0_dirty(c, key, &znode, &n);  	if (found < 0) {  		err = found; @@ -2359,7 +2345,7 @@ int ubifs_tnc_add_nm(struct ubifs_info *c, const union ubifs_key *key,  			 * by passing 'ubifs_tnc_remove_nm()' the same key but  			 * an unmatchable name.  			 */ -			struct qstr noname = { .len = 0, .name = "" }; +			struct qstr noname = { .name = "" };  			err = dbg_check_tnc(c, 0);  			mutex_unlock(&c->tnc_mutex); @@ -2394,14 +2380,14 @@ static int tnc_delete(struct ubifs_info *c, struct ubifs_znode *znode, int n)  	/* Delete without merge for now */  	ubifs_assert(znode->level == 0);  	ubifs_assert(n >= 0 && n < c->fanout); -	dbg_tnc("deleting %s", DBGKEY(&znode->zbranch[n].key)); +	dbg_tnck(&znode->zbranch[n].key, "deleting key ");  	zbr = &znode->zbranch[n];  	lnc_free(zbr);  	err = ubifs_add_dirt(c, zbr->lnum, zbr->len);  	if (err) { -		dbg_dump_znode(c, znode); +		ubifs_dump_znode(c, znode);  		return err;  	} @@ -2419,7 +2405,7 @@ static int tnc_delete(struct ubifs_info *c, struct ubifs_znode *znode, int n)  	 */  	do { -		ubifs_assert(!test_bit(OBSOLETE_ZNODE, &znode->flags)); +		ubifs_assert(!ubifs_zn_obsolete(znode));  		ubifs_assert(ubifs_zn_dirty(znode));  		zp = znode->parent; @@ -2475,9 +2461,8 @@ static int tnc_delete(struct ubifs_info *c, struct ubifs_znode *znode, int n)  			c->zroot.offs = zbr->offs;  			c->zroot.len = zbr->len;  			c->zroot.znode = znode; -			ubifs_assert(!test_bit(OBSOLETE_ZNODE, -				     &zp->flags)); -			ubifs_assert(test_bit(DIRTY_ZNODE, &zp->flags)); +			ubifs_assert(!ubifs_zn_obsolete(zp)); +			ubifs_assert(ubifs_zn_dirty(zp));  			atomic_long_dec(&c->dirty_zn_cnt);  			if (zp->cnext) { @@ -2505,7 +2490,7 @@ int ubifs_tnc_remove(struct ubifs_info *c, const union ubifs_key *key)  	struct ubifs_znode *znode;  	mutex_lock(&c->tnc_mutex); -	dbg_tnc("key %s", DBGKEY(key)); +	dbg_tnck(key, "key ");  	found = lookup_level0_dirty(c, key, &znode, &n);  	if (found < 0) {  		err = found; @@ -2536,7 +2521,7 @@ int ubifs_tnc_remove_nm(struct ubifs_info *c, const union ubifs_key *key,  	struct ubifs_znode *znode;  	mutex_lock(&c->tnc_mutex); -	dbg_tnc("%.*s, key %s", nm->len, nm->name, DBGKEY(key)); +	dbg_tnck(key, "%.*s, key ", nm->len, nm->name);  	err = lookup_level0_dirty(c, key, &znode, &n);  	if (err < 0)  		goto out_unlock; @@ -2553,11 +2538,11 @@ int ubifs_tnc_remove_nm(struct ubifs_info *c, const union ubifs_key *key,  		if (err) {  			/* Ensure the znode is dirtied */  			if (znode->cnext || !ubifs_zn_dirty(znode)) { -				    znode = dirty_cow_bottom_up(c, znode); -				    if (IS_ERR(znode)) { -					    err = PTR_ERR(znode); -					    goto out_unlock; -				    } +				znode = dirty_cow_bottom_up(c, znode); +				if (IS_ERR(znode)) { +					err = PTR_ERR(znode); +					goto out_unlock; +				}  			}  			err = tnc_delete(c, znode, n);  		} @@ -2648,10 +2633,10 @@ int ubifs_tnc_remove_range(struct ubifs_info *c, union ubifs_key *from_key,  			err = ubifs_add_dirt(c, znode->zbranch[i].lnum,  					     znode->zbranch[i].len);  			if (err) { -				dbg_dump_znode(c, znode); +				ubifs_dump_znode(c, znode);  				goto out_unlock;  			} -			dbg_tnc("removing %s", DBGKEY(key)); +			dbg_tnck(key, "removing key ");  		}  		if (k) {  			for (i = n + 1 + k; i < znode->child_cnt; i++) @@ -2771,7 +2756,7 @@ struct ubifs_dent_node *ubifs_tnc_next_ent(struct ubifs_info *c,  	struct ubifs_zbranch *zbr;  	union ubifs_key *dkey; -	dbg_tnc("%s %s", nm->name ? (char *)nm->name : "(lowest)", DBGKEY(key)); +	dbg_tnck(key, "%s ", nm->name ? (char *)nm->name : "(lowest)");  	ubifs_assert(is_hash_key(c, key));  	mutex_lock(&c->tnc_mutex); @@ -2861,7 +2846,7 @@ static void tnc_destroy_cnext(struct ubifs_info *c)  		struct ubifs_znode *znode = cnext;  		cnext = cnext->cnext; -		if (test_bit(OBSOLETE_ZNODE, &znode->flags)) +		if (ubifs_zn_obsolete(znode))  			kfree(znode);  	} while (cnext && cnext != c->cnext);  } @@ -2872,12 +2857,14 @@ static void tnc_destroy_cnext(struct ubifs_info *c)   */  void ubifs_tnc_close(struct ubifs_info *c)  { -	long clean_freed; -  	tnc_destroy_cnext(c);  	if (c->zroot.znode) { -		clean_freed = ubifs_destroy_tnc_subtree(c->zroot.znode); -		atomic_long_sub(clean_freed, &ubifs_clean_zn_cnt); +		long n, freed; + +		n = atomic_long_read(&c->clean_zn_cnt); +		freed = ubifs_destroy_tnc_subtree(c->zroot.znode); +		ubifs_assert(freed == n); +		atomic_long_sub(n, &ubifs_clean_zn_cnt);  	}  	kfree(c->gap_lebs);  	kfree(c->ilebs); @@ -3273,8 +3260,6 @@ out_unlock:  	return err;  } -#ifdef CONFIG_UBIFS_FS_DEBUG -  /**   * dbg_check_inode_size - check if inode size is correct.   * @c: UBIFS file-system description object @@ -3296,7 +3281,7 @@ int dbg_check_inode_size(struct ubifs_info *c, const struct inode *inode,  	if (!S_ISREG(inode->i_mode))  		return 0; -	if (!(ubifs_chk_flags & UBIFS_CHK_GEN)) +	if (!dbg_is_chk_gen(c))  		return 0;  	block = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT; @@ -3329,16 +3314,15 @@ int dbg_check_inode_size(struct ubifs_info *c, const struct inode *inode,  out_dump:  	block = key_block(c, key); -	ubifs_err("inode %lu has size %lld, but there are data at offset %lld " -		  "(data key %s)", (unsigned long)inode->i_ino, size, -		  ((loff_t)block) << UBIFS_BLOCK_SHIFT, DBGKEY(key)); -	dbg_dump_inode(c, inode); -	dbg_dump_stack(); -	err = -EINVAL; +	ubifs_err("inode %lu has size %lld, but there are data at offset %lld", +		  (unsigned long)inode->i_ino, size, +		  ((loff_t)block) << UBIFS_BLOCK_SHIFT); +	mutex_unlock(&c->tnc_mutex); +	ubifs_dump_inode(c, inode); +	dump_stack(); +	return -EINVAL;  out_unlock:  	mutex_unlock(&c->tnc_mutex);  	return err;  } - -#endif /* CONFIG_UBIFS_FS_DEBUG */  | 
