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

📄 inode.c

📁 嵌入式系统设计与实验教材二源码linux内核移植与编译
💻 C
📖 第 1 页 / 共 3 页
字号:
		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;	}	/* Force an attribute cache update */	NFS_CACHEINV(inode);	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);}/* * Ensure that mmap has a recent RPC credential for use when writing out * shared pages */static inline voidnfs_set_mmcred(struct inode *inode, struct rpc_cred *cred){	struct rpc_cred **p = &NFS_I(inode)->mm_cred,			*oldcred = *p;	*p = get_rpccred(cred);	if (oldcred)		put_rpccred(oldcred);}/* * 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;	if (filp->f_mode & FMODE_WRITE)		nfs_set_mmcred(inode, cred);	unlock_kernel();	return 0;}int nfs_release(struct inode *inode, struct file *filp){	struct rpc_cred *cred;	lock_kernel();	cred = nfs_file_cred(filp);	if (cred)		put_rpccred(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 = -ESTALE;	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)) 		goto out_nowait;	if (NFS_STALE(inode) && inode != inode->i_sb->s_root->d_inode) 		goto out_nowait;	while (NFS_REVALIDATING(inode)) {		status = nfs_wait_on_inode(inode, NFS_INO_REVALIDATING);		if (status < 0)			goto out_nowait;		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;			if (inode != inode->i_sb->s_root->d_inode)				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));	NFS_FLAGS(inode) &= ~NFS_INO_STALE;out:	NFS_FLAGS(inode) &= ~NFS_INO_REVALIDATING;	wake_up(&inode->i_wait); out_nowait:	unlock_kernel();	return status;}/* * nfs_fattr_obsolete - Test if attribute data is newer than cached data * @inode: inode * @fattr: attributes to test * * Avoid stuffing the attribute cache with obsolete information. * We always accept updates if the attribute cache timed out, or if * fattr->ctime is newer than our cached value. * If fattr->ctime matches the cached value, we still accept the update * if it increases the file size. */static inlineint nfs_fattr_obsolete(struct inode *inode, struct nfs_fattr *fattr){	s64 cdif;	if (time_after(jiffies, NFS_READTIME(inode)+NFS_ATTRTIMEO(inode)))		goto out_valid;	if ((cdif = (s64)fattr->ctime - (s64)NFS_CACHE_CTIME(inode)) > 0)		goto out_valid;	/* Ugh... */	if (cdif == 0 && fattr->size > NFS_CACHE_ISIZE(inode))		goto out_valid;	return -1; out_valid:	return 0;}/* * 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. */int__nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr){	__u64		new_size, new_mtime;	loff_t		new_isize;	time_t		new_atime;	int		invalid = 0;	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_err;	}	/*	 * 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);	new_atime = nfs_time_to_secs(fattr->atime);	/* Avoid races */	if (nfs_fattr_obsolete(inode, fattr))		goto out_nochange;	/*	 * 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);	inode->i_atime = new_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);	return 0; out_nochange:	if (new_atime - inode->i_atime > 0)		inode->i_atime = new_atime;	return 0; 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); out_err:	return -EIO;}/* * 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);extern int nfs_init_writepagecache(void);extern int nfs_destroy_writepagecache(void);/* * Initialize NFS */static int __init init_nfs_fs(void){	int err;	err = nfs_init_nfspagecache();	if (err)		return err;	err = nfs_init_readpagecache();	if (err)		return err;	err = nfs_init_writepagecache();	if (err)		return err;#ifdef CONFIG_PROC_FS	rpc_proc_register(&nfs_rpcstat);#endif        return register_filesystem(&nfs_fs_type);}static void __exit exit_nfs_fs(void){	nfs_destroy_writepagecache();	nfs_destroy_readpagecache();	nfs_destroy_nfspagecache();#ifdef CONFIG_PROC_FS	rpc_proc_unregister("nfs");#endif	unregister_filesystem(&nfs_fs_type);}EXPORT_NO_SYMBOLS;/* Not quite true; I just maintain it */MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");MODULE_LICENSE("GPL");module_init(init_nfs_fs)module_exit(exit_nfs_fs)

⌨️ 快捷键说明

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