nilfs2: get rid of private conversion macros on bmap key and pointer
[cascardo/linux.git] / fs / nilfs2 / btree.c
index b27a342..b2347f7 100644 (file)
@@ -71,17 +71,24 @@ static int nilfs_btree_get_block(const struct nilfs_btree *btree, __u64 ptr,
 {
        struct address_space *btnc =
                &NILFS_BMAP_I((struct nilfs_bmap *)btree)->i_btnode_cache;
+       struct buffer_head *bh;
        int err;
 
        err = nilfs_btnode_submit_block(btnc, ptr, 0, bhp);
        if (err)
                return err == -EEXIST ? 0 : err;
 
-       wait_on_buffer(*bhp);
-       if (!buffer_uptodate(*bhp)) {
-               brelse(*bhp);
+       bh = *bhp;
+       wait_on_buffer(bh);
+       if (!buffer_uptodate(bh)) {
+               brelse(bh);
                return -EIO;
        }
+       if (nilfs_btree_broken_node_block(bh)) {
+               clear_buffer_uptodate(bh);
+               brelse(bh);
+               return -EINVAL;
+       }
        return 0;
 }
 
@@ -184,29 +191,27 @@ nilfs_btree_node_dptrs(const struct nilfs_btree_node *node,
 static inline __u64
 nilfs_btree_node_get_key(const struct nilfs_btree_node *node, int index)
 {
-       return nilfs_bmap_dkey_to_key(*(nilfs_btree_node_dkeys(node) + index));
+       return le64_to_cpu(*(nilfs_btree_node_dkeys(node) + index));
 }
 
 static inline void
 nilfs_btree_node_set_key(struct nilfs_btree_node *node, int index, __u64 key)
 {
-       *(nilfs_btree_node_dkeys(node) + index) = nilfs_bmap_key_to_dkey(key);
+       *(nilfs_btree_node_dkeys(node) + index) = cpu_to_le64(key);
 }
 
 static inline __u64
 nilfs_btree_node_get_ptr(const struct nilfs_btree *btree,
                         const struct nilfs_btree_node *node, int index)
 {
-       return nilfs_bmap_dptr_to_ptr(*(nilfs_btree_node_dptrs(node, btree) +
-                                       index));
+       return le64_to_cpu(*(nilfs_btree_node_dptrs(node, btree) + index));
 }
 
 static inline void
 nilfs_btree_node_set_ptr(struct nilfs_btree *btree,
                         struct nilfs_btree_node *node, int index, __u64 ptr)
 {
-       *(nilfs_btree_node_dptrs(node, btree) + index) =
-               nilfs_bmap_ptr_to_dptr(ptr);
+       *(nilfs_btree_node_dptrs(node, btree) + index) = cpu_to_le64(ptr);
 }
 
 static void nilfs_btree_node_init(struct nilfs_btree *btree,
@@ -225,8 +230,8 @@ static void nilfs_btree_node_init(struct nilfs_btree *btree,
        dkeys = nilfs_btree_node_dkeys(node);
        dptrs = nilfs_btree_node_dptrs(node, btree);
        for (i = 0; i < nchildren; i++) {
-               dkeys[i] = nilfs_bmap_key_to_dkey(keys[i]);
-               dptrs[i] = nilfs_bmap_ptr_to_dptr(ptrs[i]);
+               dkeys[i] = cpu_to_le64(keys[i]);
+               dptrs[i] = cpu_to_le64(ptrs[i]);
        }
 }
 
@@ -306,8 +311,8 @@ static void nilfs_btree_node_insert(struct nilfs_btree *btree,
                memmove(dptrs + index + 1, dptrs + index,
                        (nchildren - index) * sizeof(*dptrs));
        }
-       dkeys[index] = nilfs_bmap_key_to_dkey(key);
-       dptrs[index] = nilfs_bmap_ptr_to_dptr(ptr);
+       dkeys[index] = cpu_to_le64(key);
+       dptrs[index] = cpu_to_le64(ptr);
        nchildren++;
        nilfs_btree_node_set_nchildren(node, nchildren);
 }
@@ -325,8 +330,8 @@ static void nilfs_btree_node_delete(struct nilfs_btree *btree,
 
        dkeys = nilfs_btree_node_dkeys(node);
        dptrs = nilfs_btree_node_dptrs(node, btree);
-       key = nilfs_bmap_dkey_to_key(dkeys[index]);
-       ptr = nilfs_bmap_dptr_to_ptr(dptrs[index]);
+       key = le64_to_cpu(dkeys[index]);
+       ptr = le64_to_cpu(dptrs[index]);
        nchildren = nilfs_btree_node_get_nchildren(node);
        if (keyp != NULL)
                *keyp = key;
@@ -382,6 +387,43 @@ static int nilfs_btree_node_lookup(const struct nilfs_btree_node *node,
        return s == 0;
 }
 
+/**
+ * nilfs_btree_node_broken - verify consistency of btree node
+ * @node: btree node block to be examined
+ * @size: node size (in bytes)
+ * @blocknr: block number
+ *
+ * Return Value: If node is broken, 1 is returned. Otherwise, 0 is returned.
+ */
+static int nilfs_btree_node_broken(const struct nilfs_btree_node *node,
+                                  size_t size, sector_t blocknr)
+{
+       int level, flags, nchildren;
+       int ret = 0;
+
+       level = nilfs_btree_node_get_level(node);
+       flags = nilfs_btree_node_get_flags(node);
+       nchildren = nilfs_btree_node_get_nchildren(node);
+
+       if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN ||
+                    level >= NILFS_BTREE_LEVEL_MAX ||
+                    (flags & NILFS_BTREE_NODE_ROOT) ||
+                    nchildren < 0 ||
+                    nchildren > NILFS_BTREE_NODE_NCHILDREN_MAX(size))) {
+               printk(KERN_CRIT "NILFS: bad btree node (blocknr=%llu): "
+                      "level = %d, flags = 0x%x, nchildren = %d\n",
+                      (unsigned long long)blocknr, level, flags, nchildren);
+               ret = 1;
+       }
+       return ret;
+}
+
+int nilfs_btree_broken_node_block(struct buffer_head *bh)
+{
+       return nilfs_btree_node_broken((struct nilfs_btree_node *)bh->b_data,
+                                      bh->b_size, bh->b_blocknr);
+}
+
 static inline struct nilfs_btree_node *
 nilfs_btree_get_root(const struct nilfs_btree *btree)
 {
@@ -1525,8 +1567,8 @@ static int nilfs_btree_gather_data(struct nilfs_bmap *bmap,
        dkeys = nilfs_btree_node_dkeys(node);
        dptrs = nilfs_btree_node_dptrs(node, btree);
        for (i = 0; i < nitems; i++) {
-               keys[i] = nilfs_bmap_dkey_to_key(dkeys[i]);
-               ptrs[i] = nilfs_bmap_dptr_to_ptr(dptrs[i]);
+               keys[i] = le64_to_cpu(dkeys[i]);
+               ptrs[i] = le64_to_cpu(dptrs[i]);
        }
 
        if (bh != NULL)
@@ -1920,6 +1962,18 @@ static void nilfs_btree_add_dirty_buffer(struct nilfs_btree *btree,
        node = (struct nilfs_btree_node *)bh->b_data;
        key = nilfs_btree_node_get_key(node, 0);
        level = nilfs_btree_node_get_level(node);
+       if (level < NILFS_BTREE_LEVEL_NODE_MIN ||
+           level >= NILFS_BTREE_LEVEL_MAX) {
+               dump_stack();
+               printk(KERN_WARNING
+                      "%s: invalid btree level: %d (key=%llu, ino=%lu, "
+                      "blocknr=%llu)\n",
+                      __func__, level, (unsigned long long)key,
+                      NILFS_BMAP_I(&btree->bt_bmap)->vfs_inode.i_ino,
+                      (unsigned long long)bh->b_blocknr);
+               return;
+       }
+
        list_for_each(head, &lists[level]) {
                cbh = list_entry(head, struct buffer_head, b_assoc_buffers);
                cnode = (struct nilfs_btree_node *)cbh->b_data;
@@ -2003,7 +2057,7 @@ static int nilfs_btree_assign_p(struct nilfs_btree *btree,
 
        key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
        /* on-disk format */
-       binfo->bi_dat.bi_blkoff = nilfs_bmap_key_to_dkey(key);
+       binfo->bi_dat.bi_blkoff = cpu_to_le64(key);
        binfo->bi_dat.bi_level = level;
 
        return 0;
@@ -2034,8 +2088,8 @@ static int nilfs_btree_assign_v(struct nilfs_btree *btree,
 
        key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
        /* on-disk format */
-       binfo->bi_v.bi_vblocknr = nilfs_bmap_ptr_to_dptr(ptr);
-       binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key);
+       binfo->bi_v.bi_vblocknr = cpu_to_le64(ptr);
+       binfo->bi_v.bi_blkoff = cpu_to_le64(key);
 
        return 0;
 }
@@ -2103,7 +2157,7 @@ static int nilfs_btree_assign_gc(struct nilfs_bmap *bmap,
 
        /* on-disk format */
        binfo->bi_v.bi_vblocknr = cpu_to_le64((*bh)->b_blocknr);
-       binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key);
+       binfo->bi_v.bi_blkoff = cpu_to_le64(key);
 
        return 0;
 }