1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * linux/fs/hfsplus/bnode.c 4 * 5 * Copyright (C) 2001 6 * Brad Boyer (flar@allandria.com) 7 * (C) 2003 Ardis Technologies <roman@ardistech.com> 8 * 9 * Handle basic btree node operations 10 */ 11 12 #include <linux/string.h> 13 #include <linux/slab.h> 14 #include <linux/pagemap.h> 15 #include <linux/fs.h> 16 #include <linux/swap.h> 17 18 #include "hfsplus_fs.h" 19 #include "hfsplus_raw.h" 20 21 22 /* Copy a specified range of bytes from the raw data of a node */ 23 void hfs_bnode_read(struct hfs_bnode *node, void *buf, u32 off, u32 len) 24 { 25 struct page **pagep; 26 u32 l; 27 28 memset(buf, 0, len); 29 30 if (!is_bnode_offset_valid(node, off)) 31 return; 32 33 if (len == 0) { 34 pr_err("requested zero length: " 35 "NODE: id %u, type %#x, height %u, " 36 "node_size %u, offset %u, len %u\n", 37 node->this, node->type, node->height, 38 node->tree->node_size, off, len); 39 return; 40 } 41 42 len = check_and_correct_requested_length(node, off, len); 43 44 off += node->page_offset; 45 pagep = node->page + (off >> PAGE_SHIFT); 46 off &= ~PAGE_MASK; 47 48 l = min_t(u32, len, PAGE_SIZE - off); 49 memcpy_from_page(buf, *pagep, off, l); 50 51 while ((len -= l) != 0) { 52 buf += l; 53 l = min_t(u32, len, PAGE_SIZE); 54 memcpy_from_page(buf, *++pagep, 0, l); 55 } 56 } 57 58 u16 hfs_bnode_read_u16(struct hfs_bnode *node, u32 off) 59 { 60 __be16 data; 61 /* TODO: optimize later... */ 62 hfs_bnode_read(node, &data, off, 2); 63 return be16_to_cpu(data); 64 } 65 66 u8 hfs_bnode_read_u8(struct hfs_bnode *node, u32 off) 67 { 68 u8 data; 69 /* TODO: optimize later... */ 70 hfs_bnode_read(node, &data, off, 1); 71 return data; 72 } 73 74 void hfs_bnode_read_key(struct hfs_bnode *node, void *key, u32 off) 75 { 76 struct hfs_btree *tree; 77 u32 key_len; 78 79 tree = node->tree; 80 if (node->type == HFS_NODE_LEAF || 81 tree->attributes & HFS_TREE_VARIDXKEYS || 82 node->tree->cnid == HFSPLUS_ATTR_CNID) 83 key_len = hfs_bnode_read_u16(node, off) + 2; 84 else 85 key_len = tree->max_key_len + 2; 86 87 if (key_len > sizeof(hfsplus_btree_key) || key_len < 1) { 88 memset(key, 0, sizeof(hfsplus_btree_key)); 89 pr_err("hfsplus: Invalid key length: %u\n", key_len); 90 return; 91 } 92 93 hfs_bnode_read(node, key, off, key_len); 94 } 95 96 void hfs_bnode_write(struct hfs_bnode *node, void *buf, u32 off, u32 len) 97 { 98 struct page **pagep; 99 u32 l; 100 101 if (!is_bnode_offset_valid(node, off)) 102 return; 103 104 if (len == 0) { 105 pr_err("requested zero length: " 106 "NODE: id %u, type %#x, height %u, " 107 "node_size %u, offset %u, len %u\n", 108 node->this, node->type, node->height, 109 node->tree->node_size, off, len); 110 return; 111 } 112 113 len = check_and_correct_requested_length(node, off, len); 114 115 off += node->page_offset; 116 pagep = node->page + (off >> PAGE_SHIFT); 117 off &= ~PAGE_MASK; 118 119 l = min_t(u32, len, PAGE_SIZE - off); 120 memcpy_to_page(*pagep, off, buf, l); 121 set_page_dirty(*pagep); 122 123 while ((len -= l) != 0) { 124 buf += l; 125 l = min_t(u32, len, PAGE_SIZE); 126 memcpy_to_page(*++pagep, 0, buf, l); 127 set_page_dirty(*pagep); 128 } 129 } 130 131 void hfs_bnode_write_u16(struct hfs_bnode *node, u32 off, u16 data) 132 { 133 __be16 v = cpu_to_be16(data); 134 /* TODO: optimize later... */ 135 hfs_bnode_write(node, &v, off, 2); 136 } 137 138 void hfs_bnode_clear(struct hfs_bnode *node, u32 off, u32 len) 139 { 140 struct page **pagep; 141 u32 l; 142 143 if (!is_bnode_offset_valid(node, off)) 144 return; 145 146 if (len == 0) { 147 pr_err("requested zero length: " 148 "NODE: id %u, type %#x, height %u, " 149 "node_size %u, offset %u, len %u\n", 150 node->this, node->type, node->height, 151 node->tree->node_size, off, len); 152 return; 153 } 154 155 len = check_and_correct_requested_length(node, off, len); 156 157 off += node->page_offset; 158 pagep = node->page + (off >> PAGE_SHIFT); 159 off &= ~PAGE_MASK; 160 161 l = min_t(u32, len, PAGE_SIZE - off); 162 memzero_page(*pagep, off, l); 163 set_page_dirty(*pagep); 164 165 while ((len -= l) != 0) { 166 l = min_t(u32, len, PAGE_SIZE); 167 memzero_page(*++pagep, 0, l); 168 set_page_dirty(*pagep); 169 } 170 } 171 172 void hfs_bnode_copy(struct hfs_bnode *dst_node, u32 dst, 173 struct hfs_bnode *src_node, u32 src, u32 len) 174 { 175 struct page **src_page, **dst_page; 176 u32 l; 177 178 hfs_dbg("dst %u, src %u, len %u\n", dst, src, len); 179 if (!len) 180 return; 181 182 len = check_and_correct_requested_length(src_node, src, len); 183 len = check_and_correct_requested_length(dst_node, dst, len); 184 185 src += src_node->page_offset; 186 dst += dst_node->page_offset; 187 src_page = src_node->page + (src >> PAGE_SHIFT); 188 src &= ~PAGE_MASK; 189 dst_page = dst_node->page + (dst >> PAGE_SHIFT); 190 dst &= ~PAGE_MASK; 191 192 if (src == dst) { 193 l = min_t(u32, len, PAGE_SIZE - src); 194 memcpy_page(*dst_page, src, *src_page, src, l); 195 set_page_dirty(*dst_page); 196 197 while ((len -= l) != 0) { 198 l = min_t(u32, len, PAGE_SIZE); 199 memcpy_page(*++dst_page, 0, *++src_page, 0, l); 200 set_page_dirty(*dst_page); 201 } 202 } else { 203 void *src_ptr, *dst_ptr; 204 205 do { 206 dst_ptr = kmap_local_page(*dst_page) + dst; 207 src_ptr = kmap_local_page(*src_page) + src; 208 if (PAGE_SIZE - src < PAGE_SIZE - dst) { 209 l = PAGE_SIZE - src; 210 src = 0; 211 dst += l; 212 } else { 213 l = PAGE_SIZE - dst; 214 src += l; 215 dst = 0; 216 } 217 l = min(len, l); 218 memcpy(dst_ptr, src_ptr, l); 219 kunmap_local(src_ptr); 220 set_page_dirty(*dst_page); 221 kunmap_local(dst_ptr); 222 if (!dst) 223 dst_page++; 224 else 225 src_page++; 226 } while ((len -= l)); 227 } 228 } 229 230 void hfs_bnode_move(struct hfs_bnode *node, u32 dst, u32 src, u32 len) 231 { 232 struct page **src_page, **dst_page; 233 void *src_ptr, *dst_ptr; 234 u32 l; 235 236 hfs_dbg("dst %u, src %u, len %u\n", dst, src, len); 237 if (!len) 238 return; 239 240 len = check_and_correct_requested_length(node, src, len); 241 len = check_and_correct_requested_length(node, dst, len); 242 243 src += node->page_offset; 244 dst += node->page_offset; 245 if (dst > src) { 246 src += len - 1; 247 src_page = node->page + (src >> PAGE_SHIFT); 248 src = (src & ~PAGE_MASK) + 1; 249 dst += len - 1; 250 dst_page = node->page + (dst >> PAGE_SHIFT); 251 dst = (dst & ~PAGE_MASK) + 1; 252 253 if (src == dst) { 254 while (src < len) { 255 dst_ptr = kmap_local_page(*dst_page); 256 src_ptr = kmap_local_page(*src_page); 257 memmove(dst_ptr, src_ptr, src); 258 kunmap_local(src_ptr); 259 set_page_dirty(*dst_page); 260 kunmap_local(dst_ptr); 261 len -= src; 262 src = PAGE_SIZE; 263 src_page--; 264 dst_page--; 265 } 266 src -= len; 267 dst_ptr = kmap_local_page(*dst_page); 268 src_ptr = kmap_local_page(*src_page); 269 memmove(dst_ptr + src, src_ptr + src, len); 270 kunmap_local(src_ptr); 271 set_page_dirty(*dst_page); 272 kunmap_local(dst_ptr); 273 } else { 274 do { 275 dst_ptr = kmap_local_page(*dst_page) + dst; 276 src_ptr = kmap_local_page(*src_page) + src; 277 if (src < dst) { 278 l = src; 279 src = PAGE_SIZE; 280 dst -= l; 281 } else { 282 l = dst; 283 src -= l; 284 dst = PAGE_SIZE; 285 } 286 l = min(len, l); 287 memmove(dst_ptr - l, src_ptr - l, l); 288 kunmap_local(src_ptr); 289 set_page_dirty(*dst_page); 290 kunmap_local(dst_ptr); 291 if (dst == PAGE_SIZE) 292 dst_page--; 293 else 294 src_page--; 295 } while ((len -= l)); 296 } 297 } else { 298 src_page = node->page + (src >> PAGE_SHIFT); 299 src &= ~PAGE_MASK; 300 dst_page = node->page + (dst >> PAGE_SHIFT); 301 dst &= ~PAGE_MASK; 302 303 if (src == dst) { 304 l = min_t(u32, len, PAGE_SIZE - src); 305 306 dst_ptr = kmap_local_page(*dst_page) + src; 307 src_ptr = kmap_local_page(*src_page) + src; 308 memmove(dst_ptr, src_ptr, l); 309 kunmap_local(src_ptr); 310 set_page_dirty(*dst_page); 311 kunmap_local(dst_ptr); 312 313 while ((len -= l) != 0) { 314 l = min_t(u32, len, PAGE_SIZE); 315 dst_ptr = kmap_local_page(*++dst_page); 316 src_ptr = kmap_local_page(*++src_page); 317 memmove(dst_ptr, src_ptr, l); 318 kunmap_local(src_ptr); 319 set_page_dirty(*dst_page); 320 kunmap_local(dst_ptr); 321 } 322 } else { 323 do { 324 dst_ptr = kmap_local_page(*dst_page) + dst; 325 src_ptr = kmap_local_page(*src_page) + src; 326 if (PAGE_SIZE - src < 327 PAGE_SIZE - dst) { 328 l = PAGE_SIZE - src; 329 src = 0; 330 dst += l; 331 } else { 332 l = PAGE_SIZE - dst; 333 src += l; 334 dst = 0; 335 } 336 l = min(len, l); 337 memmove(dst_ptr, src_ptr, l); 338 kunmap_local(src_ptr); 339 set_page_dirty(*dst_page); 340 kunmap_local(dst_ptr); 341 if (!dst) 342 dst_page++; 343 else 344 src_page++; 345 } while ((len -= l)); 346 } 347 } 348 } 349 350 void hfs_bnode_dump(struct hfs_bnode *node) 351 { 352 struct hfs_bnode_desc desc; 353 __be32 cnid; 354 int i, off, key_off; 355 u16 num_recs; 356 357 hfs_dbg("node %d\n", node->this); 358 hfs_bnode_read(node, &desc, 0, sizeof(desc)); 359 num_recs = node->num_recs; 360 hfs_dbg("next %d, prev %d, type %d, height %d, num_recs %d\n", 361 be32_to_cpu(desc.next), be32_to_cpu(desc.prev), 362 desc.type, desc.height, be16_to_cpu(desc.num_recs)); 363 364 if (hfs_bnode_num_recs_invalid(node)) { 365 hfs_dbg("invalid num_recs %u\n", num_recs); 366 return; 367 } 368 369 off = node->tree->node_size - 2; 370 for (i = num_recs; i >= 0; off -= 2, i--) { 371 key_off = hfs_bnode_read_u16(node, off); 372 hfs_dbg(" key_off %d", key_off); 373 if (i && node->type == HFS_NODE_INDEX) { 374 int tmp; 375 376 if (node->tree->attributes & HFS_TREE_VARIDXKEYS || 377 node->tree->cnid == HFSPLUS_ATTR_CNID) 378 tmp = hfs_bnode_read_u16(node, key_off) + 2; 379 else 380 tmp = node->tree->max_key_len + 2; 381 hfs_dbg(" (%d", tmp); 382 hfs_bnode_read(node, &cnid, key_off + tmp, 4); 383 hfs_dbg(", cnid %d)", be32_to_cpu(cnid)); 384 } else if (i && node->type == HFS_NODE_LEAF) { 385 int tmp; 386 387 tmp = hfs_bnode_read_u16(node, key_off); 388 hfs_dbg(" (%d)", tmp); 389 } 390 } 391 hfs_dbg("\n"); 392 } 393 394 void hfs_bnode_unlink(struct hfs_bnode *node) 395 { 396 struct hfs_btree *tree; 397 struct hfs_bnode *tmp; 398 __be32 cnid; 399 400 tree = node->tree; 401 if (node->prev) { 402 tmp = hfs_bnode_find(tree, node->prev); 403 if (IS_ERR(tmp)) 404 return; 405 tmp->next = node->next; 406 cnid = cpu_to_be32(tmp->next); 407 hfs_bnode_write(tmp, &cnid, 408 offsetof(struct hfs_bnode_desc, next), 4); 409 hfs_bnode_put(tmp); 410 } else if (node->type == HFS_NODE_LEAF) 411 tree->leaf_head = node->next; 412 413 if (node->next) { 414 tmp = hfs_bnode_find(tree, node->next); 415 if (IS_ERR(tmp)) 416 return; 417 tmp->prev = node->prev; 418 cnid = cpu_to_be32(tmp->prev); 419 hfs_bnode_write(tmp, &cnid, 420 offsetof(struct hfs_bnode_desc, prev), 4); 421 hfs_bnode_put(tmp); 422 } else if (node->type == HFS_NODE_LEAF) 423 tree->leaf_tail = node->prev; 424 425 /* move down? */ 426 if (!node->prev && !node->next) 427 hfs_dbg("btree delete level\n"); 428 if (!node->parent) { 429 tree->root = 0; 430 tree->depth = 0; 431 } 432 433 spin_lock(&tree->hash_lock); 434 set_bit(HFS_BNODE_DELETED, &node->flags); 435 spin_unlock(&tree->hash_lock); 436 } 437 438 static inline int hfs_bnode_hash(u32 num) 439 { 440 num = (num >> 16) + num; 441 num += num >> 8; 442 return num & (NODE_HASH_SIZE - 1); 443 } 444 445 struct hfs_bnode *hfs_bnode_findhash(struct hfs_btree *tree, u32 cnid) 446 { 447 struct hfs_bnode *node; 448 449 if (cnid >= tree->node_count) { 450 pr_err("request for non-existent node %d in B*Tree\n", 451 cnid); 452 return NULL; 453 } 454 455 for (node = tree->node_hash[hfs_bnode_hash(cnid)]; 456 node; node = node->next_hash) 457 if (node->this == cnid) 458 return node; 459 return NULL; 460 } 461 462 static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid) 463 { 464 struct hfs_bnode *node, *node2; 465 struct address_space *mapping; 466 struct page *page; 467 int block, i, hash; 468 loff_t off; 469 470 if (cnid >= tree->node_count) { 471 pr_err("request for non-existent node %d in B*Tree\n", 472 cnid); 473 return NULL; 474 } 475 476 node = kzalloc_flex(*node, page, tree->pages_per_bnode); 477 if (!node) 478 return NULL; 479 node->tree = tree; 480 node->this = cnid; 481 set_bit(HFS_BNODE_NEW, &node->flags); 482 atomic_set(&node->refcnt, 1); 483 hfs_dbg("cnid %d, node %d, refcnt 1\n", 484 node->tree->cnid, node->this); 485 init_waitqueue_head(&node->lock_wq); 486 spin_lock(&tree->hash_lock); 487 node2 = hfs_bnode_findhash(tree, cnid); 488 if (!node2) { 489 hash = hfs_bnode_hash(cnid); 490 node->next_hash = tree->node_hash[hash]; 491 tree->node_hash[hash] = node; 492 tree->node_hash_cnt++; 493 } else { 494 hfs_bnode_get(node2); 495 spin_unlock(&tree->hash_lock); 496 kfree(node); 497 wait_event(node2->lock_wq, 498 !test_bit(HFS_BNODE_NEW, &node2->flags)); 499 return node2; 500 } 501 spin_unlock(&tree->hash_lock); 502 503 mapping = tree->inode->i_mapping; 504 off = (loff_t)cnid << tree->node_size_shift; 505 block = off >> PAGE_SHIFT; 506 node->page_offset = off & ~PAGE_MASK; 507 for (i = 0; i < tree->pages_per_bnode; block++, i++) { 508 page = read_mapping_page(mapping, block, NULL); 509 if (IS_ERR(page)) 510 goto fail; 511 node->page[i] = page; 512 } 513 514 return node; 515 fail: 516 set_bit(HFS_BNODE_ERROR, &node->flags); 517 return node; 518 } 519 520 void hfs_bnode_unhash(struct hfs_bnode *node) 521 { 522 struct hfs_bnode **p; 523 524 hfs_dbg("cnid %d, node %d, refcnt %d\n", 525 node->tree->cnid, node->this, atomic_read(&node->refcnt)); 526 for (p = &node->tree->node_hash[hfs_bnode_hash(node->this)]; 527 *p && *p != node; p = &(*p)->next_hash) 528 ; 529 BUG_ON(!*p); 530 *p = node->next_hash; 531 node->tree->node_hash_cnt--; 532 } 533 534 /* Load a particular node out of a tree */ 535 struct hfs_bnode *hfs_bnode_find(struct hfs_btree *tree, u32 num) 536 { 537 struct hfs_bnode *node; 538 struct hfs_bnode_desc *desc; 539 int i, rec_off, off, next_off; 540 int entry_size, key_size; 541 542 spin_lock(&tree->hash_lock); 543 node = hfs_bnode_findhash(tree, num); 544 if (node) { 545 hfs_bnode_get(node); 546 spin_unlock(&tree->hash_lock); 547 wait_event(node->lock_wq, 548 !test_bit(HFS_BNODE_NEW, &node->flags)); 549 if (test_bit(HFS_BNODE_ERROR, &node->flags)) 550 goto node_error; 551 return node; 552 } 553 spin_unlock(&tree->hash_lock); 554 node = __hfs_bnode_create(tree, num); 555 if (!node) 556 return ERR_PTR(-ENOMEM); 557 if (test_bit(HFS_BNODE_ERROR, &node->flags)) 558 goto node_error; 559 if (!test_bit(HFS_BNODE_NEW, &node->flags)) 560 return node; 561 562 desc = (struct hfs_bnode_desc *)(kmap_local_page(node->page[0]) + 563 node->page_offset); 564 node->prev = be32_to_cpu(desc->prev); 565 node->next = be32_to_cpu(desc->next); 566 node->num_recs = be16_to_cpu(desc->num_recs); 567 node->type = desc->type; 568 node->height = desc->height; 569 kunmap_local(desc); 570 571 if (hfs_bnode_num_recs_invalid(node)) 572 goto node_error; 573 574 switch (node->type) { 575 case HFS_NODE_HEADER: 576 case HFS_NODE_MAP: 577 if (node->height != 0) 578 goto node_error; 579 break; 580 case HFS_NODE_LEAF: 581 if (node->height != 1) 582 goto node_error; 583 break; 584 case HFS_NODE_INDEX: 585 if (node->height <= 1 || node->height > tree->depth) 586 goto node_error; 587 break; 588 default: 589 goto node_error; 590 } 591 592 rec_off = tree->node_size - 2; 593 off = hfs_bnode_read_u16(node, rec_off); 594 if (off != sizeof(struct hfs_bnode_desc)) 595 goto node_error; 596 for (i = 1; i <= node->num_recs; off = next_off, i++) { 597 rec_off -= 2; 598 next_off = hfs_bnode_read_u16(node, rec_off); 599 if (hfs_brec_offsets_invalid(node, off, next_off)) 600 goto node_error; 601 entry_size = next_off - off; 602 if (node->type != HFS_NODE_INDEX && 603 node->type != HFS_NODE_LEAF) 604 continue; 605 key_size = hfs_bnode_read_u16(node, off) + 2; 606 if (key_size >= entry_size || key_size & 1) 607 goto node_error; 608 } 609 clear_bit(HFS_BNODE_NEW, &node->flags); 610 wake_up(&node->lock_wq); 611 return node; 612 613 node_error: 614 set_bit(HFS_BNODE_ERROR, &node->flags); 615 clear_bit(HFS_BNODE_NEW, &node->flags); 616 wake_up(&node->lock_wq); 617 hfs_bnode_put(node); 618 return ERR_PTR(-EIO); 619 } 620 621 void hfs_bnode_free(struct hfs_bnode *node) 622 { 623 int i; 624 625 for (i = 0; i < node->tree->pages_per_bnode; i++) 626 if (node->page[i]) 627 put_page(node->page[i]); 628 kfree(node); 629 } 630 631 struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num) 632 { 633 struct hfs_bnode *node; 634 struct page **pagep; 635 int i; 636 637 spin_lock(&tree->hash_lock); 638 node = hfs_bnode_findhash(tree, num); 639 spin_unlock(&tree->hash_lock); 640 if (node) { 641 pr_crit("new node %u already hashed?\n", num); 642 WARN_ON(1); 643 return ERR_PTR(-EEXIST); 644 } 645 node = __hfs_bnode_create(tree, num); 646 if (!node) 647 return ERR_PTR(-ENOMEM); 648 if (test_bit(HFS_BNODE_ERROR, &node->flags)) { 649 hfs_bnode_put(node); 650 return ERR_PTR(-EIO); 651 } 652 653 pagep = node->page; 654 memzero_page(*pagep, node->page_offset, 655 min_t(int, PAGE_SIZE, tree->node_size)); 656 set_page_dirty(*pagep); 657 for (i = 1; i < tree->pages_per_bnode; i++) { 658 memzero_page(*++pagep, 0, PAGE_SIZE); 659 set_page_dirty(*pagep); 660 } 661 clear_bit(HFS_BNODE_NEW, &node->flags); 662 wake_up(&node->lock_wq); 663 664 return node; 665 } 666 667 void hfs_bnode_get(struct hfs_bnode *node) 668 { 669 if (node) { 670 atomic_inc(&node->refcnt); 671 hfs_dbg("cnid %d, node %d, refcnt %d\n", 672 node->tree->cnid, node->this, 673 atomic_read(&node->refcnt)); 674 } 675 } 676 677 /* Dispose of resources used by a node */ 678 void hfs_bnode_put(struct hfs_bnode *node) 679 { 680 if (node) { 681 struct hfs_btree *tree = node->tree; 682 int i; 683 684 hfs_dbg("cnid %d, node %d, refcnt %d\n", 685 node->tree->cnid, node->this, 686 atomic_read(&node->refcnt)); 687 BUG_ON(!atomic_read(&node->refcnt)); 688 if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock)) 689 return; 690 for (i = 0; i < tree->pages_per_bnode; i++) { 691 if (!node->page[i]) 692 continue; 693 mark_page_accessed(node->page[i]); 694 } 695 696 if (test_bit(HFS_BNODE_DELETED, &node->flags)) { 697 hfs_bnode_unhash(node); 698 spin_unlock(&tree->hash_lock); 699 if (hfs_bnode_need_zeroout(tree)) 700 hfs_bnode_clear(node, 0, tree->node_size); 701 hfs_bmap_free(node); 702 hfs_bnode_free(node); 703 return; 704 } 705 spin_unlock(&tree->hash_lock); 706 } 707 } 708 709 /* 710 * Unused nodes have to be zeroed if this is the catalog tree and 711 * a corresponding flag in the volume header is set. 712 */ 713 bool hfs_bnode_need_zeroout(struct hfs_btree *tree) 714 { 715 struct super_block *sb = tree->inode->i_sb; 716 struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); 717 const u32 volume_attr = be32_to_cpu(sbi->s_vhdr->attributes); 718 719 return volume_attr & HFSPLUS_VOL_UNUSED_NODE_FIX; 720 } 721