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