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

📄 inode.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/** * inode.c - NTFS kernel inode handling. Part of the Linux-NTFS project. * * Copyright (c) 2001-2007 Anton Altaparmakov * * This program/include file 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/include file 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 (in the main directory of the Linux-NTFS * distribution in the file COPYING); if not, write to the Free Software * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include <linux/buffer_head.h>#include <linux/fs.h>#include <linux/mm.h>#include <linux/mount.h>#include <linux/mutex.h>#include <linux/pagemap.h>#include <linux/quotaops.h>#include <linux/slab.h>#include "aops.h"#include "attrib.h"#include "bitmap.h"#include "dir.h"#include "debug.h"#include "inode.h"#include "lcnalloc.h"#include "malloc.h"#include "mft.h"#include "time.h"#include "ntfs.h"/** * ntfs_test_inode - compare two (possibly fake) inodes for equality * @vi:		vfs inode which to test * @na:		ntfs attribute which is being tested with * * Compare the ntfs attribute embedded in the ntfs specific part of the vfs * inode @vi for equality with the ntfs attribute @na. * * If searching for the normal file/directory inode, set @na->type to AT_UNUSED. * @na->name and @na->name_len are then ignored. * * Return 1 if the attributes match and 0 if not. * * NOTE: This function runs with the inode_lock spin lock held so it is not * allowed to sleep. */int ntfs_test_inode(struct inode *vi, ntfs_attr *na){	ntfs_inode *ni;	if (vi->i_ino != na->mft_no)		return 0;	ni = NTFS_I(vi);	/* If !NInoAttr(ni), @vi is a normal file or directory inode. */	if (likely(!NInoAttr(ni))) {		/* If not looking for a normal inode this is a mismatch. */		if (unlikely(na->type != AT_UNUSED))			return 0;	} else {		/* A fake inode describing an attribute. */		if (ni->type != na->type)			return 0;		if (ni->name_len != na->name_len)			return 0;		if (na->name_len && memcmp(ni->name, na->name,				na->name_len * sizeof(ntfschar)))			return 0;	}	/* Match! */	return 1;}/** * ntfs_init_locked_inode - initialize an inode * @vi:		vfs inode to initialize * @na:		ntfs attribute which to initialize @vi to * * Initialize the vfs inode @vi with the values from the ntfs attribute @na in * order to enable ntfs_test_inode() to do its work. * * If initializing the normal file/directory inode, set @na->type to AT_UNUSED. * In that case, @na->name and @na->name_len should be set to NULL and 0, * respectively. Although that is not strictly necessary as * ntfs_read_locked_inode() will fill them in later. * * Return 0 on success and -errno on error. * * NOTE: This function runs with the inode_lock spin lock held so it is not * allowed to sleep. (Hence the GFP_ATOMIC allocation.) */static int ntfs_init_locked_inode(struct inode *vi, ntfs_attr *na){	ntfs_inode *ni = NTFS_I(vi);	vi->i_ino = na->mft_no;	ni->type = na->type;	if (na->type == AT_INDEX_ALLOCATION)		NInoSetMstProtected(ni);	ni->name = na->name;	ni->name_len = na->name_len;	/* If initializing a normal inode, we are done. */	if (likely(na->type == AT_UNUSED)) {		BUG_ON(na->name);		BUG_ON(na->name_len);		return 0;	}	/* It is a fake inode. */	NInoSetAttr(ni);	/*	 * We have I30 global constant as an optimization as it is the name	 * in >99.9% of named attributes! The other <0.1% incur a GFP_ATOMIC	 * allocation but that is ok. And most attributes are unnamed anyway,	 * thus the fraction of named attributes with name != I30 is actually	 * absolutely tiny.	 */	if (na->name_len && na->name != I30) {		unsigned int i;		BUG_ON(!na->name);		i = na->name_len * sizeof(ntfschar);		ni->name = kmalloc(i + sizeof(ntfschar), GFP_ATOMIC);		if (!ni->name)			return -ENOMEM;		memcpy(ni->name, na->name, i);		ni->name[na->name_len] = 0;	}	return 0;}typedef int (*set_t)(struct inode *, void *);static int ntfs_read_locked_inode(struct inode *vi);static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi);static int ntfs_read_locked_index_inode(struct inode *base_vi,		struct inode *vi);/** * ntfs_iget - obtain a struct inode corresponding to a specific normal inode * @sb:		super block of mounted volume * @mft_no:	mft record number / inode number to obtain * * Obtain the struct inode corresponding to a specific normal inode (i.e. a * file or directory). * * If the inode is in the cache, it is just returned with an increased * reference count. Otherwise, a new struct inode is allocated and initialized, * and finally ntfs_read_locked_inode() is called to read in the inode and * fill in the remainder of the inode structure. * * Return the struct inode on success. Check the return value with IS_ERR() and * if true, the function failed and the error code is obtained from PTR_ERR(). */struct inode *ntfs_iget(struct super_block *sb, unsigned long mft_no){	struct inode *vi;	int err;	ntfs_attr na;	na.mft_no = mft_no;	na.type = AT_UNUSED;	na.name = NULL;	na.name_len = 0;	vi = iget5_locked(sb, mft_no, (test_t)ntfs_test_inode,			(set_t)ntfs_init_locked_inode, &na);	if (unlikely(!vi))		return ERR_PTR(-ENOMEM);	err = 0;	/* If this is a freshly allocated inode, need to read it now. */	if (vi->i_state & I_NEW) {		err = ntfs_read_locked_inode(vi);		unlock_new_inode(vi);	}	/*	 * There is no point in keeping bad inodes around if the failure was	 * due to ENOMEM. We want to be able to retry again later.	 */	if (unlikely(err == -ENOMEM)) {		iput(vi);		vi = ERR_PTR(err);	}	return vi;}/** * ntfs_attr_iget - obtain a struct inode corresponding to an attribute * @base_vi:	vfs base inode containing the attribute * @type:	attribute type * @name:	Unicode name of the attribute (NULL if unnamed) * @name_len:	length of @name in Unicode characters (0 if unnamed) * * Obtain the (fake) struct inode corresponding to the attribute specified by * @type, @name, and @name_len, which is present in the base mft record * specified by the vfs inode @base_vi. * * If the attribute inode is in the cache, it is just returned with an * increased reference count. Otherwise, a new struct inode is allocated and * initialized, and finally ntfs_read_locked_attr_inode() is called to read the * attribute and fill in the inode structure. * * Note, for index allocation attributes, you need to use ntfs_index_iget() * instead of ntfs_attr_iget() as working with indices is a lot more complex. * * Return the struct inode of the attribute inode on success. Check the return * value with IS_ERR() and if true, the function failed and the error code is * obtained from PTR_ERR(). */struct inode *ntfs_attr_iget(struct inode *base_vi, ATTR_TYPE type,		ntfschar *name, u32 name_len){	struct inode *vi;	int err;	ntfs_attr na;	/* Make sure no one calls ntfs_attr_iget() for indices. */	BUG_ON(type == AT_INDEX_ALLOCATION);	na.mft_no = base_vi->i_ino;	na.type = type;	na.name = name;	na.name_len = name_len;	vi = iget5_locked(base_vi->i_sb, na.mft_no, (test_t)ntfs_test_inode,			(set_t)ntfs_init_locked_inode, &na);	if (unlikely(!vi))		return ERR_PTR(-ENOMEM);	err = 0;	/* If this is a freshly allocated inode, need to read it now. */	if (vi->i_state & I_NEW) {		err = ntfs_read_locked_attr_inode(base_vi, vi);		unlock_new_inode(vi);	}	/*	 * There is no point in keeping bad attribute inodes around. This also	 * simplifies things in that we never need to check for bad attribute	 * inodes elsewhere.	 */	if (unlikely(err)) {		iput(vi);		vi = ERR_PTR(err);	}	return vi;}/** * ntfs_index_iget - obtain a struct inode corresponding to an index * @base_vi:	vfs base inode containing the index related attributes * @name:	Unicode name of the index * @name_len:	length of @name in Unicode characters * * Obtain the (fake) struct inode corresponding to the index specified by @name * and @name_len, which is present in the base mft record specified by the vfs * inode @base_vi. * * If the index inode is in the cache, it is just returned with an increased * reference count.  Otherwise, a new struct inode is allocated and * initialized, and finally ntfs_read_locked_index_inode() is called to read * the index related attributes and fill in the inode structure. * * Return the struct inode of the index inode on success. Check the return * value with IS_ERR() and if true, the function failed and the error code is * obtained from PTR_ERR(). */struct inode *ntfs_index_iget(struct inode *base_vi, ntfschar *name,		u32 name_len){	struct inode *vi;	int err;	ntfs_attr na;	na.mft_no = base_vi->i_ino;	na.type = AT_INDEX_ALLOCATION;	na.name = name;	na.name_len = name_len;	vi = iget5_locked(base_vi->i_sb, na.mft_no, (test_t)ntfs_test_inode,			(set_t)ntfs_init_locked_inode, &na);	if (unlikely(!vi))		return ERR_PTR(-ENOMEM);	err = 0;	/* If this is a freshly allocated inode, need to read it now. */	if (vi->i_state & I_NEW) {		err = ntfs_read_locked_index_inode(base_vi, vi);		unlock_new_inode(vi);	}	/*	 * There is no point in keeping bad index inodes around.  This also	 * simplifies things in that we never need to check for bad index	 * inodes elsewhere.	 */	if (unlikely(err)) {		iput(vi);		vi = ERR_PTR(err);	}	return vi;}struct inode *ntfs_alloc_big_inode(struct super_block *sb){	ntfs_inode *ni;	ntfs_debug("Entering.");	ni = kmem_cache_alloc(ntfs_big_inode_cache, GFP_NOFS);	if (likely(ni != NULL)) {		ni->state = 0;		return VFS_I(ni);	}	ntfs_error(sb, "Allocation of NTFS big inode structure failed.");	return NULL;}void ntfs_destroy_big_inode(struct inode *inode){	ntfs_inode *ni = NTFS_I(inode);	ntfs_debug("Entering.");	BUG_ON(ni->page);	if (!atomic_dec_and_test(&ni->count))		BUG();	kmem_cache_free(ntfs_big_inode_cache, NTFS_I(inode));}static inline ntfs_inode *ntfs_alloc_extent_inode(void){	ntfs_inode *ni;	ntfs_debug("Entering.");	ni = kmem_cache_alloc(ntfs_inode_cache, GFP_NOFS);	if (likely(ni != NULL)) {		ni->state = 0;		return ni;	}	ntfs_error(NULL, "Allocation of NTFS inode structure failed.");	return NULL;}static void ntfs_destroy_extent_inode(ntfs_inode *ni){	ntfs_debug("Entering.");	BUG_ON(ni->page);	if (!atomic_dec_and_test(&ni->count))		BUG();	kmem_cache_free(ntfs_inode_cache, ni);}/* * The attribute runlist lock has separate locking rules from the * normal runlist lock, so split the two lock-classes: */static struct lock_class_key attr_list_rl_lock_class;/** * __ntfs_init_inode - initialize ntfs specific part of an inode * @sb:		super block of mounted volume * @ni:		freshly allocated ntfs inode which to initialize * * Initialize an ntfs inode to defaults. * * NOTE: ni->mft_no, ni->state, ni->type, ni->name, and ni->name_len are left * untouched. Make sure to initialize them elsewhere. * * Return zero on success and -ENOMEM on error. */void __ntfs_init_inode(struct super_block *sb, ntfs_inode *ni){	ntfs_debug("Entering.");	rwlock_init(&ni->size_lock);	ni->initialized_size = ni->allocated_size = 0;	ni->seq_no = 0;	atomic_set(&ni->count, 1);	ni->vol = NTFS_SB(sb);	ntfs_init_runlist(&ni->runlist);	mutex_init(&ni->mrec_lock);	ni->page = NULL;	ni->page_ofs = 0;	ni->attr_list_size = 0;	ni->attr_list = NULL;	ntfs_init_runlist(&ni->attr_list_rl);	lockdep_set_class(&ni->attr_list_rl.lock,				&attr_list_rl_lock_class);	ni->itype.index.block_size = 0;	ni->itype.index.vcn_size = 0;	ni->itype.index.collation_rule = 0;	ni->itype.index.block_size_bits = 0;	ni->itype.index.vcn_size_bits = 0;	mutex_init(&ni->extent_lock);	ni->nr_extents = 0;	ni->ext.base_ntfs_ino = NULL;}/* * Extent inodes get MFT-mapped in a nested way, while the base inode

⌨️ 快捷键说明

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