11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds * linux/fs/hfs/inode.c
31da177e4SLinus Torvalds *
41da177e4SLinus Torvalds * Copyright (C) 1995-1997 Paul H. Hargrove
51da177e4SLinus Torvalds * (C) 2003 Ardis Technologies <roman@ardistech.com>
61da177e4SLinus Torvalds * This file may be distributed under the terms of the GNU General Public License.
71da177e4SLinus Torvalds *
81da177e4SLinus Torvalds * This file contains inode-related functions which do not depend on
91da177e4SLinus Torvalds * which scheme is being used to represent forks.
101da177e4SLinus Torvalds *
111da177e4SLinus Torvalds * Based on the minix file system code, (C) 1991, 1992 by Linus Torvalds
121da177e4SLinus Torvalds */
131da177e4SLinus Torvalds
141da177e4SLinus Torvalds #include <linux/pagemap.h>
151da177e4SLinus Torvalds #include <linux/mpage.h>
16e8edc6e0SAlexey Dobriyan #include <linux/sched.h>
175b825c3aSIngo Molnar #include <linux/cred.h>
18e2e40f2cSChristoph Hellwig #include <linux/uio.h>
19b8020effSAndreas Gruenbacher #include <linux/xattr.h>
203f1266f1SChristoph Hellwig #include <linux/blkdev.h>
211da177e4SLinus Torvalds
221da177e4SLinus Torvalds #include "hfs_fs.h"
231da177e4SLinus Torvalds #include "btree.h"
241da177e4SLinus Torvalds
254b6f5d20SArjan van de Ven static const struct file_operations hfs_file_operations;
2692e1d5beSArjan van de Ven static const struct inode_operations hfs_file_inode_operations;
271da177e4SLinus Torvalds
281da177e4SLinus Torvalds /*================ Variable-like macros ================*/
291da177e4SLinus Torvalds
301da177e4SLinus Torvalds #define HFS_VALID_MODE_BITS (S_IFREG | S_IFDIR | S_IRWXUGO)
311da177e4SLinus Torvalds
hfs_writepage(struct page * page,struct writeback_control * wbc)321da177e4SLinus Torvalds static int hfs_writepage(struct page *page, struct writeback_control *wbc)
331da177e4SLinus Torvalds {
341da177e4SLinus Torvalds return block_write_full_page(page, hfs_get_block, wbc);
351da177e4SLinus Torvalds }
361da177e4SLinus Torvalds
hfs_read_folio(struct file * file,struct folio * folio)372c69e205SMatthew Wilcox (Oracle) static int hfs_read_folio(struct file *file, struct folio *folio)
381da177e4SLinus Torvalds {
392c69e205SMatthew Wilcox (Oracle) return block_read_full_folio(folio, hfs_get_block);
401da177e4SLinus Torvalds }
411da177e4SLinus Torvalds
hfs_write_failed(struct address_space * mapping,loff_t to)42c8cf464bSMarco Stornelli static void hfs_write_failed(struct address_space *mapping, loff_t to)
43c8cf464bSMarco Stornelli {
44c8cf464bSMarco Stornelli struct inode *inode = mapping->host;
45c8cf464bSMarco Stornelli
46c8cf464bSMarco Stornelli if (to > inode->i_size) {
477caef267SKirill A. Shutemov truncate_pagecache(inode, inode->i_size);
48c8cf464bSMarco Stornelli hfs_file_truncate(inode);
49c8cf464bSMarco Stornelli }
50c8cf464bSMarco Stornelli }
51c8cf464bSMarco Stornelli
hfs_write_begin(struct file * file,struct address_space * mapping,loff_t pos,unsigned len,struct page ** pagep,void ** fsdata)52cfef1f7bSMatthew Wilcox (Oracle) int hfs_write_begin(struct file *file, struct address_space *mapping,
53cfef1f7bSMatthew Wilcox (Oracle) loff_t pos, unsigned len, struct page **pagep, void **fsdata)
541da177e4SLinus Torvalds {
55282dc178SChristoph Hellwig int ret;
56282dc178SChristoph Hellwig
577903d9eeSNick Piggin *pagep = NULL;
58be3bbbc5SMatthew Wilcox (Oracle) ret = cont_write_begin(file, mapping, pos, len, pagep, fsdata,
597903d9eeSNick Piggin hfs_get_block,
607903d9eeSNick Piggin &HFS_I(mapping->host)->phys_size);
61c8cf464bSMarco Stornelli if (unlikely(ret))
62c8cf464bSMarco Stornelli hfs_write_failed(mapping, pos + len);
63282dc178SChristoph Hellwig
64282dc178SChristoph Hellwig return ret;
651da177e4SLinus Torvalds }
661da177e4SLinus Torvalds
hfs_bmap(struct address_space * mapping,sector_t block)671da177e4SLinus Torvalds static sector_t hfs_bmap(struct address_space *mapping, sector_t block)
681da177e4SLinus Torvalds {
691da177e4SLinus Torvalds return generic_block_bmap(mapping, block, hfs_get_block);
701da177e4SLinus Torvalds }
711da177e4SLinus Torvalds
hfs_release_folio(struct folio * folio,gfp_t mask)725784f09bSMatthew Wilcox (Oracle) static bool hfs_release_folio(struct folio *folio, gfp_t mask)
731da177e4SLinus Torvalds {
745784f09bSMatthew Wilcox (Oracle) struct inode *inode = folio->mapping->host;
751da177e4SLinus Torvalds struct super_block *sb = inode->i_sb;
761da177e4SLinus Torvalds struct hfs_btree *tree;
771da177e4SLinus Torvalds struct hfs_bnode *node;
781da177e4SLinus Torvalds u32 nidx;
795784f09bSMatthew Wilcox (Oracle) int i;
805784f09bSMatthew Wilcox (Oracle) bool res = true;
811da177e4SLinus Torvalds
821da177e4SLinus Torvalds switch (inode->i_ino) {
831da177e4SLinus Torvalds case HFS_EXT_CNID:
841da177e4SLinus Torvalds tree = HFS_SB(sb)->ext_tree;
851da177e4SLinus Torvalds break;
861da177e4SLinus Torvalds case HFS_CAT_CNID:
871da177e4SLinus Torvalds tree = HFS_SB(sb)->cat_tree;
881da177e4SLinus Torvalds break;
891da177e4SLinus Torvalds default:
901da177e4SLinus Torvalds BUG();
915784f09bSMatthew Wilcox (Oracle) return false;
921da177e4SLinus Torvalds }
93eb2e5f45SDave Anderson
94eb2e5f45SDave Anderson if (!tree)
955784f09bSMatthew Wilcox (Oracle) return false;
96eb2e5f45SDave Anderson
9709cbfeafSKirill A. Shutemov if (tree->node_size >= PAGE_SIZE) {
985784f09bSMatthew Wilcox (Oracle) nidx = folio->index >> (tree->node_size_shift - PAGE_SHIFT);
991da177e4SLinus Torvalds spin_lock(&tree->hash_lock);
1001da177e4SLinus Torvalds node = hfs_bnode_findhash(tree, nidx);
1011da177e4SLinus Torvalds if (!node)
1021da177e4SLinus Torvalds ;
1031da177e4SLinus Torvalds else if (atomic_read(&node->refcnt))
1045784f09bSMatthew Wilcox (Oracle) res = false;
1051da177e4SLinus Torvalds if (res && node) {
1061da177e4SLinus Torvalds hfs_bnode_unhash(node);
1071da177e4SLinus Torvalds hfs_bnode_free(node);
1081da177e4SLinus Torvalds }
1091da177e4SLinus Torvalds spin_unlock(&tree->hash_lock);
1101da177e4SLinus Torvalds } else {
1115784f09bSMatthew Wilcox (Oracle) nidx = folio->index << (PAGE_SHIFT - tree->node_size_shift);
11209cbfeafSKirill A. Shutemov i = 1 << (PAGE_SHIFT - tree->node_size_shift);
1131da177e4SLinus Torvalds spin_lock(&tree->hash_lock);
1141da177e4SLinus Torvalds do {
1151da177e4SLinus Torvalds node = hfs_bnode_findhash(tree, nidx++);
1161da177e4SLinus Torvalds if (!node)
1171da177e4SLinus Torvalds continue;
1181da177e4SLinus Torvalds if (atomic_read(&node->refcnt)) {
1195784f09bSMatthew Wilcox (Oracle) res = false;
1201da177e4SLinus Torvalds break;
1211da177e4SLinus Torvalds }
1221da177e4SLinus Torvalds hfs_bnode_unhash(node);
1231da177e4SLinus Torvalds hfs_bnode_free(node);
1241da177e4SLinus Torvalds } while (--i && nidx < tree->node_count);
1251da177e4SLinus Torvalds spin_unlock(&tree->hash_lock);
1261da177e4SLinus Torvalds }
12768189fefSMatthew Wilcox (Oracle) return res ? try_to_free_buffers(folio) : false;
1281da177e4SLinus Torvalds }
1291da177e4SLinus Torvalds
hfs_direct_IO(struct kiocb * iocb,struct iov_iter * iter)130c8b8e32dSChristoph Hellwig static ssize_t hfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
1311da177e4SLinus Torvalds {
1321da177e4SLinus Torvalds struct file *file = iocb->ki_filp;
133c8cf464bSMarco Stornelli struct address_space *mapping = file->f_mapping;
13493c76a3dSAl Viro struct inode *inode = mapping->host;
135a6cbcd4aSAl Viro size_t count = iov_iter_count(iter);
136eafdc7d1SChristoph Hellwig ssize_t ret;
1371da177e4SLinus Torvalds
138c8b8e32dSChristoph Hellwig ret = blockdev_direct_IO(iocb, inode, iter, hfs_get_block);
139eafdc7d1SChristoph Hellwig
140eafdc7d1SChristoph Hellwig /*
141eafdc7d1SChristoph Hellwig * In case of error extending write may have instantiated a few
142eafdc7d1SChristoph Hellwig * blocks outside i_size. Trim these off again.
143eafdc7d1SChristoph Hellwig */
1446f673763SOmar Sandoval if (unlikely(iov_iter_rw(iter) == WRITE && ret < 0)) {
145eafdc7d1SChristoph Hellwig loff_t isize = i_size_read(inode);
146c8b8e32dSChristoph Hellwig loff_t end = iocb->ki_pos + count;
147eafdc7d1SChristoph Hellwig
148eafdc7d1SChristoph Hellwig if (end > isize)
149c8cf464bSMarco Stornelli hfs_write_failed(mapping, end);
150eafdc7d1SChristoph Hellwig }
151eafdc7d1SChristoph Hellwig
152eafdc7d1SChristoph Hellwig return ret;
1531da177e4SLinus Torvalds }
1541da177e4SLinus Torvalds
hfs_writepages(struct address_space * mapping,struct writeback_control * wbc)1551da177e4SLinus Torvalds static int hfs_writepages(struct address_space *mapping,
1561da177e4SLinus Torvalds struct writeback_control *wbc)
1571da177e4SLinus Torvalds {
1581da177e4SLinus Torvalds return mpage_writepages(mapping, wbc, hfs_get_block);
1591da177e4SLinus Torvalds }
1601da177e4SLinus Torvalds
161f5e54d6eSChristoph Hellwig const struct address_space_operations hfs_btree_aops = {
162e621900aSMatthew Wilcox (Oracle) .dirty_folio = block_dirty_folio,
1637ba13abbSMatthew Wilcox (Oracle) .invalidate_folio = block_invalidate_folio,
1642c69e205SMatthew Wilcox (Oracle) .read_folio = hfs_read_folio,
1651da177e4SLinus Torvalds .writepage = hfs_writepage,
1667903d9eeSNick Piggin .write_begin = hfs_write_begin,
1677903d9eeSNick Piggin .write_end = generic_write_end,
1681da177e4SLinus Torvalds .bmap = hfs_bmap,
1695784f09bSMatthew Wilcox (Oracle) .release_folio = hfs_release_folio,
1701da177e4SLinus Torvalds };
1711da177e4SLinus Torvalds
172f5e54d6eSChristoph Hellwig const struct address_space_operations hfs_aops = {
173e621900aSMatthew Wilcox (Oracle) .dirty_folio = block_dirty_folio,
1747ba13abbSMatthew Wilcox (Oracle) .invalidate_folio = block_invalidate_folio,
1752c69e205SMatthew Wilcox (Oracle) .read_folio = hfs_read_folio,
1767903d9eeSNick Piggin .write_begin = hfs_write_begin,
1777903d9eeSNick Piggin .write_end = generic_write_end,
1781da177e4SLinus Torvalds .bmap = hfs_bmap,
1791da177e4SLinus Torvalds .direct_IO = hfs_direct_IO,
1801da177e4SLinus Torvalds .writepages = hfs_writepages,
181ba195d9fSChristoph Hellwig .migrate_folio = buffer_migrate_folio,
1821da177e4SLinus Torvalds };
1831da177e4SLinus Torvalds
1841da177e4SLinus Torvalds /*
1851da177e4SLinus Torvalds * hfs_new_inode
1861da177e4SLinus Torvalds */
hfs_new_inode(struct inode * dir,const struct qstr * name,umode_t mode)18771e93963SAl Viro struct inode *hfs_new_inode(struct inode *dir, const struct qstr *name, umode_t mode)
1881da177e4SLinus Torvalds {
1891da177e4SLinus Torvalds struct super_block *sb = dir->i_sb;
1901da177e4SLinus Torvalds struct inode *inode = new_inode(sb);
1911da177e4SLinus Torvalds if (!inode)
1921da177e4SLinus Torvalds return NULL;
1931da177e4SLinus Torvalds
19439f8d472SMatthias Kaehlcke mutex_init(&HFS_I(inode)->extents_lock);
1951da177e4SLinus Torvalds INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list);
1969717a91bSAl Viro spin_lock_init(&HFS_I(inode)->open_dir_lock);
197328b9227SRoman Zippel hfs_cat_build_key(sb, (btree_key *)&HFS_I(inode)->cat_key, dir->i_ino, name);
1981da177e4SLinus Torvalds inode->i_ino = HFS_SB(sb)->next_id++;
1991da177e4SLinus Torvalds inode->i_mode = mode;
20094c9a5eeSDavid Howells inode->i_uid = current_fsuid();
20194c9a5eeSDavid Howells inode->i_gid = current_fsgid();
202bfe86848SMiklos Szeredi set_nlink(inode, 1);
2037305586aSJeff Layton inode->i_mtime = inode->i_atime = inode_set_ctime_current(inode);
2041da177e4SLinus Torvalds HFS_I(inode)->flags = 0;
2051da177e4SLinus Torvalds HFS_I(inode)->rsrc_inode = NULL;
2061da177e4SLinus Torvalds HFS_I(inode)->fs_blocks = 0;
207*9c4e40b9SChao Yu HFS_I(inode)->tz_secondswest = sys_tz.tz_minuteswest * 60;
2081da177e4SLinus Torvalds if (S_ISDIR(mode)) {
2091da177e4SLinus Torvalds inode->i_size = 2;
2101da177e4SLinus Torvalds HFS_SB(sb)->folder_count++;
2111da177e4SLinus Torvalds if (dir->i_ino == HFS_ROOT_CNID)
2121da177e4SLinus Torvalds HFS_SB(sb)->root_dirs++;
2131da177e4SLinus Torvalds inode->i_op = &hfs_dir_inode_operations;
2141da177e4SLinus Torvalds inode->i_fop = &hfs_dir_operations;
2151da177e4SLinus Torvalds inode->i_mode |= S_IRWXUGO;
2161da177e4SLinus Torvalds inode->i_mode &= ~HFS_SB(inode->i_sb)->s_dir_umask;
2171da177e4SLinus Torvalds } else if (S_ISREG(mode)) {
2181da177e4SLinus Torvalds HFS_I(inode)->clump_blocks = HFS_SB(sb)->clumpablks;
2191da177e4SLinus Torvalds HFS_SB(sb)->file_count++;
2201da177e4SLinus Torvalds if (dir->i_ino == HFS_ROOT_CNID)
2211da177e4SLinus Torvalds HFS_SB(sb)->root_files++;
2221da177e4SLinus Torvalds inode->i_op = &hfs_file_inode_operations;
2231da177e4SLinus Torvalds inode->i_fop = &hfs_file_operations;
2241da177e4SLinus Torvalds inode->i_mapping->a_ops = &hfs_aops;
2251da177e4SLinus Torvalds inode->i_mode |= S_IRUGO|S_IXUGO;
2261da177e4SLinus Torvalds if (mode & S_IWUSR)
2271da177e4SLinus Torvalds inode->i_mode |= S_IWUGO;
2281da177e4SLinus Torvalds inode->i_mode &= ~HFS_SB(inode->i_sb)->s_file_umask;
2291da177e4SLinus Torvalds HFS_I(inode)->phys_size = 0;
2301da177e4SLinus Torvalds HFS_I(inode)->alloc_blocks = 0;
2311da177e4SLinus Torvalds HFS_I(inode)->first_blocks = 0;
2321da177e4SLinus Torvalds HFS_I(inode)->cached_start = 0;
2331da177e4SLinus Torvalds HFS_I(inode)->cached_blocks = 0;
2341da177e4SLinus Torvalds memset(HFS_I(inode)->first_extents, 0, sizeof(hfs_extent_rec));
2351da177e4SLinus Torvalds memset(HFS_I(inode)->cached_extents, 0, sizeof(hfs_extent_rec));
2361da177e4SLinus Torvalds }
2371da177e4SLinus Torvalds insert_inode_hash(inode);
2381da177e4SLinus Torvalds mark_inode_dirty(inode);
2391da177e4SLinus Torvalds set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
2405687b578SArtem Bityutskiy hfs_mark_mdb_dirty(sb);
2411da177e4SLinus Torvalds
2421da177e4SLinus Torvalds return inode;
2431da177e4SLinus Torvalds }
2441da177e4SLinus Torvalds
hfs_delete_inode(struct inode * inode)2451da177e4SLinus Torvalds void hfs_delete_inode(struct inode *inode)
2461da177e4SLinus Torvalds {
2471da177e4SLinus Torvalds struct super_block *sb = inode->i_sb;
2481da177e4SLinus Torvalds
249c2b3e1f7SJoe Perches hfs_dbg(INODE, "delete_inode: %lu\n", inode->i_ino);
2501da177e4SLinus Torvalds if (S_ISDIR(inode->i_mode)) {
2511da177e4SLinus Torvalds HFS_SB(sb)->folder_count--;
2521da177e4SLinus Torvalds if (HFS_I(inode)->cat_key.ParID == cpu_to_be32(HFS_ROOT_CNID))
2531da177e4SLinus Torvalds HFS_SB(sb)->root_dirs--;
2541da177e4SLinus Torvalds set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
2555687b578SArtem Bityutskiy hfs_mark_mdb_dirty(sb);
2561da177e4SLinus Torvalds return;
2571da177e4SLinus Torvalds }
2581da177e4SLinus Torvalds HFS_SB(sb)->file_count--;
2591da177e4SLinus Torvalds if (HFS_I(inode)->cat_key.ParID == cpu_to_be32(HFS_ROOT_CNID))
2601da177e4SLinus Torvalds HFS_SB(sb)->root_files--;
2611da177e4SLinus Torvalds if (S_ISREG(inode->i_mode)) {
2621da177e4SLinus Torvalds if (!inode->i_nlink) {
2631da177e4SLinus Torvalds inode->i_size = 0;
2641da177e4SLinus Torvalds hfs_file_truncate(inode);
2651da177e4SLinus Torvalds }
2661da177e4SLinus Torvalds }
2671da177e4SLinus Torvalds set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
2685687b578SArtem Bityutskiy hfs_mark_mdb_dirty(sb);
2691da177e4SLinus Torvalds }
2701da177e4SLinus Torvalds
hfs_inode_read_fork(struct inode * inode,struct hfs_extent * ext,__be32 __log_size,__be32 phys_size,u32 clump_size)2711da177e4SLinus Torvalds void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext,
2721da177e4SLinus Torvalds __be32 __log_size, __be32 phys_size, u32 clump_size)
2731da177e4SLinus Torvalds {
2741da177e4SLinus Torvalds struct super_block *sb = inode->i_sb;
2751da177e4SLinus Torvalds u32 log_size = be32_to_cpu(__log_size);
2761da177e4SLinus Torvalds u16 count;
2771da177e4SLinus Torvalds int i;
2781da177e4SLinus Torvalds
2791da177e4SLinus Torvalds memcpy(HFS_I(inode)->first_extents, ext, sizeof(hfs_extent_rec));
2801da177e4SLinus Torvalds for (count = 0, i = 0; i < 3; i++)
2811da177e4SLinus Torvalds count += be16_to_cpu(ext[i].count);
2821da177e4SLinus Torvalds HFS_I(inode)->first_blocks = count;
283*9c4e40b9SChao Yu HFS_I(inode)->cached_start = 0;
284*9c4e40b9SChao Yu HFS_I(inode)->cached_blocks = 0;
2851da177e4SLinus Torvalds
2861da177e4SLinus Torvalds inode->i_size = HFS_I(inode)->phys_size = log_size;
2871da177e4SLinus Torvalds HFS_I(inode)->fs_blocks = (log_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
2881da177e4SLinus Torvalds inode_set_bytes(inode, HFS_I(inode)->fs_blocks << sb->s_blocksize_bits);
2891da177e4SLinus Torvalds HFS_I(inode)->alloc_blocks = be32_to_cpu(phys_size) /
2901da177e4SLinus Torvalds HFS_SB(sb)->alloc_blksz;
2911da177e4SLinus Torvalds HFS_I(inode)->clump_blocks = clump_size / HFS_SB(sb)->alloc_blksz;
2921da177e4SLinus Torvalds if (!HFS_I(inode)->clump_blocks)
2931da177e4SLinus Torvalds HFS_I(inode)->clump_blocks = HFS_SB(sb)->clumpablks;
2941da177e4SLinus Torvalds }
2951da177e4SLinus Torvalds
2961da177e4SLinus Torvalds struct hfs_iget_data {
2971da177e4SLinus Torvalds struct hfs_cat_key *key;
2981da177e4SLinus Torvalds hfs_cat_rec *rec;
2991da177e4SLinus Torvalds };
3001da177e4SLinus Torvalds
hfs_test_inode(struct inode * inode,void * data)3011da177e4SLinus Torvalds static int hfs_test_inode(struct inode *inode, void *data)
3021da177e4SLinus Torvalds {
3031da177e4SLinus Torvalds struct hfs_iget_data *idata = data;
3041da177e4SLinus Torvalds hfs_cat_rec *rec;
3051da177e4SLinus Torvalds
3061da177e4SLinus Torvalds rec = idata->rec;
3071da177e4SLinus Torvalds switch (rec->type) {
3081da177e4SLinus Torvalds case HFS_CDR_DIR:
3091da177e4SLinus Torvalds return inode->i_ino == be32_to_cpu(rec->dir.DirID);
3101da177e4SLinus Torvalds case HFS_CDR_FIL:
3111da177e4SLinus Torvalds return inode->i_ino == be32_to_cpu(rec->file.FlNum);
3121da177e4SLinus Torvalds default:
3131da177e4SLinus Torvalds BUG();
3141da177e4SLinus Torvalds return 1;
3151da177e4SLinus Torvalds }
3161da177e4SLinus Torvalds }
3171da177e4SLinus Torvalds
3181da177e4SLinus Torvalds /*
3191da177e4SLinus Torvalds * hfs_read_inode
3201da177e4SLinus Torvalds */
hfs_read_inode(struct inode * inode,void * data)3211da177e4SLinus Torvalds static int hfs_read_inode(struct inode *inode, void *data)
3221da177e4SLinus Torvalds {
3231da177e4SLinus Torvalds struct hfs_iget_data *idata = data;
3241da177e4SLinus Torvalds struct hfs_sb_info *hsb = HFS_SB(inode->i_sb);
3251da177e4SLinus Torvalds hfs_cat_rec *rec;
3261da177e4SLinus Torvalds
3271da177e4SLinus Torvalds HFS_I(inode)->flags = 0;
3281da177e4SLinus Torvalds HFS_I(inode)->rsrc_inode = NULL;
32939f8d472SMatthias Kaehlcke mutex_init(&HFS_I(inode)->extents_lock);
3301da177e4SLinus Torvalds INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list);
3319717a91bSAl Viro spin_lock_init(&HFS_I(inode)->open_dir_lock);
3321da177e4SLinus Torvalds
3331da177e4SLinus Torvalds /* Initialize the inode */
3341da177e4SLinus Torvalds inode->i_uid = hsb->s_uid;
3351da177e4SLinus Torvalds inode->i_gid = hsb->s_gid;
336bfe86848SMiklos Szeredi set_nlink(inode, 1);
3371da177e4SLinus Torvalds
3381da177e4SLinus Torvalds if (idata->key)
3391da177e4SLinus Torvalds HFS_I(inode)->cat_key = *idata->key;
3401da177e4SLinus Torvalds else
3411da177e4SLinus Torvalds HFS_I(inode)->flags |= HFS_FLG_RSRC;
3421da177e4SLinus Torvalds HFS_I(inode)->tz_secondswest = sys_tz.tz_minuteswest * 60;
3431da177e4SLinus Torvalds
3441da177e4SLinus Torvalds rec = idata->rec;
3451da177e4SLinus Torvalds switch (rec->type) {
3461da177e4SLinus Torvalds case HFS_CDR_FIL:
3471da177e4SLinus Torvalds if (!HFS_IS_RSRC(inode)) {
3481da177e4SLinus Torvalds hfs_inode_read_fork(inode, rec->file.ExtRec, rec->file.LgLen,
3491da177e4SLinus Torvalds rec->file.PyLen, be16_to_cpu(rec->file.ClpSize));
3501da177e4SLinus Torvalds } else {
3511da177e4SLinus Torvalds hfs_inode_read_fork(inode, rec->file.RExtRec, rec->file.RLgLen,
3521da177e4SLinus Torvalds rec->file.RPyLen, be16_to_cpu(rec->file.ClpSize));
3531da177e4SLinus Torvalds }
3541da177e4SLinus Torvalds
3551da177e4SLinus Torvalds inode->i_ino = be32_to_cpu(rec->file.FlNum);
3561da177e4SLinus Torvalds inode->i_mode = S_IRUGO | S_IXUGO;
3571da177e4SLinus Torvalds if (!(rec->file.Flags & HFS_FIL_LOCK))
3581da177e4SLinus Torvalds inode->i_mode |= S_IWUGO;
3591da177e4SLinus Torvalds inode->i_mode &= ~hsb->s_file_umask;
3601da177e4SLinus Torvalds inode->i_mode |= S_IFREG;
3617305586aSJeff Layton inode->i_atime = inode->i_mtime = inode_set_ctime_to_ts(inode,
3627305586aSJeff Layton hfs_m_to_utime(rec->file.MdDat));
3631da177e4SLinus Torvalds inode->i_op = &hfs_file_inode_operations;
3641da177e4SLinus Torvalds inode->i_fop = &hfs_file_operations;
3651da177e4SLinus Torvalds inode->i_mapping->a_ops = &hfs_aops;
3661da177e4SLinus Torvalds break;
3671da177e4SLinus Torvalds case HFS_CDR_DIR:
3681da177e4SLinus Torvalds inode->i_ino = be32_to_cpu(rec->dir.DirID);
3691da177e4SLinus Torvalds inode->i_size = be16_to_cpu(rec->dir.Val) + 2;
3701da177e4SLinus Torvalds HFS_I(inode)->fs_blocks = 0;
3711da177e4SLinus Torvalds inode->i_mode = S_IFDIR | (S_IRWXUGO & ~hsb->s_dir_umask);
3727305586aSJeff Layton inode->i_atime = inode->i_mtime = inode_set_ctime_to_ts(inode,
3737305586aSJeff Layton hfs_m_to_utime(rec->dir.MdDat));
3741da177e4SLinus Torvalds inode->i_op = &hfs_dir_inode_operations;
3751da177e4SLinus Torvalds inode->i_fop = &hfs_dir_operations;
3761da177e4SLinus Torvalds break;
3771da177e4SLinus Torvalds default:
3781da177e4SLinus Torvalds make_bad_inode(inode);
3791da177e4SLinus Torvalds }
3801da177e4SLinus Torvalds return 0;
3811da177e4SLinus Torvalds }
3821da177e4SLinus Torvalds
3831da177e4SLinus Torvalds /*
3841da177e4SLinus Torvalds * __hfs_iget()
3851da177e4SLinus Torvalds *
3861da177e4SLinus Torvalds * Given the MDB for a HFS filesystem, a 'key' and an 'entry' in
3871da177e4SLinus Torvalds * the catalog B-tree and the 'type' of the desired file return the
3881da177e4SLinus Torvalds * inode for that file/directory or NULL. Note that 'type' indicates
3891da177e4SLinus Torvalds * whether we want the actual file or directory, or the corresponding
3901da177e4SLinus Torvalds * metadata (AppleDouble header file or CAP metadata file).
3911da177e4SLinus Torvalds */
hfs_iget(struct super_block * sb,struct hfs_cat_key * key,hfs_cat_rec * rec)3921da177e4SLinus Torvalds struct inode *hfs_iget(struct super_block *sb, struct hfs_cat_key *key, hfs_cat_rec *rec)
3931da177e4SLinus Torvalds {
3941da177e4SLinus Torvalds struct hfs_iget_data data = { key, rec };
3951da177e4SLinus Torvalds struct inode *inode;
3961da177e4SLinus Torvalds u32 cnid;
3971da177e4SLinus Torvalds
3981da177e4SLinus Torvalds switch (rec->type) {
3991da177e4SLinus Torvalds case HFS_CDR_DIR:
4001da177e4SLinus Torvalds cnid = be32_to_cpu(rec->dir.DirID);
4011da177e4SLinus Torvalds break;
4021da177e4SLinus Torvalds case HFS_CDR_FIL:
4031da177e4SLinus Torvalds cnid = be32_to_cpu(rec->file.FlNum);
4041da177e4SLinus Torvalds break;
4051da177e4SLinus Torvalds default:
4061da177e4SLinus Torvalds return NULL;
4071da177e4SLinus Torvalds }
4081da177e4SLinus Torvalds inode = iget5_locked(sb, cnid, hfs_test_inode, hfs_read_inode, &data);
4091da177e4SLinus Torvalds if (inode && (inode->i_state & I_NEW))
4101da177e4SLinus Torvalds unlock_new_inode(inode);
4111da177e4SLinus Torvalds return inode;
4121da177e4SLinus Torvalds }
4131da177e4SLinus Torvalds
hfs_inode_write_fork(struct inode * inode,struct hfs_extent * ext,__be32 * log_size,__be32 * phys_size)4141da177e4SLinus Torvalds void hfs_inode_write_fork(struct inode *inode, struct hfs_extent *ext,
4151da177e4SLinus Torvalds __be32 *log_size, __be32 *phys_size)
4161da177e4SLinus Torvalds {
4171da177e4SLinus Torvalds memcpy(ext, HFS_I(inode)->first_extents, sizeof(hfs_extent_rec));
4181da177e4SLinus Torvalds
4191da177e4SLinus Torvalds if (log_size)
4201da177e4SLinus Torvalds *log_size = cpu_to_be32(inode->i_size);
4211da177e4SLinus Torvalds if (phys_size)
4221da177e4SLinus Torvalds *phys_size = cpu_to_be32(HFS_I(inode)->alloc_blocks *
4231da177e4SLinus Torvalds HFS_SB(inode->i_sb)->alloc_blksz);
4241da177e4SLinus Torvalds }
4251da177e4SLinus Torvalds
hfs_write_inode(struct inode * inode,struct writeback_control * wbc)426a9185b41SChristoph Hellwig int hfs_write_inode(struct inode *inode, struct writeback_control *wbc)
4271da177e4SLinus Torvalds {
4281da177e4SLinus Torvalds struct inode *main_inode = inode;
4291da177e4SLinus Torvalds struct hfs_find_data fd;
4301da177e4SLinus Torvalds hfs_cat_rec rec;
4319509f178SAlexey Khoroshilov int res;
4321da177e4SLinus Torvalds
433c2b3e1f7SJoe Perches hfs_dbg(INODE, "hfs_write_inode: %lu\n", inode->i_ino);
4349509f178SAlexey Khoroshilov res = hfs_ext_write_extent(inode);
4359509f178SAlexey Khoroshilov if (res)
4369509f178SAlexey Khoroshilov return res;
4371da177e4SLinus Torvalds
4381da177e4SLinus Torvalds if (inode->i_ino < HFS_FIRSTUSER_CNID) {
4391da177e4SLinus Torvalds switch (inode->i_ino) {
4401da177e4SLinus Torvalds case HFS_ROOT_CNID:
4411da177e4SLinus Torvalds break;
4421da177e4SLinus Torvalds case HFS_EXT_CNID:
4431da177e4SLinus Torvalds hfs_btree_write(HFS_SB(inode->i_sb)->ext_tree);
4441da177e4SLinus Torvalds return 0;
4451da177e4SLinus Torvalds case HFS_CAT_CNID:
4461da177e4SLinus Torvalds hfs_btree_write(HFS_SB(inode->i_sb)->cat_tree);
4471da177e4SLinus Torvalds return 0;
4481da177e4SLinus Torvalds default:
4491da177e4SLinus Torvalds BUG();
4501da177e4SLinus Torvalds return -EIO;
4511da177e4SLinus Torvalds }
4521da177e4SLinus Torvalds }
4531da177e4SLinus Torvalds
4541da177e4SLinus Torvalds if (HFS_IS_RSRC(inode))
4551da177e4SLinus Torvalds main_inode = HFS_I(inode)->rsrc_inode;
4561da177e4SLinus Torvalds
4571da177e4SLinus Torvalds if (!main_inode->i_nlink)
4581da177e4SLinus Torvalds return 0;
4591da177e4SLinus Torvalds
4601da177e4SLinus Torvalds if (hfs_find_init(HFS_SB(main_inode->i_sb)->cat_tree, &fd))
4611da177e4SLinus Torvalds /* panic? */
4621da177e4SLinus Torvalds return -EIO;
4631da177e4SLinus Torvalds
464cb7a95afSLinus Torvalds res = -EIO;
4658d824e69SZhangPeng if (HFS_I(main_inode)->cat_key.CName.len > HFS_NAMELEN)
466cb7a95afSLinus Torvalds goto out;
4671da177e4SLinus Torvalds fd.search_key->cat = HFS_I(main_inode)->cat_key;
4681da177e4SLinus Torvalds if (hfs_brec_find(&fd))
4691da177e4SLinus Torvalds goto out;
4701da177e4SLinus Torvalds
4711da177e4SLinus Torvalds if (S_ISDIR(main_inode->i_mode)) {
472cb7a95afSLinus Torvalds if (fd.entrylength < sizeof(struct hfs_cat_dir))
473cb7a95afSLinus Torvalds goto out;
4741da177e4SLinus Torvalds hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
4751da177e4SLinus Torvalds sizeof(struct hfs_cat_dir));
4761da177e4SLinus Torvalds if (rec.type != HFS_CDR_DIR ||
4771da177e4SLinus Torvalds be32_to_cpu(rec.dir.DirID) != inode->i_ino) {
4781da177e4SLinus Torvalds }
4791da177e4SLinus Torvalds
4801da177e4SLinus Torvalds rec.dir.MdDat = hfs_u_to_mtime(inode->i_mtime);
4811da177e4SLinus Torvalds rec.dir.Val = cpu_to_be16(inode->i_size - 2);
4821da177e4SLinus Torvalds
4831da177e4SLinus Torvalds hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
4841da177e4SLinus Torvalds sizeof(struct hfs_cat_dir));
4851da177e4SLinus Torvalds } else if (HFS_IS_RSRC(inode)) {
486cb7a95afSLinus Torvalds if (fd.entrylength < sizeof(struct hfs_cat_file))
487cb7a95afSLinus Torvalds goto out;
4881da177e4SLinus Torvalds hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
4891da177e4SLinus Torvalds sizeof(struct hfs_cat_file));
4901da177e4SLinus Torvalds hfs_inode_write_fork(inode, rec.file.RExtRec,
4911da177e4SLinus Torvalds &rec.file.RLgLen, &rec.file.RPyLen);
4921da177e4SLinus Torvalds hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
4931da177e4SLinus Torvalds sizeof(struct hfs_cat_file));
4941da177e4SLinus Torvalds } else {
495cb7a95afSLinus Torvalds if (fd.entrylength < sizeof(struct hfs_cat_file))
496cb7a95afSLinus Torvalds goto out;
4971da177e4SLinus Torvalds hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
4981da177e4SLinus Torvalds sizeof(struct hfs_cat_file));
4991da177e4SLinus Torvalds if (rec.type != HFS_CDR_FIL ||
5001da177e4SLinus Torvalds be32_to_cpu(rec.file.FlNum) != inode->i_ino) {
5011da177e4SLinus Torvalds }
5021da177e4SLinus Torvalds
5031da177e4SLinus Torvalds if (inode->i_mode & S_IWUSR)
5041da177e4SLinus Torvalds rec.file.Flags &= ~HFS_FIL_LOCK;
5051da177e4SLinus Torvalds else
5061da177e4SLinus Torvalds rec.file.Flags |= HFS_FIL_LOCK;
5071da177e4SLinus Torvalds hfs_inode_write_fork(inode, rec.file.ExtRec, &rec.file.LgLen, &rec.file.PyLen);
5081da177e4SLinus Torvalds rec.file.MdDat = hfs_u_to_mtime(inode->i_mtime);
5091da177e4SLinus Torvalds
5101da177e4SLinus Torvalds hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
5111da177e4SLinus Torvalds sizeof(struct hfs_cat_file));
5121da177e4SLinus Torvalds }
513cb7a95afSLinus Torvalds res = 0;
5141da177e4SLinus Torvalds out:
5151da177e4SLinus Torvalds hfs_find_exit(&fd);
516cb7a95afSLinus Torvalds return res;
5171da177e4SLinus Torvalds }
5181da177e4SLinus Torvalds
hfs_file_lookup(struct inode * dir,struct dentry * dentry,unsigned int flags)5191da177e4SLinus Torvalds static struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry,
52000cd8dd3SAl Viro unsigned int flags)
5211da177e4SLinus Torvalds {
5221da177e4SLinus Torvalds struct inode *inode = NULL;
5231da177e4SLinus Torvalds hfs_cat_rec rec;
5241da177e4SLinus Torvalds struct hfs_find_data fd;
5251da177e4SLinus Torvalds int res;
5261da177e4SLinus Torvalds
5271da177e4SLinus Torvalds if (HFS_IS_RSRC(dir) || strcmp(dentry->d_name.name, "rsrc"))
5281da177e4SLinus Torvalds goto out;
5291da177e4SLinus Torvalds
5301da177e4SLinus Torvalds inode = HFS_I(dir)->rsrc_inode;
5311da177e4SLinus Torvalds if (inode)
5321da177e4SLinus Torvalds goto out;
5331da177e4SLinus Torvalds
5341da177e4SLinus Torvalds inode = new_inode(dir->i_sb);
5351da177e4SLinus Torvalds if (!inode)
5361da177e4SLinus Torvalds return ERR_PTR(-ENOMEM);
5371da177e4SLinus Torvalds
5389509f178SAlexey Khoroshilov res = hfs_find_init(HFS_SB(dir->i_sb)->cat_tree, &fd);
5399509f178SAlexey Khoroshilov if (res) {
5409509f178SAlexey Khoroshilov iput(inode);
5419509f178SAlexey Khoroshilov return ERR_PTR(res);
5429509f178SAlexey Khoroshilov }
5431da177e4SLinus Torvalds fd.search_key->cat = HFS_I(dir)->cat_key;
5441da177e4SLinus Torvalds res = hfs_brec_read(&fd, &rec, sizeof(rec));
5451da177e4SLinus Torvalds if (!res) {
5461da177e4SLinus Torvalds struct hfs_iget_data idata = { NULL, &rec };
5471da177e4SLinus Torvalds hfs_read_inode(inode, &idata);
5481da177e4SLinus Torvalds }
5491da177e4SLinus Torvalds hfs_find_exit(&fd);
5501da177e4SLinus Torvalds if (res) {
5511da177e4SLinus Torvalds iput(inode);
5521da177e4SLinus Torvalds return ERR_PTR(res);
5531da177e4SLinus Torvalds }
5541da177e4SLinus Torvalds HFS_I(inode)->rsrc_inode = dir;
5551da177e4SLinus Torvalds HFS_I(dir)->rsrc_inode = inode;
5561da177e4SLinus Torvalds igrab(dir);
5575bef9151SAl Viro inode_fake_hash(inode);
5581da177e4SLinus Torvalds mark_inode_dirty(inode);
5590e5c56fdSAl Viro dont_mount(dentry);
5601da177e4SLinus Torvalds out:
5616b9cceeaSAl Viro return d_splice_alias(inode, dentry);
5621da177e4SLinus Torvalds }
5631da177e4SLinus Torvalds
hfs_evict_inode(struct inode * inode)564b57922d9SAl Viro void hfs_evict_inode(struct inode *inode)
5651da177e4SLinus Torvalds {
56691b0abe3SJohannes Weiner truncate_inode_pages_final(&inode->i_data);
567dbd5768fSJan Kara clear_inode(inode);
5681da177e4SLinus Torvalds if (HFS_IS_RSRC(inode) && HFS_I(inode)->rsrc_inode) {
5691da177e4SLinus Torvalds HFS_I(HFS_I(inode)->rsrc_inode)->rsrc_inode = NULL;
5701da177e4SLinus Torvalds iput(HFS_I(inode)->rsrc_inode);
5711da177e4SLinus Torvalds }
5721da177e4SLinus Torvalds }
5731da177e4SLinus Torvalds
hfs_file_open(struct inode * inode,struct file * file)5741da177e4SLinus Torvalds static int hfs_file_open(struct inode *inode, struct file *file)
5751da177e4SLinus Torvalds {
5761da177e4SLinus Torvalds if (HFS_IS_RSRC(inode))
5771da177e4SLinus Torvalds inode = HFS_I(inode)->rsrc_inode;
5781da177e4SLinus Torvalds atomic_inc(&HFS_I(inode)->opencnt);
5791da177e4SLinus Torvalds return 0;
5801da177e4SLinus Torvalds }
5811da177e4SLinus Torvalds
hfs_file_release(struct inode * inode,struct file * file)5821da177e4SLinus Torvalds static int hfs_file_release(struct inode *inode, struct file *file)
5831da177e4SLinus Torvalds {
5841da177e4SLinus Torvalds //struct super_block *sb = inode->i_sb;
5851da177e4SLinus Torvalds
5861da177e4SLinus Torvalds if (HFS_IS_RSRC(inode))
5871da177e4SLinus Torvalds inode = HFS_I(inode)->rsrc_inode;
5881da177e4SLinus Torvalds if (atomic_dec_and_test(&HFS_I(inode)->opencnt)) {
5895955102cSAl Viro inode_lock(inode);
5901da177e4SLinus Torvalds hfs_file_truncate(inode);
5911da177e4SLinus Torvalds //if (inode->i_flags & S_DEAD) {
5921da177e4SLinus Torvalds // hfs_delete_cat(inode->i_ino, HFSPLUS_SB(sb).hidden_dir, NULL);
5931da177e4SLinus Torvalds // hfs_delete_inode(inode);
5941da177e4SLinus Torvalds //}
5955955102cSAl Viro inode_unlock(inode);
5961da177e4SLinus Torvalds }
5971da177e4SLinus Torvalds return 0;
5981da177e4SLinus Torvalds }
5991da177e4SLinus Torvalds
6001da177e4SLinus Torvalds /*
6011da177e4SLinus Torvalds * hfs_notify_change()
6021da177e4SLinus Torvalds *
6031da177e4SLinus Torvalds * Based very closely on fs/msdos/inode.c by Werner Almesberger
6041da177e4SLinus Torvalds *
6051da177e4SLinus Torvalds * This is the notify_change() field in the super_operations structure
6061da177e4SLinus Torvalds * for HFS file systems. The purpose is to take that changes made to
6071da177e4SLinus Torvalds * an inode and apply then in a filesystem-dependent manner. In this
6081da177e4SLinus Torvalds * case the process has a few of tasks to do:
6091da177e4SLinus Torvalds * 1) prevent changes to the i_uid and i_gid fields.
6101da177e4SLinus Torvalds * 2) map file permissions to the closest allowable permissions
6111da177e4SLinus Torvalds * 3) Since multiple Linux files can share the same on-disk inode under
6121da177e4SLinus Torvalds * HFS (for instance the data and resource forks of a file) a change
6131da177e4SLinus Torvalds * to permissions must be applied to all other in-core inodes which
6141da177e4SLinus Torvalds * correspond to the same HFS file.
6151da177e4SLinus Torvalds */
6161da177e4SLinus Torvalds
hfs_inode_setattr(struct mnt_idmap * idmap,struct dentry * dentry,struct iattr * attr)617c1632a0fSChristian Brauner int hfs_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
618549c7297SChristian Brauner struct iattr *attr)
6191da177e4SLinus Torvalds {
6202b0143b5SDavid Howells struct inode *inode = d_inode(dentry);
6211da177e4SLinus Torvalds struct hfs_sb_info *hsb = HFS_SB(inode->i_sb);
6221da177e4SLinus Torvalds int error;
6231da177e4SLinus Torvalds
624c1632a0fSChristian Brauner error = setattr_prepare(&nop_mnt_idmap, dentry,
625549c7297SChristian Brauner attr); /* basic permission checks */
6261da177e4SLinus Torvalds if (error)
6271da177e4SLinus Torvalds return error;
6281da177e4SLinus Torvalds
6291da177e4SLinus Torvalds /* no uig/gid changes and limit which mode bits can be set */
6301da177e4SLinus Torvalds if (((attr->ia_valid & ATTR_UID) &&
63143b5e4ccSEric W. Biederman (!uid_eq(attr->ia_uid, hsb->s_uid))) ||
6321da177e4SLinus Torvalds ((attr->ia_valid & ATTR_GID) &&
63343b5e4ccSEric W. Biederman (!gid_eq(attr->ia_gid, hsb->s_gid))) ||
6341da177e4SLinus Torvalds ((attr->ia_valid & ATTR_MODE) &&
6351da177e4SLinus Torvalds ((S_ISDIR(inode->i_mode) &&
6361da177e4SLinus Torvalds (attr->ia_mode != inode->i_mode)) ||
6371da177e4SLinus Torvalds (attr->ia_mode & ~HFS_VALID_MODE_BITS)))) {
6381da177e4SLinus Torvalds return hsb->s_quiet ? 0 : error;
6391da177e4SLinus Torvalds }
6401da177e4SLinus Torvalds
6411da177e4SLinus Torvalds if (attr->ia_valid & ATTR_MODE) {
6421da177e4SLinus Torvalds /* Only the 'w' bits can ever change and only all together. */
6431da177e4SLinus Torvalds if (attr->ia_mode & S_IWUSR)
6441da177e4SLinus Torvalds attr->ia_mode = inode->i_mode | S_IWUGO;
6451da177e4SLinus Torvalds else
6461da177e4SLinus Torvalds attr->ia_mode = inode->i_mode & ~S_IWUGO;
6471da177e4SLinus Torvalds attr->ia_mode &= S_ISDIR(inode->i_mode) ? ~hsb->s_dir_umask: ~hsb->s_file_umask;
6481da177e4SLinus Torvalds }
6491025774cSChristoph Hellwig
6501025774cSChristoph Hellwig if ((attr->ia_valid & ATTR_SIZE) &&
6511025774cSChristoph Hellwig attr->ia_size != i_size_read(inode)) {
652562c72aaSChristoph Hellwig inode_dio_wait(inode);
653562c72aaSChristoph Hellwig
654c8cf464bSMarco Stornelli error = inode_newsize_ok(inode, attr->ia_size);
6551da177e4SLinus Torvalds if (error)
6561da177e4SLinus Torvalds return error;
657c8cf464bSMarco Stornelli
658c8cf464bSMarco Stornelli truncate_setsize(inode, attr->ia_size);
659c8cf464bSMarco Stornelli hfs_file_truncate(inode);
6607305586aSJeff Layton inode->i_atime = inode->i_mtime = inode_set_ctime_current(inode);
6611025774cSChristoph Hellwig }
6621da177e4SLinus Torvalds
663c1632a0fSChristian Brauner setattr_copy(&nop_mnt_idmap, inode, attr);
6641025774cSChristoph Hellwig mark_inode_dirty(inode);
6651da177e4SLinus Torvalds return 0;
6661da177e4SLinus Torvalds }
6671da177e4SLinus Torvalds
hfs_file_fsync(struct file * filp,loff_t start,loff_t end,int datasync)66802c24a82SJosef Bacik static int hfs_file_fsync(struct file *filp, loff_t start, loff_t end,
66902c24a82SJosef Bacik int datasync)
670b5fc510cSAl Viro {
671b5fc510cSAl Viro struct inode *inode = filp->f_mapping->host;
672b5fc510cSAl Viro struct super_block * sb;
673b5fc510cSAl Viro int ret, err;
674b5fc510cSAl Viro
6753b49c9a1SJeff Layton ret = file_write_and_wait_range(filp, start, end);
67602c24a82SJosef Bacik if (ret)
67702c24a82SJosef Bacik return ret;
6785955102cSAl Viro inode_lock(inode);
67902c24a82SJosef Bacik
680b5fc510cSAl Viro /* sync the inode to buffers */
681b5fc510cSAl Viro ret = write_inode_now(inode, 0);
682b5fc510cSAl Viro
683b5fc510cSAl Viro /* sync the superblock to buffers */
684b5fc510cSAl Viro sb = inode->i_sb;
68543829731STejun Heo flush_delayed_work(&HFS_SB(sb)->mdb_work);
686b5fc510cSAl Viro /* .. finally sync the buffers to disk */
687b5fc510cSAl Viro err = sync_blockdev(sb->s_bdev);
688b5fc510cSAl Viro if (!ret)
689b5fc510cSAl Viro ret = err;
6905955102cSAl Viro inode_unlock(inode);
691b5fc510cSAl Viro return ret;
692b5fc510cSAl Viro }
6931da177e4SLinus Torvalds
6944b6f5d20SArjan van de Ven static const struct file_operations hfs_file_operations = {
6951da177e4SLinus Torvalds .llseek = generic_file_llseek,
696aad4f8bbSAl Viro .read_iter = generic_file_read_iter,
6978174202bSAl Viro .write_iter = generic_file_write_iter,
6981da177e4SLinus Torvalds .mmap = generic_file_mmap,
6992cb1e089SDavid Howells .splice_read = filemap_splice_read,
700b5fc510cSAl Viro .fsync = hfs_file_fsync,
7011da177e4SLinus Torvalds .open = hfs_file_open,
7021da177e4SLinus Torvalds .release = hfs_file_release,
7031da177e4SLinus Torvalds };
7041da177e4SLinus Torvalds
70592e1d5beSArjan van de Ven static const struct inode_operations hfs_file_inode_operations = {
7061da177e4SLinus Torvalds .lookup = hfs_file_lookup,
7071da177e4SLinus Torvalds .setattr = hfs_inode_setattr,
708b8020effSAndreas Gruenbacher .listxattr = generic_listxattr,
7091da177e4SLinus Torvalds };
710