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