Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 213006
b: refs/heads/master
c: 3bb66b4
h: refs/heads/master
v: v3
  • Loading branch information
Artem Bityutskiy authored and Artem Bityutskiy committed Aug 30, 2010
1 parent dc93e2f commit 29e69a2
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1a9476a77083354005750c9df45ba9d71ad12c8c
refs/heads/master: 3bb66b47a4268a4419594b4c4aec58dbeb6b58d2
156 changes: 156 additions & 0 deletions trunk/fs/ubifs/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -2239,6 +2239,162 @@ int dbg_check_filesystem(struct ubifs_info *c)
return err;
}

/**
* dbg_check_data_nodes_order - check that list of data nodes is sorted.
* @c: UBIFS file-system description object
* @head: the list of nodes ('struct ubifs_scan_node' objects)
*
* This function returns zero if the list of data nodes is sorted correctly,
* and %-EINVAL if not.
*/
int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head)
{
struct list_head *cur;
struct ubifs_scan_node *sa, *sb;

if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
return 0;

for (cur = head->next; cur->next != head; cur = cur->next) {
ino_t inuma, inumb;
uint32_t blka, blkb;

cond_resched();
sa = container_of(cur, struct ubifs_scan_node, list);
sb = container_of(cur->next, struct ubifs_scan_node, list);

if (sa->type != UBIFS_DATA_NODE) {
ubifs_err("bad node type %d", sa->type);
dbg_dump_node(c, sa->node);
return -EINVAL;
}
if (sb->type != UBIFS_DATA_NODE) {
ubifs_err("bad node type %d", sb->type);
dbg_dump_node(c, sb->node);
return -EINVAL;
}

inuma = key_inum(c, &sa->key);
inumb = key_inum(c, &sb->key);

if (inuma < inumb)
continue;
if (inuma > inumb) {
ubifs_err("larger inum %lu goes before inum %lu",
(unsigned long)inuma, (unsigned long)inumb);
goto error_dump;
}

blka = key_block(c, &sa->key);
blkb = key_block(c, &sb->key);

if (blka > blkb) {
ubifs_err("larger block %u goes before %u", blka, blkb);
goto error_dump;
}
if (blka == blkb) {
ubifs_err("two data nodes for the same block");
goto error_dump;
}
}

return 0;

error_dump:
dbg_dump_node(c, sa->node);
dbg_dump_node(c, sb->node);
return -EINVAL;
}

/**
* dbg_check_nondata_nodes_order - check that list of data nodes is sorted.
* @c: UBIFS file-system description object
* @head: the list of nodes ('struct ubifs_scan_node' objects)
*
* This function returns zero if the list of non-data nodes is sorted correctly,
* and %-EINVAL if not.
*/
int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head)
{
struct list_head *cur;
struct ubifs_scan_node *sa, *sb;

if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
return 0;

for (cur = head->next; cur->next != head; cur = cur->next) {
ino_t inuma, inumb;
uint32_t hasha, hashb;

cond_resched();
sa = container_of(cur, struct ubifs_scan_node, list);
sb = container_of(cur->next, struct ubifs_scan_node, list);

if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE &&
sa->type != UBIFS_XENT_NODE) {
ubifs_err("bad node type %d", sa->type);
dbg_dump_node(c, sa->node);
return -EINVAL;
}
if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE &&
sa->type != UBIFS_XENT_NODE) {
ubifs_err("bad node type %d", sb->type);
dbg_dump_node(c, sb->node);
return -EINVAL;
}

if (sa->type != UBIFS_INO_NODE && sb->type == UBIFS_INO_NODE) {
ubifs_err("non-inode node goes before inode node");
goto error_dump;
}

if (sa->type == UBIFS_INO_NODE && sb->type != UBIFS_INO_NODE)
continue;

if (sa->type == UBIFS_INO_NODE && sb->type == UBIFS_INO_NODE) {
/* Inode nodes are sorted in descending size order */
if (sa->len < sb->len) {
ubifs_err("smaller inode node goes first");
goto error_dump;
}
continue;
}

/*
* This is either a dentry or xentry, which should be sorted in
* ascending (parent ino, hash) order.
*/
inuma = key_inum(c, &sa->key);
inumb = key_inum(c, &sb->key);

if (inuma < inumb)
continue;
if (inuma > inumb) {
ubifs_err("larger inum %lu goes before inum %lu",
(unsigned long)inuma, (unsigned long)inumb);
goto error_dump;
}

hasha = key_block(c, &sa->key);
hashb = key_block(c, &sb->key);

if (hasha > hashb) {
ubifs_err("larger hash %u goes before %u", hasha, hashb);
goto error_dump;
}
}

return 0;

error_dump:
ubifs_msg("dumping first node");
dbg_dump_node(c, sa->node);
ubifs_msg("dumping second node");
dbg_dump_node(c, sb->node);
return -EINVAL;
return 0;
}

static int invocation_cnt;

int dbg_force_in_the_gaps(void)
Expand Down
4 changes: 4 additions & 0 deletions trunk/fs/ubifs/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,8 @@ int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode,
int row, int col);
int dbg_check_inode_size(struct ubifs_info *c, const struct inode *inode,
loff_t size);
int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head);
int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head);

/* Force the use of in-the-gaps method for testing */

Expand Down Expand Up @@ -465,6 +467,8 @@ void dbg_debugfs_exit_fs(struct ubifs_info *c);
#define dbg_check_lprops(c) 0
#define dbg_check_lpt_nodes(c, cnode, row, col) 0
#define dbg_check_inode_size(c, inode, size) 0
#define dbg_check_data_nodes_order(c, head) 0
#define dbg_check_nondata_nodes_order(c, head) 0
#define dbg_force_in_the_gaps_enabled 0
#define dbg_force_in_the_gaps() 0
#define dbg_failure_mode 0
Expand Down
10 changes: 8 additions & 2 deletions trunk/fs/ubifs/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,14 +242,13 @@ int nondata_nodes_cmp(void *priv, struct list_head *a, struct list_head *b)
static int sort_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
struct list_head *nondata, int *min)
{
int err;
struct ubifs_scan_node *snod, *tmp;

*min = INT_MAX;

/* Separate data nodes and non-data nodes */
list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) {
int err;

ubifs_assert(snod->type == UBIFS_INO_NODE ||
snod->type == UBIFS_DATA_NODE ||
snod->type == UBIFS_DENT_NODE ||
Expand Down Expand Up @@ -293,6 +292,13 @@ static int sort_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
/* Sort data and non-data nodes */
list_sort(c, &sleb->nodes, &data_nodes_cmp);
list_sort(c, nondata, &nondata_nodes_cmp);

err = dbg_check_data_nodes_order(c, &sleb->nodes);
if (err)
return err;
err = dbg_check_nondata_nodes_order(c, nondata);
if (err)
return err;
return 0;
}

Expand Down

0 comments on commit 29e69a2

Please sign in to comment.