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

📄 inode.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 4 页
字号:
		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_update_inode(inode, &fattr, verifier);	if (status) {		dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n",			 inode->i_sb->s_id,			 (long long)NFS_FILEID(inode), status);		goto out;	}	flags = nfsi->flags;	/*	 * We may need to keep the attributes marked as invalid if	 * we raced with nfs_end_attr_update().	 */	if (verifier == nfsi->cache_change_attribute)		nfsi->flags &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME);	/* Do the page cache invalidation */	if (flags & NFS_INO_INVALID_DATA) {		if (S_ISREG(inode->i_mode)) {			if (filemap_fdatawrite(inode->i_mapping) == 0)				filemap_fdatawait(inode->i_mapping);			nfs_wb_all(inode);		}		nfsi->flags &= ~NFS_INO_INVALID_DATA;		invalidate_inode_pages2(inode->i_mapping);		memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));		dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n",				inode->i_sb->s_id,				(long long)NFS_FILEID(inode));		/* This ensures we revalidate dentries */		nfsi->cache_change_attribute++;	}	dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n",		inode->i_sb->s_id,		(long long)NFS_FILEID(inode));	NFS_FLAGS(inode) &= ~NFS_INO_STALE;out:	NFS_FLAGS(inode) &= ~NFS_INO_REVALIDATING;	wake_up(&nfsi->nfs_i_wait); out_nowait:	unlock_kernel();	return status;}int nfs_attribute_timeout(struct inode *inode){	struct nfs_inode *nfsi = NFS_I(inode);	if (nfs_have_delegation(inode, FMODE_READ))		return 0;	return time_after(jiffies, nfsi->read_cache_jiffies+nfsi->attrtimeo);}/** * nfs_revalidate_inode - Revalidate the inode attributes * @server - pointer to nfs_server struct * @inode - pointer to inode struct * * Updates inode attribute information by retrieving the data from the server. */int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode){	if (!(NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))			&& !nfs_attribute_timeout(inode))		return NFS_STALE(inode) ? -ESTALE : 0;	return __nfs_revalidate_inode(server, inode);}/** * nfs_begin_data_update * @inode - pointer to inode * Declare that a set of operations will update file data on the server */void nfs_begin_data_update(struct inode *inode){	atomic_inc(&NFS_I(inode)->data_updates);}/** * nfs_end_data_update * @inode - pointer to inode * Declare end of the operations that will update file data * This will mark the inode as immediately needing revalidation * of its attribute cache. */void nfs_end_data_update(struct inode *inode){	struct nfs_inode *nfsi = NFS_I(inode);	if (!nfs_have_delegation(inode, FMODE_READ)) {		/* Mark the attribute cache for revalidation */		nfsi->flags |= NFS_INO_INVALID_ATTR;		/* Directories and symlinks: invalidate page cache too */		if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))			nfsi->flags |= NFS_INO_INVALID_DATA;	}	nfsi->cache_change_attribute ++;	atomic_dec(&nfsi->data_updates);}/** * nfs_end_data_update_defer * @inode - pointer to inode * Declare end of the operations that will update file data * This will defer marking the inode as needing revalidation * unless there are no other pending updates. */void nfs_end_data_update_defer(struct inode *inode){	struct nfs_inode *nfsi = NFS_I(inode);	if (atomic_dec_and_test(&nfsi->data_updates)) {		/* Mark the attribute cache for revalidation */		nfsi->flags |= NFS_INO_INVALID_ATTR;		/* Directories and symlinks: invalidate page cache too */		if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))			nfsi->flags |= NFS_INO_INVALID_DATA;		nfsi->cache_change_attribute ++;	}}/** * nfs_refresh_inode - verify consistency of the inode attribute cache * @inode - pointer to inode * @fattr - updated attributes * * Verifies the attribute cache. If we have just changed the attributes, * so that fattr carries weak cache consistency data, then it may * also update the ctime/mtime/change_attribute. */int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr){	struct nfs_inode *nfsi = NFS_I(inode);	loff_t cur_size, new_isize;	int data_unstable;	/* Do we hold a delegation? */	if (nfs_have_delegation(inode, FMODE_READ))		return 0;	/* Are we in the process of updating data on the server? */	data_unstable = nfs_caches_unstable(inode);	if (fattr->valid & NFS_ATTR_FATTR_V4) {		if ((fattr->valid & NFS_ATTR_PRE_CHANGE) != 0				&& nfsi->change_attr == fattr->pre_change_attr)			nfsi->change_attr = fattr->change_attr;		if (!data_unstable && nfsi->change_attr != fattr->change_attr)			nfsi->flags |= NFS_INO_INVALID_ATTR;	}	if ((fattr->valid & NFS_ATTR_FATTR) == 0)		return 0;	/* Has the inode gone and changed behind our back? */	if (nfsi->fileid != fattr->fileid			|| (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT))		return -EIO;	cur_size = i_size_read(inode); 	new_isize = nfs_size_to_loff_t(fattr->size);	/* If we have atomic WCC data, we may update some attributes */	if ((fattr->valid & NFS_ATTR_WCC) != 0) {		if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime))			memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));		if (timespec_equal(&inode->i_mtime, &fattr->pre_mtime))			memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));	}	/* Verify a few of the more important attributes */	if (!data_unstable) {		if (!timespec_equal(&inode->i_mtime, &fattr->mtime)				|| cur_size != new_isize)			nfsi->flags |= NFS_INO_INVALID_ATTR;	} else if (S_ISREG(inode->i_mode) && new_isize > cur_size)			nfsi->flags |= NFS_INO_INVALID_ATTR;	/* Have any file permissions changed? */	if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)			|| inode->i_uid != fattr->uid			|| inode->i_gid != fattr->gid)		nfsi->flags |= NFS_INO_INVALID_ATTR;	/* Has the link count changed? */	if (inode->i_nlink != fattr->nlink)		nfsi->flags |= NFS_INO_INVALID_ATTR;	if (!timespec_equal(&inode->i_atime, &fattr->atime))		nfsi->flags |= NFS_INO_INVALID_ATIME;	nfsi->read_cache_jiffies = fattr->timestamp;	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. */static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsigned long verifier){	struct nfs_inode *nfsi = NFS_I(inode);	__u64		new_size;	loff_t		new_isize;	unsigned int	invalid = 0;	loff_t		cur_isize;	int data_unstable;	dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n",			__FUNCTION__, inode->i_sb->s_id, inode->i_ino,			atomic_read(&inode->i_count), fattr->valid);	if ((fattr->valid & NFS_ATTR_FATTR) == 0)		return 0;	if (nfsi->fileid != fattr->fileid) {		printk(KERN_ERR "%s: inode number mismatch\n"		       "expected (%s/0x%Lx), got (%s/0x%Lx)\n",		       __FUNCTION__,		       inode->i_sb->s_id, (long long)nfsi->fileid,		       inode->i_sb->s_id, (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;	/*	 * Update the read time so we don't revalidate too often.	 */	nfsi->read_cache_jiffies = fattr->timestamp;	/* Are we racing with known updates of the metadata on the server? */	data_unstable = ! nfs_verify_change_attribute(inode, verifier);	/* Check if the file size agrees */	new_size = fattr->size; 	new_isize = nfs_size_to_loff_t(fattr->size);	cur_isize = i_size_read(inode);	if (cur_isize != new_size) {#ifdef NFS_DEBUG_VERBOSE		printk(KERN_DEBUG "NFS: isize change on %s/%ld\n", inode->i_sb->s_id, inode->i_ino);#endif		/*		 * If we have pending writebacks, things can get		 * messy.		 */		if (S_ISREG(inode->i_mode) && data_unstable) {			if (new_isize > cur_isize) {				inode->i_size = new_isize;				invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;			}		} else {			inode->i_size = new_isize;			invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;		}	}	/*	 * Note: we don't check inode->i_mtime since pipes etc.	 *       can change this value in VFS without requiring a	 *	 cache revalidation.	 */	if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) {		memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));#ifdef NFS_DEBUG_VERBOSE		printk(KERN_DEBUG "NFS: mtime change on %s/%ld\n", inode->i_sb->s_id, inode->i_ino);#endif		if (!data_unstable)			invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;	}	if ((fattr->valid & NFS_ATTR_FATTR_V4)	    && nfsi->change_attr != fattr->change_attr) {#ifdef NFS_DEBUG_VERBOSE		printk(KERN_DEBUG "NFS: change_attr change on %s/%ld\n",		       inode->i_sb->s_id, inode->i_ino);#endif		nfsi->change_attr = fattr->change_attr;		if (!data_unstable)			invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;	}	memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));	memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime));	if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) ||	    inode->i_uid != fattr->uid ||	    inode->i_gid != fattr->gid) {		struct rpc_cred **cred = &NFS_I(inode)->cache_access.cred;		if (*cred) {			put_rpccred(*cred);			*cred = NULL;		}		invalid |= NFS_INO_INVALID_ATTR;	}	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 | NFS_ATTR_FATTR_V4)) {		/*		 * 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; 	}	/* Update attrtimeo value if we're out of the unstable period */	if (invalid & NFS_INO_INVALID_ATTR) {		nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);		nfsi->attrtimeo_timestamp = jiffies;	} else if (time_after(jiffies, nfsi->attrtimeo_timestamp+nfsi->attrtimeo)) {		if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode))			nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode);		nfsi->attrtimeo_timestamp = jiffies;	}	/* Don't invalidate the data if we were to blame */	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)				|| S_ISLNK(inode->i_mode)))		invalid &= ~NFS_INO_INVALID_DATA;	if (!nfs_have_delegation(inode, FMODE_READ))		nfsi->flags |= invalid;	return 0; out_changed:	/*	 * Big trouble! The inode has become a different object.	 */#ifdef NFS_PARANOIA	printk(KERN_DEBUG "%s: inode %ld mode changed, %07o to %07o\n",			__FUNCTION__, 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 int nfs_set_super(struct super_block *s, void *data){	s->s_fs_info = data;	return set_anon_super(s, data);} static int nfs_compare_super(struct super_block *sb, void *data){	struct nfs_server *server = data;	struct nfs_server *old = NFS_SB(sb);	if (old->addr.sin_addr.s_addr != server->addr.sin_addr.s_addr)		return 0;	if (old->addr.sin_port != server->addr.sin_port)		return 0;	return !nfs_compare_fh(&old->fh, &server->fh);}static struct super_block *nfs_get_sb(struct file_system_type *fs_type,	int flags, const char *dev_name, void *raw_data){	int error;	struct nfs_server *server;	struct super_block *s;	struct nfs_fh *root;	struct nfs_mount_data *data = raw_data;	if (!data) {		printk("nfs_read_super: missing data argument\n");		return ERR_PTR(-EINVAL);	}	server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL);	if (!server)		return ERR_PTR(-ENOMEM);	memset(server, 0, sizeof(struct nfs_server));	/* Zero out the NFS state stuff */	init_nfsv4_state(server);	if (data->version != NFS_MOUNT_VERSION) {		printk("nfs warning: mount version %s than kernel\n",			data->version < NFS_MOUNT_VERSION ? "older" : "newer");		if (data->version < 2)			data->namlen = 0;		if (data->version < 3)			data->bsize  = 0;		if (data->version < 4) {			data->flags &= ~NFS_MOUNT_VER3;			data->root.size = NFS2_FHSIZE;			memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);		}		if (data->version < 5)			data->flags &= ~NFS_MOUNT_SECFLAVOUR;	}	root = &server->fh;	if (data->flags & NFS_MOUNT_VER3)		root->size = data->root.size;	else		root->size = NFS2_FHSIZE;	if (root->size > sizeof(root->data)) {		printk("nfs_get_sb: invalid root filehandle\n");		kfree(server);		return ERR_PTR(-EINVAL);	}	memcpy(root->data, data->root.data, root->size);	/* We now require that the mount process passes the remote address */	memcpy(&server->addr, &data->addr, sizeof(server->addr));	if (server->addr.sin_addr.s_addr == INADDR_ANY) {		printk("NFS: mount program didn't pass remote address!\n");		kfree(server);		return ERR_PTR(-EINVAL);	}	s = sget(fs_type, nfs_compare_super, nfs_set_super, server);	if (IS_ERR(s) || s->s_root) {		kfree(server);		return s;	}	s->s_flags = flags;	/* Fire up rpciod if not yet running */	if (rpciod_up() != 0) {		printk(KERN_WARNING "NFS: couldn't start rpciod!\n");		kfree(server);		return ERR_PTR(-EIO);	}	error = nfs_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);	if (error) {		up_write(&s->s_umount);		deactivate_super(s);		return ERR_PTR(error);	}	s->s_flags |= MS_ACTIVE;	return s;}static void nfs_kill_super(struct super_block *s){	struct nfs_server *server = NFS_SB(s);	kill_anon_super(s);	nfs4_renewd_prepare_shutdown(server);	if (server->client != NULL && !IS_ERR(server->client))		rpc_shutdown_client(server->client);	if (server->client_sys != NULL && !IS_ERR(server->client_sys))		rpc_shutdown_client(server->client_sys);	if (!(server->flags & NFS_MOUNT_NONLM))		lockd_down();	/* release rpc.lockd */

⌨️ 快捷键说明

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