162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * linux/fs/hfs/inode.c 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 1995-1997 Paul H. Hargrove 562306a36Sopenharmony_ci * (C) 2003 Ardis Technologies <roman@ardistech.com> 662306a36Sopenharmony_ci * This file may be distributed under the terms of the GNU General Public License. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * This file contains inode-related functions which do not depend on 962306a36Sopenharmony_ci * which scheme is being used to represent forks. 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * Based on the minix file system code, (C) 1991, 1992 by Linus Torvalds 1262306a36Sopenharmony_ci */ 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <linux/pagemap.h> 1562306a36Sopenharmony_ci#include <linux/mpage.h> 1662306a36Sopenharmony_ci#include <linux/sched.h> 1762306a36Sopenharmony_ci#include <linux/cred.h> 1862306a36Sopenharmony_ci#include <linux/uio.h> 1962306a36Sopenharmony_ci#include <linux/xattr.h> 2062306a36Sopenharmony_ci#include <linux/blkdev.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include "hfs_fs.h" 2362306a36Sopenharmony_ci#include "btree.h" 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic const struct file_operations hfs_file_operations; 2662306a36Sopenharmony_cistatic const struct inode_operations hfs_file_inode_operations; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci/*================ Variable-like macros ================*/ 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define HFS_VALID_MODE_BITS (S_IFREG | S_IFDIR | S_IRWXUGO) 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistatic int hfs_writepage(struct page *page, struct writeback_control *wbc) 3362306a36Sopenharmony_ci{ 3462306a36Sopenharmony_ci return block_write_full_page(page, hfs_get_block, wbc); 3562306a36Sopenharmony_ci} 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistatic int hfs_read_folio(struct file *file, struct folio *folio) 3862306a36Sopenharmony_ci{ 3962306a36Sopenharmony_ci return block_read_full_folio(folio, hfs_get_block); 4062306a36Sopenharmony_ci} 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic void hfs_write_failed(struct address_space *mapping, loff_t to) 4362306a36Sopenharmony_ci{ 4462306a36Sopenharmony_ci struct inode *inode = mapping->host; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci if (to > inode->i_size) { 4762306a36Sopenharmony_ci truncate_pagecache(inode, inode->i_size); 4862306a36Sopenharmony_ci hfs_file_truncate(inode); 4962306a36Sopenharmony_ci } 5062306a36Sopenharmony_ci} 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ciint hfs_write_begin(struct file *file, struct address_space *mapping, 5362306a36Sopenharmony_ci loff_t pos, unsigned len, struct page **pagep, void **fsdata) 5462306a36Sopenharmony_ci{ 5562306a36Sopenharmony_ci int ret; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci *pagep = NULL; 5862306a36Sopenharmony_ci ret = cont_write_begin(file, mapping, pos, len, pagep, fsdata, 5962306a36Sopenharmony_ci hfs_get_block, 6062306a36Sopenharmony_ci &HFS_I(mapping->host)->phys_size); 6162306a36Sopenharmony_ci if (unlikely(ret)) 6262306a36Sopenharmony_ci hfs_write_failed(mapping, pos + len); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci return ret; 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistatic sector_t hfs_bmap(struct address_space *mapping, sector_t block) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci return generic_block_bmap(mapping, block, hfs_get_block); 7062306a36Sopenharmony_ci} 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_cistatic bool hfs_release_folio(struct folio *folio, gfp_t mask) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci struct inode *inode = folio->mapping->host; 7562306a36Sopenharmony_ci struct super_block *sb = inode->i_sb; 7662306a36Sopenharmony_ci struct hfs_btree *tree; 7762306a36Sopenharmony_ci struct hfs_bnode *node; 7862306a36Sopenharmony_ci u32 nidx; 7962306a36Sopenharmony_ci int i; 8062306a36Sopenharmony_ci bool res = true; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci switch (inode->i_ino) { 8362306a36Sopenharmony_ci case HFS_EXT_CNID: 8462306a36Sopenharmony_ci tree = HFS_SB(sb)->ext_tree; 8562306a36Sopenharmony_ci break; 8662306a36Sopenharmony_ci case HFS_CAT_CNID: 8762306a36Sopenharmony_ci tree = HFS_SB(sb)->cat_tree; 8862306a36Sopenharmony_ci break; 8962306a36Sopenharmony_ci default: 9062306a36Sopenharmony_ci BUG(); 9162306a36Sopenharmony_ci return false; 9262306a36Sopenharmony_ci } 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci if (!tree) 9562306a36Sopenharmony_ci return false; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci if (tree->node_size >= PAGE_SIZE) { 9862306a36Sopenharmony_ci nidx = folio->index >> (tree->node_size_shift - PAGE_SHIFT); 9962306a36Sopenharmony_ci spin_lock(&tree->hash_lock); 10062306a36Sopenharmony_ci node = hfs_bnode_findhash(tree, nidx); 10162306a36Sopenharmony_ci if (!node) 10262306a36Sopenharmony_ci ; 10362306a36Sopenharmony_ci else if (atomic_read(&node->refcnt)) 10462306a36Sopenharmony_ci res = false; 10562306a36Sopenharmony_ci if (res && node) { 10662306a36Sopenharmony_ci hfs_bnode_unhash(node); 10762306a36Sopenharmony_ci hfs_bnode_free(node); 10862306a36Sopenharmony_ci } 10962306a36Sopenharmony_ci spin_unlock(&tree->hash_lock); 11062306a36Sopenharmony_ci } else { 11162306a36Sopenharmony_ci nidx = folio->index << (PAGE_SHIFT - tree->node_size_shift); 11262306a36Sopenharmony_ci i = 1 << (PAGE_SHIFT - tree->node_size_shift); 11362306a36Sopenharmony_ci spin_lock(&tree->hash_lock); 11462306a36Sopenharmony_ci do { 11562306a36Sopenharmony_ci node = hfs_bnode_findhash(tree, nidx++); 11662306a36Sopenharmony_ci if (!node) 11762306a36Sopenharmony_ci continue; 11862306a36Sopenharmony_ci if (atomic_read(&node->refcnt)) { 11962306a36Sopenharmony_ci res = false; 12062306a36Sopenharmony_ci break; 12162306a36Sopenharmony_ci } 12262306a36Sopenharmony_ci hfs_bnode_unhash(node); 12362306a36Sopenharmony_ci hfs_bnode_free(node); 12462306a36Sopenharmony_ci } while (--i && nidx < tree->node_count); 12562306a36Sopenharmony_ci spin_unlock(&tree->hash_lock); 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci return res ? try_to_free_buffers(folio) : false; 12862306a36Sopenharmony_ci} 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cistatic ssize_t hfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) 13162306a36Sopenharmony_ci{ 13262306a36Sopenharmony_ci struct file *file = iocb->ki_filp; 13362306a36Sopenharmony_ci struct address_space *mapping = file->f_mapping; 13462306a36Sopenharmony_ci struct inode *inode = mapping->host; 13562306a36Sopenharmony_ci size_t count = iov_iter_count(iter); 13662306a36Sopenharmony_ci ssize_t ret; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci ret = blockdev_direct_IO(iocb, inode, iter, hfs_get_block); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci /* 14162306a36Sopenharmony_ci * In case of error extending write may have instantiated a few 14262306a36Sopenharmony_ci * blocks outside i_size. Trim these off again. 14362306a36Sopenharmony_ci */ 14462306a36Sopenharmony_ci if (unlikely(iov_iter_rw(iter) == WRITE && ret < 0)) { 14562306a36Sopenharmony_ci loff_t isize = i_size_read(inode); 14662306a36Sopenharmony_ci loff_t end = iocb->ki_pos + count; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci if (end > isize) 14962306a36Sopenharmony_ci hfs_write_failed(mapping, end); 15062306a36Sopenharmony_ci } 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci return ret; 15362306a36Sopenharmony_ci} 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_cistatic int hfs_writepages(struct address_space *mapping, 15662306a36Sopenharmony_ci struct writeback_control *wbc) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci return mpage_writepages(mapping, wbc, hfs_get_block); 15962306a36Sopenharmony_ci} 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ciconst struct address_space_operations hfs_btree_aops = { 16262306a36Sopenharmony_ci .dirty_folio = block_dirty_folio, 16362306a36Sopenharmony_ci .invalidate_folio = block_invalidate_folio, 16462306a36Sopenharmony_ci .read_folio = hfs_read_folio, 16562306a36Sopenharmony_ci .writepage = hfs_writepage, 16662306a36Sopenharmony_ci .write_begin = hfs_write_begin, 16762306a36Sopenharmony_ci .write_end = generic_write_end, 16862306a36Sopenharmony_ci .bmap = hfs_bmap, 16962306a36Sopenharmony_ci .release_folio = hfs_release_folio, 17062306a36Sopenharmony_ci}; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ciconst struct address_space_operations hfs_aops = { 17362306a36Sopenharmony_ci .dirty_folio = block_dirty_folio, 17462306a36Sopenharmony_ci .invalidate_folio = block_invalidate_folio, 17562306a36Sopenharmony_ci .read_folio = hfs_read_folio, 17662306a36Sopenharmony_ci .write_begin = hfs_write_begin, 17762306a36Sopenharmony_ci .write_end = generic_write_end, 17862306a36Sopenharmony_ci .bmap = hfs_bmap, 17962306a36Sopenharmony_ci .direct_IO = hfs_direct_IO, 18062306a36Sopenharmony_ci .writepages = hfs_writepages, 18162306a36Sopenharmony_ci .migrate_folio = buffer_migrate_folio, 18262306a36Sopenharmony_ci}; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci/* 18562306a36Sopenharmony_ci * hfs_new_inode 18662306a36Sopenharmony_ci */ 18762306a36Sopenharmony_cistruct inode *hfs_new_inode(struct inode *dir, const struct qstr *name, umode_t mode) 18862306a36Sopenharmony_ci{ 18962306a36Sopenharmony_ci struct super_block *sb = dir->i_sb; 19062306a36Sopenharmony_ci struct inode *inode = new_inode(sb); 19162306a36Sopenharmony_ci if (!inode) 19262306a36Sopenharmony_ci return NULL; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci mutex_init(&HFS_I(inode)->extents_lock); 19562306a36Sopenharmony_ci INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list); 19662306a36Sopenharmony_ci spin_lock_init(&HFS_I(inode)->open_dir_lock); 19762306a36Sopenharmony_ci hfs_cat_build_key(sb, (btree_key *)&HFS_I(inode)->cat_key, dir->i_ino, name); 19862306a36Sopenharmony_ci inode->i_ino = HFS_SB(sb)->next_id++; 19962306a36Sopenharmony_ci inode->i_mode = mode; 20062306a36Sopenharmony_ci inode->i_uid = current_fsuid(); 20162306a36Sopenharmony_ci inode->i_gid = current_fsgid(); 20262306a36Sopenharmony_ci set_nlink(inode, 1); 20362306a36Sopenharmony_ci inode->i_mtime = inode->i_atime = inode_set_ctime_current(inode); 20462306a36Sopenharmony_ci HFS_I(inode)->flags = 0; 20562306a36Sopenharmony_ci HFS_I(inode)->rsrc_inode = NULL; 20662306a36Sopenharmony_ci HFS_I(inode)->fs_blocks = 0; 20762306a36Sopenharmony_ci if (S_ISDIR(mode)) { 20862306a36Sopenharmony_ci inode->i_size = 2; 20962306a36Sopenharmony_ci HFS_SB(sb)->folder_count++; 21062306a36Sopenharmony_ci if (dir->i_ino == HFS_ROOT_CNID) 21162306a36Sopenharmony_ci HFS_SB(sb)->root_dirs++; 21262306a36Sopenharmony_ci inode->i_op = &hfs_dir_inode_operations; 21362306a36Sopenharmony_ci inode->i_fop = &hfs_dir_operations; 21462306a36Sopenharmony_ci inode->i_mode |= S_IRWXUGO; 21562306a36Sopenharmony_ci inode->i_mode &= ~HFS_SB(inode->i_sb)->s_dir_umask; 21662306a36Sopenharmony_ci } else if (S_ISREG(mode)) { 21762306a36Sopenharmony_ci HFS_I(inode)->clump_blocks = HFS_SB(sb)->clumpablks; 21862306a36Sopenharmony_ci HFS_SB(sb)->file_count++; 21962306a36Sopenharmony_ci if (dir->i_ino == HFS_ROOT_CNID) 22062306a36Sopenharmony_ci HFS_SB(sb)->root_files++; 22162306a36Sopenharmony_ci inode->i_op = &hfs_file_inode_operations; 22262306a36Sopenharmony_ci inode->i_fop = &hfs_file_operations; 22362306a36Sopenharmony_ci inode->i_mapping->a_ops = &hfs_aops; 22462306a36Sopenharmony_ci inode->i_mode |= S_IRUGO|S_IXUGO; 22562306a36Sopenharmony_ci if (mode & S_IWUSR) 22662306a36Sopenharmony_ci inode->i_mode |= S_IWUGO; 22762306a36Sopenharmony_ci inode->i_mode &= ~HFS_SB(inode->i_sb)->s_file_umask; 22862306a36Sopenharmony_ci HFS_I(inode)->phys_size = 0; 22962306a36Sopenharmony_ci HFS_I(inode)->alloc_blocks = 0; 23062306a36Sopenharmony_ci HFS_I(inode)->first_blocks = 0; 23162306a36Sopenharmony_ci HFS_I(inode)->cached_start = 0; 23262306a36Sopenharmony_ci HFS_I(inode)->cached_blocks = 0; 23362306a36Sopenharmony_ci memset(HFS_I(inode)->first_extents, 0, sizeof(hfs_extent_rec)); 23462306a36Sopenharmony_ci memset(HFS_I(inode)->cached_extents, 0, sizeof(hfs_extent_rec)); 23562306a36Sopenharmony_ci } 23662306a36Sopenharmony_ci insert_inode_hash(inode); 23762306a36Sopenharmony_ci mark_inode_dirty(inode); 23862306a36Sopenharmony_ci set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags); 23962306a36Sopenharmony_ci hfs_mark_mdb_dirty(sb); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci return inode; 24262306a36Sopenharmony_ci} 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_civoid hfs_delete_inode(struct inode *inode) 24562306a36Sopenharmony_ci{ 24662306a36Sopenharmony_ci struct super_block *sb = inode->i_sb; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci hfs_dbg(INODE, "delete_inode: %lu\n", inode->i_ino); 24962306a36Sopenharmony_ci if (S_ISDIR(inode->i_mode)) { 25062306a36Sopenharmony_ci HFS_SB(sb)->folder_count--; 25162306a36Sopenharmony_ci if (HFS_I(inode)->cat_key.ParID == cpu_to_be32(HFS_ROOT_CNID)) 25262306a36Sopenharmony_ci HFS_SB(sb)->root_dirs--; 25362306a36Sopenharmony_ci set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags); 25462306a36Sopenharmony_ci hfs_mark_mdb_dirty(sb); 25562306a36Sopenharmony_ci return; 25662306a36Sopenharmony_ci } 25762306a36Sopenharmony_ci HFS_SB(sb)->file_count--; 25862306a36Sopenharmony_ci if (HFS_I(inode)->cat_key.ParID == cpu_to_be32(HFS_ROOT_CNID)) 25962306a36Sopenharmony_ci HFS_SB(sb)->root_files--; 26062306a36Sopenharmony_ci if (S_ISREG(inode->i_mode)) { 26162306a36Sopenharmony_ci if (!inode->i_nlink) { 26262306a36Sopenharmony_ci inode->i_size = 0; 26362306a36Sopenharmony_ci hfs_file_truncate(inode); 26462306a36Sopenharmony_ci } 26562306a36Sopenharmony_ci } 26662306a36Sopenharmony_ci set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags); 26762306a36Sopenharmony_ci hfs_mark_mdb_dirty(sb); 26862306a36Sopenharmony_ci} 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_civoid hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext, 27162306a36Sopenharmony_ci __be32 __log_size, __be32 phys_size, u32 clump_size) 27262306a36Sopenharmony_ci{ 27362306a36Sopenharmony_ci struct super_block *sb = inode->i_sb; 27462306a36Sopenharmony_ci u32 log_size = be32_to_cpu(__log_size); 27562306a36Sopenharmony_ci u16 count; 27662306a36Sopenharmony_ci int i; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci memcpy(HFS_I(inode)->first_extents, ext, sizeof(hfs_extent_rec)); 27962306a36Sopenharmony_ci for (count = 0, i = 0; i < 3; i++) 28062306a36Sopenharmony_ci count += be16_to_cpu(ext[i].count); 28162306a36Sopenharmony_ci HFS_I(inode)->first_blocks = count; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci inode->i_size = HFS_I(inode)->phys_size = log_size; 28462306a36Sopenharmony_ci HFS_I(inode)->fs_blocks = (log_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits; 28562306a36Sopenharmony_ci inode_set_bytes(inode, HFS_I(inode)->fs_blocks << sb->s_blocksize_bits); 28662306a36Sopenharmony_ci HFS_I(inode)->alloc_blocks = be32_to_cpu(phys_size) / 28762306a36Sopenharmony_ci HFS_SB(sb)->alloc_blksz; 28862306a36Sopenharmony_ci HFS_I(inode)->clump_blocks = clump_size / HFS_SB(sb)->alloc_blksz; 28962306a36Sopenharmony_ci if (!HFS_I(inode)->clump_blocks) 29062306a36Sopenharmony_ci HFS_I(inode)->clump_blocks = HFS_SB(sb)->clumpablks; 29162306a36Sopenharmony_ci} 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_cistruct hfs_iget_data { 29462306a36Sopenharmony_ci struct hfs_cat_key *key; 29562306a36Sopenharmony_ci hfs_cat_rec *rec; 29662306a36Sopenharmony_ci}; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_cistatic int hfs_test_inode(struct inode *inode, void *data) 29962306a36Sopenharmony_ci{ 30062306a36Sopenharmony_ci struct hfs_iget_data *idata = data; 30162306a36Sopenharmony_ci hfs_cat_rec *rec; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci rec = idata->rec; 30462306a36Sopenharmony_ci switch (rec->type) { 30562306a36Sopenharmony_ci case HFS_CDR_DIR: 30662306a36Sopenharmony_ci return inode->i_ino == be32_to_cpu(rec->dir.DirID); 30762306a36Sopenharmony_ci case HFS_CDR_FIL: 30862306a36Sopenharmony_ci return inode->i_ino == be32_to_cpu(rec->file.FlNum); 30962306a36Sopenharmony_ci default: 31062306a36Sopenharmony_ci BUG(); 31162306a36Sopenharmony_ci return 1; 31262306a36Sopenharmony_ci } 31362306a36Sopenharmony_ci} 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci/* 31662306a36Sopenharmony_ci * hfs_read_inode 31762306a36Sopenharmony_ci */ 31862306a36Sopenharmony_cistatic int hfs_read_inode(struct inode *inode, void *data) 31962306a36Sopenharmony_ci{ 32062306a36Sopenharmony_ci struct hfs_iget_data *idata = data; 32162306a36Sopenharmony_ci struct hfs_sb_info *hsb = HFS_SB(inode->i_sb); 32262306a36Sopenharmony_ci hfs_cat_rec *rec; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci HFS_I(inode)->flags = 0; 32562306a36Sopenharmony_ci HFS_I(inode)->rsrc_inode = NULL; 32662306a36Sopenharmony_ci mutex_init(&HFS_I(inode)->extents_lock); 32762306a36Sopenharmony_ci INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list); 32862306a36Sopenharmony_ci spin_lock_init(&HFS_I(inode)->open_dir_lock); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci /* Initialize the inode */ 33162306a36Sopenharmony_ci inode->i_uid = hsb->s_uid; 33262306a36Sopenharmony_ci inode->i_gid = hsb->s_gid; 33362306a36Sopenharmony_ci set_nlink(inode, 1); 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci if (idata->key) 33662306a36Sopenharmony_ci HFS_I(inode)->cat_key = *idata->key; 33762306a36Sopenharmony_ci else 33862306a36Sopenharmony_ci HFS_I(inode)->flags |= HFS_FLG_RSRC; 33962306a36Sopenharmony_ci HFS_I(inode)->tz_secondswest = sys_tz.tz_minuteswest * 60; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci rec = idata->rec; 34262306a36Sopenharmony_ci switch (rec->type) { 34362306a36Sopenharmony_ci case HFS_CDR_FIL: 34462306a36Sopenharmony_ci if (!HFS_IS_RSRC(inode)) { 34562306a36Sopenharmony_ci hfs_inode_read_fork(inode, rec->file.ExtRec, rec->file.LgLen, 34662306a36Sopenharmony_ci rec->file.PyLen, be16_to_cpu(rec->file.ClpSize)); 34762306a36Sopenharmony_ci } else { 34862306a36Sopenharmony_ci hfs_inode_read_fork(inode, rec->file.RExtRec, rec->file.RLgLen, 34962306a36Sopenharmony_ci rec->file.RPyLen, be16_to_cpu(rec->file.ClpSize)); 35062306a36Sopenharmony_ci } 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci inode->i_ino = be32_to_cpu(rec->file.FlNum); 35362306a36Sopenharmony_ci inode->i_mode = S_IRUGO | S_IXUGO; 35462306a36Sopenharmony_ci if (!(rec->file.Flags & HFS_FIL_LOCK)) 35562306a36Sopenharmony_ci inode->i_mode |= S_IWUGO; 35662306a36Sopenharmony_ci inode->i_mode &= ~hsb->s_file_umask; 35762306a36Sopenharmony_ci inode->i_mode |= S_IFREG; 35862306a36Sopenharmony_ci inode->i_atime = inode->i_mtime = inode_set_ctime_to_ts(inode, 35962306a36Sopenharmony_ci hfs_m_to_utime(rec->file.MdDat)); 36062306a36Sopenharmony_ci inode->i_op = &hfs_file_inode_operations; 36162306a36Sopenharmony_ci inode->i_fop = &hfs_file_operations; 36262306a36Sopenharmony_ci inode->i_mapping->a_ops = &hfs_aops; 36362306a36Sopenharmony_ci break; 36462306a36Sopenharmony_ci case HFS_CDR_DIR: 36562306a36Sopenharmony_ci inode->i_ino = be32_to_cpu(rec->dir.DirID); 36662306a36Sopenharmony_ci inode->i_size = be16_to_cpu(rec->dir.Val) + 2; 36762306a36Sopenharmony_ci HFS_I(inode)->fs_blocks = 0; 36862306a36Sopenharmony_ci inode->i_mode = S_IFDIR | (S_IRWXUGO & ~hsb->s_dir_umask); 36962306a36Sopenharmony_ci inode->i_atime = inode->i_mtime = inode_set_ctime_to_ts(inode, 37062306a36Sopenharmony_ci hfs_m_to_utime(rec->dir.MdDat)); 37162306a36Sopenharmony_ci inode->i_op = &hfs_dir_inode_operations; 37262306a36Sopenharmony_ci inode->i_fop = &hfs_dir_operations; 37362306a36Sopenharmony_ci break; 37462306a36Sopenharmony_ci default: 37562306a36Sopenharmony_ci make_bad_inode(inode); 37662306a36Sopenharmony_ci } 37762306a36Sopenharmony_ci return 0; 37862306a36Sopenharmony_ci} 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci/* 38162306a36Sopenharmony_ci * __hfs_iget() 38262306a36Sopenharmony_ci * 38362306a36Sopenharmony_ci * Given the MDB for a HFS filesystem, a 'key' and an 'entry' in 38462306a36Sopenharmony_ci * the catalog B-tree and the 'type' of the desired file return the 38562306a36Sopenharmony_ci * inode for that file/directory or NULL. Note that 'type' indicates 38662306a36Sopenharmony_ci * whether we want the actual file or directory, or the corresponding 38762306a36Sopenharmony_ci * metadata (AppleDouble header file or CAP metadata file). 38862306a36Sopenharmony_ci */ 38962306a36Sopenharmony_cistruct inode *hfs_iget(struct super_block *sb, struct hfs_cat_key *key, hfs_cat_rec *rec) 39062306a36Sopenharmony_ci{ 39162306a36Sopenharmony_ci struct hfs_iget_data data = { key, rec }; 39262306a36Sopenharmony_ci struct inode *inode; 39362306a36Sopenharmony_ci u32 cnid; 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci switch (rec->type) { 39662306a36Sopenharmony_ci case HFS_CDR_DIR: 39762306a36Sopenharmony_ci cnid = be32_to_cpu(rec->dir.DirID); 39862306a36Sopenharmony_ci break; 39962306a36Sopenharmony_ci case HFS_CDR_FIL: 40062306a36Sopenharmony_ci cnid = be32_to_cpu(rec->file.FlNum); 40162306a36Sopenharmony_ci break; 40262306a36Sopenharmony_ci default: 40362306a36Sopenharmony_ci return NULL; 40462306a36Sopenharmony_ci } 40562306a36Sopenharmony_ci inode = iget5_locked(sb, cnid, hfs_test_inode, hfs_read_inode, &data); 40662306a36Sopenharmony_ci if (inode && (inode->i_state & I_NEW)) 40762306a36Sopenharmony_ci unlock_new_inode(inode); 40862306a36Sopenharmony_ci return inode; 40962306a36Sopenharmony_ci} 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_civoid hfs_inode_write_fork(struct inode *inode, struct hfs_extent *ext, 41262306a36Sopenharmony_ci __be32 *log_size, __be32 *phys_size) 41362306a36Sopenharmony_ci{ 41462306a36Sopenharmony_ci memcpy(ext, HFS_I(inode)->first_extents, sizeof(hfs_extent_rec)); 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci if (log_size) 41762306a36Sopenharmony_ci *log_size = cpu_to_be32(inode->i_size); 41862306a36Sopenharmony_ci if (phys_size) 41962306a36Sopenharmony_ci *phys_size = cpu_to_be32(HFS_I(inode)->alloc_blocks * 42062306a36Sopenharmony_ci HFS_SB(inode->i_sb)->alloc_blksz); 42162306a36Sopenharmony_ci} 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ciint hfs_write_inode(struct inode *inode, struct writeback_control *wbc) 42462306a36Sopenharmony_ci{ 42562306a36Sopenharmony_ci struct inode *main_inode = inode; 42662306a36Sopenharmony_ci struct hfs_find_data fd; 42762306a36Sopenharmony_ci hfs_cat_rec rec; 42862306a36Sopenharmony_ci int res; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci hfs_dbg(INODE, "hfs_write_inode: %lu\n", inode->i_ino); 43162306a36Sopenharmony_ci res = hfs_ext_write_extent(inode); 43262306a36Sopenharmony_ci if (res) 43362306a36Sopenharmony_ci return res; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci if (inode->i_ino < HFS_FIRSTUSER_CNID) { 43662306a36Sopenharmony_ci switch (inode->i_ino) { 43762306a36Sopenharmony_ci case HFS_ROOT_CNID: 43862306a36Sopenharmony_ci break; 43962306a36Sopenharmony_ci case HFS_EXT_CNID: 44062306a36Sopenharmony_ci hfs_btree_write(HFS_SB(inode->i_sb)->ext_tree); 44162306a36Sopenharmony_ci return 0; 44262306a36Sopenharmony_ci case HFS_CAT_CNID: 44362306a36Sopenharmony_ci hfs_btree_write(HFS_SB(inode->i_sb)->cat_tree); 44462306a36Sopenharmony_ci return 0; 44562306a36Sopenharmony_ci default: 44662306a36Sopenharmony_ci BUG(); 44762306a36Sopenharmony_ci return -EIO; 44862306a36Sopenharmony_ci } 44962306a36Sopenharmony_ci } 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci if (HFS_IS_RSRC(inode)) 45262306a36Sopenharmony_ci main_inode = HFS_I(inode)->rsrc_inode; 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci if (!main_inode->i_nlink) 45562306a36Sopenharmony_ci return 0; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci if (hfs_find_init(HFS_SB(main_inode->i_sb)->cat_tree, &fd)) 45862306a36Sopenharmony_ci /* panic? */ 45962306a36Sopenharmony_ci return -EIO; 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci res = -EIO; 46262306a36Sopenharmony_ci if (HFS_I(main_inode)->cat_key.CName.len > HFS_NAMELEN) 46362306a36Sopenharmony_ci goto out; 46462306a36Sopenharmony_ci fd.search_key->cat = HFS_I(main_inode)->cat_key; 46562306a36Sopenharmony_ci if (hfs_brec_find(&fd)) 46662306a36Sopenharmony_ci goto out; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci if (S_ISDIR(main_inode->i_mode)) { 46962306a36Sopenharmony_ci if (fd.entrylength < sizeof(struct hfs_cat_dir)) 47062306a36Sopenharmony_ci goto out; 47162306a36Sopenharmony_ci hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, 47262306a36Sopenharmony_ci sizeof(struct hfs_cat_dir)); 47362306a36Sopenharmony_ci if (rec.type != HFS_CDR_DIR || 47462306a36Sopenharmony_ci be32_to_cpu(rec.dir.DirID) != inode->i_ino) { 47562306a36Sopenharmony_ci } 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci rec.dir.MdDat = hfs_u_to_mtime(inode->i_mtime); 47862306a36Sopenharmony_ci rec.dir.Val = cpu_to_be16(inode->i_size - 2); 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci hfs_bnode_write(fd.bnode, &rec, fd.entryoffset, 48162306a36Sopenharmony_ci sizeof(struct hfs_cat_dir)); 48262306a36Sopenharmony_ci } else if (HFS_IS_RSRC(inode)) { 48362306a36Sopenharmony_ci if (fd.entrylength < sizeof(struct hfs_cat_file)) 48462306a36Sopenharmony_ci goto out; 48562306a36Sopenharmony_ci hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, 48662306a36Sopenharmony_ci sizeof(struct hfs_cat_file)); 48762306a36Sopenharmony_ci hfs_inode_write_fork(inode, rec.file.RExtRec, 48862306a36Sopenharmony_ci &rec.file.RLgLen, &rec.file.RPyLen); 48962306a36Sopenharmony_ci hfs_bnode_write(fd.bnode, &rec, fd.entryoffset, 49062306a36Sopenharmony_ci sizeof(struct hfs_cat_file)); 49162306a36Sopenharmony_ci } else { 49262306a36Sopenharmony_ci if (fd.entrylength < sizeof(struct hfs_cat_file)) 49362306a36Sopenharmony_ci goto out; 49462306a36Sopenharmony_ci hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, 49562306a36Sopenharmony_ci sizeof(struct hfs_cat_file)); 49662306a36Sopenharmony_ci if (rec.type != HFS_CDR_FIL || 49762306a36Sopenharmony_ci be32_to_cpu(rec.file.FlNum) != inode->i_ino) { 49862306a36Sopenharmony_ci } 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci if (inode->i_mode & S_IWUSR) 50162306a36Sopenharmony_ci rec.file.Flags &= ~HFS_FIL_LOCK; 50262306a36Sopenharmony_ci else 50362306a36Sopenharmony_ci rec.file.Flags |= HFS_FIL_LOCK; 50462306a36Sopenharmony_ci hfs_inode_write_fork(inode, rec.file.ExtRec, &rec.file.LgLen, &rec.file.PyLen); 50562306a36Sopenharmony_ci rec.file.MdDat = hfs_u_to_mtime(inode->i_mtime); 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci hfs_bnode_write(fd.bnode, &rec, fd.entryoffset, 50862306a36Sopenharmony_ci sizeof(struct hfs_cat_file)); 50962306a36Sopenharmony_ci } 51062306a36Sopenharmony_ci res = 0; 51162306a36Sopenharmony_ciout: 51262306a36Sopenharmony_ci hfs_find_exit(&fd); 51362306a36Sopenharmony_ci return res; 51462306a36Sopenharmony_ci} 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_cistatic struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry, 51762306a36Sopenharmony_ci unsigned int flags) 51862306a36Sopenharmony_ci{ 51962306a36Sopenharmony_ci struct inode *inode = NULL; 52062306a36Sopenharmony_ci hfs_cat_rec rec; 52162306a36Sopenharmony_ci struct hfs_find_data fd; 52262306a36Sopenharmony_ci int res; 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci if (HFS_IS_RSRC(dir) || strcmp(dentry->d_name.name, "rsrc")) 52562306a36Sopenharmony_ci goto out; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci inode = HFS_I(dir)->rsrc_inode; 52862306a36Sopenharmony_ci if (inode) 52962306a36Sopenharmony_ci goto out; 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci inode = new_inode(dir->i_sb); 53262306a36Sopenharmony_ci if (!inode) 53362306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci res = hfs_find_init(HFS_SB(dir->i_sb)->cat_tree, &fd); 53662306a36Sopenharmony_ci if (res) { 53762306a36Sopenharmony_ci iput(inode); 53862306a36Sopenharmony_ci return ERR_PTR(res); 53962306a36Sopenharmony_ci } 54062306a36Sopenharmony_ci fd.search_key->cat = HFS_I(dir)->cat_key; 54162306a36Sopenharmony_ci res = hfs_brec_read(&fd, &rec, sizeof(rec)); 54262306a36Sopenharmony_ci if (!res) { 54362306a36Sopenharmony_ci struct hfs_iget_data idata = { NULL, &rec }; 54462306a36Sopenharmony_ci hfs_read_inode(inode, &idata); 54562306a36Sopenharmony_ci } 54662306a36Sopenharmony_ci hfs_find_exit(&fd); 54762306a36Sopenharmony_ci if (res) { 54862306a36Sopenharmony_ci iput(inode); 54962306a36Sopenharmony_ci return ERR_PTR(res); 55062306a36Sopenharmony_ci } 55162306a36Sopenharmony_ci HFS_I(inode)->rsrc_inode = dir; 55262306a36Sopenharmony_ci HFS_I(dir)->rsrc_inode = inode; 55362306a36Sopenharmony_ci igrab(dir); 55462306a36Sopenharmony_ci inode_fake_hash(inode); 55562306a36Sopenharmony_ci mark_inode_dirty(inode); 55662306a36Sopenharmony_ci dont_mount(dentry); 55762306a36Sopenharmony_ciout: 55862306a36Sopenharmony_ci return d_splice_alias(inode, dentry); 55962306a36Sopenharmony_ci} 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_civoid hfs_evict_inode(struct inode *inode) 56262306a36Sopenharmony_ci{ 56362306a36Sopenharmony_ci truncate_inode_pages_final(&inode->i_data); 56462306a36Sopenharmony_ci clear_inode(inode); 56562306a36Sopenharmony_ci if (HFS_IS_RSRC(inode) && HFS_I(inode)->rsrc_inode) { 56662306a36Sopenharmony_ci HFS_I(HFS_I(inode)->rsrc_inode)->rsrc_inode = NULL; 56762306a36Sopenharmony_ci iput(HFS_I(inode)->rsrc_inode); 56862306a36Sopenharmony_ci } 56962306a36Sopenharmony_ci} 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_cistatic int hfs_file_open(struct inode *inode, struct file *file) 57262306a36Sopenharmony_ci{ 57362306a36Sopenharmony_ci if (HFS_IS_RSRC(inode)) 57462306a36Sopenharmony_ci inode = HFS_I(inode)->rsrc_inode; 57562306a36Sopenharmony_ci atomic_inc(&HFS_I(inode)->opencnt); 57662306a36Sopenharmony_ci return 0; 57762306a36Sopenharmony_ci} 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_cistatic int hfs_file_release(struct inode *inode, struct file *file) 58062306a36Sopenharmony_ci{ 58162306a36Sopenharmony_ci //struct super_block *sb = inode->i_sb; 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci if (HFS_IS_RSRC(inode)) 58462306a36Sopenharmony_ci inode = HFS_I(inode)->rsrc_inode; 58562306a36Sopenharmony_ci if (atomic_dec_and_test(&HFS_I(inode)->opencnt)) { 58662306a36Sopenharmony_ci inode_lock(inode); 58762306a36Sopenharmony_ci hfs_file_truncate(inode); 58862306a36Sopenharmony_ci //if (inode->i_flags & S_DEAD) { 58962306a36Sopenharmony_ci // hfs_delete_cat(inode->i_ino, HFSPLUS_SB(sb).hidden_dir, NULL); 59062306a36Sopenharmony_ci // hfs_delete_inode(inode); 59162306a36Sopenharmony_ci //} 59262306a36Sopenharmony_ci inode_unlock(inode); 59362306a36Sopenharmony_ci } 59462306a36Sopenharmony_ci return 0; 59562306a36Sopenharmony_ci} 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci/* 59862306a36Sopenharmony_ci * hfs_notify_change() 59962306a36Sopenharmony_ci * 60062306a36Sopenharmony_ci * Based very closely on fs/msdos/inode.c by Werner Almesberger 60162306a36Sopenharmony_ci * 60262306a36Sopenharmony_ci * This is the notify_change() field in the super_operations structure 60362306a36Sopenharmony_ci * for HFS file systems. The purpose is to take that changes made to 60462306a36Sopenharmony_ci * an inode and apply then in a filesystem-dependent manner. In this 60562306a36Sopenharmony_ci * case the process has a few of tasks to do: 60662306a36Sopenharmony_ci * 1) prevent changes to the i_uid and i_gid fields. 60762306a36Sopenharmony_ci * 2) map file permissions to the closest allowable permissions 60862306a36Sopenharmony_ci * 3) Since multiple Linux files can share the same on-disk inode under 60962306a36Sopenharmony_ci * HFS (for instance the data and resource forks of a file) a change 61062306a36Sopenharmony_ci * to permissions must be applied to all other in-core inodes which 61162306a36Sopenharmony_ci * correspond to the same HFS file. 61262306a36Sopenharmony_ci */ 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ciint hfs_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry, 61562306a36Sopenharmony_ci struct iattr *attr) 61662306a36Sopenharmony_ci{ 61762306a36Sopenharmony_ci struct inode *inode = d_inode(dentry); 61862306a36Sopenharmony_ci struct hfs_sb_info *hsb = HFS_SB(inode->i_sb); 61962306a36Sopenharmony_ci int error; 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci error = setattr_prepare(&nop_mnt_idmap, dentry, 62262306a36Sopenharmony_ci attr); /* basic permission checks */ 62362306a36Sopenharmony_ci if (error) 62462306a36Sopenharmony_ci return error; 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci /* no uig/gid changes and limit which mode bits can be set */ 62762306a36Sopenharmony_ci if (((attr->ia_valid & ATTR_UID) && 62862306a36Sopenharmony_ci (!uid_eq(attr->ia_uid, hsb->s_uid))) || 62962306a36Sopenharmony_ci ((attr->ia_valid & ATTR_GID) && 63062306a36Sopenharmony_ci (!gid_eq(attr->ia_gid, hsb->s_gid))) || 63162306a36Sopenharmony_ci ((attr->ia_valid & ATTR_MODE) && 63262306a36Sopenharmony_ci ((S_ISDIR(inode->i_mode) && 63362306a36Sopenharmony_ci (attr->ia_mode != inode->i_mode)) || 63462306a36Sopenharmony_ci (attr->ia_mode & ~HFS_VALID_MODE_BITS)))) { 63562306a36Sopenharmony_ci return hsb->s_quiet ? 0 : error; 63662306a36Sopenharmony_ci } 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci if (attr->ia_valid & ATTR_MODE) { 63962306a36Sopenharmony_ci /* Only the 'w' bits can ever change and only all together. */ 64062306a36Sopenharmony_ci if (attr->ia_mode & S_IWUSR) 64162306a36Sopenharmony_ci attr->ia_mode = inode->i_mode | S_IWUGO; 64262306a36Sopenharmony_ci else 64362306a36Sopenharmony_ci attr->ia_mode = inode->i_mode & ~S_IWUGO; 64462306a36Sopenharmony_ci attr->ia_mode &= S_ISDIR(inode->i_mode) ? ~hsb->s_dir_umask: ~hsb->s_file_umask; 64562306a36Sopenharmony_ci } 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci if ((attr->ia_valid & ATTR_SIZE) && 64862306a36Sopenharmony_ci attr->ia_size != i_size_read(inode)) { 64962306a36Sopenharmony_ci inode_dio_wait(inode); 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci error = inode_newsize_ok(inode, attr->ia_size); 65262306a36Sopenharmony_ci if (error) 65362306a36Sopenharmony_ci return error; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci truncate_setsize(inode, attr->ia_size); 65662306a36Sopenharmony_ci hfs_file_truncate(inode); 65762306a36Sopenharmony_ci inode->i_atime = inode->i_mtime = inode_set_ctime_current(inode); 65862306a36Sopenharmony_ci } 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci setattr_copy(&nop_mnt_idmap, inode, attr); 66162306a36Sopenharmony_ci mark_inode_dirty(inode); 66262306a36Sopenharmony_ci return 0; 66362306a36Sopenharmony_ci} 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_cistatic int hfs_file_fsync(struct file *filp, loff_t start, loff_t end, 66662306a36Sopenharmony_ci int datasync) 66762306a36Sopenharmony_ci{ 66862306a36Sopenharmony_ci struct inode *inode = filp->f_mapping->host; 66962306a36Sopenharmony_ci struct super_block * sb; 67062306a36Sopenharmony_ci int ret, err; 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci ret = file_write_and_wait_range(filp, start, end); 67362306a36Sopenharmony_ci if (ret) 67462306a36Sopenharmony_ci return ret; 67562306a36Sopenharmony_ci inode_lock(inode); 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci /* sync the inode to buffers */ 67862306a36Sopenharmony_ci ret = write_inode_now(inode, 0); 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci /* sync the superblock to buffers */ 68162306a36Sopenharmony_ci sb = inode->i_sb; 68262306a36Sopenharmony_ci flush_delayed_work(&HFS_SB(sb)->mdb_work); 68362306a36Sopenharmony_ci /* .. finally sync the buffers to disk */ 68462306a36Sopenharmony_ci err = sync_blockdev(sb->s_bdev); 68562306a36Sopenharmony_ci if (!ret) 68662306a36Sopenharmony_ci ret = err; 68762306a36Sopenharmony_ci inode_unlock(inode); 68862306a36Sopenharmony_ci return ret; 68962306a36Sopenharmony_ci} 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_cistatic const struct file_operations hfs_file_operations = { 69262306a36Sopenharmony_ci .llseek = generic_file_llseek, 69362306a36Sopenharmony_ci .read_iter = generic_file_read_iter, 69462306a36Sopenharmony_ci .write_iter = generic_file_write_iter, 69562306a36Sopenharmony_ci .mmap = generic_file_mmap, 69662306a36Sopenharmony_ci .splice_read = filemap_splice_read, 69762306a36Sopenharmony_ci .fsync = hfs_file_fsync, 69862306a36Sopenharmony_ci .open = hfs_file_open, 69962306a36Sopenharmony_ci .release = hfs_file_release, 70062306a36Sopenharmony_ci}; 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_cistatic const struct inode_operations hfs_file_inode_operations = { 70362306a36Sopenharmony_ci .lookup = hfs_file_lookup, 70462306a36Sopenharmony_ci .setattr = hfs_inode_setattr, 70562306a36Sopenharmony_ci .listxattr = generic_listxattr, 70662306a36Sopenharmony_ci}; 707