1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * linux/fs/hfs/btree.c
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Copyright (C) 2001
61da177e4SLinus Torvalds * Brad Boyer (flar@allandria.com)
71da177e4SLinus Torvalds * (C) 2003 Ardis Technologies <roman@ardistech.com>
81da177e4SLinus Torvalds *
91da177e4SLinus Torvalds * Handle opening/closing btree
101da177e4SLinus Torvalds */
111da177e4SLinus Torvalds
121da177e4SLinus Torvalds #include <linux/pagemap.h>
135a0e3ad6STejun Heo #include <linux/slab.h>
14e1b5c1d3SVignesh Babu BM #include <linux/log2.h>
151da177e4SLinus Torvalds
161da177e4SLinus Torvalds #include "btree.h"
171da177e4SLinus Torvalds
181da177e4SLinus Torvalds /* Get a reference to a B*Tree and do some initial checks */
hfs_btree_open(struct super_block * sb,u32 id,btree_keycmp keycmp)191da177e4SLinus Torvalds struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp keycmp)
201da177e4SLinus Torvalds {
211da177e4SLinus Torvalds struct hfs_btree *tree;
221da177e4SLinus Torvalds struct hfs_btree_header_rec *head;
231da177e4SLinus Torvalds struct address_space *mapping;
241da177e4SLinus Torvalds struct page *page;
251da177e4SLinus Torvalds unsigned int size;
261da177e4SLinus Torvalds
27f8314dc6SPanagiotis Issaris tree = kzalloc(sizeof(*tree), GFP_KERNEL);
281da177e4SLinus Torvalds if (!tree)
291da177e4SLinus Torvalds return NULL;
301da177e4SLinus Torvalds
314a941035SThomas Gleixner mutex_init(&tree->tree_lock);
321da177e4SLinus Torvalds spin_lock_init(&tree->hash_lock);
331da177e4SLinus Torvalds /* Set the correct compare function */
341da177e4SLinus Torvalds tree->sb = sb;
351da177e4SLinus Torvalds tree->cnid = id;
361da177e4SLinus Torvalds tree->keycmp = keycmp;
371da177e4SLinus Torvalds
381da177e4SLinus Torvalds tree->inode = iget_locked(sb, id);
391da177e4SLinus Torvalds if (!tree->inode)
401da177e4SLinus Torvalds goto free_tree;
414d4ef9abSEric Sesterhenn BUG_ON(!(tree->inode->i_state & I_NEW));
421da177e4SLinus Torvalds {
431da177e4SLinus Torvalds struct hfs_mdb *mdb = HFS_SB(sb)->mdb;
441da177e4SLinus Torvalds HFS_I(tree->inode)->flags = 0;
4539f8d472SMatthias Kaehlcke mutex_init(&HFS_I(tree->inode)->extents_lock);
461da177e4SLinus Torvalds switch (id) {
471da177e4SLinus Torvalds case HFS_EXT_CNID:
481da177e4SLinus Torvalds hfs_inode_read_fork(tree->inode, mdb->drXTExtRec, mdb->drXTFlSize,
491da177e4SLinus Torvalds mdb->drXTFlSize, be32_to_cpu(mdb->drXTClpSiz));
50434a964dSPhillip Lougher if (HFS_I(tree->inode)->alloc_blocks >
51434a964dSPhillip Lougher HFS_I(tree->inode)->first_blocks) {
52d6142673SJoe Perches pr_err("invalid btree extent records\n");
53434a964dSPhillip Lougher unlock_new_inode(tree->inode);
54434a964dSPhillip Lougher goto free_inode;
55434a964dSPhillip Lougher }
56434a964dSPhillip Lougher
571da177e4SLinus Torvalds tree->inode->i_mapping->a_ops = &hfs_btree_aops;
581da177e4SLinus Torvalds break;
591da177e4SLinus Torvalds case HFS_CAT_CNID:
601da177e4SLinus Torvalds hfs_inode_read_fork(tree->inode, mdb->drCTExtRec, mdb->drCTFlSize,
611da177e4SLinus Torvalds mdb->drCTFlSize, be32_to_cpu(mdb->drCTClpSiz));
62434a964dSPhillip Lougher
63434a964dSPhillip Lougher if (!HFS_I(tree->inode)->first_blocks) {
64d6142673SJoe Perches pr_err("invalid btree extent records (0 size)\n");
65434a964dSPhillip Lougher unlock_new_inode(tree->inode);
66434a964dSPhillip Lougher goto free_inode;
67434a964dSPhillip Lougher }
68434a964dSPhillip Lougher
691da177e4SLinus Torvalds tree->inode->i_mapping->a_ops = &hfs_btree_aops;
701da177e4SLinus Torvalds break;
711da177e4SLinus Torvalds default:
721da177e4SLinus Torvalds BUG();
731da177e4SLinus Torvalds }
741da177e4SLinus Torvalds }
751da177e4SLinus Torvalds unlock_new_inode(tree->inode);
761da177e4SLinus Torvalds
771da177e4SLinus Torvalds mapping = tree->inode->i_mapping;
78090d2b18SPekka Enberg page = read_mapping_page(mapping, 0, NULL);
791da177e4SLinus Torvalds if (IS_ERR(page))
8046a39c1cSEric Sandeen goto free_inode;
811da177e4SLinus Torvalds
821da177e4SLinus Torvalds /* Load the header */
83*21490effSFabio M. De Francesco head = (struct hfs_btree_header_rec *)(kmap_local_page(page) +
84*21490effSFabio M. De Francesco sizeof(struct hfs_bnode_desc));
851da177e4SLinus Torvalds tree->root = be32_to_cpu(head->root);
861da177e4SLinus Torvalds tree->leaf_count = be32_to_cpu(head->leaf_count);
871da177e4SLinus Torvalds tree->leaf_head = be32_to_cpu(head->leaf_head);
881da177e4SLinus Torvalds tree->leaf_tail = be32_to_cpu(head->leaf_tail);
891da177e4SLinus Torvalds tree->node_count = be32_to_cpu(head->node_count);
901da177e4SLinus Torvalds tree->free_nodes = be32_to_cpu(head->free_nodes);
911da177e4SLinus Torvalds tree->attributes = be32_to_cpu(head->attributes);
921da177e4SLinus Torvalds tree->node_size = be16_to_cpu(head->node_size);
931da177e4SLinus Torvalds tree->max_key_len = be16_to_cpu(head->max_key_len);
941da177e4SLinus Torvalds tree->depth = be16_to_cpu(head->depth);
951da177e4SLinus Torvalds
961da177e4SLinus Torvalds size = tree->node_size;
97e1b5c1d3SVignesh Babu BM if (!is_power_of_2(size))
981da177e4SLinus Torvalds goto fail_page;
991da177e4SLinus Torvalds if (!tree->node_count)
1001da177e4SLinus Torvalds goto fail_page;
10155581d01SEric Sandeen switch (id) {
10255581d01SEric Sandeen case HFS_EXT_CNID:
10355581d01SEric Sandeen if (tree->max_key_len != HFS_MAX_EXT_KEYLEN) {
104d6142673SJoe Perches pr_err("invalid extent max_key_len %d\n",
105cf059462SEric Sandeen tree->max_key_len);
106cf059462SEric Sandeen goto fail_page;
107cf059462SEric Sandeen }
10855581d01SEric Sandeen break;
10955581d01SEric Sandeen case HFS_CAT_CNID:
11055581d01SEric Sandeen if (tree->max_key_len != HFS_MAX_CAT_KEYLEN) {
111d6142673SJoe Perches pr_err("invalid catalog max_key_len %d\n",
112cf059462SEric Sandeen tree->max_key_len);
113cf059462SEric Sandeen goto fail_page;
114cf059462SEric Sandeen }
11555581d01SEric Sandeen break;
11655581d01SEric Sandeen default:
11755581d01SEric Sandeen BUG();
11855581d01SEric Sandeen }
119cf059462SEric Sandeen
1201da177e4SLinus Torvalds tree->node_size_shift = ffs(size) - 1;
12109cbfeafSKirill A. Shutemov tree->pages_per_bnode = (tree->node_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
1221da177e4SLinus Torvalds
123*21490effSFabio M. De Francesco kunmap_local(head);
12409cbfeafSKirill A. Shutemov put_page(page);
1251da177e4SLinus Torvalds return tree;
1261da177e4SLinus Torvalds
1271da177e4SLinus Torvalds fail_page:
128*21490effSFabio M. De Francesco kunmap_local(head);
12909cbfeafSKirill A. Shutemov put_page(page);
13046a39c1cSEric Sandeen free_inode:
131cf059462SEric Sandeen tree->inode->i_mapping->a_ops = &hfs_aops;
1321da177e4SLinus Torvalds iput(tree->inode);
13346a39c1cSEric Sandeen free_tree:
1341da177e4SLinus Torvalds kfree(tree);
1351da177e4SLinus Torvalds return NULL;
1361da177e4SLinus Torvalds }
1371da177e4SLinus Torvalds
1381da177e4SLinus Torvalds /* Release resources used by a btree */
hfs_btree_close(struct hfs_btree * tree)1391da177e4SLinus Torvalds void hfs_btree_close(struct hfs_btree *tree)
1401da177e4SLinus Torvalds {
1411da177e4SLinus Torvalds struct hfs_bnode *node;
1421da177e4SLinus Torvalds int i;
1431da177e4SLinus Torvalds
1441da177e4SLinus Torvalds if (!tree)
1451da177e4SLinus Torvalds return;
1461da177e4SLinus Torvalds
1471da177e4SLinus Torvalds for (i = 0; i < NODE_HASH_SIZE; i++) {
1481da177e4SLinus Torvalds while ((node = tree->node_hash[i])) {
1491da177e4SLinus Torvalds tree->node_hash[i] = node->next_hash;
1501da177e4SLinus Torvalds if (atomic_read(&node->refcnt))
151d6142673SJoe Perches pr_err("node %d:%d still has %d user(s)!\n",
152d6142673SJoe Perches node->tree->cnid, node->this,
153d6142673SJoe Perches atomic_read(&node->refcnt));
1541da177e4SLinus Torvalds hfs_bnode_free(node);
1551da177e4SLinus Torvalds tree->node_hash_cnt--;
1561da177e4SLinus Torvalds }
1571da177e4SLinus Torvalds }
1581da177e4SLinus Torvalds iput(tree->inode);
1591da177e4SLinus Torvalds kfree(tree);
1601da177e4SLinus Torvalds }
1611da177e4SLinus Torvalds
hfs_btree_write(struct hfs_btree * tree)1621da177e4SLinus Torvalds void hfs_btree_write(struct hfs_btree *tree)
1631da177e4SLinus Torvalds {
1641da177e4SLinus Torvalds struct hfs_btree_header_rec *head;
1651da177e4SLinus Torvalds struct hfs_bnode *node;
1661da177e4SLinus Torvalds struct page *page;
1671da177e4SLinus Torvalds
1681da177e4SLinus Torvalds node = hfs_bnode_find(tree, 0);
1691da177e4SLinus Torvalds if (IS_ERR(node))
1701da177e4SLinus Torvalds /* panic? */
1711da177e4SLinus Torvalds return;
1721da177e4SLinus Torvalds /* Load the header */
1731da177e4SLinus Torvalds page = node->page[0];
174*21490effSFabio M. De Francesco head = (struct hfs_btree_header_rec *)(kmap_local_page(page) +
175*21490effSFabio M. De Francesco sizeof(struct hfs_bnode_desc));
1761da177e4SLinus Torvalds
1771da177e4SLinus Torvalds head->root = cpu_to_be32(tree->root);
1781da177e4SLinus Torvalds head->leaf_count = cpu_to_be32(tree->leaf_count);
1791da177e4SLinus Torvalds head->leaf_head = cpu_to_be32(tree->leaf_head);
1801da177e4SLinus Torvalds head->leaf_tail = cpu_to_be32(tree->leaf_tail);
1811da177e4SLinus Torvalds head->node_count = cpu_to_be32(tree->node_count);
1821da177e4SLinus Torvalds head->free_nodes = cpu_to_be32(tree->free_nodes);
1831da177e4SLinus Torvalds head->attributes = cpu_to_be32(tree->attributes);
1841da177e4SLinus Torvalds head->depth = cpu_to_be16(tree->depth);
1851da177e4SLinus Torvalds
186*21490effSFabio M. De Francesco kunmap_local(head);
1871da177e4SLinus Torvalds set_page_dirty(page);
1881da177e4SLinus Torvalds hfs_bnode_put(node);
1891da177e4SLinus Torvalds }
1901da177e4SLinus Torvalds
hfs_bmap_new_bmap(struct hfs_bnode * prev,u32 idx)1911da177e4SLinus Torvalds static struct hfs_bnode *hfs_bmap_new_bmap(struct hfs_bnode *prev, u32 idx)
1921da177e4SLinus Torvalds {
1931da177e4SLinus Torvalds struct hfs_btree *tree = prev->tree;
1941da177e4SLinus Torvalds struct hfs_bnode *node;
1951da177e4SLinus Torvalds struct hfs_bnode_desc desc;
1961da177e4SLinus Torvalds __be32 cnid;
1971da177e4SLinus Torvalds
1981da177e4SLinus Torvalds node = hfs_bnode_create(tree, idx);
1991da177e4SLinus Torvalds if (IS_ERR(node))
2001da177e4SLinus Torvalds return node;
2011da177e4SLinus Torvalds
2021da177e4SLinus Torvalds if (!tree->free_nodes)
2031da177e4SLinus Torvalds panic("FIXME!!!");
2041da177e4SLinus Torvalds tree->free_nodes--;
2051da177e4SLinus Torvalds prev->next = idx;
2061da177e4SLinus Torvalds cnid = cpu_to_be32(idx);
2071da177e4SLinus Torvalds hfs_bnode_write(prev, &cnid, offsetof(struct hfs_bnode_desc, next), 4);
2081da177e4SLinus Torvalds
2091da177e4SLinus Torvalds node->type = HFS_NODE_MAP;
2101da177e4SLinus Torvalds node->num_recs = 1;
2111da177e4SLinus Torvalds hfs_bnode_clear(node, 0, tree->node_size);
2121da177e4SLinus Torvalds desc.next = 0;
2131da177e4SLinus Torvalds desc.prev = 0;
2141da177e4SLinus Torvalds desc.type = HFS_NODE_MAP;
2151da177e4SLinus Torvalds desc.height = 0;
2161da177e4SLinus Torvalds desc.num_recs = cpu_to_be16(1);
2171da177e4SLinus Torvalds desc.reserved = 0;
2181da177e4SLinus Torvalds hfs_bnode_write(node, &desc, 0, sizeof(desc));
2191da177e4SLinus Torvalds hfs_bnode_write_u16(node, 14, 0x8000);
2201da177e4SLinus Torvalds hfs_bnode_write_u16(node, tree->node_size - 2, 14);
2211da177e4SLinus Torvalds hfs_bnode_write_u16(node, tree->node_size - 4, tree->node_size - 6);
2221da177e4SLinus Torvalds
2231da177e4SLinus Torvalds return node;
2241da177e4SLinus Torvalds }
2251da177e4SLinus Torvalds
22654640c75SErnesto A. Fernández /* Make sure @tree has enough space for the @rsvd_nodes */
hfs_bmap_reserve(struct hfs_btree * tree,int rsvd_nodes)22754640c75SErnesto A. Fernández int hfs_bmap_reserve(struct hfs_btree *tree, int rsvd_nodes)
22854640c75SErnesto A. Fernández {
22954640c75SErnesto A. Fernández struct inode *inode = tree->inode;
23054640c75SErnesto A. Fernández u32 count;
23154640c75SErnesto A. Fernández int res;
23254640c75SErnesto A. Fernández
23354640c75SErnesto A. Fernández while (tree->free_nodes < rsvd_nodes) {
23454640c75SErnesto A. Fernández res = hfs_extend_file(inode);
23554640c75SErnesto A. Fernández if (res)
23654640c75SErnesto A. Fernández return res;
23754640c75SErnesto A. Fernández HFS_I(inode)->phys_size = inode->i_size =
23854640c75SErnesto A. Fernández (loff_t)HFS_I(inode)->alloc_blocks *
23954640c75SErnesto A. Fernández HFS_SB(tree->sb)->alloc_blksz;
24054640c75SErnesto A. Fernández HFS_I(inode)->fs_blocks = inode->i_size >>
24154640c75SErnesto A. Fernández tree->sb->s_blocksize_bits;
24254640c75SErnesto A. Fernández inode_set_bytes(inode, inode->i_size);
24354640c75SErnesto A. Fernández count = inode->i_size >> tree->node_size_shift;
24454640c75SErnesto A. Fernández tree->free_nodes += count - tree->node_count;
24554640c75SErnesto A. Fernández tree->node_count = count;
24654640c75SErnesto A. Fernández }
24754640c75SErnesto A. Fernández return 0;
24854640c75SErnesto A. Fernández }
24954640c75SErnesto A. Fernández
hfs_bmap_alloc(struct hfs_btree * tree)2501da177e4SLinus Torvalds struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
2511da177e4SLinus Torvalds {
2521da177e4SLinus Torvalds struct hfs_bnode *node, *next_node;
2531da177e4SLinus Torvalds struct page **pagep;
2541da177e4SLinus Torvalds u32 nidx, idx;
2553e5a5097SAndrew Morton unsigned off;
2563e5a5097SAndrew Morton u16 off16;
2573e5a5097SAndrew Morton u16 len;
2581da177e4SLinus Torvalds u8 *data, byte, m;
25954640c75SErnesto A. Fernández int i, res;
2601da177e4SLinus Torvalds
26154640c75SErnesto A. Fernández res = hfs_bmap_reserve(tree, 1);
2621da177e4SLinus Torvalds if (res)
2631da177e4SLinus Torvalds return ERR_PTR(res);
2641da177e4SLinus Torvalds
2651da177e4SLinus Torvalds nidx = 0;
2661da177e4SLinus Torvalds node = hfs_bnode_find(tree, nidx);
2671da177e4SLinus Torvalds if (IS_ERR(node))
2681da177e4SLinus Torvalds return node;
2693e5a5097SAndrew Morton len = hfs_brec_lenoff(node, 2, &off16);
2703e5a5097SAndrew Morton off = off16;
2711da177e4SLinus Torvalds
2721da177e4SLinus Torvalds off += node->page_offset;
27309cbfeafSKirill A. Shutemov pagep = node->page + (off >> PAGE_SHIFT);
274*21490effSFabio M. De Francesco data = kmap_local_page(*pagep);
27509cbfeafSKirill A. Shutemov off &= ~PAGE_MASK;
2761da177e4SLinus Torvalds idx = 0;
2771da177e4SLinus Torvalds
2781da177e4SLinus Torvalds for (;;) {
2791da177e4SLinus Torvalds while (len) {
2801da177e4SLinus Torvalds byte = data[off];
2811da177e4SLinus Torvalds if (byte != 0xff) {
2821da177e4SLinus Torvalds for (m = 0x80, i = 0; i < 8; m >>= 1, i++) {
2831da177e4SLinus Torvalds if (!(byte & m)) {
2841da177e4SLinus Torvalds idx += i;
2851da177e4SLinus Torvalds data[off] |= m;
2861da177e4SLinus Torvalds set_page_dirty(*pagep);
287*21490effSFabio M. De Francesco kunmap_local(data);
2881da177e4SLinus Torvalds tree->free_nodes--;
2891da177e4SLinus Torvalds mark_inode_dirty(tree->inode);
2901da177e4SLinus Torvalds hfs_bnode_put(node);
2911da177e4SLinus Torvalds return hfs_bnode_create(tree, idx);
2921da177e4SLinus Torvalds }
2931da177e4SLinus Torvalds }
2941da177e4SLinus Torvalds }
29509cbfeafSKirill A. Shutemov if (++off >= PAGE_SIZE) {
296*21490effSFabio M. De Francesco kunmap_local(data);
297*21490effSFabio M. De Francesco data = kmap_local_page(*++pagep);
2981da177e4SLinus Torvalds off = 0;
2991da177e4SLinus Torvalds }
3001da177e4SLinus Torvalds idx += 8;
3011da177e4SLinus Torvalds len--;
3021da177e4SLinus Torvalds }
303*21490effSFabio M. De Francesco kunmap_local(data);
3041da177e4SLinus Torvalds nidx = node->next;
3051da177e4SLinus Torvalds if (!nidx) {
306d6142673SJoe Perches printk(KERN_DEBUG "create new bmap node...\n");
3071da177e4SLinus Torvalds next_node = hfs_bmap_new_bmap(node, idx);
3081da177e4SLinus Torvalds } else
3091da177e4SLinus Torvalds next_node = hfs_bnode_find(tree, nidx);
3101da177e4SLinus Torvalds hfs_bnode_put(node);
3111da177e4SLinus Torvalds if (IS_ERR(next_node))
3121da177e4SLinus Torvalds return next_node;
3131da177e4SLinus Torvalds node = next_node;
3141da177e4SLinus Torvalds
3153e5a5097SAndrew Morton len = hfs_brec_lenoff(node, 0, &off16);
3163e5a5097SAndrew Morton off = off16;
3171da177e4SLinus Torvalds off += node->page_offset;
31809cbfeafSKirill A. Shutemov pagep = node->page + (off >> PAGE_SHIFT);
319*21490effSFabio M. De Francesco data = kmap_local_page(*pagep);
32009cbfeafSKirill A. Shutemov off &= ~PAGE_MASK;
3211da177e4SLinus Torvalds }
3221da177e4SLinus Torvalds }
3231da177e4SLinus Torvalds
hfs_bmap_free(struct hfs_bnode * node)3241da177e4SLinus Torvalds void hfs_bmap_free(struct hfs_bnode *node)
3251da177e4SLinus Torvalds {
3261da177e4SLinus Torvalds struct hfs_btree *tree;
3271da177e4SLinus Torvalds struct page *page;
3281da177e4SLinus Torvalds u16 off, len;
3291da177e4SLinus Torvalds u32 nidx;
3301da177e4SLinus Torvalds u8 *data, byte, m;
3311da177e4SLinus Torvalds
332c2b3e1f7SJoe Perches hfs_dbg(BNODE_MOD, "btree_free_node: %u\n", node->this);
3331da177e4SLinus Torvalds tree = node->tree;
3341da177e4SLinus Torvalds nidx = node->this;
3351da177e4SLinus Torvalds node = hfs_bnode_find(tree, 0);
3361da177e4SLinus Torvalds if (IS_ERR(node))
3371da177e4SLinus Torvalds return;
3381da177e4SLinus Torvalds len = hfs_brec_lenoff(node, 2, &off);
3391da177e4SLinus Torvalds while (nidx >= len * 8) {
3401da177e4SLinus Torvalds u32 i;
3411da177e4SLinus Torvalds
3421da177e4SLinus Torvalds nidx -= len * 8;
3431da177e4SLinus Torvalds i = node->next;
3441da177e4SLinus Torvalds if (!i) {
3451da177e4SLinus Torvalds /* panic */;
346d6142673SJoe Perches pr_crit("unable to free bnode %u. bmap not found!\n",
347d6142673SJoe Perches node->this);
348ce96a407SPan Bian hfs_bnode_put(node);
3491da177e4SLinus Torvalds return;
3501da177e4SLinus Torvalds }
351ce96a407SPan Bian hfs_bnode_put(node);
3521da177e4SLinus Torvalds node = hfs_bnode_find(tree, i);
3531da177e4SLinus Torvalds if (IS_ERR(node))
3541da177e4SLinus Torvalds return;
3551da177e4SLinus Torvalds if (node->type != HFS_NODE_MAP) {
3561da177e4SLinus Torvalds /* panic */;
357d6142673SJoe Perches pr_crit("invalid bmap found! (%u,%d)\n",
358d6142673SJoe Perches node->this, node->type);
3591da177e4SLinus Torvalds hfs_bnode_put(node);
3601da177e4SLinus Torvalds return;
3611da177e4SLinus Torvalds }
3621da177e4SLinus Torvalds len = hfs_brec_lenoff(node, 0, &off);
3631da177e4SLinus Torvalds }
3641da177e4SLinus Torvalds off += node->page_offset + nidx / 8;
36509cbfeafSKirill A. Shutemov page = node->page[off >> PAGE_SHIFT];
366*21490effSFabio M. De Francesco data = kmap_local_page(page);
36709cbfeafSKirill A. Shutemov off &= ~PAGE_MASK;
3681da177e4SLinus Torvalds m = 1 << (~nidx & 7);
3691da177e4SLinus Torvalds byte = data[off];
3701da177e4SLinus Torvalds if (!(byte & m)) {
371d6142673SJoe Perches pr_crit("trying to free free bnode %u(%d)\n",
372d6142673SJoe Perches node->this, node->type);
373*21490effSFabio M. De Francesco kunmap_local(data);
3741da177e4SLinus Torvalds hfs_bnode_put(node);
3751da177e4SLinus Torvalds return;
3761da177e4SLinus Torvalds }
3771da177e4SLinus Torvalds data[off] = byte & ~m;
3781da177e4SLinus Torvalds set_page_dirty(page);
379*21490effSFabio M. De Francesco kunmap_local(data);
3801da177e4SLinus Torvalds hfs_bnode_put(node);
3811da177e4SLinus Torvalds tree->free_nodes++;
3821da177e4SLinus Torvalds mark_inode_dirty(tree->inode);
3831da177e4SLinus Torvalds }
384