Commit ccfeef0f authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.infradead.org/ubifs-2.6

* 'for-linus' of git://git.infradead.org/ubifs-2.6:
  UBI: do not select KALLSYMS_ALL
  UBI: do not compare array with NULL
  UBI: check if we are in RO mode in the erase routine
  UBIFS: fix debugging failure in dbg_check_space_info
  UBIFS: fix error path in dbg_debugfs_init_fs
  UBIFS: unify error path dbg_debugfs_init_fs
  UBIFS: do not select KALLSYMS_ALL
  UBIFS: fix assertion warnings
  UBIFS: fix oops on error path in read_pnode
  UBIFS: do not read flash unnecessarily
parents 42933bac 6bef0b67
...@@ -56,7 +56,7 @@ config MTD_UBI_DEBUG ...@@ -56,7 +56,7 @@ config MTD_UBI_DEBUG
bool "UBI debugging" bool "UBI debugging"
depends on SYSFS depends on SYSFS
select DEBUG_FS select DEBUG_FS
select KALLSYMS_ALL if KALLSYMS && DEBUG_KERNEL select KALLSYMS
help help
This option enables UBI debugging. This option enables UBI debugging.
......
...@@ -344,6 +344,12 @@ static int do_sync_erase(struct ubi_device *ubi, int pnum) ...@@ -344,6 +344,12 @@ static int do_sync_erase(struct ubi_device *ubi, int pnum)
wait_queue_head_t wq; wait_queue_head_t wq;
dbg_io("erase PEB %d", pnum); dbg_io("erase PEB %d", pnum);
ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
if (ubi->ro_mode) {
ubi_err("read-only mode");
return -EROFS;
}
retry: retry:
init_waitqueue_head(&wq); init_waitqueue_head(&wq);
...@@ -390,7 +396,7 @@ static int do_sync_erase(struct ubi_device *ubi, int pnum) ...@@ -390,7 +396,7 @@ static int do_sync_erase(struct ubi_device *ubi, int pnum)
if (err) if (err)
return err; return err;
if (ubi_dbg_is_erase_failure() && !err) { if (ubi_dbg_is_erase_failure()) {
dbg_err("cannot erase PEB %d (emulated)", pnum); dbg_err("cannot erase PEB %d (emulated)", pnum);
return -EIO; return -EIO;
} }
......
...@@ -790,11 +790,6 @@ static int paranoid_check_volume(struct ubi_device *ubi, int vol_id) ...@@ -790,11 +790,6 @@ static int paranoid_check_volume(struct ubi_device *ubi, int vol_id)
goto fail; goto fail;
} }
if (!vol->name) {
ubi_err("NULL volume name");
goto fail;
}
n = strnlen(vol->name, vol->name_len + 1); n = strnlen(vol->name, vol->name_len + 1);
if (n != vol->name_len) { if (n != vol->name_len) {
ubi_err("bad name_len %lld", n); ubi_err("bad name_len %lld", n);
......
...@@ -47,7 +47,7 @@ config UBIFS_FS_DEBUG ...@@ -47,7 +47,7 @@ config UBIFS_FS_DEBUG
bool "Enable debugging support" bool "Enable debugging support"
depends on UBIFS_FS depends on UBIFS_FS
select DEBUG_FS select DEBUG_FS
select KALLSYMS_ALL select KALLSYMS
help help
This option enables UBIFS debugging support. It makes sure various This option enables UBIFS debugging support. It makes sure various
assertions, self-checks, debugging messages and test modes are compiled assertions, self-checks, debugging messages and test modes are compiled
......
...@@ -577,7 +577,7 @@ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot) ...@@ -577,7 +577,7 @@ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot)
size_t sz; size_t sz;
if (!(ubifs_chk_flags & UBIFS_CHK_OLD_IDX)) if (!(ubifs_chk_flags & UBIFS_CHK_OLD_IDX))
goto out; return 0;
INIT_LIST_HEAD(&list); INIT_LIST_HEAD(&list);
......
...@@ -972,11 +972,39 @@ void dbg_dump_index(struct ubifs_info *c) ...@@ -972,11 +972,39 @@ void dbg_dump_index(struct ubifs_info *c)
void dbg_save_space_info(struct ubifs_info *c) void dbg_save_space_info(struct ubifs_info *c)
{ {
struct ubifs_debug_info *d = c->dbg; struct ubifs_debug_info *d = c->dbg;
int freeable_cnt;
ubifs_get_lp_stats(c, &d->saved_lst);
spin_lock(&c->space_lock); spin_lock(&c->space_lock);
memcpy(&d->saved_lst, &c->lst, sizeof(struct ubifs_lp_stats));
/*
* We use a dirty hack here and zero out @c->freeable_cnt, because it
* affects the free space calculations, and UBIFS might not know about
* all freeable eraseblocks. Indeed, we know about freeable eraseblocks
* only when we read their lprops, and we do this only lazily, upon the
* need. So at any given point of time @c->freeable_cnt might be not
* exactly accurate.
*
* Just one example about the issue we hit when we did not zero
* @c->freeable_cnt.
* 1. The file-system is mounted R/O, c->freeable_cnt is %0. We save the
* amount of free space in @d->saved_free
* 2. We re-mount R/W, which makes UBIFS to read the "lsave"
* information from flash, where we cache LEBs from various
* categories ('ubifs_remount_fs()' -> 'ubifs_lpt_init()'
* -> 'lpt_init_wr()' -> 'read_lsave()' -> 'ubifs_lpt_lookup()'
* -> 'ubifs_get_pnode()' -> 'update_cats()'
* -> 'ubifs_add_to_cat()').
* 3. Lsave contains a freeable eraseblock, and @c->freeable_cnt
* becomes %1.
* 4. We calculate the amount of free space when the re-mount is
* finished in 'dbg_check_space_info()' and it does not match
* @d->saved_free.
*/
freeable_cnt = c->freeable_cnt;
c->freeable_cnt = 0;
d->saved_free = ubifs_get_free_space_nolock(c); d->saved_free = ubifs_get_free_space_nolock(c);
c->freeable_cnt = freeable_cnt;
spin_unlock(&c->space_lock); spin_unlock(&c->space_lock);
} }
...@@ -993,12 +1021,15 @@ int dbg_check_space_info(struct ubifs_info *c) ...@@ -993,12 +1021,15 @@ int dbg_check_space_info(struct ubifs_info *c)
{ {
struct ubifs_debug_info *d = c->dbg; struct ubifs_debug_info *d = c->dbg;
struct ubifs_lp_stats lst; struct ubifs_lp_stats lst;
long long avail, free; long long free;
int freeable_cnt;
spin_lock(&c->space_lock); spin_lock(&c->space_lock);
avail = ubifs_calc_available(c, c->min_idx_lebs); freeable_cnt = c->freeable_cnt;
c->freeable_cnt = 0;
free = ubifs_get_free_space_nolock(c);
c->freeable_cnt = freeable_cnt;
spin_unlock(&c->space_lock); spin_unlock(&c->space_lock);
free = ubifs_get_free_space(c);
if (free != d->saved_free) { if (free != d->saved_free) {
ubifs_err("free space changed from %lld to %lld", ubifs_err("free space changed from %lld to %lld",
...@@ -2806,40 +2837,38 @@ int dbg_debugfs_init_fs(struct ubifs_info *c) ...@@ -2806,40 +2837,38 @@ int dbg_debugfs_init_fs(struct ubifs_info *c)
struct ubifs_debug_info *d = c->dbg; struct ubifs_debug_info *d = c->dbg;
sprintf(d->dfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id); sprintf(d->dfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id);
d->dfs_dir = debugfs_create_dir(d->dfs_dir_name, dfs_rootdir); fname = d->dfs_dir_name;
if (IS_ERR(d->dfs_dir)) { dent = debugfs_create_dir(fname, dfs_rootdir);
err = PTR_ERR(d->dfs_dir); if (IS_ERR_OR_NULL(dent))
ubifs_err("cannot create \"%s\" debugfs directory, error %d\n",
d->dfs_dir_name, err);
goto out; goto out;
} d->dfs_dir = dent;
fname = "dump_lprops"; fname = "dump_lprops";
dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops);
if (IS_ERR(dent)) if (IS_ERR_OR_NULL(dent))
goto out_remove; goto out_remove;
d->dfs_dump_lprops = dent; d->dfs_dump_lprops = dent;
fname = "dump_budg"; fname = "dump_budg";
dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops);
if (IS_ERR(dent)) if (IS_ERR_OR_NULL(dent))
goto out_remove; goto out_remove;
d->dfs_dump_budg = dent; d->dfs_dump_budg = dent;
fname = "dump_tnc"; fname = "dump_tnc";
dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops);
if (IS_ERR(dent)) if (IS_ERR_OR_NULL(dent))
goto out_remove; goto out_remove;
d->dfs_dump_tnc = dent; d->dfs_dump_tnc = dent;
return 0; return 0;
out_remove: out_remove:
err = PTR_ERR(dent);
ubifs_err("cannot create \"%s\" debugfs directory, error %d\n",
fname, err);
debugfs_remove_recursive(d->dfs_dir); debugfs_remove_recursive(d->dfs_dir);
out: out:
err = dent ? PTR_ERR(dent) : -ENODEV;
ubifs_err("cannot create \"%s\" debugfs directory, error %d\n",
fname, err);
return err; return err;
} }
......
...@@ -1270,10 +1270,9 @@ static int read_pnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip) ...@@ -1270,10 +1270,9 @@ static int read_pnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
lnum = branch->lnum; lnum = branch->lnum;
offs = branch->offs; offs = branch->offs;
pnode = kzalloc(sizeof(struct ubifs_pnode), GFP_NOFS); pnode = kzalloc(sizeof(struct ubifs_pnode), GFP_NOFS);
if (!pnode) { if (!pnode)
err = -ENOMEM; return -ENOMEM;
goto out;
}
if (lnum == 0) { if (lnum == 0) {
/* /*
* This pnode was not written which just means that the LEB * This pnode was not written which just means that the LEB
......
...@@ -1568,6 +1568,7 @@ static int ubifs_remount_rw(struct ubifs_info *c) ...@@ -1568,6 +1568,7 @@ static int ubifs_remount_rw(struct ubifs_info *c)
mutex_lock(&c->umount_mutex); mutex_lock(&c->umount_mutex);
dbg_save_space_info(c); dbg_save_space_info(c);
c->remounting_rw = 1; c->remounting_rw = 1;
c->ro_mount = 0;
err = check_free_space(c); err = check_free_space(c);
if (err) if (err)
...@@ -1676,13 +1677,13 @@ static int ubifs_remount_rw(struct ubifs_info *c) ...@@ -1676,13 +1677,13 @@ static int ubifs_remount_rw(struct ubifs_info *c)
} }
dbg_gen("re-mounted read-write"); dbg_gen("re-mounted read-write");
c->ro_mount = 0;
c->remounting_rw = 0; c->remounting_rw = 0;
err = dbg_check_space_info(c); err = dbg_check_space_info(c);
mutex_unlock(&c->umount_mutex); mutex_unlock(&c->umount_mutex);
return err; return err;
out: out:
c->ro_mount = 1;
vfree(c->orph_buf); vfree(c->orph_buf);
c->orph_buf = NULL; c->orph_buf = NULL;
if (c->bgt) { if (c->bgt) {
......
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