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

📄 inode.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  linux/fs/nfs/inode.c * *  Copyright (C) 1992  Rick Sladkey * *  nfs inode and superblock handling functions * *  Modularised by Alan Cox <Alan.Cox@linux.org>, while hacking some *  experimental NFS changes. Modularisation taken straight from SYS5 fs. * *  Change to nfs_read_super() to permit NFS mounts to multi-homed hosts. *  J.S.Peatfield@damtp.cam.ac.uk * */#include <linux/module.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/time.h>#include <linux/kernel.h>#include <linux/mm.h>#include <linux/string.h>#include <linux/stat.h>#include <linux/errno.h>#include <linux/unistd.h>#include <linux/sunrpc/clnt.h>#include <linux/sunrpc/stats.h>#include <linux/sunrpc/metrics.h>#include <linux/nfs_fs.h>#include <linux/nfs_mount.h>#include <linux/nfs4_mount.h>#include <linux/lockd/bind.h>#include <linux/smp_lock.h>#include <linux/seq_file.h>#include <linux/mount.h>#include <linux/nfs_idmap.h>#include <linux/vfs.h>#include <linux/inet.h>#include <linux/nfs_xdr.h>#include <asm/system.h>#include <asm/uaccess.h>#include "nfs4_fs.h"#include "callback.h"#include "delegation.h"#include "iostat.h"#include "internal.h"#define NFSDBG_FACILITY		NFSDBG_VFS#define NFS_64_BIT_INODE_NUMBERS_ENABLED	1/* Default is to see 64-bit inode numbers */static int enable_ino64 = NFS_64_BIT_INODE_NUMBERS_ENABLED;static void nfs_invalidate_inode(struct inode *);static int nfs_update_inode(struct inode *, struct nfs_fattr *);static void nfs_zap_acl_cache(struct inode *);static struct kmem_cache * nfs_inode_cachep;static inline unsigned longnfs_fattr_to_ino_t(struct nfs_fattr *fattr){	return nfs_fileid_to_ino_t(fattr->fileid);}/** * nfs_compat_user_ino64 - returns the user-visible inode number * @fileid: 64-bit fileid * * This function returns a 32-bit inode number if the boot parameter * nfs.enable_ino64 is zero. */u64 nfs_compat_user_ino64(u64 fileid){	int ino;	if (enable_ino64)		return fileid;	ino = fileid;	if (sizeof(ino) < sizeof(fileid))		ino ^= fileid >> (sizeof(fileid)-sizeof(ino)) * 8;	return ino;}int nfs_write_inode(struct inode *inode, int sync){	int ret;	if (sync) {		ret = filemap_fdatawait(inode->i_mapping);		if (ret == 0)			ret = nfs_commit_inode(inode, FLUSH_SYNC);	} else		ret = nfs_commit_inode(inode, 0);	if (ret >= 0)		return 0;	__mark_inode_dirty(inode, I_DIRTY_DATASYNC);	return ret;}void nfs_clear_inode(struct inode *inode){	/*	 * The following should never happen...	 */	BUG_ON(nfs_have_writebacks(inode));	BUG_ON(!list_empty(&NFS_I(inode)->open_files));	nfs_zap_acl_cache(inode);	nfs_access_zap_cache(inode);}/** * nfs_sync_mapping - helper to flush all mmapped dirty data to disk */int nfs_sync_mapping(struct address_space *mapping){	int ret;	if (mapping->nrpages == 0)		return 0;	unmap_mapping_range(mapping, 0, 0, 0);	ret = filemap_write_and_wait(mapping);	if (ret != 0)		goto out;	ret = nfs_wb_all(mapping->host);out:	return ret;}/* * Invalidate the local caches */static void nfs_zap_caches_locked(struct inode *inode){	struct nfs_inode *nfsi = NFS_I(inode);	int mode = inode->i_mode;	nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE);	nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);	nfsi->attrtimeo_timestamp = jiffies;	memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));	if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))		nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;	else		nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;}void nfs_zap_caches(struct inode *inode){	spin_lock(&inode->i_lock);	nfs_zap_caches_locked(inode);	spin_unlock(&inode->i_lock);}void nfs_zap_mapping(struct inode *inode, struct address_space *mapping){	if (mapping->nrpages != 0) {		spin_lock(&inode->i_lock);		NFS_I(inode)->cache_validity |= NFS_INO_INVALID_DATA;		spin_unlock(&inode->i_lock);	}}static void nfs_zap_acl_cache(struct inode *inode){	void (*clear_acl_cache)(struct inode *);	clear_acl_cache = NFS_PROTO(inode)->clear_acl_cache;	if (clear_acl_cache != NULL)		clear_acl_cache(inode);	spin_lock(&inode->i_lock);	NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_ACL;	spin_unlock(&inode->i_lock);}void nfs_invalidate_atime(struct inode *inode){	spin_lock(&inode->i_lock);	NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME;	spin_unlock(&inode->i_lock);}/* * Invalidate, but do not unhash, the inode. * NB: must be called with inode->i_lock held! */static void nfs_invalidate_inode(struct inode *inode){	set_bit(NFS_INO_STALE, &NFS_FLAGS(inode));	nfs_zap_caches_locked(inode);}struct nfs_find_desc {	struct nfs_fh		*fh;	struct nfs_fattr	*fattr;};/* * In NFSv3 we can have 64bit inode numbers. In order to support * this, and re-exported directories (also seen in NFSv2) * we are forced to allow 2 different inodes to have the same * i_ino. */static intnfs_find_actor(struct inode *inode, void *opaque){	struct nfs_find_desc	*desc = (struct nfs_find_desc *)opaque;	struct nfs_fh		*fh = desc->fh;	struct nfs_fattr	*fattr = desc->fattr;	if (NFS_FILEID(inode) != fattr->fileid)		return 0;	if (nfs_compare_fh(NFS_FH(inode), fh))		return 0;	if (is_bad_inode(inode) || NFS_STALE(inode))		return 0;	return 1;}static intnfs_init_locked(struct inode *inode, void *opaque){	struct nfs_find_desc	*desc = (struct nfs_find_desc *)opaque;	struct nfs_fattr	*fattr = desc->fattr;	NFS_FILEID(inode) = fattr->fileid;	nfs_copy_fh(NFS_FH(inode), desc->fh);	return 0;}/* Don't use READDIRPLUS on directories that we believe are too large */#define NFS_LIMIT_READDIRPLUS (8*PAGE_SIZE)/* * This is our front-end to iget that looks up inodes by file handle * instead of inode number. */struct inode *nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr){	struct nfs_find_desc desc = {		.fh	= fh,		.fattr	= fattr	};	struct inode *inode = ERR_PTR(-ENOENT);	unsigned long hash;	if ((fattr->valid & NFS_ATTR_FATTR) == 0)		goto out_no_inode;	if (!fattr->nlink) {		printk("NFS: Buggy server - nlink == 0!\n");		goto out_no_inode;	}	hash = nfs_fattr_to_ino_t(fattr);	inode = iget5_locked(sb, hash, nfs_find_actor, nfs_init_locked, &desc);	if (inode == NULL) {		inode = ERR_PTR(-ENOMEM);		goto out_no_inode;	}	if (inode->i_state & I_NEW) {		struct nfs_inode *nfsi = NFS_I(inode);		unsigned long now = jiffies;		/* We set i_ino for the few things that still rely on it,		 * such as stat(2) */		inode->i_ino = hash;		/* We can't support update_atime(), since the server will reset it */		inode->i_flags |= S_NOATIME|S_NOCMTIME;		inode->i_mode = fattr->mode;		/* Why so? Because we want revalidate for devices/FIFOs, and		 * that's precisely what we have in nfs_file_inode_operations.		 */		inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->file_inode_ops;		if (S_ISREG(inode->i_mode)) {			inode->i_fop = &nfs_file_operations;			inode->i_data.a_ops = &nfs_file_aops;			inode->i_data.backing_dev_info = &NFS_SB(sb)->backing_dev_info;		} else if (S_ISDIR(inode->i_mode)) {			inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->dir_inode_ops;			inode->i_fop = &nfs_dir_operations;			if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS)			    && fattr->size <= NFS_LIMIT_READDIRPLUS)				set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode));			/* Deal with crossing mountpoints */			if (!nfs_fsid_equal(&NFS_SB(sb)->fsid, &fattr->fsid)) {				if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL)					inode->i_op = &nfs_referral_inode_operations;				else					inode->i_op = &nfs_mountpoint_inode_operations;				inode->i_fop = NULL;			}		} else if (S_ISLNK(inode->i_mode))			inode->i_op = &nfs_symlink_inode_operations;		else			init_special_inode(inode, inode->i_mode, fattr->rdev);		nfsi->read_cache_jiffies = fattr->time_start;		nfsi->last_updated = now;		nfsi->cache_change_attribute = now;		inode->i_atime = fattr->atime;		inode->i_mtime = fattr->mtime;		inode->i_ctime = fattr->ctime;		if (fattr->valid & NFS_ATTR_FATTR_V4)			nfsi->change_attr = fattr->change_attr;		inode->i_size = nfs_size_to_loff_t(fattr->size);		inode->i_nlink = fattr->nlink;		inode->i_uid = fattr->uid;		inode->i_gid = fattr->gid;		if (fattr->valid & (NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4)) {			/*			 * report the blocks in 512byte units			 */			inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used);		} else {			inode->i_blocks = fattr->du.nfs2.blocks;		}		nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);		nfsi->attrtimeo_timestamp = now;		memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf));		nfsi->access_cache = RB_ROOT;		unlock_new_inode(inode);	} else		nfs_refresh_inode(inode, fattr);	dprintk("NFS: nfs_fhget(%s/%Ld ct=%d)\n",		inode->i_sb->s_id,		(long long)NFS_FILEID(inode),		atomic_read(&inode->i_count));out:	return inode;out_no_inode:	dprintk("nfs_fhget: iget failed with error %ld\n", PTR_ERR(inode));	goto out;}#define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET)intnfs_setattr(struct dentry *dentry, struct iattr *attr){	struct inode *inode = dentry->d_inode;	struct nfs_fattr fattr;	int error;	nfs_inc_stats(inode, NFSIOS_VFSSETATTR);	/* skip mode change if it's just for clearing setuid/setgid */	if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))		attr->ia_valid &= ~ATTR_MODE;	if (attr->ia_valid & ATTR_SIZE) {		if (!S_ISREG(inode->i_mode) || attr->ia_size == i_size_read(inode))			attr->ia_valid &= ~ATTR_SIZE;	}	/* Optimization: if the end result is no change, don't RPC */	attr->ia_valid &= NFS_VALID_ATTRS;	if (attr->ia_valid == 0)		return 0;	lock_kernel();	/* Write all dirty data */	if (S_ISREG(inode->i_mode)) {		filemap_write_and_wait(inode->i_mapping);		nfs_wb_all(inode);	}	/*	 * Return any delegations if we're going to change ACLs	 */	if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0)		nfs_inode_return_delegation(inode);	error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr);	if (error == 0)		nfs_refresh_inode(inode, &fattr);	unlock_kernel();	return error;}/** * nfs_setattr_update_inode - Update inode metadata after a setattr call. * @inode: pointer to struct inode * @attr: pointer to struct iattr * * Note: we do this in the *proc.c in order to ensure that *       it works for things like exclusive creates too. */void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr){	if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) {		if ((attr->ia_valid & ATTR_MODE) != 0) {			int mode = attr->ia_mode & S_IALLUGO;			mode |= inode->i_mode & ~S_IALLUGO;			inode->i_mode = mode;		}		if ((attr->ia_valid & ATTR_UID) != 0)			inode->i_uid = attr->ia_uid;		if ((attr->ia_valid & ATTR_GID) != 0)			inode->i_gid = attr->ia_gid;		spin_lock(&inode->i_lock);		NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;		spin_unlock(&inode->i_lock);	}	if ((attr->ia_valid & ATTR_SIZE) != 0) {		nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC);		inode->i_size = attr->ia_size;		vmtruncate(inode, attr->ia_size);	}}static int nfs_wait_schedule(void *word){	if (signal_pending(current))		return -ERESTARTSYS;	schedule();	return 0;}

⌨️ 快捷键说明

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