⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inode.c

📁 ocfs1.4.1 oracle分布式文件系统
💻 C
📖 第 1 页 / 共 3 页
字号:
/* -*- mode: c; c-basic-offset: 8; -*- * vim: noexpandtab sw=8 ts=8 sts=0: * * inode.c * * vfs' aops, fops, dops and iops * * Copyright (C) 2002, 2004 Oracle.  All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 021110-1307, USA. */#include <linux/fs.h>#include <linux/types.h>#include <linux/slab.h>#include <linux/highmem.h>#include <linux/pagemap.h>#include <asm/byteorder.h>#define MLOG_MASK_PREFIX ML_INODE#include <cluster/masklog.h>#include "ocfs2.h"#include "alloc.h"#include "dlmglue.h"#include "extent_map.h"#include "file.h"#include "heartbeat.h"#include "inode.h"#include "journal.h"#include "namei.h"#include "suballoc.h"#include "super.h"#include "symlink.h"#include "sysfile.h"#include "uptodate.h"#include "buffer_head_io.h"struct ocfs2_find_inode_args{	u64		fi_blkno;	unsigned long	fi_ino;	unsigned int	fi_flags;	unsigned int	fi_sysfile_type;};#ifndef NO_LOCKDEPstatic struct lock_class_key ocfs2_sysfile_lock_key[NUM_SYSTEM_INODES];#endifstatic int ocfs2_read_locked_inode(struct inode *inode,				   struct ocfs2_find_inode_args *args);static int ocfs2_init_locked_inode(struct inode *inode, void *opaque);static int ocfs2_find_actor(struct inode *inode, void *opaque);static int ocfs2_truncate_for_delete(struct ocfs2_super *osb,				    struct inode *inode,				    struct buffer_head *fe_bh);void ocfs2_set_inode_flags(struct inode *inode){	unsigned int flags = OCFS2_I(inode)->ip_attr;	inode->i_flags &= ~(S_IMMUTABLE |		S_SYNC | S_APPEND | S_NOATIME | S_DIRSYNC);	if (flags & OCFS2_IMMUTABLE_FL)		inode->i_flags |= S_IMMUTABLE;	if (flags & OCFS2_SYNC_FL)		inode->i_flags |= S_SYNC;	if (flags & OCFS2_APPEND_FL)		inode->i_flags |= S_APPEND;	if (flags & OCFS2_NOATIME_FL)		inode->i_flags |= S_NOATIME;	if (flags & OCFS2_DIRSYNC_FL)		inode->i_flags |= S_DIRSYNC;}/* Propagate flags from i_flags to OCFS2_I(inode)->ip_attr */void ocfs2_get_inode_flags(struct ocfs2_inode_info *oi){	unsigned int flags = oi->vfs_inode.i_flags;	oi->ip_attr &= ~(OCFS2_SYNC_FL|OCFS2_APPEND_FL|			OCFS2_IMMUTABLE_FL|OCFS2_NOATIME_FL|OCFS2_DIRSYNC_FL);	if (flags & S_SYNC)		oi->ip_attr |= OCFS2_SYNC_FL;	if (flags & S_APPEND)		oi->ip_attr |= OCFS2_APPEND_FL;	if (flags & S_IMMUTABLE)		oi->ip_attr |= OCFS2_IMMUTABLE_FL;	if (flags & S_NOATIME)		oi->ip_attr |= OCFS2_NOATIME_FL;	if (flags & S_DIRSYNC)		oi->ip_attr |= OCFS2_DIRSYNC_FL;}struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, unsigned flags,			 int sysfile_type){	struct inode *inode = NULL;	struct super_block *sb = osb->sb;	struct ocfs2_find_inode_args args;	mlog_entry("(blkno = %llu)\n", (unsigned long long)blkno);	/* Ok. By now we've either got the offsets passed to us by the	 * caller, or we just pulled them off the bh. Lets do some	 * sanity checks to make sure they're OK. */	if (blkno == 0) {		inode = ERR_PTR(-EINVAL);		mlog_errno(PTR_ERR(inode));		goto bail;	}	args.fi_blkno = blkno;	args.fi_flags = flags;	args.fi_ino = ino_from_blkno(sb, blkno);	args.fi_sysfile_type = sysfile_type;	inode = iget5_locked(sb, args.fi_ino, ocfs2_find_actor,			     ocfs2_init_locked_inode, &args);	/* inode was *not* in the inode cache. 2.6.x requires	 * us to do our own read_inode call and unlock it	 * afterwards. */	if (inode && inode->i_state & I_NEW) {		mlog(0, "Inode was not in inode cache, reading it.\n");		ocfs2_read_locked_inode(inode, &args);		unlock_new_inode(inode);	}	if (inode == NULL) {		inode = ERR_PTR(-ENOMEM);		mlog_errno(PTR_ERR(inode));		goto bail;	}	if (is_bad_inode(inode)) {		iput(inode);		inode = ERR_PTR(-ESTALE);		goto bail;	}bail:	if (!IS_ERR(inode)) {		mlog(0, "returning inode with number %llu\n",		     (unsigned long long)OCFS2_I(inode)->ip_blkno);		mlog_exit_ptr(inode);	}	return inode;}/* * here's how inodes get read from disk: * iget5_locked -> find_actor -> OCFS2_FIND_ACTOR * found? : return the in-memory inode * not found? : get_new_inode -> OCFS2_INIT_LOCKED_INODE */static int ocfs2_find_actor(struct inode *inode, void *opaque){	struct ocfs2_find_inode_args *args = NULL;	struct ocfs2_inode_info *oi = OCFS2_I(inode);	int ret = 0;	mlog_entry("(0x%p, %lu, 0x%p)\n", inode, inode->i_ino, opaque);	args = opaque;	mlog_bug_on_msg(!inode, "No inode in find actor!\n");	if (oi->ip_blkno != args->fi_blkno)		goto bail;	ret = 1;bail:	mlog_exit(ret);	return ret;}/* * initialize the new inode, but don't do anything that would cause * us to sleep. * return 0 on success, 1 on failure */static int ocfs2_init_locked_inode(struct inode *inode, void *opaque){	struct ocfs2_find_inode_args *args = opaque;	mlog_entry("inode = %p, opaque = %p\n", inode, opaque);	inode->i_ino = args->fi_ino;	OCFS2_I(inode)->ip_blkno = args->fi_blkno;#ifndef NO_LOCKDEP	if (args->fi_sysfile_type != 0)		lockdep_set_class(&inode->i_mutex,			&ocfs2_sysfile_lock_key[args->fi_sysfile_type]);#endif	mlog_exit(0);	return 0;}int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,		     	 int create_ino){	struct super_block *sb;	struct ocfs2_super *osb;	int status = -EINVAL;	mlog_entry("(0x%p, size:%llu)\n", inode,		   (unsigned long long)le64_to_cpu(fe->i_size));	sb = inode->i_sb;	osb = OCFS2_SB(sb);	/* this means that read_inode cannot create a superblock inode	 * today.  change if needed. */	if (!OCFS2_IS_VALID_DINODE(fe) ||	    !(fe->i_flags & cpu_to_le32(OCFS2_VALID_FL))) {		mlog(0, "Invalid dinode: i_ino=%lu, i_blkno=%llu, "		     "signature = %.*s, flags = 0x%x\n",		     inode->i_ino,		     (unsigned long long)le64_to_cpu(fe->i_blkno), 7,		     fe->i_signature, le32_to_cpu(fe->i_flags));		goto bail;	}	if (le32_to_cpu(fe->i_fs_generation) != osb->fs_generation) {		mlog(ML_ERROR, "file entry generation does not match "		     "superblock! osb->fs_generation=%x, "		     "fe->i_fs_generation=%x\n",		     osb->fs_generation, le32_to_cpu(fe->i_fs_generation));		goto bail;	}	OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters);	OCFS2_I(inode)->ip_attr = le32_to_cpu(fe->i_attr);	OCFS2_I(inode)->ip_dyn_features = le16_to_cpu(fe->i_dyn_features);	inode->i_version = 1;	inode->i_generation = le32_to_cpu(fe->i_generation);	inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev));	inode->i_mode = le16_to_cpu(fe->i_mode);	inode->i_uid = le32_to_cpu(fe->i_uid);	inode->i_gid = le32_to_cpu(fe->i_gid);	/* Fast symlinks will have i_size but no allocated clusters. */	if (S_ISLNK(inode->i_mode) && !fe->i_clusters)		inode->i_blocks = 0;	else		inode->i_blocks = ocfs2_inode_sector_count(inode);	inode->i_mapping->a_ops = &ocfs2_aops;	inode->i_atime.tv_sec = le64_to_cpu(fe->i_atime);	inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec);	inode->i_mtime.tv_sec = le64_to_cpu(fe->i_mtime);	inode->i_mtime.tv_nsec = le32_to_cpu(fe->i_mtime_nsec);	inode->i_ctime.tv_sec = le64_to_cpu(fe->i_ctime);	inode->i_ctime.tv_nsec = le32_to_cpu(fe->i_ctime_nsec);	if (OCFS2_I(inode)->ip_blkno != le64_to_cpu(fe->i_blkno))		mlog(ML_ERROR,		     "ip_blkno %llu != i_blkno %llu!\n",		     (unsigned long long)OCFS2_I(inode)->ip_blkno,		     (unsigned long long)le64_to_cpu(fe->i_blkno));	inode->i_nlink = le16_to_cpu(fe->i_links_count);	if (fe->i_flags & cpu_to_le32(OCFS2_SYSTEM_FL))		OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SYSTEM_FILE;	if (fe->i_flags & cpu_to_le32(OCFS2_LOCAL_ALLOC_FL)) {		OCFS2_I(inode)->ip_flags |= OCFS2_INODE_BITMAP;		mlog(0, "local alloc inode: i_ino=%lu\n", inode->i_ino);	} else if (fe->i_flags & cpu_to_le32(OCFS2_BITMAP_FL)) {		OCFS2_I(inode)->ip_flags |= OCFS2_INODE_BITMAP;	} else if (fe->i_flags & cpu_to_le32(OCFS2_SUPER_BLOCK_FL)) {		mlog(0, "superblock inode: i_ino=%lu\n", inode->i_ino);		/* we can't actually hit this as read_inode can't		 * handle superblocks today ;-) */		BUG();	}	switch (inode->i_mode & S_IFMT) {	    case S_IFREG:		    inode->i_fop = &ocfs2_fops;		    inode->i_op = &ocfs2_file_iops;		    i_size_write(inode, le64_to_cpu(fe->i_size));		    break;	    case S_IFDIR:		    inode->i_op = &ocfs2_dir_iops;		    inode->i_fop = &ocfs2_dops;		    i_size_write(inode, le64_to_cpu(fe->i_size));		    break;	    case S_IFLNK:		    if (ocfs2_inode_is_fast_symlink(inode))			inode->i_op = &ocfs2_fast_symlink_inode_operations;		    else			inode->i_op = &ocfs2_symlink_inode_operations;		    i_size_write(inode, le64_to_cpu(fe->i_size));		    break;	    default:		    inode->i_op = &ocfs2_special_file_iops;		    init_special_inode(inode, inode->i_mode,				       inode->i_rdev);		    break;	}	if (create_ino) {		inode->i_ino = ino_from_blkno(inode->i_sb,			       le64_to_cpu(fe->i_blkno));		/*		 * If we ever want to create system files from kernel,		 * the generation argument to		 * ocfs2_inode_lock_res_init() will have to change.		 */		BUG_ON(le32_to_cpu(fe->i_flags) & OCFS2_SYSTEM_FL);		ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_inode_lockres,					  OCFS2_LOCK_TYPE_META, 0, inode);		ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_open_lockres,					  OCFS2_LOCK_TYPE_OPEN, 0, inode);	}	ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_rw_lockres,				  OCFS2_LOCK_TYPE_RW, inode->i_generation,				  inode);	ocfs2_set_inode_flags(inode);	status = 0;bail:	mlog_exit(status);	return status;}static int ocfs2_read_locked_inode(struct inode *inode,				   struct ocfs2_find_inode_args *args){	struct super_block *sb;	struct ocfs2_super *osb;	struct ocfs2_dinode *fe;	struct buffer_head *bh = NULL;	int status, can_lock;	u32 generation = 0;	mlog_entry("(0x%p, 0x%p)\n", inode, args);	status = -EINVAL;	if (inode == NULL || inode->i_sb == NULL) {		mlog(ML_ERROR, "bad inode\n");		return status;	}	sb = inode->i_sb;	osb = OCFS2_SB(sb);	if (!args) {		mlog(ML_ERROR, "bad inode args\n");		make_bad_inode(inode);		return status;	}	/*	 * To improve performance of cold-cache inode stats, we take	 * the cluster lock here if possible.	 *	 * Generally, OCFS2 never trusts the contents of an inode	 * unless it's holding a cluster lock, so taking it here isn't	 * a correctness issue as much as it is a performance	 * improvement.	 *	 * There are three times when taking the lock is not a good idea:	 *	 * 1) During startup, before we have initialized the DLM.	 *	 * 2) If we are reading certain system files which never get	 *    cluster locks (local alloc, truncate log).	 *	 * 3) If the process doing the iget() is responsible for	 *    orphan dir recovery. We're holding the orphan dir lock and	 *    can get into a deadlock with another process on another	 *    node in ->delete_inode().	 *	 * #1 and #2 can be simply solved by never taking the lock	 * here for system files (which are the only type we read	 * during mount). It's a heavier approach, but our main	 * concern is user-accesible files anyway.	 *	 * #3 works itself out because we'll eventually take the	 * cluster lock before trusting anything anyway.	 */	can_lock = !(args->fi_flags & OCFS2_FI_FLAG_SYSFILE)		&& !(args->fi_flags & OCFS2_FI_FLAG_ORPHAN_RECOVERY)		&& !ocfs2_mount_local(osb);	/*	 * To maintain backwards compatibility with older versions of	 * ocfs2-tools, we still store the generation value for system	 * files. The only ones that actually matter to userspace are	 * the journals, but it's easier and inexpensive to just flag	 * all system files similarly.	 */	if (args->fi_flags & OCFS2_FI_FLAG_SYSFILE)		generation = osb->fs_generation;	ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_inode_lockres,				  OCFS2_LOCK_TYPE_META,				  generation, inode);	ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_open_lockres,				  OCFS2_LOCK_TYPE_OPEN,				  0, inode);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -