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

📄 inode.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
 */static voidnfs_fill_inode(struct inode *inode, struct nfs_fh *fh, struct nfs_fattr *fattr){	/*	 * Check whether the mode has been set, as we only want to	 * do this once. (We don't allow inodes to change types.)	 */	if (inode->i_mode == 0) {		NFS_FILEID(inode) = fattr->fileid;		NFS_FSID(inode) = fattr->fsid;		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_file_inode_operations;		if (S_ISREG(inode->i_mode)) {			inode->i_fop = &nfs_file_operations;			inode->i_data.a_ops = &nfs_file_aops;		} else if (S_ISDIR(inode->i_mode)) {			inode->i_op = &nfs_dir_inode_operations;			inode->i_fop = &nfs_dir_operations;		} else if (S_ISLNK(inode->i_mode))			inode->i_op = &nfs_symlink_inode_operations;		else			init_special_inode(inode, inode->i_mode, fattr->rdev);		/*		 * Preset the size and mtime, as there's no need		 * to invalidate the caches.		 */ 		inode->i_size  = nfs_size_to_loff_t(fattr->size);		inode->i_mtime = nfs_time_to_secs(fattr->mtime);		inode->i_atime = nfs_time_to_secs(fattr->atime);		inode->i_ctime = nfs_time_to_secs(fattr->ctime);		NFS_CACHE_CTIME(inode) = fattr->ctime;		NFS_CACHE_MTIME(inode) = fattr->mtime;		NFS_CACHE_ATIME(inode) = fattr->atime;		NFS_CACHE_ISIZE(inode) = fattr->size;		NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);		NFS_ATTRTIMEO_UPDATE(inode) = jiffies;		memcpy(&inode->u.nfs_i.fh, fh, sizeof(inode->u.nfs_i.fh));	}	nfs_refresh_inode(inode, fattr);}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, unsigned long ino, 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_FSID(inode) != fattr->fsid)		return 0;	if (NFS_FILEID(inode) != fattr->fileid)		return 0;	if (memcmp(&inode->u.nfs_i.fh, fh, sizeof(inode->u.nfs_i.fh)) != 0)		return 0;	return 1;}intnfs_inode_is_stale(struct inode *inode, struct nfs_fh *fh, struct nfs_fattr *fattr){	/* Empty inodes are not stale */	if (!inode->i_mode)		return 0;	if ((fattr->mode & S_IFMT) != (inode->i_mode & S_IFMT))		return 1;	if (is_bad_inode(inode))		return 1;	/* Has the filehandle changed? If so is the old one stale? */	if (memcmp(&inode->u.nfs_i.fh, fh, sizeof(inode->u.nfs_i.fh)) != 0 &&	    __nfs_revalidate_inode(NFS_SERVER(inode),inode) == -ESTALE)		return 1;	return 0;}/* * This is our own version of iget that looks up inodes by file handle * instead of inode number.  We use this technique instead of using * the vfs read_inode function because there is no way to pass the * file handle or current attributes into the read_inode function. * */struct inode *nfs_fhget(struct dentry *dentry, struct nfs_fh *fhandle,				 struct nfs_fattr *fattr){	struct super_block *sb = dentry->d_sb;	dprintk("NFS: nfs_fhget(%s/%s fileid=%Ld)\n",		dentry->d_parent->d_name.name, dentry->d_name.name,		(long long)fattr->fileid);	return __nfs_fhget(sb, fhandle, fattr);}/* * Look up the inode by super block and fattr->fileid. */static struct inode *__nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr){	struct nfs_find_desc desc = { fh, fattr };	struct inode *inode = NULL;	unsigned long ino;	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;	}	ino = nfs_fattr_to_ino_t(fattr);	if (!(inode = iget4(sb, ino, nfs_find_actor, &desc)))		goto out_no_inode;	nfs_fill_inode(inode, fh, fattr);	dprintk("NFS: __nfs_fhget(%x/%Ld ct=%d)\n",		inode->i_dev, (long long)NFS_FILEID(inode),		atomic_read(&inode->i_count));out:	return inode;out_no_inode:	printk("__nfs_fhget: iget failed\n");	goto out;}intnfs_notify_change(struct dentry *dentry, struct iattr *attr){	struct inode *inode = dentry->d_inode;	struct nfs_fattr fattr;	int error;	/*	 * Make sure the inode is up-to-date.	 */	error = nfs_revalidate(dentry);	if (error) {#ifdef NFS_PARANOIAprintk("nfs_notify_change: revalidate failed, error=%d\n", error);#endif		goto out;	}	if (!S_ISREG(inode->i_mode))		attr->ia_valid &= ~ATTR_SIZE;	error = nfs_wb_all(inode);	if (error)		goto out;	error = NFS_PROTO(inode)->setattr(inode, &fattr, attr);	if (error)		goto out;	/*	 * If we changed the size or mtime, update the inode	 * now to avoid invalidating the page cache.	 */	if (attr->ia_valid & ATTR_SIZE) {		if (attr->ia_size != fattr.size)			printk("nfs_notify_change: attr=%Ld, fattr=%Ld??\n",			       (long long) attr->ia_size, (long long)fattr.size);		vmtruncate(inode, attr->ia_size);	}	/*	 * If we changed the size or mtime, update the inode	 * now to avoid invalidating the page cache.	 */	if (!(fattr.valid & NFS_ATTR_WCC)) {		fattr.pre_size = NFS_CACHE_ISIZE(inode);		fattr.pre_mtime = NFS_CACHE_MTIME(inode);		fattr.pre_ctime = NFS_CACHE_CTIME(inode);		fattr.valid |= NFS_ATTR_WCC;	}	error = nfs_refresh_inode(inode, &fattr);out:	return error;}/* * Wait for the inode to get unlocked. * (Used for NFS_INO_LOCKED and NFS_INO_REVALIDATING). */intnfs_wait_on_inode(struct inode *inode, int flag){	struct rpc_clnt	*clnt = NFS_CLIENT(inode);	int error;	if (!(NFS_FLAGS(inode) & flag))		return 0;	atomic_inc(&inode->i_count);	error = nfs_wait_event(clnt, inode->i_wait, !(NFS_FLAGS(inode) & flag));	iput(inode);	return error;}/* * Externally visible revalidation function */intnfs_revalidate(struct dentry *dentry){	struct inode *inode = dentry->d_inode;	return nfs_revalidate_inode(NFS_SERVER(inode), inode);}/* * These are probably going to contain hooks for * allocating and releasing RPC credentials for * the file. I'll have to think about Tronds patch * a bit more.. */int nfs_open(struct inode *inode, struct file *filp){	struct rpc_auth *auth;	struct rpc_cred *cred;	lock_kernel();	auth = NFS_CLIENT(inode)->cl_auth;	cred = rpcauth_lookupcred(auth, 0);	filp->private_data = cred;	unlock_kernel();	return 0;}int nfs_release(struct inode *inode, struct file *filp){	struct rpc_auth *auth;	struct rpc_cred *cred;	lock_kernel();	auth = NFS_CLIENT(inode)->cl_auth;	cred = nfs_file_cred(filp);	if (cred)		rpcauth_releasecred(auth, cred);	unlock_kernel();	return 0;}/* * This function is called whenever some part of NFS notices that * the cached attributes have to be refreshed. */int__nfs_revalidate_inode(struct nfs_server *server, struct inode *inode){	int		 status = 0;	struct nfs_fattr fattr;	dfprintk(PAGECACHE, "NFS: revalidating (%x/%Ld)\n",		inode->i_dev, (long long)NFS_FILEID(inode));	lock_kernel();	if (!inode || is_bad_inode(inode) || NFS_STALE(inode)) {		unlock_kernel();		return -ESTALE;	}	while (NFS_REVALIDATING(inode)) {		status = nfs_wait_on_inode(inode, NFS_INO_REVALIDATING);		if (status < 0) {			unlock_kernel();			return status;		}		if (time_before(jiffies,NFS_READTIME(inode)+NFS_ATTRTIMEO(inode))) {			status = NFS_STALE(inode) ? -ESTALE : 0;			goto out_nowait;		}	}	NFS_FLAGS(inode) |= NFS_INO_REVALIDATING;	status = NFS_PROTO(inode)->getattr(inode, &fattr);	if (status) {		dfprintk(PAGECACHE, "nfs_revalidate_inode: (%x/%Ld) getattr failed, error=%d\n",			 inode->i_dev, (long long)NFS_FILEID(inode), status);		if (status == -ESTALE) {			NFS_FLAGS(inode) |= NFS_INO_STALE;			remove_inode_hash(inode);		}		goto out;	}	status = nfs_refresh_inode(inode, &fattr);	if (status) {		dfprintk(PAGECACHE, "nfs_revalidate_inode: (%x/%Ld) refresh failed, error=%d\n",			 inode->i_dev, (long long)NFS_FILEID(inode), status);		goto out;	}	dfprintk(PAGECACHE, "NFS: (%x/%Ld) revalidation complete\n",		inode->i_dev, (long long)NFS_FILEID(inode));out:	NFS_FLAGS(inode) &= ~NFS_INO_REVALIDATING;	wake_up(&inode->i_wait); out_nowait:	unlock_kernel();	return status;}/* * Many nfs protocol calls return the new file attributes after * an operation.  Here we update the inode to reflect the state * of the server's inode. * * This is a bit tricky because we have to make sure all dirty pages * have been sent off to the server before calling invalidate_inode_pages. * To make sure no other process adds more write requests while we try * our best to flush them, we make them sleep during the attribute refresh. * * A very similar scenario holds for the dir cache. */intnfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr){	__u64		new_size, new_mtime;	loff_t		new_isize;	int		invalid = 0;	int		error = -EIO;	if (!inode || !fattr) {		printk(KERN_ERR "nfs_refresh_inode: inode or fattr is NULL\n");		goto out;	}	if (inode->i_mode == 0) {		printk(KERN_ERR "nfs_refresh_inode: empty inode\n");		goto out;	}	if ((fattr->valid & NFS_ATTR_FATTR) == 0)		goto out;	if (is_bad_inode(inode))		goto out;	dfprintk(VFS, "NFS: refresh_inode(%x/%ld ct=%d info=0x%x)\n",			inode->i_dev, inode->i_ino,			atomic_read(&inode->i_count), fattr->valid);	if (NFS_FSID(inode) != fattr->fsid ||	    NFS_FILEID(inode) != fattr->fileid) {		printk(KERN_ERR "nfs_refresh_inode: inode number mismatch\n"		       "expected (0x%Lx/0x%Lx), got (0x%Lx/0x%Lx)\n",		       (long long)NFS_FSID(inode), (long long)NFS_FILEID(inode),		       (long long)fattr->fsid, (long long)fattr->fileid);		goto out;	}	/*	 * Make sure the inode's type hasn't changed.	 */	if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT))		goto out_changed; 	new_mtime = fattr->mtime;	new_size = fattr->size; 	new_isize = nfs_size_to_loff_t(fattr->size);	error = 0;	/*	 * Update the read time so we don't revalidate too often.	 */	NFS_READTIME(inode) = jiffies;	/*	 * Note: NFS_CACHE_ISIZE(inode) reflects the state of the cache.	 *       NOT inode->i_size!!!	 */	if (NFS_CACHE_ISIZE(inode) != new_size) {#ifdef NFS_DEBUG_VERBOSE		printk(KERN_DEBUG "NFS: isize change on %x/%ld\n", inode->i_dev, inode->i_ino);#endif		invalid = 1;	}	/*	 * Note: we don't check inode->i_mtime since pipes etc.	 *       can change this value in VFS without requiring a	 *	 cache revalidation.	 */	if (NFS_CACHE_MTIME(inode) != new_mtime) {#ifdef NFS_DEBUG_VERBOSE		printk(KERN_DEBUG "NFS: mtime change on %x/%ld\n", inode->i_dev, inode->i_ino);#endif		invalid = 1;	}	/* Check Weak Cache Consistency data.	 * If size and mtime match the pre-operation values, we can	 * assume that any attribute changes were caused by our NFS         * operation, so there's no need to invalidate the caches.         */        if ((fattr->valid & NFS_ATTR_WCC)	    && NFS_CACHE_ISIZE(inode) == fattr->pre_size	    && NFS_CACHE_MTIME(inode) == fattr->pre_mtime) {		invalid = 0;	}	/*	 * If we have pending writebacks, things can get	 * messy.	 */	if (nfs_have_writebacks(inode) && new_isize < inode->i_size)		new_isize = inode->i_size;	NFS_CACHE_CTIME(inode) = fattr->ctime;	inode->i_ctime = nfs_time_to_secs(fattr->ctime);	/* If we've been messing around with atime, don't	 * update it. Save the server value in NFS_CACHE_ATIME.	 */	NFS_CACHE_ATIME(inode) = fattr->atime;	if (time_before(inode->i_atime, nfs_time_to_secs(fattr->atime)))		inode->i_atime = nfs_time_to_secs(fattr->atime);	NFS_CACHE_MTIME(inode) = new_mtime;	inode->i_mtime = nfs_time_to_secs(new_mtime);	NFS_CACHE_ISIZE(inode) = new_size;	inode->i_size = new_isize;	inode->i_mode = fattr->mode;	inode->i_nlink = fattr->nlink;	inode->i_uid = fattr->uid;	inode->i_gid = fattr->gid;	if (fattr->valid & NFS_ATTR_FATTR_V3) {		/*		 * report the blocks in 512byte units		 */		inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used);		inode->i_blksize = inode->i_sb->s_blocksize; 	} else { 		inode->i_blocks = fattr->du.nfs2.blocks; 		inode->i_blksize = fattr->du.nfs2.blocksize; 	} 	inode->i_rdev = 0; 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) 		inode->i_rdev = to_kdev_t(fattr->rdev); 	/* Update attrtimeo value */	if (!invalid && time_after(jiffies, NFS_ATTRTIMEO_UPDATE(inode)+NFS_ATTRTIMEO(inode))) {		if ((NFS_ATTRTIMEO(inode) <<= 1) > NFS_MAXATTRTIMEO(inode))			NFS_ATTRTIMEO(inode) = NFS_MAXATTRTIMEO(inode);		NFS_ATTRTIMEO_UPDATE(inode) = jiffies;	}	if (invalid)		nfs_zap_caches(inode);out:	return error;out_changed:	/*	 * Big trouble! The inode has become a different object.	 */#ifdef NFS_PARANOIA	printk(KERN_DEBUG "nfs_refresh_inode: inode %ld mode changed, %07o to %07o\n",	       inode->i_ino, inode->i_mode, fattr->mode);#endif	/*	 * No need to worry about unhashing the dentry, as the	 * lookup validation will know that the inode is bad.	 * (But we fall through to invalidate the caches.)	 */	nfs_invalidate_inode(inode);	goto out;}/* * File system information */static DECLARE_FSTYPE(nfs_fs_type, "nfs", nfs_read_super, FS_ODD_RENAME);extern int nfs_init_nfspagecache(void);extern void nfs_destroy_nfspagecache(void);extern int nfs_init_readpagecache(void);extern int nfs_destroy_readpagecache(void);/* * Initialize NFS */intinit_nfs_fs(void){	int err;	err = nfs_init_nfspagecache();	if (err)		return err;	err = nfs_init_readpagecache();	if (err)		return err;#ifdef CONFIG_PROC_FS	rpc_proc_register(&nfs_rpcstat);#endif        return register_filesystem(&nfs_fs_type);}/* * Every kernel module contains stuff like this. */#ifdef MODULEEXPORT_NO_SYMBOLS;/* Not quite true; I just maintain it */MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");intinit_module(void){	return init_nfs_fs();}voidcleanup_module(void){	nfs_destroy_readpagecache();	nfs_destroy_nfspagecache();#ifdef CONFIG_PROC_FS	rpc_proc_unregister("nfs");#endif	unregister_filesystem(&nfs_fs_type);}#endif

⌨️ 快捷键说明

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