📄 inode.c
字号:
/* * linux/fs/hfsplus/inode.c * * Copyright (C) 2001 * Brad Boyer (flar@allandria.com) * (C) 2003 Ardis Technologies <roman@ardistech.com> * * Inode handling routines */#include <linux/mm.h>#include <linux/fs.h>#include <linux/pagemap.h>#include <linux/mpage.h>#include <linux/sched.h>#include "hfsplus_fs.h"#include "hfsplus_raw.h"static int hfsplus_readpage(struct file *file, struct page *page){ return block_read_full_page(page, hfsplus_get_block);}static int hfsplus_writepage(struct page *page, struct writeback_control *wbc){ return block_write_full_page(page, hfsplus_get_block, wbc);}static int hfsplus_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata){ *pagep = NULL; return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, hfsplus_get_block, &HFSPLUS_I(mapping->host).phys_size);}static sector_t hfsplus_bmap(struct address_space *mapping, sector_t block){ return generic_block_bmap(mapping, block, hfsplus_get_block);}static int hfsplus_releasepage(struct page *page, gfp_t mask){ struct inode *inode = page->mapping->host; struct super_block *sb = inode->i_sb; struct hfs_btree *tree; struct hfs_bnode *node; u32 nidx; int i, res = 1; switch (inode->i_ino) { case HFSPLUS_EXT_CNID: tree = HFSPLUS_SB(sb).ext_tree; break; case HFSPLUS_CAT_CNID: tree = HFSPLUS_SB(sb).cat_tree; break; case HFSPLUS_ATTR_CNID: tree = HFSPLUS_SB(sb).attr_tree; break; default: BUG(); return 0; } if (tree->node_size >= PAGE_CACHE_SIZE) { nidx = page->index >> (tree->node_size_shift - PAGE_CACHE_SHIFT); spin_lock(&tree->hash_lock); node = hfs_bnode_findhash(tree, nidx); if (!node) ; else if (atomic_read(&node->refcnt)) res = 0; if (res && node) { hfs_bnode_unhash(node); hfs_bnode_free(node); } spin_unlock(&tree->hash_lock); } else { nidx = page->index << (PAGE_CACHE_SHIFT - tree->node_size_shift); i = 1 << (PAGE_CACHE_SHIFT - tree->node_size_shift); spin_lock(&tree->hash_lock); do { node = hfs_bnode_findhash(tree, nidx++); if (!node) continue; if (atomic_read(&node->refcnt)) { res = 0; break; } hfs_bnode_unhash(node); hfs_bnode_free(node); } while (--i && nidx < tree->node_count); spin_unlock(&tree->hash_lock); } return res ? try_to_free_buffers(page) : 0;}static ssize_t hfsplus_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t offset, unsigned long nr_segs){ struct file *file = iocb->ki_filp; struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host; return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, offset, nr_segs, hfsplus_get_block, NULL);}static int hfsplus_writepages(struct address_space *mapping, struct writeback_control *wbc){ return mpage_writepages(mapping, wbc, hfsplus_get_block);}const struct address_space_operations hfsplus_btree_aops = { .readpage = hfsplus_readpage, .writepage = hfsplus_writepage, .sync_page = block_sync_page, .write_begin = hfsplus_write_begin, .write_end = generic_write_end, .bmap = hfsplus_bmap, .releasepage = hfsplus_releasepage,};const struct address_space_operations hfsplus_aops = { .readpage = hfsplus_readpage, .writepage = hfsplus_writepage, .sync_page = block_sync_page, .write_begin = hfsplus_write_begin, .write_end = generic_write_end, .bmap = hfsplus_bmap, .direct_IO = hfsplus_direct_IO, .writepages = hfsplus_writepages,};struct dentry_operations hfsplus_dentry_operations = { .d_hash = hfsplus_hash_dentry, .d_compare = hfsplus_compare_dentry,};static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){ struct hfs_find_data fd; struct super_block *sb = dir->i_sb; struct inode *inode = NULL; int err; if (HFSPLUS_IS_RSRC(dir) || strcmp(dentry->d_name.name, "rsrc")) goto out; inode = HFSPLUS_I(dir).rsrc_inode; if (inode) goto out; inode = new_inode(sb); if (!inode) return ERR_PTR(-ENOMEM); inode->i_ino = dir->i_ino; INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list); init_MUTEX(&HFSPLUS_I(inode).extents_lock); HFSPLUS_I(inode).flags = HFSPLUS_FLG_RSRC; hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); err = hfsplus_find_cat(sb, dir->i_ino, &fd); if (!err) err = hfsplus_cat_read_inode(inode, &fd); hfs_find_exit(&fd); if (err) { iput(inode); return ERR_PTR(err); } HFSPLUS_I(inode).rsrc_inode = dir; HFSPLUS_I(dir).rsrc_inode = inode; igrab(dir); hlist_add_head(&inode->i_hash, &HFSPLUS_SB(sb).rsrc_inodes); mark_inode_dirty(inode);out: d_add(dentry, inode); return NULL;}static void hfsplus_get_perms(struct inode *inode, struct hfsplus_perm *perms, int dir){ struct super_block *sb = inode->i_sb; u16 mode; mode = be16_to_cpu(perms->mode); inode->i_uid = be32_to_cpu(perms->owner); if (!inode->i_uid && !mode) inode->i_uid = HFSPLUS_SB(sb).uid; inode->i_gid = be32_to_cpu(perms->group); if (!inode->i_gid && !mode) inode->i_gid = HFSPLUS_SB(sb).gid; if (dir) { mode = mode ? (mode & S_IALLUGO) : (S_IRWXUGO & ~(HFSPLUS_SB(sb).umask)); mode |= S_IFDIR; } else if (!mode) mode = S_IFREG | ((S_IRUGO|S_IWUGO) & ~(HFSPLUS_SB(sb).umask)); inode->i_mode = mode; HFSPLUS_I(inode).rootflags = perms->rootflags; HFSPLUS_I(inode).userflags = perms->userflags; if (perms->rootflags & HFSPLUS_FLG_IMMUTABLE) inode->i_flags |= S_IMMUTABLE; else inode->i_flags &= ~S_IMMUTABLE; if (perms->rootflags & HFSPLUS_FLG_APPEND) inode->i_flags |= S_APPEND; else inode->i_flags &= ~S_APPEND;}static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms){ if (inode->i_flags & S_IMMUTABLE) perms->rootflags |= HFSPLUS_FLG_IMMUTABLE; else perms->rootflags &= ~HFSPLUS_FLG_IMMUTABLE; if (inode->i_flags & S_APPEND) perms->rootflags |= HFSPLUS_FLG_APPEND; else perms->rootflags &= ~HFSPLUS_FLG_APPEND; perms->userflags = HFSPLUS_I(inode).userflags; perms->mode = cpu_to_be16(inode->i_mode); perms->owner = cpu_to_be32(inode->i_uid); perms->group = cpu_to_be32(inode->i_gid); perms->dev = cpu_to_be32(HFSPLUS_I(inode).dev);}static int hfsplus_permission(struct inode *inode, int mask, struct nameidata *nd){ /* MAY_EXEC is also used for lookup, if no x bit is set allow lookup, * open_exec has the same test, so it's still not executable, if a x bit * is set fall back to standard permission check. */ if (S_ISREG(inode->i_mode) && mask & MAY_EXEC && !(inode->i_mode & 0111)) return 0; return generic_permission(inode, mask, NULL);}static int hfsplus_file_open(struct inode *inode, struct file *file){ if (HFSPLUS_IS_RSRC(inode)) inode = HFSPLUS_I(inode).rsrc_inode; if (atomic_read(&file->f_count) != 1) return 0; atomic_inc(&HFSPLUS_I(inode).opencnt); return 0;}static int hfsplus_file_release(struct inode *inode, struct file *file){ struct super_block *sb = inode->i_sb; if (HFSPLUS_IS_RSRC(inode)) inode = HFSPLUS_I(inode).rsrc_inode; if (atomic_read(&file->f_count) != 0) return 0; if (atomic_dec_and_test(&HFSPLUS_I(inode).opencnt)) { mutex_lock(&inode->i_mutex); hfsplus_file_truncate(inode); if (inode->i_flags & S_DEAD) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -