Merge branch 'linux-next' of git://git.infradead.org/ubifs-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 22 Oct 2010 23:34:03 +0000 (16:34 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 22 Oct 2010 23:34:03 +0000 (16:34 -0700)
* 'linux-next' of git://git.infradead.org/ubifs-2.6:
  UBIFS: do not allocate unneeded scan buffer
  UBIFS: do not forget to cancel timers
  UBIFS: remove a bit of unneeded code
  UBIFS: add a commentary about log recovery
  UBIFS: avoid kernel error if ubifs superblock read fails
  UBIFS: introduce new flags for RO mounts
  UBIFS: introduce new flag for RO due to errors
  UBIFS: check return code of pnode_lookup
  UBIFS: check return code of ubifs_lpt_lookup
  UBIFS: improve error reporting when reading bad node
  UBIFS: introduce list sorting debugging checks
  UBIFS: fix assertion warnings in comparison function
  UBIFS: mark unused key objects as invalid
  UBIFS: do not write rubbish into truncation scanning node
  UBIFS: improve assertion in node comparison functions
  UBIFS: do not use key type in list_sort
  UBIFS: do not look up truncation nodes
  UBIFS: fix assertion warning
  UBIFS: do not treat ENOSPC specially
  UBIFS: switch to RO mode after synchronizing

1  2 
fs/ubifs/debug.c

diff --combined fs/ubifs/debug.c
@@@ -2239,6 -2239,162 +2239,162 @@@ out_free
        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)
@@@ -2625,7 -2781,6 +2781,7 @@@ static const struct file_operations dfs
        .open = open_debugfs_file,
        .write = write_debugfs_file,
        .owner = THIS_MODULE,
 +      .llseek = default_llseek,
  };
  
  /**