Commit 59a7ac12 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'linux-next' of git://git.infradead.org/ubifs-2.6

* 'linux-next' of git://git.infradead.org/ubifs-2.6: (32 commits)
  MAINTAINERS: change e-mail of Adrian Hunter
  UBIFS: fix master node recovery
  UBIFS: improve power cut emulation testing
  UBIFS: rename recovery testing variables
  UBIFS: remove custom list of superblocks
  UBIFS: stop re-defining UBI operations
  UBIFS: switch to I/O helpers
  UBIFS: switch to ubifs_leb_write
  UBIFS: switch to ubifs_leb_read
  UBIFS: introduce more I/O helpers
  UBIFS: always print stacktrace when switching to R/O mode
  UBIFS: remove unused and unneeded debugging function
  UBIFS: add global debugfs knobs
  UBIFS: introduce debugfs helpers
  UBIFS: re-arrange debugging code a bit
  UBIFS: be more informative in failure mode
  UBIFS: switch self-check knobs to debugfs
  UBIFS: lessen amount of debugging check types
  UBIFS: introduce helper functions for debugging checks and tests
  UBIFS: amend debugging inode size check function prototype
  ...
parents f99b7880 cc8f9b99
...@@ -111,34 +111,6 @@ The following is an example of the kernel boot arguments to attach mtd0 ...@@ -111,34 +111,6 @@ The following is an example of the kernel boot arguments to attach mtd0
to UBI and mount volume "rootfs": to UBI and mount volume "rootfs":
ubi.mtd=0 root=ubi0:rootfs rootfstype=ubifs ubi.mtd=0 root=ubi0:rootfs rootfstype=ubifs
Module Parameters for Debugging
===============================
When UBIFS has been compiled with debugging enabled, there are 2 module
parameters that are available to control aspects of testing and debugging.
debug_chks Selects extra checks that UBIFS can do while running:
Check Flag value
General checks 1
Check Tree Node Cache (TNC) 2
Check indexing tree size 4
Check orphan area 8
Check old indexing tree 16
Check LEB properties (lprops) 32
Check leaf nodes and inodes 64
debug_tsts Selects a mode of testing, as follows:
Test mode Flag value
Failure mode for recovery testing 4
For example, set debug_chks to 3 to enable general and TNC checks.
References References
========== ==========
......
List of maintainers and how to submit kernel changes List of maintainers and how to submit kernel changes
Please try to follow the guidelines below. This will make things Please try to follow the guidelines below. This will make things
...@@ -6321,7 +6322,7 @@ F: drivers/scsi/u14-34f.c ...@@ -6321,7 +6322,7 @@ F: drivers/scsi/u14-34f.c
UBI FILE SYSTEM (UBIFS) UBI FILE SYSTEM (UBIFS)
M: Artem Bityutskiy <dedekind1@gmail.com> M: Artem Bityutskiy <dedekind1@gmail.com>
M: Adrian Hunter <adrian.hunter@nokia.com> M: Adrian Hunter <adrian.hunter@intel.com>
L: linux-mtd@lists.infradead.org L: linux-mtd@lists.infradead.org
T: git git://git.infradead.org/ubifs-2.6.git T: git git://git.infradead.org/ubifs-2.6.git
W: http://www.linux-mtd.infradead.org/doc/ubifs.html W: http://www.linux-mtd.infradead.org/doc/ubifs.html
......
...@@ -78,7 +78,7 @@ static int nothing_to_commit(struct ubifs_info *c) ...@@ -78,7 +78,7 @@ static int nothing_to_commit(struct ubifs_info *c)
* If the root TNC node is dirty, we definitely have something to * If the root TNC node is dirty, we definitely have something to
* commit. * commit.
*/ */
if (c->zroot.znode && test_bit(DIRTY_ZNODE, &c->zroot.znode->flags)) if (c->zroot.znode && ubifs_zn_dirty(c->zroot.znode))
return 0; return 0;
/* /*
...@@ -418,7 +418,7 @@ int ubifs_run_commit(struct ubifs_info *c) ...@@ -418,7 +418,7 @@ int ubifs_run_commit(struct ubifs_info *c)
spin_lock(&c->cs_lock); spin_lock(&c->cs_lock);
if (c->cmt_state == COMMIT_BROKEN) { if (c->cmt_state == COMMIT_BROKEN) {
err = -EINVAL; err = -EROFS;
goto out; goto out;
} }
...@@ -444,7 +444,7 @@ int ubifs_run_commit(struct ubifs_info *c) ...@@ -444,7 +444,7 @@ int ubifs_run_commit(struct ubifs_info *c)
* re-check it. * re-check it.
*/ */
if (c->cmt_state == COMMIT_BROKEN) { if (c->cmt_state == COMMIT_BROKEN) {
err = -EINVAL; err = -EROFS;
goto out_cmt_unlock; goto out_cmt_unlock;
} }
...@@ -576,7 +576,7 @@ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot) ...@@ -576,7 +576,7 @@ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot)
struct idx_node *i; struct idx_node *i;
size_t sz; size_t sz;
if (!(ubifs_chk_flags & UBIFS_CHK_OLD_IDX)) if (!dbg_is_chk_index(c))
return 0; return 0;
INIT_LIST_HEAD(&list); INIT_LIST_HEAD(&list);
......
This diff is collapsed.
This diff is collapsed.
...@@ -102,7 +102,7 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir, ...@@ -102,7 +102,7 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir,
* UBIFS has to fully control "clean <-> dirty" transitions of inodes * UBIFS has to fully control "clean <-> dirty" transitions of inodes
* to make budgeting work. * to make budgeting work.
*/ */
inode->i_flags |= (S_NOCMTIME); inode->i_flags |= S_NOCMTIME;
inode_init_owner(inode, dir, mode); inode_init_owner(inode, dir, mode);
inode->i_mtime = inode->i_atime = inode->i_ctime = inode->i_mtime = inode->i_atime = inode->i_ctime =
...@@ -172,9 +172,11 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir, ...@@ -172,9 +172,11 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir,
#ifdef CONFIG_UBIFS_FS_DEBUG #ifdef CONFIG_UBIFS_FS_DEBUG
static int dbg_check_name(struct ubifs_dent_node *dent, struct qstr *nm) static int dbg_check_name(const struct ubifs_info *c,
const struct ubifs_dent_node *dent,
const struct qstr *nm)
{ {
if (!(ubifs_chk_flags & UBIFS_CHK_GEN)) if (!dbg_is_chk_gen(c))
return 0; return 0;
if (le16_to_cpu(dent->nlen) != nm->len) if (le16_to_cpu(dent->nlen) != nm->len)
return -EINVAL; return -EINVAL;
...@@ -185,7 +187,7 @@ static int dbg_check_name(struct ubifs_dent_node *dent, struct qstr *nm) ...@@ -185,7 +187,7 @@ static int dbg_check_name(struct ubifs_dent_node *dent, struct qstr *nm)
#else #else
#define dbg_check_name(dent, nm) 0 #define dbg_check_name(c, dent, nm) 0
#endif #endif
...@@ -219,7 +221,7 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry, ...@@ -219,7 +221,7 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
goto out; goto out;
} }
if (dbg_check_name(dent, &dentry->d_name)) { if (dbg_check_name(c, dent, &dentry->d_name)) {
err = -EINVAL; err = -EINVAL;
goto out; goto out;
} }
...@@ -522,7 +524,7 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir, ...@@ -522,7 +524,7 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
ubifs_assert(mutex_is_locked(&dir->i_mutex)); ubifs_assert(mutex_is_locked(&dir->i_mutex));
ubifs_assert(mutex_is_locked(&inode->i_mutex)); ubifs_assert(mutex_is_locked(&inode->i_mutex));
err = dbg_check_synced_i_size(inode); err = dbg_check_synced_i_size(c, inode);
if (err) if (err)
return err; return err;
...@@ -577,7 +579,7 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -577,7 +579,7 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry)
inode->i_nlink, dir->i_ino); inode->i_nlink, dir->i_ino);
ubifs_assert(mutex_is_locked(&dir->i_mutex)); ubifs_assert(mutex_is_locked(&dir->i_mutex));
ubifs_assert(mutex_is_locked(&inode->i_mutex)); ubifs_assert(mutex_is_locked(&inode->i_mutex));
err = dbg_check_synced_i_size(inode); err = dbg_check_synced_i_size(c, inode);
if (err) if (err)
return err; return err;
......
...@@ -1263,7 +1263,7 @@ int ubifs_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -1263,7 +1263,7 @@ int ubifs_setattr(struct dentry *dentry, struct iattr *attr)
if (err) if (err)
return err; return err;
err = dbg_check_synced_i_size(inode); err = dbg_check_synced_i_size(c, inode);
if (err) if (err)
return err; return err;
......
...@@ -86,8 +86,125 @@ void ubifs_ro_mode(struct ubifs_info *c, int err) ...@@ -86,8 +86,125 @@ void ubifs_ro_mode(struct ubifs_info *c, int err)
c->no_chk_data_crc = 0; c->no_chk_data_crc = 0;
c->vfs_sb->s_flags |= MS_RDONLY; c->vfs_sb->s_flags |= MS_RDONLY;
ubifs_warn("switched to read-only mode, error %d", err); ubifs_warn("switched to read-only mode, error %d", err);
dump_stack();
}
}
/*
* Below are simple wrappers over UBI I/O functions which include some
* additional checks and UBIFS debugging stuff. See corresponding UBI function
* for more information.
*/
int ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs,
int len, int even_ebadmsg)
{
int err;
err = ubi_read(c->ubi, lnum, buf, offs, len);
/*
* In case of %-EBADMSG print the error message only if the
* @even_ebadmsg is true.
*/
if (err && (err != -EBADMSG || even_ebadmsg)) {
ubifs_err("reading %d bytes from LEB %d:%d failed, error %d",
len, lnum, offs, err);
dbg_dump_stack();
}
return err;
}
int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
int len, int dtype)
{
int err;
ubifs_assert(!c->ro_media && !c->ro_mount);
if (c->ro_error)
return -EROFS;
if (!dbg_is_tst_rcvry(c))
err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
else
err = dbg_leb_write(c, lnum, buf, offs, len, dtype);
if (err) {
ubifs_err("writing %d bytes to LEB %d:%d failed, error %d",
len, lnum, offs, err);
ubifs_ro_mode(c, err);
dbg_dump_stack();
}
return err;
}
int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len,
int dtype)
{
int err;
ubifs_assert(!c->ro_media && !c->ro_mount);
if (c->ro_error)
return -EROFS;
if (!dbg_is_tst_rcvry(c))
err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
else
err = dbg_leb_change(c, lnum, buf, len, dtype);
if (err) {
ubifs_err("changing %d bytes in LEB %d failed, error %d",
len, lnum, err);
ubifs_ro_mode(c, err);
dbg_dump_stack();
}
return err;
}
int ubifs_leb_unmap(struct ubifs_info *c, int lnum)
{
int err;
ubifs_assert(!c->ro_media && !c->ro_mount);
if (c->ro_error)
return -EROFS;
if (!dbg_is_tst_rcvry(c))
err = ubi_leb_unmap(c->ubi, lnum);
else
err = dbg_leb_unmap(c, lnum);
if (err) {
ubifs_err("unmap LEB %d failed, error %d", lnum, err);
ubifs_ro_mode(c, err);
dbg_dump_stack();
}
return err;
}
int ubifs_leb_map(struct ubifs_info *c, int lnum, int dtype)
{
int err;
ubifs_assert(!c->ro_media && !c->ro_mount);
if (c->ro_error)
return -EROFS;
if (!dbg_is_tst_rcvry(c))
err = ubi_leb_map(c->ubi, lnum, dtype);
else
err = dbg_leb_map(c, lnum, dtype);
if (err) {
ubifs_err("mapping LEB %d failed, error %d", lnum, err);
ubifs_ro_mode(c, err);
dbg_dump_stack();
}
return err;
}
int ubifs_is_mapped(const struct ubifs_info *c, int lnum)
{
int err;
err = ubi_is_mapped(c->ubi, lnum);
if (err < 0) {
ubifs_err("ubi_is_mapped failed for LEB %d, error %d",
lnum, err);
dbg_dump_stack(); dbg_dump_stack();
} }
return err;
} }
/** /**
...@@ -406,14 +523,10 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf) ...@@ -406,14 +523,10 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)
dirt = sync_len - wbuf->used; dirt = sync_len - wbuf->used;
if (dirt) if (dirt)
ubifs_pad(c, wbuf->buf + wbuf->used, dirt); ubifs_pad(c, wbuf->buf + wbuf->used, dirt);
err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs, err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, wbuf->offs, sync_len,
sync_len, wbuf->dtype); wbuf->dtype);
if (err) { if (err)
ubifs_err("cannot write %d bytes to LEB %d:%d",
sync_len, wbuf->lnum, wbuf->offs);
dbg_dump_stack();
return err; return err;
}
spin_lock(&wbuf->lock); spin_lock(&wbuf->lock);
wbuf->offs += sync_len; wbuf->offs += sync_len;
...@@ -605,9 +718,9 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len) ...@@ -605,9 +718,9 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
if (aligned_len == wbuf->avail) { if (aligned_len == wbuf->avail) {
dbg_io("flush jhead %s wbuf to LEB %d:%d", dbg_io("flush jhead %s wbuf to LEB %d:%d",
dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs); dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs);
err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf,
wbuf->offs, wbuf->size, wbuf->offs, wbuf->size,
wbuf->dtype); wbuf->dtype);
if (err) if (err)
goto out; goto out;
...@@ -642,8 +755,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len) ...@@ -642,8 +755,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
dbg_io("flush jhead %s wbuf to LEB %d:%d", dbg_io("flush jhead %s wbuf to LEB %d:%d",
dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs); dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs);
memcpy(wbuf->buf + wbuf->used, buf, wbuf->avail); memcpy(wbuf->buf + wbuf->used, buf, wbuf->avail);
err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs, err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, wbuf->offs,
wbuf->size, wbuf->dtype); wbuf->size, wbuf->dtype);
if (err) if (err)
goto out; goto out;
...@@ -661,8 +774,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len) ...@@ -661,8 +774,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
*/ */
dbg_io("write %d bytes to LEB %d:%d", dbg_io("write %d bytes to LEB %d:%d",
wbuf->size, wbuf->lnum, wbuf->offs); wbuf->size, wbuf->lnum, wbuf->offs);
err = ubi_leb_write(c->ubi, wbuf->lnum, buf, wbuf->offs, err = ubifs_leb_write(c, wbuf->lnum, buf, wbuf->offs,
wbuf->size, wbuf->dtype); wbuf->size, wbuf->dtype);
if (err) if (err)
goto out; goto out;
...@@ -683,8 +796,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len) ...@@ -683,8 +796,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
n <<= c->max_write_shift; n <<= c->max_write_shift;
dbg_io("write %d bytes to LEB %d:%d", n, wbuf->lnum, dbg_io("write %d bytes to LEB %d:%d", n, wbuf->lnum,
wbuf->offs); wbuf->offs);
err = ubi_leb_write(c->ubi, wbuf->lnum, buf + written, err = ubifs_leb_write(c, wbuf->lnum, buf + written,
wbuf->offs, n, wbuf->dtype); wbuf->offs, n, wbuf->dtype);
if (err) if (err)
goto out; goto out;
wbuf->offs += n; wbuf->offs += n;
...@@ -766,13 +879,9 @@ int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum, ...@@ -766,13 +879,9 @@ int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum,
return -EROFS; return -EROFS;
ubifs_prepare_node(c, buf, len, 1); ubifs_prepare_node(c, buf, len, 1);
err = ubi_leb_write(c->ubi, lnum, buf, offs, buf_len, dtype); err = ubifs_leb_write(c, lnum, buf, offs, buf_len, dtype);
if (err) { if (err)
ubifs_err("cannot write %d bytes to LEB %d:%d, error %d",
buf_len, lnum, offs, err);
dbg_dump_node(c, buf); dbg_dump_node(c, buf);
dbg_dump_stack();
}
return err; return err;
} }
...@@ -824,13 +933,9 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len, ...@@ -824,13 +933,9 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
if (rlen > 0) { if (rlen > 0) {
/* Read everything that goes before write-buffer */ /* Read everything that goes before write-buffer */
err = ubi_read(c->ubi, lnum, buf, offs, rlen); err = ubifs_leb_read(c, lnum, buf, offs, rlen, 0);
if (err && err != -EBADMSG) { if (err && err != -EBADMSG)
ubifs_err("failed to read node %d from LEB %d:%d, "
"error %d", type, lnum, offs, err);
dbg_dump_stack();
return err; return err;
}
} }
if (type != ch->node_type) { if (type != ch->node_type) {
...@@ -885,12 +990,9 @@ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len, ...@@ -885,12 +990,9 @@ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
ubifs_assert(!(offs & 7) && offs < c->leb_size); ubifs_assert(!(offs & 7) && offs < c->leb_size);
ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT); ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT);
err = ubi_read(c->ubi, lnum, buf, offs, len); err = ubifs_leb_read(c, lnum, buf, offs, len, 0);
if (err && err != -EBADMSG) { if (err && err != -EBADMSG)
ubifs_err("cannot read node %d from LEB %d:%d, error %d",
type, lnum, offs, err);
return err; return err;
}
if (type != ch->node_type) { if (type != ch->node_type) {
ubifs_err("bad node type (%d but expected %d)", ubifs_err("bad node type (%d but expected %d)",
......
...@@ -262,7 +262,7 @@ int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs) ...@@ -262,7 +262,7 @@ int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs)
* an unclean reboot, because the target LEB might have been * an unclean reboot, because the target LEB might have been
* unmapped, but not yet physically erased. * unmapped, but not yet physically erased.
*/ */
err = ubi_leb_map(c->ubi, bud->lnum, UBI_SHORTTERM); err = ubifs_leb_map(c, bud->lnum, UBI_SHORTTERM);
if (err) if (err)
goto out_unlock; goto out_unlock;
} }
...@@ -283,8 +283,6 @@ int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs) ...@@ -283,8 +283,6 @@ int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs)
return 0; return 0;
out_unlock: out_unlock:
if (err != -EAGAIN)
ubifs_ro_mode(c, err);
mutex_unlock(&c->log_mutex); mutex_unlock(&c->log_mutex);
kfree(ref); kfree(ref);
kfree(bud); kfree(bud);
...@@ -752,7 +750,7 @@ static int dbg_check_bud_bytes(struct ubifs_info *c) ...@@ -752,7 +750,7 @@ static int dbg_check_bud_bytes(struct ubifs_info *c)
struct ubifs_bud *bud; struct ubifs_bud *bud;
long long bud_bytes = 0; long long bud_bytes = 0;
if (!(ubifs_chk_flags & UBIFS_CHK_GEN)) if (!dbg_is_chk_gen(c))
return 0; return 0;
spin_lock(&c->buds_lock); spin_lock(&c->buds_lock);
......
...@@ -504,7 +504,7 @@ static int is_lprops_dirty(struct ubifs_info *c, struct ubifs_lprops *lprops) ...@@ -504,7 +504,7 @@ static int is_lprops_dirty(struct ubifs_info *c, struct ubifs_lprops *lprops)
pnode = (struct ubifs_pnode *)container_of(lprops - pos, pnode = (struct ubifs_pnode *)container_of(lprops - pos,
struct ubifs_pnode, struct ubifs_pnode,
lprops[0]); lprops[0]);
return !test_bit(COW_ZNODE, &pnode->flags) && return !test_bit(COW_CNODE, &pnode->flags) &&
test_bit(DIRTY_CNODE, &pnode->flags); test_bit(DIRTY_CNODE, &pnode->flags);
} }
...@@ -860,7 +860,7 @@ int dbg_check_cats(struct ubifs_info *c) ...@@ -860,7 +860,7 @@ int dbg_check_cats(struct ubifs_info *c)
struct list_head *pos; struct list_head *pos;
int i, cat; int i, cat;
if (!(ubifs_chk_flags & (UBIFS_CHK_GEN | UBIFS_CHK_LPROPS))) if (!dbg_is_chk_gen(c) && !dbg_is_chk_lprops(c))
return 0; return 0;
list_for_each_entry(lprops, &c->empty_list, list) { list_for_each_entry(lprops, &c->empty_list, list) {
...@@ -958,7 +958,7 @@ void dbg_check_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat, ...@@ -958,7 +958,7 @@ void dbg_check_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat,
{ {
int i = 0, j, err = 0; int i = 0, j, err = 0;
if (!(ubifs_chk_flags & (UBIFS_CHK_GEN | UBIFS_CHK_LPROPS))) if (!dbg_is_chk_gen(c) && !dbg_is_chk_lprops(c))
return; return;
for (i = 0; i < heap->cnt; i++) { for (i = 0; i < heap->cnt; i++) {
...@@ -1262,7 +1262,7 @@ int dbg_check_lprops(struct ubifs_info *c) ...@@ -1262,7 +1262,7 @@ int dbg_check_lprops(struct ubifs_info *c)
int i, err; int i, err;
struct ubifs_lp_stats lst; struct ubifs_lp_stats lst;
if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS)) if (!dbg_is_chk_lprops(c))
return 0; return 0;
/* /*
......
...@@ -701,8 +701,8 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first, ...@@ -701,8 +701,8 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
alen = ALIGN(len, c->min_io_size); alen = ALIGN(len, c->min_io_size);
set_ltab(c, lnum, c->leb_size - alen, alen - len); set_ltab(c, lnum, c->leb_size - alen, alen - len);
memset(p, 0xff, alen - len); memset(p, 0xff, alen - len);
err = ubi_leb_change(c->ubi, lnum++, buf, alen, err = ubifs_leb_change(c, lnum++, buf, alen,
UBI_SHORTTERM); UBI_SHORTTERM);
if (err) if (err)
goto out; goto out;
p = buf; p = buf;
...@@ -732,8 +732,8 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first, ...@@ -732,8 +732,8 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
set_ltab(c, lnum, c->leb_size - alen, set_ltab(c, lnum, c->leb_size - alen,
alen - len); alen - len);
memset(p, 0xff, alen - len); memset(p, 0xff, alen - len);
err = ubi_leb_change(c->ubi, lnum++, buf, alen, err = ubifs_leb_change(c, lnum++, buf, alen,
UBI_SHORTTERM); UBI_SHORTTERM);
if (err) if (err)
goto out; goto out;
p = buf; p = buf;
...@@ -780,8 +780,8 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first, ...@@ -780,8 +780,8 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
alen = ALIGN(len, c->min_io_size); alen = ALIGN(len, c->min_io_size);
set_ltab(c, lnum, c->leb_size - alen, alen - len); set_ltab(c, lnum, c->leb_size - alen, alen - len);
memset(p, 0xff, alen - len); memset(p, 0xff, alen - len);
err = ubi_leb_change(c->ubi, lnum++, buf, alen, err = ubifs_leb_change(c, lnum++, buf, alen,
UBI_SHORTTERM); UBI_SHORTTERM);
if (err) if (err)
goto out; goto out;
p = buf; p = buf;
...@@ -806,7 +806,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first, ...@@ -806,7 +806,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
alen = ALIGN(len, c->min_io_size); alen = ALIGN(len, c->min_io_size);
set_ltab(c, lnum, c->leb_size - alen, alen - len); set_ltab(c, lnum, c->leb_size - alen, alen - len);
memset(p, 0xff, alen - len); memset(p, 0xff, alen - len);
err = ubi_leb_change(c->ubi, lnum++, buf, alen, UBI_SHORTTERM); err = ubifs_leb_change(c, lnum++, buf, alen, UBI_SHORTTERM);
if (err) if (err)
goto out; goto out;
p = buf; p = buf;
...@@ -826,7 +826,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first, ...@@ -826,7 +826,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
/* Write remaining buffer */ /* Write remaining buffer */
memset(p, 0xff, alen - len); memset(p, 0xff, alen - len);
err = ubi_leb_change(c->ubi, lnum, buf, alen, UBI_SHORTTERM); err = ubifs_leb_change(c, lnum, buf, alen, UBI_SHORTTERM);
if (err) if (err)
goto out; goto out;
...@@ -1222,7 +1222,7 @@ int ubifs_read_nnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip) ...@@ -1222,7 +1222,7 @@ int ubifs_read_nnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
if (c->big_lpt) if (c->big_lpt)
nnode->num = calc_nnode_num_from_parent(c, parent, iip); nnode->num = calc_nnode_num_from_parent(c, parent, iip);
} else { } else {
err = ubi_read(c->ubi, lnum, buf, offs, c->nnode_sz); err = ubifs_leb_read(c, lnum, buf, offs, c->nnode_sz, 1);
if (err) if (err)
goto out; goto out;
err = ubifs_unpack_nnode(c, buf, nnode); err = ubifs_unpack_nnode(c, buf, nnode);
...@@ -1247,6 +1247,7 @@ int ubifs_read_nnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip) ...@@ -1247,6 +1247,7 @@ int ubifs_read_nnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
out: out:
ubifs_err("error %d reading nnode at %d:%d", err, lnum, offs); ubifs_err("error %d reading nnode at %d:%d", err, lnum, offs);
dbg_dump_stack();
kfree(nnode); kfree(nnode);
return err; return err;
} }
...@@ -1290,7 +1291,7 @@ static int read_pnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip) ...@@ -1290,7 +1291,7 @@ static int read_pnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
lprops->flags = ubifs_categorize_lprops(c, lprops); lprops->flags = ubifs_categorize_lprops(c, lprops);
} }
} else { } else {
err = ubi_read(c->ubi, lnum, buf, offs, c->pnode_sz); err = ubifs_leb_read(c, lnum, buf, offs, c->pnode_sz, 1);
if (err) if (err)
goto out; goto out;
err = unpack_pnode(c, buf, pnode); err = unpack_pnode(c, buf, pnode);
...@@ -1312,6 +1313,7 @@ static int read_pnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip) ...@@ -1312,6 +1313,7 @@ static int read_pnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
out: out:
ubifs_err("error %d reading pnode at %d:%d", err, lnum, offs); ubifs_err("error %d reading pnode at %d:%d", err, lnum, offs);
dbg_dump_pnode(c, pnode, parent, iip); dbg_dump_pnode(c, pnode, parent, iip);
dbg_dump_stack();
dbg_msg("calc num: %d", calc_pnode_num_from_parent(c, parent, iip)); dbg_msg("calc num: %d", calc_pnode_num_from_parent(c, parent, iip));
kfree(pnode); kfree(pnode);
return err; return err;
...@@ -1331,7 +1333,7 @@ static int read_ltab(struct ubifs_info *c) ...@@ -1331,7 +1333,7 @@ static int read_ltab(struct ubifs_info *c)
buf = vmalloc(c->ltab_sz); buf = vmalloc(c->ltab_sz);
if (!buf) if (!buf)
return -ENOMEM; return -ENOMEM;
err = ubi_read(c->ubi, c->ltab_lnum, buf, c->ltab_offs, c->ltab_sz); err = ubifs_leb_read(c, c->ltab_lnum, buf, c->ltab_offs, c->ltab_sz, 1);
if (err) if (err)
goto out; goto out;
err = unpack_ltab(c, buf); err = unpack_ltab(c, buf);
...@@ -1354,7 +1356,8 @@ static int read_lsave(struct ubifs_info *c) ...@@ -1354,7 +1356,8 @@ static int read_lsave(struct ubifs_info *c)
buf = vmalloc(c->lsave_sz); buf = vmalloc(c->lsave_sz);
if (!buf) if (!buf)
return -ENOMEM; return -ENOMEM;
err = ubi_read(c->ubi, c->lsave_lnum, buf, c->lsave_offs, c->lsave_sz); err = ubifs_leb_read(c, c->lsave_lnum, buf, c->lsave_offs,
c->lsave_sz, 1);
if (err) if (err)
goto out; goto out;
err = unpack_lsave(c, buf); err = unpack_lsave(c, buf);
...@@ -1814,8 +1817,8 @@ static struct ubifs_nnode *scan_get_nnode(struct ubifs_info *c, ...@@ -1814,8 +1817,8 @@ static struct ubifs_nnode *scan_get_nnode(struct ubifs_info *c,
if (c->big_lpt) if (c->big_lpt)
nnode->num = calc_nnode_num_from_parent(c, parent, iip); nnode->num = calc_nnode_num_from_parent(c, parent, iip);
} else { } else {
err = ubi_read(c->ubi, branch->lnum, buf, branch->offs, err = ubifs_leb_read(c, branch->lnum, buf, branch->offs,
c->nnode_sz); c->nnode_sz, 1);
if (err) if (err)
return ERR_PTR(err); return ERR_PTR(err);
err = ubifs_unpack_nnode(c, buf, nnode); err = ubifs_unpack_nnode(c, buf, nnode);
...@@ -1883,8 +1886,8 @@ static struct ubifs_pnode *scan_get_pnode(struct ubifs_info *c, ...@@ -1883,8 +1886,8 @@ static struct ubifs_pnode *scan_get_pnode(struct ubifs_info *c,
ubifs_assert(branch->lnum >= c->lpt_first && ubifs_assert(branch->lnum >= c->lpt_first &&
branch->lnum <= c->lpt_last); branch->lnum <= c->lpt_last);
ubifs_assert(branch->offs >= 0 && branch->offs < c->leb_size); ubifs_assert(branch->offs >= 0 && branch->offs < c->leb_size);
err = ubi_read(c->ubi, branch->lnum, buf, branch->offs, err = ubifs_leb_read(c, branch->lnum, buf, branch->offs,
c->pnode_sz); c->pnode_sz, 1);
if (err) if (err)
return ERR_PTR(err); return ERR_PTR(err);
err = unpack_pnode(c, buf, pnode); err = unpack_pnode(c, buf, pnode);
...@@ -2224,7 +2227,7 @@ int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode, ...@@ -2224,7 +2227,7 @@ int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode,
struct ubifs_cnode *cn; struct ubifs_cnode *cn;
int num, iip = 0, err; int num, iip = 0, err;
if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS)) if (!dbg_is_chk_lprops(c))
return 0; return 0;
while (cnode) { while (cnode) {
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/crc16.h> #include <linux/crc16.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/random.h>
#include "ubifs.h" #include "ubifs.h"
#ifdef CONFIG_UBIFS_FS_DEBUG #ifdef CONFIG_UBIFS_FS_DEBUG
...@@ -116,8 +117,8 @@ static int get_cnodes_to_commit(struct ubifs_info *c) ...@@ -116,8 +117,8 @@ static int get_cnodes_to_commit(struct ubifs_info *c)
return 0; return 0;
cnt += 1; cnt += 1;
while (1) { while (1) {
ubifs_assert(!test_bit(COW_ZNODE, &cnode->flags)); ubifs_assert(!test_bit(COW_CNODE, &cnode->flags));
__set_bit(COW_ZNODE, &cnode->flags); __set_bit(COW_CNODE, &cnode->flags);
cnext = next_dirty_cnode(cnode); cnext = next_dirty_cnode(cnode);
if (!cnext) { if (!cnext) {
cnode->cnext = c->lpt_cnext; cnode->cnext = c->lpt_cnext;
...@@ -465,7 +466,7 @@ static int write_cnodes(struct ubifs_info *c) ...@@ -465,7 +466,7 @@ static int write_cnodes(struct ubifs_info *c)
*/ */
clear_bit(DIRTY_CNODE, &cnode->flags); clear_bit(DIRTY_CNODE, &cnode->flags);
smp_mb__before_clear_bit(); smp_mb__before_clear_bit();
clear_bit(COW_ZNODE, &cnode->flags); clear_bit(COW_CNODE, &cnode->flags);
smp_mb__after_clear_bit(); smp_mb__after_clear_bit();
offs += len; offs += len;
dbg_chk_lpt_sz(c, 1, len); dbg_chk_lpt_sz(c, 1, len);
...@@ -1160,11 +1161,11 @@ static int lpt_gc_lnum(struct ubifs_info *c, int lnum) ...@@ -1160,11 +1161,11 @@ static int lpt_gc_lnum(struct ubifs_info *c, int lnum)
void *buf = c->lpt_buf; void *buf = c->lpt_buf;
dbg_lp("LEB %d", lnum); dbg_lp("LEB %d", lnum);
err = ubi_read(c->ubi, lnum, buf, 0, c->leb_size);
if (err) { err = ubifs_leb_read(c, lnum, buf, 0, c->leb_size, 1);
ubifs_err("cannot read LEB %d, error %d", lnum, err); if (err)
return err; return err;
}
while (1) { while (1) {
if (!is_a_node(c, buf, len)) { if (!is_a_node(c, buf, len)) {
int pad_len; int pad_len;
...@@ -1640,7 +1641,7 @@ static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum) ...@@ -1640,7 +1641,7 @@ static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum)
int ret; int ret;
void *buf, *p; void *buf, *p;
if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS)) if (!dbg_is_chk_lprops(c))
return 0; return 0;
buf = p = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL); buf = p = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL);
...@@ -1650,11 +1651,11 @@ static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum) ...@@ -1650,11 +1651,11 @@ static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum)
} }
dbg_lp("LEB %d", lnum); dbg_lp("LEB %d", lnum);
err = ubi_read(c->ubi, lnum, buf, 0, c->leb_size);
if (err) { err = ubifs_leb_read(c, lnum, buf, 0, c->leb_size, 1);
dbg_msg("ubi_read failed, LEB %d, error %d", lnum, err); if (err)
goto out; goto out;
}
while (1) { while (1) {
if (!is_a_node(c, p, len)) { if (!is_a_node(c, p, len)) {
int i, pad_len; int i, pad_len;
...@@ -1711,7 +1712,7 @@ int dbg_check_ltab(struct ubifs_info *c) ...@@ -1711,7 +1712,7 @@ int dbg_check_ltab(struct ubifs_info *c)
{ {
int lnum, err, i, cnt; int lnum, err, i, cnt;
if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS)) if (!dbg_is_chk_lprops(c))
return 0; return 0;
/* Bring the entire tree into memory */ /* Bring the entire tree into memory */
...@@ -1754,7 +1755,7 @@ int dbg_chk_lpt_free_spc(struct ubifs_info *c) ...@@ -1754,7 +1755,7 @@ int dbg_chk_lpt_free_spc(struct ubifs_info *c)
long long free = 0; long long free = 0;
int i; int i;
if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS)) if (!dbg_is_chk_lprops(c))
return 0; return 0;
for (i = 0; i < c->lpt_lebs; i++) { for (i = 0; i < c->lpt_lebs; i++) {
...@@ -1796,7 +1797,7 @@ int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len) ...@@ -1796,7 +1797,7 @@ int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len)
long long chk_lpt_sz, lpt_sz; long long chk_lpt_sz, lpt_sz;
int err = 0; int err = 0;
if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS)) if (!dbg_is_chk_lprops(c))
return 0; return 0;
switch (action) { switch (action) {
...@@ -1901,11 +1902,10 @@ static void dump_lpt_leb(const struct ubifs_info *c, int lnum) ...@@ -1901,11 +1902,10 @@ static void dump_lpt_leb(const struct ubifs_info *c, int lnum)
return; return;
} }
err = ubi_read(c->ubi, lnum, buf, 0, c->leb_size); err = ubifs_leb_read(c, lnum, buf, 0, c->leb_size, 1);
if (err) { if (err)
ubifs_err("cannot read LEB %d, error %d", lnum, err);
goto out; goto out;
}
while (1) { while (1) {
offs = c->leb_size - len; offs = c->leb_size - len;
if (!is_a_node(c, p, len)) { if (!is_a_node(c, p, len)) {
...@@ -2019,7 +2019,7 @@ static int dbg_populate_lsave(struct ubifs_info *c) ...@@ -2019,7 +2019,7 @@ static int dbg_populate_lsave(struct ubifs_info *c)
struct ubifs_lpt_heap *heap; struct ubifs_lpt_heap *heap;
int i; int i;
if (!(ubifs_chk_flags & UBIFS_CHK_GEN)) if (!dbg_is_chk_gen(c))
return 0; return 0;
if (random32() & 3) if (random32() & 3)
return 0; return 0;
......
...@@ -38,6 +38,29 @@ static inline int ubifs_zn_dirty(const struct ubifs_znode *znode) ...@@ -38,6 +38,29 @@ static inline int ubifs_zn_dirty(const struct ubifs_znode *znode)
return !!test_bit(DIRTY_ZNODE, &znode->flags); return !!test_bit(DIRTY_ZNODE, &znode->flags);
} }
/**
* ubifs_zn_obsolete - check if znode is obsolete.
* @znode: znode to check
*
* This helper function returns %1 if @znode is obsolete and %0 otherwise.
*/
static inline int ubifs_zn_obsolete(const struct ubifs_znode *znode)
{
return !!test_bit(OBSOLETE_ZNODE, &znode->flags);
}
/**
* ubifs_zn_cow - check if znode has to be copied on write.
* @znode: znode to check
*
* This helper function returns %1 if @znode is has COW flag set and %0
* otherwise.
*/
static inline int ubifs_zn_cow(const struct ubifs_znode *znode)
{
return !!test_bit(COW_ZNODE, &znode->flags);
}
/** /**
* ubifs_wake_up_bgt - wake up background thread. * ubifs_wake_up_bgt - wake up background thread.
* @c: UBIFS file-system description object * @c: UBIFS file-system description object
...@@ -121,86 +144,6 @@ static inline int ubifs_wbuf_sync(struct ubifs_wbuf *wbuf) ...@@ -121,86 +144,6 @@ static inline int ubifs_wbuf_sync(struct ubifs_wbuf *wbuf)
return err; return err;
} }
/**
* ubifs_leb_unmap - unmap an LEB.
* @c: UBIFS file-system description object
* @lnum: LEB number to unmap
*
* This function returns %0 on success and a negative error code on failure.
*/
static inline int ubifs_leb_unmap(const struct ubifs_info *c, int lnum)
{
int err;
ubifs_assert(!c->ro_media && !c->ro_mount);
if (c->ro_error)
return -EROFS;
err = ubi_leb_unmap(c->ubi, lnum);
if (err) {
ubifs_err("unmap LEB %d failed, error %d", lnum, err);
return err;
}
return 0;
}
/**
* ubifs_leb_write - write to a LEB.
* @c: UBIFS file-system description object
* @lnum: LEB number to write
* @buf: buffer to write from
* @offs: offset within LEB to write to
* @len: length to write
* @dtype: data type
*
* This function returns %0 on success and a negative error code on failure.
*/
static inline int ubifs_leb_write(const struct ubifs_info *c, int lnum,
const void *buf, int offs, int len, int dtype)
{
int err;
ubifs_assert(!c->ro_media && !c->ro_mount);
if (c->ro_error)
return -EROFS;
err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
if (err) {
ubifs_err("writing %d bytes at %d:%d, error %d",
len, lnum, offs, err);
return err;
}
return 0;
}
/**
* ubifs_leb_change - atomic LEB change.
* @c: UBIFS file-system description object
* @lnum: LEB number to write
* @buf: buffer to write from
* @len: length to write
* @dtype: data type
*
* This function returns %0 on success and a negative error code on failure.
*/
static inline int ubifs_leb_change(const struct ubifs_info *c, int lnum,
const void *buf, int len, int dtype)
{
int err;
ubifs_assert(!c->ro_media && !c->ro_mount);
if (c->ro_error)
return -EROFS;
err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
if (err) {
ubifs_err("changing %d bytes in LEB %d, error %d",
len, lnum, err);
return err;
}
return 0;
}
/** /**
* ubifs_encode_dev - encode device node IDs. * ubifs_encode_dev - encode device node IDs.
* @dev: UBIFS device node information * @dev: UBIFS device node information
......
...@@ -929,7 +929,7 @@ static int dbg_check_orphans(struct ubifs_info *c) ...@@ -929,7 +929,7 @@ static int dbg_check_orphans(struct ubifs_info *c)
struct check_info ci; struct check_info ci;
int err; int err;
if (!(ubifs_chk_flags & UBIFS_CHK_ORPH)) if (!dbg_is_chk_orph(c))
return 0; return 0;
ci.last_ino = 0; ci.last_ino = 0;
......
...@@ -117,7 +117,7 @@ static int get_master_node(const struct ubifs_info *c, int lnum, void **pbuf, ...@@ -117,7 +117,7 @@ static int get_master_node(const struct ubifs_info *c, int lnum, void **pbuf,
if (!sbuf) if (!sbuf)
return -ENOMEM; return -ENOMEM;
err = ubi_read(c->ubi, lnum, sbuf, 0, c->leb_size); err = ubifs_leb_read(c, lnum, sbuf, 0, c->leb_size, 0);
if (err && err != -EBADMSG) if (err && err != -EBADMSG)
goto out_free; goto out_free;
...@@ -213,10 +213,10 @@ static int write_rcvrd_mst_node(struct ubifs_info *c, ...@@ -213,10 +213,10 @@ static int write_rcvrd_mst_node(struct ubifs_info *c,
mst->flags |= cpu_to_le32(UBIFS_MST_RCVRY); mst->flags |= cpu_to_le32(UBIFS_MST_RCVRY);
ubifs_prepare_node(c, mst, UBIFS_MST_NODE_SZ, 1); ubifs_prepare_node(c, mst, UBIFS_MST_NODE_SZ, 1);
err = ubi_leb_change(c->ubi, lnum, mst, sz, UBI_SHORTTERM); err = ubifs_leb_change(c, lnum, mst, sz, UBI_SHORTTERM);
if (err) if (err)
goto out; goto out;
err = ubi_leb_change(c->ubi, lnum + 1, mst, sz, UBI_SHORTTERM); err = ubifs_leb_change(c, lnum + 1, mst, sz, UBI_SHORTTERM);
if (err) if (err)
goto out; goto out;
out: out:
...@@ -274,7 +274,8 @@ int ubifs_recover_master_node(struct ubifs_info *c) ...@@ -274,7 +274,8 @@ int ubifs_recover_master_node(struct ubifs_info *c)
if (cor1) if (cor1)
goto out_err; goto out_err;
mst = mst1; mst = mst1;
} else if (offs1 == 0 && offs2 + sz >= c->leb_size) { } else if (offs1 == 0 &&
c->leb_size - offs2 - sz < sz) {
/* 1st LEB was unmapped and written, 2nd not */ /* 1st LEB was unmapped and written, 2nd not */
if (cor1) if (cor1)
goto out_err; goto out_err;
...@@ -539,8 +540,8 @@ static int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb, ...@@ -539,8 +540,8 @@ static int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
int len = ALIGN(endpt, c->min_io_size); int len = ALIGN(endpt, c->min_io_size);
if (start) { if (start) {
err = ubi_read(c->ubi, lnum, sleb->buf, 0, err = ubifs_leb_read(c, lnum, sleb->buf, 0,
start); start, 1);
if (err) if (err)
return err; return err;
} }
...@@ -554,8 +555,8 @@ static int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb, ...@@ -554,8 +555,8 @@ static int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
ubifs_pad(c, buf, pad_len); ubifs_pad(c, buf, pad_len);
} }
} }
err = ubi_leb_change(c->ubi, lnum, sleb->buf, len, err = ubifs_leb_change(c, lnum, sleb->buf, len,
UBI_UNKNOWN); UBI_UNKNOWN);
if (err) if (err)
return err; return err;
} }
...@@ -819,7 +820,8 @@ static int get_cs_sqnum(struct ubifs_info *c, int lnum, int offs, ...@@ -819,7 +820,8 @@ static int get_cs_sqnum(struct ubifs_info *c, int lnum, int offs,
return -ENOMEM; return -ENOMEM;
if (c->leb_size - offs < UBIFS_CS_NODE_SZ) if (c->leb_size - offs < UBIFS_CS_NODE_SZ)
goto out_err; goto out_err;
err = ubi_read(c->ubi, lnum, (void *)cs_node, offs, UBIFS_CS_NODE_SZ); err = ubifs_leb_read(c, lnum, (void *)cs_node, offs,
UBIFS_CS_NODE_SZ, 0);
if (err && err != -EBADMSG) if (err && err != -EBADMSG)
goto out_free; goto out_free;
ret = ubifs_scan_a_node(c, cs_node, UBIFS_CS_NODE_SZ, lnum, offs, 0); ret = ubifs_scan_a_node(c, cs_node, UBIFS_CS_NODE_SZ, lnum, offs, 0);
...@@ -919,8 +921,7 @@ struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum, ...@@ -919,8 +921,7 @@ struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum,
* *
* This function returns %0 on success and a negative error code on failure. * This function returns %0 on success and a negative error code on failure.
*/ */
static int recover_head(const struct ubifs_info *c, int lnum, int offs, static int recover_head(struct ubifs_info *c, int lnum, int offs, void *sbuf)
void *sbuf)
{ {
int len = c->max_write_size, err; int len = c->max_write_size, err;
...@@ -931,15 +932,15 @@ static int recover_head(const struct ubifs_info *c, int lnum, int offs, ...@@ -931,15 +932,15 @@ static int recover_head(const struct ubifs_info *c, int lnum, int offs,
return 0; return 0;
/* Read at the head location and check it is empty flash */ /* Read at the head location and check it is empty flash */
err = ubi_read(c->ubi, lnum, sbuf, offs, len); err = ubifs_leb_read(c, lnum, sbuf, offs, len, 1);
if (err || !is_empty(sbuf, len)) { if (err || !is_empty(sbuf, len)) {
dbg_rcvry("cleaning head at %d:%d", lnum, offs); dbg_rcvry("cleaning head at %d:%d", lnum, offs);
if (offs == 0) if (offs == 0)
return ubifs_leb_unmap(c, lnum); return ubifs_leb_unmap(c, lnum);
err = ubi_read(c->ubi, lnum, sbuf, 0, offs); err = ubifs_leb_read(c, lnum, sbuf, 0, offs, 1);
if (err) if (err)
return err; return err;
return ubi_leb_change(c->ubi, lnum, sbuf, offs, UBI_UNKNOWN); return ubifs_leb_change(c, lnum, sbuf, offs, UBI_UNKNOWN);
} }
return 0; return 0;
...@@ -962,7 +963,7 @@ static int recover_head(const struct ubifs_info *c, int lnum, int offs, ...@@ -962,7 +963,7 @@ static int recover_head(const struct ubifs_info *c, int lnum, int offs,
* *
* This function returns %0 on success and a negative error code on failure. * This function returns %0 on success and a negative error code on failure.
*/ */
int ubifs_recover_inl_heads(const struct ubifs_info *c, void *sbuf) int ubifs_recover_inl_heads(struct ubifs_info *c, void *sbuf)
{ {
int err; int err;
...@@ -993,7 +994,7 @@ int ubifs_recover_inl_heads(const struct ubifs_info *c, void *sbuf) ...@@ -993,7 +994,7 @@ int ubifs_recover_inl_heads(const struct ubifs_info *c, void *sbuf)
* *
* This function returns %0 on success and a negative error code on failure. * This function returns %0 on success and a negative error code on failure.
*/ */
static int clean_an_unclean_leb(const struct ubifs_info *c, static int clean_an_unclean_leb(struct ubifs_info *c,
struct ubifs_unclean_leb *ucleb, void *sbuf) struct ubifs_unclean_leb *ucleb, void *sbuf)
{ {
int err, lnum = ucleb->lnum, offs = 0, len = ucleb->endpt, quiet = 1; int err, lnum = ucleb->lnum, offs = 0, len = ucleb->endpt, quiet = 1;
...@@ -1009,7 +1010,7 @@ static int clean_an_unclean_leb(const struct ubifs_info *c, ...@@ -1009,7 +1010,7 @@ static int clean_an_unclean_leb(const struct ubifs_info *c,
return 0; return 0;
} }
err = ubi_read(c->ubi, lnum, buf, offs, len); err = ubifs_leb_read(c, lnum, buf, offs, len, 0);
if (err && err != -EBADMSG) if (err && err != -EBADMSG)
return err; return err;
...@@ -1069,7 +1070,7 @@ static int clean_an_unclean_leb(const struct ubifs_info *c, ...@@ -1069,7 +1070,7 @@ static int clean_an_unclean_leb(const struct ubifs_info *c,
} }
/* Write back the LEB atomically */ /* Write back the LEB atomically */
err = ubi_leb_change(c->ubi, lnum, sbuf, len, UBI_UNKNOWN); err = ubifs_leb_change(c, lnum, sbuf, len, UBI_UNKNOWN);
if (err) if (err)
return err; return err;
...@@ -1089,7 +1090,7 @@ static int clean_an_unclean_leb(const struct ubifs_info *c, ...@@ -1089,7 +1090,7 @@ static int clean_an_unclean_leb(const struct ubifs_info *c,
* *
* This function returns %0 on success and a negative error code on failure. * This function returns %0 on success and a negative error code on failure.
*/ */
int ubifs_clean_lebs(const struct ubifs_info *c, void *sbuf) int ubifs_clean_lebs(struct ubifs_info *c, void *sbuf)
{ {
dbg_rcvry("recovery"); dbg_rcvry("recovery");
while (!list_empty(&c->unclean_leb_list)) { while (!list_empty(&c->unclean_leb_list)) {
...@@ -1454,7 +1455,7 @@ static int fix_size_in_place(struct ubifs_info *c, struct size_entry *e) ...@@ -1454,7 +1455,7 @@ static int fix_size_in_place(struct ubifs_info *c, struct size_entry *e)
if (i_size >= e->d_size) if (i_size >= e->d_size)
return 0; return 0;
/* Read the LEB */ /* Read the LEB */
err = ubi_read(c->ubi, lnum, c->sbuf, 0, c->leb_size); err = ubifs_leb_read(c, lnum, c->sbuf, 0, c->leb_size, 1);
if (err) if (err)
goto out; goto out;
/* Change the size field and recalculate the CRC */ /* Change the size field and recalculate the CRC */
...@@ -1470,7 +1471,7 @@ static int fix_size_in_place(struct ubifs_info *c, struct size_entry *e) ...@@ -1470,7 +1471,7 @@ static int fix_size_in_place(struct ubifs_info *c, struct size_entry *e)
len -= 1; len -= 1;
len = ALIGN(len + 1, c->min_io_size); len = ALIGN(len + 1, c->min_io_size);
/* Atomically write the fixed LEB back again */ /* Atomically write the fixed LEB back again */
err = ubi_leb_change(c->ubi, lnum, c->sbuf, len, UBI_UNKNOWN); err = ubifs_leb_change(c, lnum, c->sbuf, len, UBI_UNKNOWN);
if (err) if (err)
goto out; goto out;
dbg_rcvry("inode %lu at %d:%d size %lld -> %lld", dbg_rcvry("inode %lu at %d:%d size %lld -> %lld",
......
...@@ -523,8 +523,7 @@ static int is_last_bud(struct ubifs_info *c, struct ubifs_bud *bud) ...@@ -523,8 +523,7 @@ static int is_last_bud(struct ubifs_info *c, struct ubifs_bud *bud)
if (!list_is_last(&next->list, &jh->buds_list)) if (!list_is_last(&next->list, &jh->buds_list))
return 0; return 0;
err = ubi_read(c->ubi, next->lnum, (char *)&data, err = ubifs_leb_read(c, next->lnum, (char *)&data, next->start, 4, 1);
next->start, 4);
if (err) if (err)
return 0; return 0;
......
...@@ -674,15 +674,15 @@ static int fixup_leb(struct ubifs_info *c, int lnum, int len) ...@@ -674,15 +674,15 @@ static int fixup_leb(struct ubifs_info *c, int lnum, int len)
if (len == 0) { if (len == 0) {
dbg_mnt("unmap empty LEB %d", lnum); dbg_mnt("unmap empty LEB %d", lnum);
return ubi_leb_unmap(c->ubi, lnum); return ubifs_leb_unmap(c, lnum);
} }
dbg_mnt("fixup LEB %d, data len %d", lnum, len); dbg_mnt("fixup LEB %d, data len %d", lnum, len);
err = ubi_read(c->ubi, lnum, c->sbuf, 0, len); err = ubifs_leb_read(c, lnum, c->sbuf, 0, len, 1);
if (err) if (err)
return err; return err;
return ubi_leb_change(c->ubi, lnum, c->sbuf, len, UBI_UNKNOWN); return ubifs_leb_change(c, lnum, c->sbuf, len, UBI_UNKNOWN);
} }
/** /**
......
...@@ -148,7 +148,7 @@ struct ubifs_scan_leb *ubifs_start_scan(const struct ubifs_info *c, int lnum, ...@@ -148,7 +148,7 @@ struct ubifs_scan_leb *ubifs_start_scan(const struct ubifs_info *c, int lnum,
INIT_LIST_HEAD(&sleb->nodes); INIT_LIST_HEAD(&sleb->nodes);
sleb->buf = sbuf; sleb->buf = sbuf;
err = ubi_read(c->ubi, lnum, sbuf + offs, offs, c->leb_size - offs); err = ubifs_leb_read(c, lnum, sbuf + offs, offs, c->leb_size - offs, 0);
if (err && err != -EBADMSG) { if (err && err != -EBADMSG) {
ubifs_err("cannot read %d bytes from LEB %d:%d," ubifs_err("cannot read %d bytes from LEB %d:%d,"
" error %d", c->leb_size - offs, lnum, offs, err); " error %d", c->leb_size - offs, lnum, offs, err);
...@@ -240,7 +240,7 @@ void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs, ...@@ -240,7 +240,7 @@ void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs,
int len; int len;
ubifs_err("corruption at LEB %d:%d", lnum, offs); ubifs_err("corruption at LEB %d:%d", lnum, offs);
if (dbg_failure_mode) if (dbg_is_tst_rcvry(c))
return; return;
len = c->leb_size - offs; len = c->leb_size - offs;
if (len > 8192) if (len > 8192)
......
...@@ -85,7 +85,7 @@ static int validate_inode(struct ubifs_info *c, const struct inode *inode) ...@@ -85,7 +85,7 @@ static int validate_inode(struct ubifs_info *c, const struct inode *inode)
if (ui->data_len < 0 || ui->data_len > UBIFS_MAX_INO_DATA) if (ui->data_len < 0 || ui->data_len > UBIFS_MAX_INO_DATA)
return 4; return 4;
if (ui->xattr && (inode->i_mode & S_IFMT) != S_IFREG) if (ui->xattr && !S_ISREG(inode->i_mode))
return 5; return 5;
if (!ubifs_compr_present(ui->compr_type)) { if (!ubifs_compr_present(ui->compr_type)) {
...@@ -94,7 +94,7 @@ static int validate_inode(struct ubifs_info *c, const struct inode *inode) ...@@ -94,7 +94,7 @@ static int validate_inode(struct ubifs_info *c, const struct inode *inode)
ubifs_compr_name(ui->compr_type)); ubifs_compr_name(ui->compr_type));
} }
err = dbg_check_dir_size(c, inode); err = dbg_check_dir(c, inode);
return err; return err;
} }
...@@ -914,7 +914,7 @@ static int check_volume_empty(struct ubifs_info *c) ...@@ -914,7 +914,7 @@ static int check_volume_empty(struct ubifs_info *c)
c->empty = 1; c->empty = 1;
for (lnum = 0; lnum < c->leb_cnt; lnum++) { for (lnum = 0; lnum < c->leb_cnt; lnum++) {
err = ubi_is_mapped(c->ubi, lnum); err = ubifs_is_mapped(c, lnum);
if (unlikely(err < 0)) if (unlikely(err < 0))
return err; return err;
if (err == 1) { if (err == 1) {
......
...@@ -223,7 +223,7 @@ static struct ubifs_znode *copy_znode(struct ubifs_info *c, ...@@ -223,7 +223,7 @@ static struct ubifs_znode *copy_znode(struct ubifs_info *c,
__set_bit(DIRTY_ZNODE, &zn->flags); __set_bit(DIRTY_ZNODE, &zn->flags);
__clear_bit(COW_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); __set_bit(OBSOLETE_ZNODE, &znode->flags);
if (znode->level != 0) { if (znode->level != 0) {
...@@ -271,7 +271,7 @@ static struct ubifs_znode *dirty_cow_znode(struct ubifs_info *c, ...@@ -271,7 +271,7 @@ static struct ubifs_znode *dirty_cow_znode(struct ubifs_info *c,
struct ubifs_znode *zn; struct ubifs_znode *zn;
int err; int err;
if (!test_bit(COW_ZNODE, &znode->flags)) { if (!ubifs_zn_cow(znode)) {
/* znode is not being committed */ /* znode is not being committed */
if (!test_and_set_bit(DIRTY_ZNODE, &znode->flags)) { if (!test_and_set_bit(DIRTY_ZNODE, &znode->flags)) {
atomic_long_inc(&c->dirty_zn_cnt); atomic_long_inc(&c->dirty_zn_cnt);
...@@ -462,7 +462,7 @@ static int try_read_node(const struct ubifs_info *c, void *buf, int type, ...@@ -462,7 +462,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); 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) { if (err) {
ubifs_err("cannot read node type %d from LEB %d:%d, error %d", ubifs_err("cannot read node type %d from LEB %d:%d, error %d",
type, lnum, offs, err); type, lnum, offs, err);
...@@ -1666,7 +1666,7 @@ static int read_wbuf(struct ubifs_wbuf *wbuf, void *buf, int len, int lnum, ...@@ -1666,7 +1666,7 @@ static int read_wbuf(struct ubifs_wbuf *wbuf, void *buf, int len, int lnum,
if (!overlap) { if (!overlap) {
/* We may safely unlock the write-buffer and read the data */ /* We may safely unlock the write-buffer and read the data */
spin_unlock(&wbuf->lock); 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 */ /* Don't read under wbuf */
...@@ -1680,7 +1680,7 @@ static int read_wbuf(struct ubifs_wbuf *wbuf, void *buf, int len, int lnum, ...@@ -1680,7 +1680,7 @@ static int read_wbuf(struct ubifs_wbuf *wbuf, void *buf, int len, int lnum,
if (rlen > 0) if (rlen > 0)
/* Read everything that goes before write-buffer */ /* 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; return 0;
} }
...@@ -1767,7 +1767,7 @@ int ubifs_tnc_bulk_read(struct ubifs_info *c, struct bu_info *bu) ...@@ -1767,7 +1767,7 @@ int ubifs_tnc_bulk_read(struct ubifs_info *c, struct bu_info *bu)
if (wbuf) if (wbuf)
err = read_wbuf(wbuf, bu->buf, len, lnum, offs); err = read_wbuf(wbuf, bu->buf, len, lnum, offs);
else 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 */ /* Check for a race with GC */
if (maybe_leb_gced(c, lnum, bu->gc_seq)) if (maybe_leb_gced(c, lnum, bu->gc_seq))
...@@ -2423,7 +2423,7 @@ static int tnc_delete(struct ubifs_info *c, struct ubifs_znode *znode, int n) ...@@ -2423,7 +2423,7 @@ static int tnc_delete(struct ubifs_info *c, struct ubifs_znode *znode, int n)
*/ */
do { do {
ubifs_assert(!test_bit(OBSOLETE_ZNODE, &znode->flags)); ubifs_assert(!ubifs_zn_obsolete(znode));
ubifs_assert(ubifs_zn_dirty(znode)); ubifs_assert(ubifs_zn_dirty(znode));
zp = znode->parent; zp = znode->parent;
...@@ -2479,9 +2479,8 @@ static int tnc_delete(struct ubifs_info *c, struct ubifs_znode *znode, int n) ...@@ -2479,9 +2479,8 @@ static int tnc_delete(struct ubifs_info *c, struct ubifs_znode *znode, int n)
c->zroot.offs = zbr->offs; c->zroot.offs = zbr->offs;
c->zroot.len = zbr->len; c->zroot.len = zbr->len;
c->zroot.znode = znode; c->zroot.znode = znode;
ubifs_assert(!test_bit(OBSOLETE_ZNODE, ubifs_assert(!ubifs_zn_obsolete(zp));
&zp->flags)); ubifs_assert(ubifs_zn_dirty(zp));
ubifs_assert(test_bit(DIRTY_ZNODE, &zp->flags));
atomic_long_dec(&c->dirty_zn_cnt); atomic_long_dec(&c->dirty_zn_cnt);
if (zp->cnext) { if (zp->cnext) {
...@@ -2865,7 +2864,7 @@ static void tnc_destroy_cnext(struct ubifs_info *c) ...@@ -2865,7 +2864,7 @@ static void tnc_destroy_cnext(struct ubifs_info *c)
struct ubifs_znode *znode = cnext; struct ubifs_znode *znode = cnext;
cnext = cnext->cnext; cnext = cnext->cnext;
if (test_bit(OBSOLETE_ZNODE, &znode->flags)) if (ubifs_zn_obsolete(znode))
kfree(znode); kfree(znode);
} while (cnext && cnext != c->cnext); } while (cnext && cnext != c->cnext);
} }
...@@ -3301,7 +3300,7 @@ int dbg_check_inode_size(struct ubifs_info *c, const struct inode *inode, ...@@ -3301,7 +3300,7 @@ int dbg_check_inode_size(struct ubifs_info *c, const struct inode *inode,
if (!S_ISREG(inode->i_mode)) if (!S_ISREG(inode->i_mode))
return 0; return 0;
if (!(ubifs_chk_flags & UBIFS_CHK_GEN)) if (!dbg_is_chk_gen(c))
return 0; return 0;
block = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT; block = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
...@@ -3337,9 +3336,10 @@ int dbg_check_inode_size(struct ubifs_info *c, const struct inode *inode, ...@@ -3337,9 +3336,10 @@ int dbg_check_inode_size(struct ubifs_info *c, const struct inode *inode,
ubifs_err("inode %lu has size %lld, but there are data at offset %lld " ubifs_err("inode %lu has size %lld, but there are data at offset %lld "
"(data key %s)", (unsigned long)inode->i_ino, size, "(data key %s)", (unsigned long)inode->i_ino, size,
((loff_t)block) << UBIFS_BLOCK_SHIFT, DBGKEY(key)); ((loff_t)block) << UBIFS_BLOCK_SHIFT, DBGKEY(key));
mutex_unlock(&c->tnc_mutex);
dbg_dump_inode(c, inode); dbg_dump_inode(c, inode);
dbg_dump_stack(); dbg_dump_stack();
err = -EINVAL; return -EINVAL;
out_unlock: out_unlock:
mutex_unlock(&c->tnc_mutex); mutex_unlock(&c->tnc_mutex);
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
/* This file implements TNC functions for committing */ /* This file implements TNC functions for committing */
#include <linux/random.h>
#include "ubifs.h" #include "ubifs.h"
/** /**
...@@ -87,8 +88,12 @@ static int make_idx_node(struct ubifs_info *c, struct ubifs_idx_node *idx, ...@@ -87,8 +88,12 @@ static int make_idx_node(struct ubifs_info *c, struct ubifs_idx_node *idx,
atomic_long_dec(&c->dirty_zn_cnt); atomic_long_dec(&c->dirty_zn_cnt);
ubifs_assert(ubifs_zn_dirty(znode)); ubifs_assert(ubifs_zn_dirty(znode));
ubifs_assert(test_bit(COW_ZNODE, &znode->flags)); ubifs_assert(ubifs_zn_cow(znode));
/*
* Note, unlike 'write_index()' we do not add memory barriers here
* because this function is called with @c->tnc_mutex locked.
*/
__clear_bit(DIRTY_ZNODE, &znode->flags); __clear_bit(DIRTY_ZNODE, &znode->flags);
__clear_bit(COW_ZNODE, &znode->flags); __clear_bit(COW_ZNODE, &znode->flags);
...@@ -377,7 +382,7 @@ static int layout_in_gaps(struct ubifs_info *c, int cnt) ...@@ -377,7 +382,7 @@ static int layout_in_gaps(struct ubifs_info *c, int cnt)
c->gap_lebs = NULL; c->gap_lebs = NULL;
return err; return err;
} }
if (dbg_force_in_the_gaps_enabled()) { if (!dbg_is_chk_index(c)) {
/* /*
* Do not print scary warnings if the debugging * Do not print scary warnings if the debugging
* option which forces in-the-gaps is enabled. * option which forces in-the-gaps is enabled.
...@@ -491,25 +496,6 @@ static int layout_in_empty_space(struct ubifs_info *c) ...@@ -491,25 +496,6 @@ static int layout_in_empty_space(struct ubifs_info *c)
else else
next_len = ubifs_idx_node_sz(c, cnext->child_cnt); next_len = ubifs_idx_node_sz(c, cnext->child_cnt);
if (c->min_io_size == 1) {
buf_offs += ALIGN(len, 8);
if (next_len) {
if (buf_offs + next_len <= c->leb_size)
continue;
err = ubifs_update_one_lp(c, lnum, 0,
c->leb_size - buf_offs, 0, 0);
if (err)
return err;
lnum = -1;
continue;
}
err = ubifs_update_one_lp(c, lnum,
c->leb_size - buf_offs, 0, 0, 0);
if (err)
return err;
break;
}
/* Update buffer positions */ /* Update buffer positions */
wlen = used + len; wlen = used + len;
used += ALIGN(len, 8); used += ALIGN(len, 8);
...@@ -658,7 +644,7 @@ static int get_znodes_to_commit(struct ubifs_info *c) ...@@ -658,7 +644,7 @@ static int get_znodes_to_commit(struct ubifs_info *c)
} }
cnt += 1; cnt += 1;
while (1) { while (1) {
ubifs_assert(!test_bit(COW_ZNODE, &znode->flags)); ubifs_assert(!ubifs_zn_cow(znode));
__set_bit(COW_ZNODE, &znode->flags); __set_bit(COW_ZNODE, &znode->flags);
znode->alt = 0; znode->alt = 0;
cnext = find_next_dirty(znode); cnext = find_next_dirty(znode);
...@@ -704,7 +690,7 @@ static int alloc_idx_lebs(struct ubifs_info *c, int cnt) ...@@ -704,7 +690,7 @@ static int alloc_idx_lebs(struct ubifs_info *c, int cnt)
c->ilebs[c->ileb_cnt++] = lnum; c->ilebs[c->ileb_cnt++] = lnum;
dbg_cmt("LEB %d", lnum); dbg_cmt("LEB %d", lnum);
} }
if (dbg_force_in_the_gaps()) if (dbg_is_chk_index(c) && !(random32() & 7))
return -ENOSPC; return -ENOSPC;
return 0; return 0;
} }
...@@ -830,7 +816,7 @@ static int write_index(struct ubifs_info *c) ...@@ -830,7 +816,7 @@ static int write_index(struct ubifs_info *c)
struct ubifs_idx_node *idx; struct ubifs_idx_node *idx;
struct ubifs_znode *znode, *cnext; struct ubifs_znode *znode, *cnext;
int i, lnum, offs, len, next_len, buf_len, buf_offs, used; int i, lnum, offs, len, next_len, buf_len, buf_offs, used;
int avail, wlen, err, lnum_pos = 0; int avail, wlen, err, lnum_pos = 0, blen, nxt_offs;
cnext = c->enext; cnext = c->enext;
if (!cnext) if (!cnext)
...@@ -907,7 +893,7 @@ static int write_index(struct ubifs_info *c) ...@@ -907,7 +893,7 @@ static int write_index(struct ubifs_info *c)
cnext = znode->cnext; cnext = znode->cnext;
ubifs_assert(ubifs_zn_dirty(znode)); ubifs_assert(ubifs_zn_dirty(znode));
ubifs_assert(test_bit(COW_ZNODE, &znode->flags)); ubifs_assert(ubifs_zn_cow(znode));
/* /*
* It is important that other threads should see %DIRTY_ZNODE * It is important that other threads should see %DIRTY_ZNODE
...@@ -922,6 +908,28 @@ static int write_index(struct ubifs_info *c) ...@@ -922,6 +908,28 @@ static int write_index(struct ubifs_info *c)
clear_bit(COW_ZNODE, &znode->flags); clear_bit(COW_ZNODE, &znode->flags);
smp_mb__after_clear_bit(); smp_mb__after_clear_bit();
/*
* We have marked the znode as clean but have not updated the
* @c->clean_zn_cnt counter. If this znode becomes dirty again
* before 'free_obsolete_znodes()' is called, then
* @c->clean_zn_cnt will be decremented before it gets
* incremented (resulting in 2 decrements for the same znode).
* This means that @c->clean_zn_cnt may become negative for a
* while.
*
* Q: why we cannot increment @c->clean_zn_cnt?
* A: because we do not have the @c->tnc_mutex locked, and the
* following code would be racy and buggy:
*
* if (!ubifs_zn_obsolete(znode)) {
* atomic_long_inc(&c->clean_zn_cnt);
* atomic_long_inc(&ubifs_clean_zn_cnt);
* }
*
* Thus, we just delay the @c->clean_zn_cnt update until we
* have the mutex locked.
*/
/* Do not access znode from this point on */ /* Do not access znode from this point on */
/* Update buffer positions */ /* Update buffer positions */
...@@ -938,65 +946,38 @@ static int write_index(struct ubifs_info *c) ...@@ -938,65 +946,38 @@ static int write_index(struct ubifs_info *c)
else else
next_len = ubifs_idx_node_sz(c, cnext->child_cnt); next_len = ubifs_idx_node_sz(c, cnext->child_cnt);
if (c->min_io_size == 1) { nxt_offs = buf_offs + used + next_len;
/* if (next_len && nxt_offs <= c->leb_size) {
* Write the prepared index node immediately if there is if (avail > 0)
* no minimum IO size
*/
err = ubifs_leb_write(c, lnum, c->cbuf, buf_offs,
wlen, UBI_SHORTTERM);
if (err)
return err;
buf_offs += ALIGN(wlen, 8);
if (next_len) {
used = 0;
avail = buf_len;
if (buf_offs + next_len > c->leb_size) {
err = ubifs_update_one_lp(c, lnum,
LPROPS_NC, 0, 0, LPROPS_TAKEN);
if (err)
return err;
lnum = -1;
}
continue; continue;
} else
blen = buf_len;
} else { } else {
int blen, nxt_offs = buf_offs + used + next_len; wlen = ALIGN(wlen, 8);
blen = ALIGN(wlen, c->min_io_size);
if (next_len && nxt_offs <= c->leb_size) { ubifs_pad(c, c->cbuf + wlen, blen - wlen);
if (avail > 0) }
continue;
else /* The buffer is full or there are no more znodes to do */
blen = buf_len; err = ubifs_leb_write(c, lnum, c->cbuf, buf_offs, blen,
} else { UBI_SHORTTERM);
wlen = ALIGN(wlen, 8); if (err)
blen = ALIGN(wlen, c->min_io_size); return err;
ubifs_pad(c, c->cbuf + wlen, blen - wlen); buf_offs += blen;
} if (next_len) {
/* if (nxt_offs > c->leb_size) {
* The buffer is full or there are no more znodes err = ubifs_update_one_lp(c, lnum, LPROPS_NC, 0,
* to do 0, LPROPS_TAKEN);
*/ if (err)
err = ubifs_leb_write(c, lnum, c->cbuf, buf_offs, return err;
blen, UBI_SHORTTERM); lnum = -1;
if (err)
return err;
buf_offs += blen;
if (next_len) {
if (nxt_offs > c->leb_size) {
err = ubifs_update_one_lp(c, lnum,
LPROPS_NC, 0, 0, LPROPS_TAKEN);
if (err)
return err;
lnum = -1;
}
used -= blen;
if (used < 0)
used = 0;
avail = buf_len - used;
memmove(c->cbuf, c->cbuf + blen, used);
continue;
} }
used -= blen;
if (used < 0)
used = 0;
avail = buf_len - used;
memmove(c->cbuf, c->cbuf + blen, used);
continue;
} }
break; break;
} }
...@@ -1029,7 +1010,7 @@ static void free_obsolete_znodes(struct ubifs_info *c) ...@@ -1029,7 +1010,7 @@ static void free_obsolete_znodes(struct ubifs_info *c)
do { do {
znode = cnext; znode = cnext;
cnext = znode->cnext; cnext = znode->cnext;
if (test_bit(OBSOLETE_ZNODE, &znode->flags)) if (ubifs_zn_obsolete(znode))
kfree(znode); kfree(znode);
else { else {
znode->cnext = NULL; znode->cnext = NULL;
......
...@@ -230,14 +230,14 @@ enum { ...@@ -230,14 +230,14 @@ enum {
* LPT cnode flag bits. * LPT cnode flag bits.
* *
* DIRTY_CNODE: cnode is dirty * DIRTY_CNODE: cnode is dirty
* COW_CNODE: cnode is being committed and must be copied before writing
* OBSOLETE_CNODE: cnode is being committed and has been copied (or deleted), * OBSOLETE_CNODE: cnode is being committed and has been copied (or deleted),
* so it can (and must) be freed when the commit is finished * so it can (and must) be freed when the commit is finished
* COW_CNODE: cnode is being committed and must be copied before writing
*/ */
enum { enum {
DIRTY_CNODE = 0, DIRTY_CNODE = 0,
COW_CNODE = 1, OBSOLETE_CNODE = 1,
OBSOLETE_CNODE = 2, COW_CNODE = 2,
}; };
/* /*
...@@ -1468,6 +1468,15 @@ extern struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT]; ...@@ -1468,6 +1468,15 @@ extern struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
/* io.c */ /* io.c */
void ubifs_ro_mode(struct ubifs_info *c, int err); void ubifs_ro_mode(struct ubifs_info *c, int err);
int ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs,
int len, int even_ebadmsg);
int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
int len, int dtype);
int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len,
int dtype);
int ubifs_leb_unmap(struct ubifs_info *c, int lnum);
int ubifs_leb_map(struct ubifs_info *c, int lnum, int dtype);
int ubifs_is_mapped(const struct ubifs_info *c, int lnum);
int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len); int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len);
int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs, int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs,
int dtype); int dtype);
...@@ -1747,8 +1756,8 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, ...@@ -1747,8 +1756,8 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
int offs, void *sbuf, int jhead); int offs, void *sbuf, int jhead);
struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum, struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum,
int offs, void *sbuf); int offs, void *sbuf);
int ubifs_recover_inl_heads(const struct ubifs_info *c, void *sbuf); int ubifs_recover_inl_heads(struct ubifs_info *c, void *sbuf);
int ubifs_clean_lebs(const struct ubifs_info *c, void *sbuf); int ubifs_clean_lebs(struct ubifs_info *c, void *sbuf);
int ubifs_rcvry_gc_commit(struct ubifs_info *c); int ubifs_rcvry_gc_commit(struct ubifs_info *c);
int ubifs_recover_size_accum(struct ubifs_info *c, union ubifs_key *key, int ubifs_recover_size_accum(struct ubifs_info *c, union ubifs_key *key,
int deletion, loff_t new_size); int deletion, loff_t new_size);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment