inode.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 552 行 · 第 1/2 页
C
552 行
/* * 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/version.h>#include <linux/mpage.h>#include "hfsplus_fs.h"#include "hfsplus_raw.h"static int hfsplus_readpage(struct file *file, struct page *page){ //printk("readpage: %lu\n", page->index); return block_read_full_page(page, hfsplus_get_block);}static int hfsplus_writepage(struct page *page, struct writeback_control *wbc){ //printk("writepage: %lu\n", page->index); return block_write_full_page(page, hfsplus_get_block, wbc);}static int hfsplus_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to){ return cont_prepare_write(page, from, to, hfsplus_get_block, &HFSPLUS_I(page->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);}int hfsplus_releasepage(struct page *page, int 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; else for (i = 0; i < tree->pages_per_bnode; i++) { if (PageActive(node->page[i])) { res = 0; break; } } 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); } //printk("releasepage: %lu,%x = %d\n", page->index, mask, res); return res;}static int hfsplus_get_blocks(struct inode *inode, sector_t iblock, unsigned long max_blocks, struct buffer_head *bh_result, int create){ int ret; ret = hfsplus_get_block(inode, iblock, bh_result, create); if (!ret) bh_result->b_size = (1 << inode->i_blkbits); return ret;}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_dentry->d_inode->i_mapping->host; return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, offset, nr_segs, hfsplus_get_blocks, NULL);}static int hfsplus_writepages(struct address_space *mapping, struct writeback_control *wbc){ return mpage_writepages(mapping, wbc, hfsplus_get_block);}struct address_space_operations hfsplus_btree_aops = { .readpage = hfsplus_readpage, .writepage = hfsplus_writepage, .sync_page = block_sync_page, .prepare_write = hfsplus_prepare_write, .commit_write = generic_commit_write, .bmap = hfsplus_bmap, .releasepage = hfsplus_releasepage,};struct address_space_operations hfsplus_aops = { .readpage = hfsplus_readpage, .writepage = hfsplus_writepage, .sync_page = block_sync_page, .prepare_write = hfsplus_prepare_write, .commit_write = generic_commit_write, .bmap = hfsplus_bmap, .direct_IO = hfsplus_direct_IO, .writepages = hfsplus_writepages,};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); { void hfsplus_inode_check(struct super_block *sb); atomic_inc(&HFSPLUS_SB(sb).inode_cnt); hfsplus_inode_check(sb); }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 vfs_permission(inode, mask);}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;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?