1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * linux/fs/hfsplus/super.c 4 * 5 * Copyright (C) 2001 6 * Brad Boyer (flar@allandria.com) 7 * (C) 2003 Ardis Technologies <roman@ardistech.com> 8 * 9 */ 10 11 #include <linux/module.h> 12 #include <linux/init.h> 13 #include <linux/pagemap.h> 14 #include <linux/blkdev.h> 15 #include <linux/backing-dev.h> 16 #include <linux/fs.h> 17 #include <linux/fs_context.h> 18 #include <linux/slab.h> 19 #include <linux/vfs.h> 20 #include <linux/nls.h> 21 22 static struct inode *hfsplus_alloc_inode(struct super_block *sb); 23 static void hfsplus_free_inode(struct inode *inode); 24 25 #include "hfsplus_fs.h" 26 #include "xattr.h" 27 28 static int hfsplus_system_read_inode(struct inode *inode) 29 { 30 struct hfsplus_vh *vhdr = HFSPLUS_SB(inode->i_sb)->s_vhdr; 31 32 switch (inode->i_ino) { 33 case HFSPLUS_EXT_CNID: 34 hfsplus_inode_read_fork(inode, &vhdr->ext_file); 35 inode->i_mapping->a_ops = &hfsplus_btree_aops; 36 break; 37 case HFSPLUS_CAT_CNID: 38 hfsplus_inode_read_fork(inode, &vhdr->cat_file); 39 inode->i_mapping->a_ops = &hfsplus_btree_aops; 40 break; 41 case HFSPLUS_ALLOC_CNID: 42 hfsplus_inode_read_fork(inode, &vhdr->alloc_file); 43 inode->i_mapping->a_ops = &hfsplus_aops; 44 break; 45 case HFSPLUS_START_CNID: 46 hfsplus_inode_read_fork(inode, &vhdr->start_file); 47 break; 48 case HFSPLUS_ATTR_CNID: 49 hfsplus_inode_read_fork(inode, &vhdr->attr_file); 50 inode->i_mapping->a_ops = &hfsplus_btree_aops; 51 break; 52 default: 53 return -EIO; 54 } 55 56 return 0; 57 } 58 59 struct inode *hfsplus_iget(struct super_block *sb, unsigned long ino) 60 { 61 struct hfs_find_data fd; 62 struct inode *inode; 63 int err; 64 65 inode = iget_locked(sb, ino); 66 if (!inode) 67 return ERR_PTR(-ENOMEM); 68 if (!(inode_state_read_once(inode) & I_NEW)) 69 return inode; 70 71 atomic_set(&HFSPLUS_I(inode)->opencnt, 0); 72 HFSPLUS_I(inode)->first_blocks = 0; 73 HFSPLUS_I(inode)->clump_blocks = 0; 74 HFSPLUS_I(inode)->alloc_blocks = 0; 75 HFSPLUS_I(inode)->cached_start = U32_MAX; 76 HFSPLUS_I(inode)->cached_blocks = 0; 77 memset(HFSPLUS_I(inode)->first_extents, 0, sizeof(hfsplus_extent_rec)); 78 memset(HFSPLUS_I(inode)->cached_extents, 0, sizeof(hfsplus_extent_rec)); 79 HFSPLUS_I(inode)->extent_state = 0; 80 mutex_init(&HFSPLUS_I(inode)->extents_lock); 81 HFSPLUS_I(inode)->rsrc_inode = NULL; 82 HFSPLUS_I(inode)->create_date = 0; 83 HFSPLUS_I(inode)->linkid = 0; 84 HFSPLUS_I(inode)->flags = 0; 85 HFSPLUS_I(inode)->fs_blocks = 0; 86 HFSPLUS_I(inode)->userflags = 0; 87 HFSPLUS_I(inode)->subfolders = 0; 88 INIT_LIST_HEAD(&HFSPLUS_I(inode)->open_dir_list); 89 spin_lock_init(&HFSPLUS_I(inode)->open_dir_lock); 90 HFSPLUS_I(inode)->phys_size = 0; 91 92 if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID || 93 inode->i_ino == HFSPLUS_ROOT_CNID) { 94 err = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd); 95 if (!err) { 96 err = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd); 97 if (!err) 98 err = hfsplus_cat_read_inode(inode, &fd); 99 hfs_find_exit(&fd); 100 } 101 } else { 102 err = hfsplus_system_read_inode(inode); 103 } 104 105 if (err) { 106 iget_failed(inode); 107 return ERR_PTR(err); 108 } 109 110 unlock_new_inode(inode); 111 return inode; 112 } 113 114 static int hfsplus_system_write_inode(struct inode *inode) 115 { 116 struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb); 117 struct hfsplus_vh *vhdr = sbi->s_vhdr; 118 struct hfsplus_fork_raw *fork; 119 struct hfs_btree *tree = NULL; 120 121 switch (inode->i_ino) { 122 case HFSPLUS_EXT_CNID: 123 fork = &vhdr->ext_file; 124 tree = sbi->ext_tree; 125 break; 126 case HFSPLUS_CAT_CNID: 127 fork = &vhdr->cat_file; 128 tree = sbi->cat_tree; 129 break; 130 case HFSPLUS_ALLOC_CNID: 131 fork = &vhdr->alloc_file; 132 break; 133 case HFSPLUS_START_CNID: 134 fork = &vhdr->start_file; 135 break; 136 case HFSPLUS_ATTR_CNID: 137 fork = &vhdr->attr_file; 138 tree = sbi->attr_tree; 139 break; 140 default: 141 return -EIO; 142 } 143 144 if (fork->total_size != cpu_to_be64(inode->i_size)) { 145 set_bit(HFSPLUS_SB_WRITEBACKUP, &sbi->flags); 146 hfsplus_mark_mdb_dirty(inode->i_sb); 147 } 148 hfsplus_inode_write_fork(inode, fork); 149 if (tree) { 150 int err = hfs_btree_write(tree); 151 152 if (err) { 153 pr_err("b-tree write err: %d, ino %lu\n", 154 err, inode->i_ino); 155 return err; 156 } 157 } 158 return 0; 159 } 160 161 static int hfsplus_write_inode(struct inode *inode, 162 struct writeback_control *wbc) 163 { 164 int err; 165 166 hfs_dbg("ino %lu\n", inode->i_ino); 167 168 err = hfsplus_ext_write_extent(inode); 169 if (err) 170 return err; 171 172 if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID || 173 inode->i_ino == HFSPLUS_ROOT_CNID) 174 return hfsplus_cat_write_inode(inode); 175 else 176 return hfsplus_system_write_inode(inode); 177 } 178 179 static void hfsplus_evict_inode(struct inode *inode) 180 { 181 hfs_dbg("ino %lu\n", inode->i_ino); 182 truncate_inode_pages_final(&inode->i_data); 183 clear_inode(inode); 184 if (HFSPLUS_IS_RSRC(inode)) { 185 HFSPLUS_I(HFSPLUS_I(inode)->rsrc_inode)->rsrc_inode = NULL; 186 iput(HFSPLUS_I(inode)->rsrc_inode); 187 } 188 } 189 190 int hfsplus_commit_superblock(struct super_block *sb) 191 { 192 struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); 193 struct hfsplus_vh *vhdr = sbi->s_vhdr; 194 int write_backup = 0; 195 int error = 0, error2; 196 197 hfs_dbg("starting...\n"); 198 199 mutex_lock(&sbi->vh_mutex); 200 mutex_lock(&sbi->alloc_mutex); 201 vhdr->free_blocks = cpu_to_be32(sbi->free_blocks); 202 vhdr->next_cnid = cpu_to_be32(sbi->next_cnid); 203 vhdr->folder_count = cpu_to_be32(sbi->folder_count); 204 vhdr->file_count = cpu_to_be32(sbi->file_count); 205 206 hfs_dbg("free_blocks %u, next_cnid %u, folder_count %u, file_count %u\n", 207 sbi->free_blocks, sbi->next_cnid, 208 sbi->folder_count, sbi->file_count); 209 210 if (test_and_clear_bit(HFSPLUS_SB_WRITEBACKUP, &sbi->flags)) { 211 memcpy(sbi->s_backup_vhdr, sbi->s_vhdr, sizeof(*sbi->s_vhdr)); 212 write_backup = 1; 213 } 214 215 error2 = hfsplus_submit_bio(sb, 216 sbi->part_start + HFSPLUS_VOLHEAD_SECTOR, 217 sbi->s_vhdr_buf, NULL, REQ_OP_WRITE); 218 if (!error) 219 error = error2; 220 if (!write_backup) 221 goto out; 222 223 error2 = hfsplus_submit_bio(sb, 224 sbi->part_start + sbi->sect_count - 2, 225 sbi->s_backup_vhdr_buf, NULL, REQ_OP_WRITE); 226 if (!error) 227 error = error2; 228 out: 229 mutex_unlock(&sbi->alloc_mutex); 230 mutex_unlock(&sbi->vh_mutex); 231 232 hfs_dbg("finished: err %d\n", error); 233 234 return error; 235 } 236 237 static int hfsplus_sync_fs(struct super_block *sb, int wait) 238 { 239 struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); 240 int error, error2; 241 242 if (!wait) 243 return 0; 244 245 hfs_dbg("starting...\n"); 246 247 /* 248 * Explicitly write out the special metadata inodes. 249 * 250 * While these special inodes are marked as hashed and written 251 * out peridocically by the flusher threads we redirty them 252 * during writeout of normal inodes, and thus the life lock 253 * prevents us from getting the latest state to disk. 254 */ 255 error = filemap_write_and_wait(sbi->cat_tree->inode->i_mapping); 256 error2 = filemap_write_and_wait(sbi->ext_tree->inode->i_mapping); 257 if (!error) 258 error = error2; 259 if (sbi->attr_tree) { 260 error2 = 261 filemap_write_and_wait(sbi->attr_tree->inode->i_mapping); 262 if (!error) 263 error = error2; 264 } 265 error2 = filemap_write_and_wait(sbi->alloc_file->i_mapping); 266 if (!error) 267 error = error2; 268 269 error2 = hfsplus_commit_superblock(sb); 270 if (!error) 271 error = error2; 272 273 if (!test_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags)) 274 blkdev_issue_flush(sb->s_bdev); 275 276 hfs_dbg("finished: err %d\n", error); 277 278 return error; 279 } 280 281 static void delayed_sync_fs(struct work_struct *work) 282 { 283 int err; 284 struct hfsplus_sb_info *sbi; 285 286 sbi = container_of(work, struct hfsplus_sb_info, sync_work.work); 287 288 spin_lock(&sbi->work_lock); 289 sbi->work_queued = 0; 290 spin_unlock(&sbi->work_lock); 291 292 err = hfsplus_sync_fs(sbi->alloc_file->i_sb, 1); 293 if (err) 294 pr_err("delayed sync fs err %d\n", err); 295 } 296 297 void hfsplus_mark_mdb_dirty(struct super_block *sb) 298 { 299 struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); 300 unsigned long delay; 301 302 if (sb_rdonly(sb)) 303 return; 304 305 spin_lock(&sbi->work_lock); 306 if (!sbi->work_queued) { 307 delay = msecs_to_jiffies(dirty_writeback_interval * 10); 308 queue_delayed_work(system_long_wq, &sbi->sync_work, delay); 309 sbi->work_queued = 1; 310 } 311 spin_unlock(&sbi->work_lock); 312 } 313 314 static void delayed_free(struct rcu_head *p) 315 { 316 struct hfsplus_sb_info *sbi = container_of(p, struct hfsplus_sb_info, rcu); 317 318 unload_nls(sbi->nls); 319 kfree(sbi); 320 } 321 322 static void hfsplus_put_super(struct super_block *sb) 323 { 324 struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); 325 326 hfs_dbg("starting...\n"); 327 328 cancel_delayed_work_sync(&sbi->sync_work); 329 330 if (!sb_rdonly(sb) && sbi->s_vhdr) { 331 struct hfsplus_vh *vhdr = sbi->s_vhdr; 332 333 vhdr->modify_date = hfsp_now2mt(); 334 vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_UNMNT); 335 vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_INCNSTNT); 336 337 hfsplus_sync_fs(sb, 1); 338 } 339 340 iput(sbi->alloc_file); 341 iput(sbi->hidden_dir); 342 hfs_btree_close(sbi->attr_tree); 343 hfs_btree_close(sbi->cat_tree); 344 hfs_btree_close(sbi->ext_tree); 345 kfree(sbi->s_vhdr_buf); 346 kfree(sbi->s_backup_vhdr_buf); 347 call_rcu(&sbi->rcu, delayed_free); 348 349 hfs_dbg("finished\n"); 350 } 351 352 static int hfsplus_statfs(struct dentry *dentry, struct kstatfs *buf) 353 { 354 struct super_block *sb = dentry->d_sb; 355 struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); 356 u64 id = huge_encode_dev(sb->s_bdev->bd_dev); 357 358 buf->f_type = HFSPLUS_SUPER_MAGIC; 359 buf->f_bsize = sb->s_blocksize; 360 buf->f_blocks = sbi->total_blocks << sbi->fs_shift; 361 buf->f_bfree = sbi->free_blocks << sbi->fs_shift; 362 buf->f_bavail = buf->f_bfree; 363 buf->f_files = 0xFFFFFFFF; 364 buf->f_ffree = 0xFFFFFFFF - sbi->next_cnid; 365 buf->f_fsid = u64_to_fsid(id); 366 buf->f_namelen = HFSPLUS_MAX_STRLEN; 367 368 return 0; 369 } 370 371 static int hfsplus_reconfigure(struct fs_context *fc) 372 { 373 struct super_block *sb = fc->root->d_sb; 374 375 sync_filesystem(sb); 376 if ((bool)(fc->sb_flags & SB_RDONLY) == sb_rdonly(sb)) 377 return 0; 378 if (!(fc->sb_flags & SB_RDONLY)) { 379 struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); 380 struct hfsplus_vh *vhdr = sbi->s_vhdr; 381 382 if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { 383 pr_warn("filesystem was not cleanly unmounted, running fsck.hfsplus is recommended. leaving read-only.\n"); 384 sb->s_flags |= SB_RDONLY; 385 fc->sb_flags |= SB_RDONLY; 386 } else if (test_bit(HFSPLUS_SB_FORCE, &sbi->flags)) { 387 /* nothing */ 388 } else if (vhdr->attributes & 389 cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { 390 pr_warn("filesystem is marked locked, leaving read-only.\n"); 391 sb->s_flags |= SB_RDONLY; 392 fc->sb_flags |= SB_RDONLY; 393 } else if (vhdr->attributes & 394 cpu_to_be32(HFSPLUS_VOL_JOURNALED)) { 395 pr_warn("filesystem is marked journaled, leaving read-only.\n"); 396 sb->s_flags |= SB_RDONLY; 397 fc->sb_flags |= SB_RDONLY; 398 } 399 } 400 return 0; 401 } 402 403 static const struct super_operations hfsplus_sops = { 404 .alloc_inode = hfsplus_alloc_inode, 405 .free_inode = hfsplus_free_inode, 406 .write_inode = hfsplus_write_inode, 407 .evict_inode = hfsplus_evict_inode, 408 .put_super = hfsplus_put_super, 409 .sync_fs = hfsplus_sync_fs, 410 .statfs = hfsplus_statfs, 411 .show_options = hfsplus_show_options, 412 }; 413 414 void hfsplus_prepare_volume_header_for_commit(struct hfsplus_vh *vhdr) 415 { 416 vhdr->last_mount_vers = cpu_to_be32(HFSP_MOUNT_VERSION); 417 vhdr->modify_date = hfsp_now2mt(); 418 be32_add_cpu(&vhdr->write_count, 1); 419 vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_UNMNT); 420 vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_INCNSTNT); 421 } 422 423 static int hfsplus_fill_super(struct super_block *sb, struct fs_context *fc) 424 { 425 struct hfsplus_vh *vhdr; 426 struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); 427 hfsplus_cat_entry entry; 428 struct hfs_find_data fd; 429 struct inode *root, *inode; 430 struct qstr str; 431 struct nls_table *nls; 432 u64 last_fs_block, last_fs_page; 433 int silent = fc->sb_flags & SB_SILENT; 434 int err; 435 436 mutex_init(&sbi->alloc_mutex); 437 mutex_init(&sbi->vh_mutex); 438 spin_lock_init(&sbi->work_lock); 439 INIT_DELAYED_WORK(&sbi->sync_work, delayed_sync_fs); 440 441 err = -EINVAL; 442 if (!sbi->nls) { 443 /* try utf8 first, as this is the old default behaviour */ 444 sbi->nls = load_nls("utf8"); 445 if (!sbi->nls) 446 sbi->nls = load_nls_default(); 447 } 448 449 /* temporarily use utf8 to correctly find the hidden dir below */ 450 nls = sbi->nls; 451 sbi->nls = load_nls("utf8"); 452 if (!sbi->nls) { 453 pr_err("unable to load nls for utf8\n"); 454 goto out_unload_nls; 455 } 456 457 /* Grab the volume header */ 458 if (hfsplus_read_wrapper(sb)) { 459 if (!silent) 460 pr_warn("unable to find HFS+ superblock\n"); 461 goto out_unload_nls; 462 } 463 vhdr = sbi->s_vhdr; 464 465 /* Copy parts of the volume header into the superblock */ 466 sb->s_magic = HFSPLUS_VOLHEAD_SIG; 467 if (be16_to_cpu(vhdr->version) < HFSPLUS_MIN_VERSION || 468 be16_to_cpu(vhdr->version) > HFSPLUS_CURRENT_VERSION) { 469 pr_err("wrong filesystem version\n"); 470 goto out_free_vhdr; 471 } 472 sbi->total_blocks = be32_to_cpu(vhdr->total_blocks); 473 sbi->free_blocks = be32_to_cpu(vhdr->free_blocks); 474 sbi->next_cnid = be32_to_cpu(vhdr->next_cnid); 475 sbi->file_count = be32_to_cpu(vhdr->file_count); 476 sbi->folder_count = be32_to_cpu(vhdr->folder_count); 477 sbi->data_clump_blocks = 478 be32_to_cpu(vhdr->data_clump_sz) >> sbi->alloc_blksz_shift; 479 if (!sbi->data_clump_blocks) 480 sbi->data_clump_blocks = 1; 481 sbi->rsrc_clump_blocks = 482 be32_to_cpu(vhdr->rsrc_clump_sz) >> sbi->alloc_blksz_shift; 483 if (!sbi->rsrc_clump_blocks) 484 sbi->rsrc_clump_blocks = 1; 485 486 err = -EFBIG; 487 last_fs_block = sbi->total_blocks - 1; 488 last_fs_page = (last_fs_block << sbi->alloc_blksz_shift) >> 489 PAGE_SHIFT; 490 491 if ((last_fs_block > (sector_t)(~0ULL) >> (sbi->alloc_blksz_shift - 9)) || 492 (last_fs_page > (pgoff_t)(~0ULL))) { 493 pr_err("filesystem size too large\n"); 494 goto out_free_vhdr; 495 } 496 497 /* Set up operations so we can load metadata */ 498 sb->s_op = &hfsplus_sops; 499 sb->s_maxbytes = MAX_LFS_FILESIZE; 500 501 if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { 502 pr_warn("Filesystem was not cleanly unmounted, running fsck.hfsplus is recommended. mounting read-only.\n"); 503 sb->s_flags |= SB_RDONLY; 504 } else if (test_and_clear_bit(HFSPLUS_SB_FORCE, &sbi->flags)) { 505 /* nothing */ 506 } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { 507 pr_warn("Filesystem is marked locked, mounting read-only.\n"); 508 sb->s_flags |= SB_RDONLY; 509 } else if ((vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) && 510 !sb_rdonly(sb)) { 511 pr_warn("write access to a journaled filesystem is not supported, use the force option at your own risk, mounting read-only.\n"); 512 sb->s_flags |= SB_RDONLY; 513 } 514 515 err = -EINVAL; 516 517 /* Load metadata objects (B*Trees) */ 518 sbi->ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID); 519 if (!sbi->ext_tree) { 520 pr_err("failed to load extents file\n"); 521 goto out_free_vhdr; 522 } 523 sbi->cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID); 524 if (!sbi->cat_tree) { 525 pr_err("failed to load catalog file\n"); 526 goto out_close_ext_tree; 527 } 528 atomic_set(&sbi->attr_tree_state, HFSPLUS_EMPTY_ATTR_TREE); 529 if (vhdr->attr_file.total_blocks != 0) { 530 sbi->attr_tree = hfs_btree_open(sb, HFSPLUS_ATTR_CNID); 531 if (!sbi->attr_tree) { 532 pr_err("failed to load attributes file\n"); 533 goto out_close_cat_tree; 534 } 535 atomic_set(&sbi->attr_tree_state, HFSPLUS_VALID_ATTR_TREE); 536 } 537 sb->s_xattr = hfsplus_xattr_handlers; 538 539 inode = hfsplus_iget(sb, HFSPLUS_ALLOC_CNID); 540 if (IS_ERR(inode)) { 541 pr_err("failed to load allocation file\n"); 542 err = PTR_ERR(inode); 543 goto out_close_attr_tree; 544 } 545 sbi->alloc_file = inode; 546 547 /* Load the root directory */ 548 root = hfsplus_iget(sb, HFSPLUS_ROOT_CNID); 549 if (IS_ERR(root)) { 550 pr_err("failed to load root directory\n"); 551 err = PTR_ERR(root); 552 goto out_put_alloc_file; 553 } 554 555 set_default_d_op(sb, &hfsplus_dentry_operations); 556 sb->s_root = d_make_root(root); 557 if (!sb->s_root) { 558 err = -ENOMEM; 559 goto out_put_alloc_file; 560 } 561 562 str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1; 563 str.name = HFSP_HIDDENDIR_NAME; 564 err = hfs_find_init(sbi->cat_tree, &fd); 565 if (err) 566 goto out_put_root; 567 err = hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_ROOT_CNID, &str); 568 if (unlikely(err < 0)) 569 goto out_put_root; 570 if (!hfs_brec_read(&fd, &entry, sizeof(entry))) { 571 hfs_find_exit(&fd); 572 if (entry.type != cpu_to_be16(HFSPLUS_FOLDER)) { 573 err = -EIO; 574 goto out_put_root; 575 } 576 inode = hfsplus_iget(sb, be32_to_cpu(entry.folder.id)); 577 if (IS_ERR(inode)) { 578 err = PTR_ERR(inode); 579 goto out_put_root; 580 } 581 sbi->hidden_dir = inode; 582 } else 583 hfs_find_exit(&fd); 584 585 if (!sb_rdonly(sb)) { 586 /* 587 * H+LX == hfsplusutils, H+Lx == this driver, H+lx is unused 588 * all three are registered with Apple for our use 589 */ 590 hfsplus_prepare_volume_header_for_commit(vhdr); 591 hfsplus_sync_fs(sb, 1); 592 593 if (!sbi->hidden_dir) { 594 mutex_lock(&sbi->vh_mutex); 595 sbi->hidden_dir = hfsplus_new_inode(sb, root, S_IFDIR); 596 if (!sbi->hidden_dir) { 597 mutex_unlock(&sbi->vh_mutex); 598 err = -ENOMEM; 599 goto out_put_root; 600 } 601 err = hfsplus_create_cat(sbi->hidden_dir->i_ino, root, 602 &str, sbi->hidden_dir); 603 if (err) { 604 mutex_unlock(&sbi->vh_mutex); 605 goto out_put_hidden_dir; 606 } 607 608 err = hfsplus_init_security(sbi->hidden_dir, 609 root, &str); 610 if (err == -EOPNOTSUPP) 611 err = 0; /* Operation is not supported. */ 612 else if (err) { 613 /* 614 * Try to delete anyway without 615 * error analysis. 616 */ 617 hfsplus_delete_cat(sbi->hidden_dir->i_ino, 618 root, &str); 619 mutex_unlock(&sbi->vh_mutex); 620 goto out_put_hidden_dir; 621 } 622 623 mutex_unlock(&sbi->vh_mutex); 624 hfsplus_mark_inode_dirty(sbi->hidden_dir, 625 HFSPLUS_I_CAT_DIRTY); 626 } 627 } 628 629 unload_nls(sbi->nls); 630 sbi->nls = nls; 631 return 0; 632 633 out_put_hidden_dir: 634 cancel_delayed_work_sync(&sbi->sync_work); 635 iput(sbi->hidden_dir); 636 out_put_root: 637 dput(sb->s_root); 638 sb->s_root = NULL; 639 out_put_alloc_file: 640 iput(sbi->alloc_file); 641 out_close_attr_tree: 642 hfs_btree_close(sbi->attr_tree); 643 out_close_cat_tree: 644 hfs_btree_close(sbi->cat_tree); 645 out_close_ext_tree: 646 hfs_btree_close(sbi->ext_tree); 647 out_free_vhdr: 648 kfree(sbi->s_vhdr_buf); 649 kfree(sbi->s_backup_vhdr_buf); 650 out_unload_nls: 651 unload_nls(sbi->nls); 652 unload_nls(nls); 653 kfree(sbi); 654 return err; 655 } 656 657 MODULE_AUTHOR("Brad Boyer"); 658 MODULE_DESCRIPTION("Extended Macintosh Filesystem"); 659 MODULE_LICENSE("GPL"); 660 661 static struct kmem_cache *hfsplus_inode_cachep; 662 663 static struct inode *hfsplus_alloc_inode(struct super_block *sb) 664 { 665 struct hfsplus_inode_info *i; 666 667 i = alloc_inode_sb(sb, hfsplus_inode_cachep, GFP_KERNEL); 668 return i ? &i->vfs_inode : NULL; 669 } 670 671 static void hfsplus_free_inode(struct inode *inode) 672 { 673 kmem_cache_free(hfsplus_inode_cachep, HFSPLUS_I(inode)); 674 } 675 676 #define HFSPLUS_INODE_SIZE sizeof(struct hfsplus_inode_info) 677 678 static int hfsplus_get_tree(struct fs_context *fc) 679 { 680 return get_tree_bdev(fc, hfsplus_fill_super); 681 } 682 683 static void hfsplus_free_fc(struct fs_context *fc) 684 { 685 kfree(fc->s_fs_info); 686 } 687 688 static const struct fs_context_operations hfsplus_context_ops = { 689 .parse_param = hfsplus_parse_param, 690 .get_tree = hfsplus_get_tree, 691 .reconfigure = hfsplus_reconfigure, 692 .free = hfsplus_free_fc, 693 }; 694 695 static int hfsplus_init_fs_context(struct fs_context *fc) 696 { 697 struct hfsplus_sb_info *sbi; 698 699 sbi = kzalloc(sizeof(struct hfsplus_sb_info), GFP_KERNEL); 700 if (!sbi) 701 return -ENOMEM; 702 703 if (fc->purpose != FS_CONTEXT_FOR_RECONFIGURE) 704 hfsplus_fill_defaults(sbi); 705 706 fc->s_fs_info = sbi; 707 fc->ops = &hfsplus_context_ops; 708 709 return 0; 710 } 711 712 static struct file_system_type hfsplus_fs_type = { 713 .owner = THIS_MODULE, 714 .name = "hfsplus", 715 .kill_sb = kill_block_super, 716 .fs_flags = FS_REQUIRES_DEV, 717 .init_fs_context = hfsplus_init_fs_context, 718 }; 719 MODULE_ALIAS_FS("hfsplus"); 720 721 static void hfsplus_init_once(void *p) 722 { 723 struct hfsplus_inode_info *i = p; 724 725 inode_init_once(&i->vfs_inode); 726 } 727 728 static int __init init_hfsplus_fs(void) 729 { 730 int err; 731 732 hfsplus_inode_cachep = kmem_cache_create("hfsplus_icache", 733 HFSPLUS_INODE_SIZE, 0, SLAB_HWCACHE_ALIGN|SLAB_ACCOUNT, 734 hfsplus_init_once); 735 if (!hfsplus_inode_cachep) 736 return -ENOMEM; 737 err = hfsplus_create_attr_tree_cache(); 738 if (err) 739 goto destroy_inode_cache; 740 err = register_filesystem(&hfsplus_fs_type); 741 if (err) 742 goto destroy_attr_tree_cache; 743 return 0; 744 745 destroy_attr_tree_cache: 746 hfsplus_destroy_attr_tree_cache(); 747 748 destroy_inode_cache: 749 kmem_cache_destroy(hfsplus_inode_cachep); 750 751 return err; 752 } 753 754 static void __exit exit_hfsplus_fs(void) 755 { 756 unregister_filesystem(&hfsplus_fs_type); 757 758 /* 759 * Make sure all delayed rcu free inodes are flushed before we 760 * destroy cache. 761 */ 762 rcu_barrier(); 763 hfsplus_destroy_attr_tree_cache(); 764 kmem_cache_destroy(hfsplus_inode_cachep); 765 } 766 767 module_init(init_hfsplus_fs) 768 module_exit(exit_hfsplus_fs) 769