root/fs/hfs/btree.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hfs_btree_open
  2. hfs_btree_close
  3. hfs_btree_write
  4. hfs_bmap_new_bmap
  5. hfs_bmap_reserve
  6. hfs_bmap_alloc
  7. hfs_bmap_free

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  *  linux/fs/hfs/btree.c
   4  *
   5  * Copyright (C) 2001
   6  * Brad Boyer (flar@allandria.com)
   7  * (C) 2003 Ardis Technologies <roman@ardistech.com>
   8  *
   9  * Handle opening/closing btree
  10  */
  11 
  12 #include <linux/pagemap.h>
  13 #include <linux/slab.h>
  14 #include <linux/log2.h>
  15 
  16 #include "btree.h"
  17 
  18 /* Get a reference to a B*Tree and do some initial checks */
  19 struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp keycmp)
  20 {
  21         struct hfs_btree *tree;
  22         struct hfs_btree_header_rec *head;
  23         struct address_space *mapping;
  24         struct page *page;
  25         unsigned int size;
  26 
  27         tree = kzalloc(sizeof(*tree), GFP_KERNEL);
  28         if (!tree)
  29                 return NULL;
  30 
  31         mutex_init(&tree->tree_lock);
  32         spin_lock_init(&tree->hash_lock);
  33         /* Set the correct compare function */
  34         tree->sb = sb;
  35         tree->cnid = id;
  36         tree->keycmp = keycmp;
  37 
  38         tree->inode = iget_locked(sb, id);
  39         if (!tree->inode)
  40                 goto free_tree;
  41         BUG_ON(!(tree->inode->i_state & I_NEW));
  42         {
  43         struct hfs_mdb *mdb = HFS_SB(sb)->mdb;
  44         HFS_I(tree->inode)->flags = 0;
  45         mutex_init(&HFS_I(tree->inode)->extents_lock);
  46         switch (id) {
  47         case HFS_EXT_CNID:
  48                 hfs_inode_read_fork(tree->inode, mdb->drXTExtRec, mdb->drXTFlSize,
  49                                     mdb->drXTFlSize, be32_to_cpu(mdb->drXTClpSiz));
  50                 if (HFS_I(tree->inode)->alloc_blocks >
  51                                         HFS_I(tree->inode)->first_blocks) {
  52                         pr_err("invalid btree extent records\n");
  53                         unlock_new_inode(tree->inode);
  54                         goto free_inode;
  55                 }
  56 
  57                 tree->inode->i_mapping->a_ops = &hfs_btree_aops;
  58                 break;
  59         case HFS_CAT_CNID:
  60                 hfs_inode_read_fork(tree->inode, mdb->drCTExtRec, mdb->drCTFlSize,
  61                                     mdb->drCTFlSize, be32_to_cpu(mdb->drCTClpSiz));
  62 
  63                 if (!HFS_I(tree->inode)->first_blocks) {
  64                         pr_err("invalid btree extent records (0 size)\n");
  65                         unlock_new_inode(tree->inode);
  66                         goto free_inode;
  67                 }
  68 
  69                 tree->inode->i_mapping->a_ops = &hfs_btree_aops;
  70                 break;
  71         default:
  72                 BUG();
  73         }
  74         }
  75         unlock_new_inode(tree->inode);
  76 
  77         mapping = tree->inode->i_mapping;
  78         page = read_mapping_page(mapping, 0, NULL);
  79         if (IS_ERR(page))
  80                 goto free_inode;
  81 
  82         /* Load the header */
  83         head = (struct hfs_btree_header_rec *)(kmap(page) + sizeof(struct hfs_bnode_desc));
  84         tree->root = be32_to_cpu(head->root);
  85         tree->leaf_count = be32_to_cpu(head->leaf_count);
  86         tree->leaf_head = be32_to_cpu(head->leaf_head);
  87         tree->leaf_tail = be32_to_cpu(head->leaf_tail);
  88         tree->node_count = be32_to_cpu(head->node_count);
  89         tree->free_nodes = be32_to_cpu(head->free_nodes);
  90         tree->attributes = be32_to_cpu(head->attributes);
  91         tree->node_size = be16_to_cpu(head->node_size);
  92         tree->max_key_len = be16_to_cpu(head->max_key_len);
  93         tree->depth = be16_to_cpu(head->depth);
  94 
  95         size = tree->node_size;
  96         if (!is_power_of_2(size))
  97                 goto fail_page;
  98         if (!tree->node_count)
  99                 goto fail_page;
 100         switch (id) {
 101         case HFS_EXT_CNID:
 102                 if (tree->max_key_len != HFS_MAX_EXT_KEYLEN) {
 103                         pr_err("invalid extent max_key_len %d\n",
 104                                tree->max_key_len);
 105                         goto fail_page;
 106                 }
 107                 break;
 108         case HFS_CAT_CNID:
 109                 if (tree->max_key_len != HFS_MAX_CAT_KEYLEN) {
 110                         pr_err("invalid catalog max_key_len %d\n",
 111                                tree->max_key_len);
 112                         goto fail_page;
 113                 }
 114                 break;
 115         default:
 116                 BUG();
 117         }
 118 
 119         tree->node_size_shift = ffs(size) - 1;
 120         tree->pages_per_bnode = (tree->node_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
 121 
 122         kunmap(page);
 123         put_page(page);
 124         return tree;
 125 
 126 fail_page:
 127         put_page(page);
 128 free_inode:
 129         tree->inode->i_mapping->a_ops = &hfs_aops;
 130         iput(tree->inode);
 131 free_tree:
 132         kfree(tree);
 133         return NULL;
 134 }
 135 
 136 /* Release resources used by a btree */
 137 void hfs_btree_close(struct hfs_btree *tree)
 138 {
 139         struct hfs_bnode *node;
 140         int i;
 141 
 142         if (!tree)
 143                 return;
 144 
 145         for (i = 0; i < NODE_HASH_SIZE; i++) {
 146                 while ((node = tree->node_hash[i])) {
 147                         tree->node_hash[i] = node->next_hash;
 148                         if (atomic_read(&node->refcnt))
 149                                 pr_err("node %d:%d still has %d user(s)!\n",
 150                                        node->tree->cnid, node->this,
 151                                        atomic_read(&node->refcnt));
 152                         hfs_bnode_free(node);
 153                         tree->node_hash_cnt--;
 154                 }
 155         }
 156         iput(tree->inode);
 157         kfree(tree);
 158 }
 159 
 160 void hfs_btree_write(struct hfs_btree *tree)
 161 {
 162         struct hfs_btree_header_rec *head;
 163         struct hfs_bnode *node;
 164         struct page *page;
 165 
 166         node = hfs_bnode_find(tree, 0);
 167         if (IS_ERR(node))
 168                 /* panic? */
 169                 return;
 170         /* Load the header */
 171         page = node->page[0];
 172         head = (struct hfs_btree_header_rec *)(kmap(page) + sizeof(struct hfs_bnode_desc));
 173 
 174         head->root = cpu_to_be32(tree->root);
 175         head->leaf_count = cpu_to_be32(tree->leaf_count);
 176         head->leaf_head = cpu_to_be32(tree->leaf_head);
 177         head->leaf_tail = cpu_to_be32(tree->leaf_tail);
 178         head->node_count = cpu_to_be32(tree->node_count);
 179         head->free_nodes = cpu_to_be32(tree->free_nodes);
 180         head->attributes = cpu_to_be32(tree->attributes);
 181         head->depth = cpu_to_be16(tree->depth);
 182 
 183         kunmap(page);
 184         set_page_dirty(page);
 185         hfs_bnode_put(node);
 186 }
 187 
 188 static struct hfs_bnode *hfs_bmap_new_bmap(struct hfs_bnode *prev, u32 idx)
 189 {
 190         struct hfs_btree *tree = prev->tree;
 191         struct hfs_bnode *node;
 192         struct hfs_bnode_desc desc;
 193         __be32 cnid;
 194 
 195         node = hfs_bnode_create(tree, idx);
 196         if (IS_ERR(node))
 197                 return node;
 198 
 199         if (!tree->free_nodes)
 200                 panic("FIXME!!!");
 201         tree->free_nodes--;
 202         prev->next = idx;
 203         cnid = cpu_to_be32(idx);
 204         hfs_bnode_write(prev, &cnid, offsetof(struct hfs_bnode_desc, next), 4);
 205 
 206         node->type = HFS_NODE_MAP;
 207         node->num_recs = 1;
 208         hfs_bnode_clear(node, 0, tree->node_size);
 209         desc.next = 0;
 210         desc.prev = 0;
 211         desc.type = HFS_NODE_MAP;
 212         desc.height = 0;
 213         desc.num_recs = cpu_to_be16(1);
 214         desc.reserved = 0;
 215         hfs_bnode_write(node, &desc, 0, sizeof(desc));
 216         hfs_bnode_write_u16(node, 14, 0x8000);
 217         hfs_bnode_write_u16(node, tree->node_size - 2, 14);
 218         hfs_bnode_write_u16(node, tree->node_size - 4, tree->node_size - 6);
 219 
 220         return node;
 221 }
 222 
 223 /* Make sure @tree has enough space for the @rsvd_nodes */
 224 int hfs_bmap_reserve(struct hfs_btree *tree, int rsvd_nodes)
 225 {
 226         struct inode *inode = tree->inode;
 227         u32 count;
 228         int res;
 229 
 230         while (tree->free_nodes < rsvd_nodes) {
 231                 res = hfs_extend_file(inode);
 232                 if (res)
 233                         return res;
 234                 HFS_I(inode)->phys_size = inode->i_size =
 235                                 (loff_t)HFS_I(inode)->alloc_blocks *
 236                                 HFS_SB(tree->sb)->alloc_blksz;
 237                 HFS_I(inode)->fs_blocks = inode->i_size >>
 238                                           tree->sb->s_blocksize_bits;
 239                 inode_set_bytes(inode, inode->i_size);
 240                 count = inode->i_size >> tree->node_size_shift;
 241                 tree->free_nodes += count - tree->node_count;
 242                 tree->node_count = count;
 243         }
 244         return 0;
 245 }
 246 
 247 struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
 248 {
 249         struct hfs_bnode *node, *next_node;
 250         struct page **pagep;
 251         u32 nidx, idx;
 252         unsigned off;
 253         u16 off16;
 254         u16 len;
 255         u8 *data, byte, m;
 256         int i, res;
 257 
 258         res = hfs_bmap_reserve(tree, 1);
 259         if (res)
 260                 return ERR_PTR(res);
 261 
 262         nidx = 0;
 263         node = hfs_bnode_find(tree, nidx);
 264         if (IS_ERR(node))
 265                 return node;
 266         len = hfs_brec_lenoff(node, 2, &off16);
 267         off = off16;
 268 
 269         off += node->page_offset;
 270         pagep = node->page + (off >> PAGE_SHIFT);
 271         data = kmap(*pagep);
 272         off &= ~PAGE_MASK;
 273         idx = 0;
 274 
 275         for (;;) {
 276                 while (len) {
 277                         byte = data[off];
 278                         if (byte != 0xff) {
 279                                 for (m = 0x80, i = 0; i < 8; m >>= 1, i++) {
 280                                         if (!(byte & m)) {
 281                                                 idx += i;
 282                                                 data[off] |= m;
 283                                                 set_page_dirty(*pagep);
 284                                                 kunmap(*pagep);
 285                                                 tree->free_nodes--;
 286                                                 mark_inode_dirty(tree->inode);
 287                                                 hfs_bnode_put(node);
 288                                                 return hfs_bnode_create(tree, idx);
 289                                         }
 290                                 }
 291                         }
 292                         if (++off >= PAGE_SIZE) {
 293                                 kunmap(*pagep);
 294                                 data = kmap(*++pagep);
 295                                 off = 0;
 296                         }
 297                         idx += 8;
 298                         len--;
 299                 }
 300                 kunmap(*pagep);
 301                 nidx = node->next;
 302                 if (!nidx) {
 303                         printk(KERN_DEBUG "create new bmap node...\n");
 304                         next_node = hfs_bmap_new_bmap(node, idx);
 305                 } else
 306                         next_node = hfs_bnode_find(tree, nidx);
 307                 hfs_bnode_put(node);
 308                 if (IS_ERR(next_node))
 309                         return next_node;
 310                 node = next_node;
 311 
 312                 len = hfs_brec_lenoff(node, 0, &off16);
 313                 off = off16;
 314                 off += node->page_offset;
 315                 pagep = node->page + (off >> PAGE_SHIFT);
 316                 data = kmap(*pagep);
 317                 off &= ~PAGE_MASK;
 318         }
 319 }
 320 
 321 void hfs_bmap_free(struct hfs_bnode *node)
 322 {
 323         struct hfs_btree *tree;
 324         struct page *page;
 325         u16 off, len;
 326         u32 nidx;
 327         u8 *data, byte, m;
 328 
 329         hfs_dbg(BNODE_MOD, "btree_free_node: %u\n", node->this);
 330         tree = node->tree;
 331         nidx = node->this;
 332         node = hfs_bnode_find(tree, 0);
 333         if (IS_ERR(node))
 334                 return;
 335         len = hfs_brec_lenoff(node, 2, &off);
 336         while (nidx >= len * 8) {
 337                 u32 i;
 338 
 339                 nidx -= len * 8;
 340                 i = node->next;
 341                 if (!i) {
 342                         /* panic */;
 343                         pr_crit("unable to free bnode %u. bmap not found!\n",
 344                                 node->this);
 345                         hfs_bnode_put(node);
 346                         return;
 347                 }
 348                 hfs_bnode_put(node);
 349                 node = hfs_bnode_find(tree, i);
 350                 if (IS_ERR(node))
 351                         return;
 352                 if (node->type != HFS_NODE_MAP) {
 353                         /* panic */;
 354                         pr_crit("invalid bmap found! (%u,%d)\n",
 355                                 node->this, node->type);
 356                         hfs_bnode_put(node);
 357                         return;
 358                 }
 359                 len = hfs_brec_lenoff(node, 0, &off);
 360         }
 361         off += node->page_offset + nidx / 8;
 362         page = node->page[off >> PAGE_SHIFT];
 363         data = kmap(page);
 364         off &= ~PAGE_MASK;
 365         m = 1 << (~nidx & 7);
 366         byte = data[off];
 367         if (!(byte & m)) {
 368                 pr_crit("trying to free free bnode %u(%d)\n",
 369                         node->this, node->type);
 370                 kunmap(page);
 371                 hfs_bnode_put(node);
 372                 return;
 373         }
 374         data[off] = byte & ~m;
 375         set_page_dirty(page);
 376         kunmap(page);
 377         hfs_bnode_put(node);
 378         tree->free_nodes++;
 379         mark_inode_dirty(tree->inode);
 380 }

/* [<][>][^][v][top][bottom][index][help] */