diff options
Diffstat (limited to 'fs/nfs/inode.c')
| -rw-r--r-- | fs/nfs/inode.c | 118 | 
1 files changed, 49 insertions, 69 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index c6073139b40..2f6f78c4b42 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -285,9 +285,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)  		inode->i_mode = fattr->mode;  		if ((fattr->valid & NFS_ATTR_FATTR_MODE) == 0  				&& nfs_server_capable(inode, NFS_CAP_MODE)) -			nfsi->cache_validity |= NFS_INO_INVALID_ATTR -				| NFS_INO_INVALID_ACCESS -				| NFS_INO_INVALID_ACL; +			nfsi->cache_validity |= NFS_INO_INVALID_ATTR;  		/* Why so? Because we want revalidate for devices/FIFOs, and  		 * that's precisely what we have in nfs_file_inode_operations.  		 */ @@ -300,8 +298,6 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)  			inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->dir_inode_ops;  			inode->i_fop = &nfs_dir_operations;  			inode->i_data.a_ops = &nfs_dir_aops; -			if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS)) -				set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags);  			/* Deal with crossing mountpoints */  			if (fattr->valid & NFS_ATTR_FATTR_MOUNTPOINT ||  					fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) { @@ -327,6 +323,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)  		inode->i_gid = -2;  		inode->i_blocks = 0;  		memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); +		nfsi->write_io = 0; +		nfsi->read_io = 0;  		nfsi->read_cache_jiffies = fattr->time_start;  		nfsi->attr_gencount = fattr->gencount; @@ -337,24 +335,19 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)  		if (fattr->valid & NFS_ATTR_FATTR_MTIME)  			inode->i_mtime = fattr->mtime;  		else if (nfs_server_capable(inode, NFS_CAP_MTIME)) -			nfsi->cache_validity |= NFS_INO_INVALID_ATTR -				| NFS_INO_INVALID_DATA; +			nfsi->cache_validity |= NFS_INO_INVALID_ATTR;  		if (fattr->valid & NFS_ATTR_FATTR_CTIME)  			inode->i_ctime = fattr->ctime;  		else if (nfs_server_capable(inode, NFS_CAP_CTIME)) -			nfsi->cache_validity |= NFS_INO_INVALID_ATTR -				| NFS_INO_INVALID_ACCESS -				| NFS_INO_INVALID_ACL; +			nfsi->cache_validity |= NFS_INO_INVALID_ATTR;  		if (fattr->valid & NFS_ATTR_FATTR_CHANGE)  			inode->i_version = fattr->change_attr;  		else if (nfs_server_capable(inode, NFS_CAP_CHANGE_ATTR)) -			nfsi->cache_validity |= NFS_INO_INVALID_ATTR -				| NFS_INO_INVALID_DATA; +			nfsi->cache_validity |= NFS_INO_INVALID_ATTR;  		if (fattr->valid & NFS_ATTR_FATTR_SIZE)  			inode->i_size = nfs_size_to_loff_t(fattr->size);  		else  			nfsi->cache_validity |= NFS_INO_INVALID_ATTR -				| NFS_INO_INVALID_DATA  				| NFS_INO_REVAL_PAGECACHE;  		if (fattr->valid & NFS_ATTR_FATTR_NLINK)  			set_nlink(inode, fattr->nlink); @@ -363,15 +356,11 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)  		if (fattr->valid & NFS_ATTR_FATTR_OWNER)  			inode->i_uid = fattr->uid;  		else if (nfs_server_capable(inode, NFS_CAP_OWNER)) -			nfsi->cache_validity |= NFS_INO_INVALID_ATTR -				| NFS_INO_INVALID_ACCESS -				| NFS_INO_INVALID_ACL; +			nfsi->cache_validity |= NFS_INO_INVALID_ATTR;  		if (fattr->valid & NFS_ATTR_FATTR_GROUP)  			inode->i_gid = fattr->gid;  		else if (nfs_server_capable(inode, NFS_CAP_OWNER_GROUP)) -			nfsi->cache_validity |= NFS_INO_INVALID_ATTR -				| NFS_INO_INVALID_ACCESS -				| NFS_INO_INVALID_ACL; +			nfsi->cache_validity |= NFS_INO_INVALID_ATTR;  		if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED)  			inode->i_blocks = fattr->du.nfs2.blocks;  		if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) { @@ -654,6 +643,7 @@ struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, fmode_t f  	nfs_init_lock_context(&ctx->lock_context);  	ctx->lock_context.open_context = ctx;  	INIT_LIST_HEAD(&ctx->list); +	ctx->mdsthreshold = NULL;  	return ctx;  } @@ -682,6 +672,7 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)  		put_rpccred(ctx->cred);  	dput(ctx->dentry);  	nfs_sb_deactive(sb); +	kfree(ctx->mdsthreshold);  	kfree(ctx);  } @@ -870,6 +861,15 @@ static int nfs_invalidate_mapping(struct inode *inode, struct address_space *map  	return 0;  } +static bool nfs_mapping_need_revalidate_inode(struct inode *inode) +{ +	if (nfs_have_delegated_attributes(inode)) +		return false; +	return (NFS_I(inode)->cache_validity & NFS_INO_REVAL_PAGECACHE) +		|| nfs_attribute_timeout(inode) +		|| NFS_STALE(inode); +} +  /**   * nfs_revalidate_mapping - Revalidate the pagecache   * @inode - pointer to host inode @@ -880,9 +880,7 @@ int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)  	struct nfs_inode *nfsi = NFS_I(inode);  	int ret = 0; -	if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) -			|| nfs_attribute_cache_expired(inode) -			|| NFS_STALE(inode)) { +	if (nfs_mapping_need_revalidate_inode(inode)) {  		ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode);  		if (ret < 0)  			goto out; @@ -948,6 +946,8 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat  	unsigned long invalid = 0; +	if (nfs_have_delegated_attributes(inode)) +		return 0;  	/* Has the inode gone and changed behind our back? */  	if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid)  		return -EIO; @@ -960,7 +960,7 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat  	/* Verify a few of the more important attributes */  	if ((fattr->valid & NFS_ATTR_FATTR_MTIME) && !timespec_equal(&inode->i_mtime, &fattr->mtime)) -		invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; +		invalid |= NFS_INO_INVALID_ATTR;  	if (fattr->valid & NFS_ATTR_FATTR_SIZE) {  		cur_size = i_size_read(inode); @@ -1279,14 +1279,26 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)  			nfs_display_fhandle_hash(NFS_FH(inode)),  			atomic_read(&inode->i_count), fattr->valid); -	if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid) -		goto out_fileid; +	if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid) { +		printk(KERN_ERR "NFS: server %s error: fileid changed\n" +			"fsid %s: expected fileid 0x%Lx, got 0x%Lx\n", +			NFS_SERVER(inode)->nfs_client->cl_hostname, +			inode->i_sb->s_id, (long long)nfsi->fileid, +			(long long)fattr->fileid); +		goto out_err; +	}  	/*  	 * Make sure the inode's type hasn't changed.  	 */ -	if ((fattr->valid & NFS_ATTR_FATTR_TYPE) && (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) -		goto out_changed; +	if ((fattr->valid & NFS_ATTR_FATTR_TYPE) && (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) { +		/* +		* Big trouble! The inode has become a different object. +		*/ +		printk(KERN_DEBUG "NFS: %s: inode %ld mode changed, %07o to %07o\n", +				__func__, inode->i_ino, inode->i_mode, fattr->mode); +		goto out_err; +	}  	server = NFS_SERVER(inode);  	/* Update the fsid? */ @@ -1314,7 +1326,11 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)  		if (inode->i_version != fattr->change_attr) {  			dprintk("NFS: change_attr change on server for file %s/%ld\n",  					inode->i_sb->s_id, inode->i_ino); -			invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; +			invalid |= NFS_INO_INVALID_ATTR +				| NFS_INO_INVALID_DATA +				| NFS_INO_INVALID_ACCESS +				| NFS_INO_INVALID_ACL +				| NFS_INO_REVAL_PAGECACHE;  			if (S_ISDIR(inode->i_mode))  				nfs_force_lookup_revalidate(inode);  			inode->i_version = fattr->change_attr; @@ -1323,38 +1339,15 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)  		invalid |= save_cache_validity;  	if (fattr->valid & NFS_ATTR_FATTR_MTIME) { -		/* NFSv2/v3: Check if the mtime agrees */ -		if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { -			dprintk("NFS: mtime change on server for file %s/%ld\n", -					inode->i_sb->s_id, inode->i_ino); -			invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; -			if (S_ISDIR(inode->i_mode)) -				nfs_force_lookup_revalidate(inode); -			memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); -		} +		memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));  	} else if (server->caps & NFS_CAP_MTIME)  		invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR -				| NFS_INO_INVALID_DATA -				| NFS_INO_REVAL_PAGECACHE  				| NFS_INO_REVAL_FORCED);  	if (fattr->valid & NFS_ATTR_FATTR_CTIME) { -		/* If ctime has changed we should definitely clear access+acl caches */ -		if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) { -			invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; -			/* and probably clear data for a directory too as utimes can cause -			 * havoc with our cache. -			 */ -			if (S_ISDIR(inode->i_mode)) { -				invalid |= NFS_INO_INVALID_DATA; -				nfs_force_lookup_revalidate(inode); -			} -			memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); -		} +		memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));  	} else if (server->caps & NFS_CAP_CTIME)  		invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR -				| NFS_INO_INVALID_ACCESS -				| NFS_INO_INVALID_ACL  				| NFS_INO_REVAL_FORCED);  	/* Check if our cached file size is stale */ @@ -1466,12 +1459,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)  		nfsi->cache_validity |= invalid;  	return 0; - out_changed: -	/* -	 * Big trouble! The inode has become a different object. -	 */ -	printk(KERN_DEBUG "NFS: %s: inode %ld mode changed, %07o to %07o\n", -			__func__, inode->i_ino, inode->i_mode, fattr->mode);   out_err:  	/*  	 * No need to worry about unhashing the dentry, as the @@ -1480,13 +1467,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)  	 */  	nfs_invalidate_inode(inode);  	return -ESTALE; - - out_fileid: -	printk(KERN_ERR "NFS: server %s error: fileid changed\n" -		"fsid %s: expected fileid 0x%Lx, got 0x%Lx\n", -		NFS_SERVER(inode)->nfs_client->cl_hostname, inode->i_sb->s_id, -		(long long)nfsi->fileid, (long long)fattr->fileid); -	goto out_err;  } @@ -1547,7 +1527,7 @@ static inline void nfs4_init_once(struct nfs_inode *nfsi)  	nfsi->delegation_state = 0;  	init_rwsem(&nfsi->rwsem);  	nfsi->layout = NULL; -	atomic_set(&nfsi->commits_outstanding, 0); +	atomic_set(&nfsi->commit_info.rpcs_out, 0);  #endif  } @@ -1559,9 +1539,9 @@ static void init_once(void *foo)  	INIT_LIST_HEAD(&nfsi->open_files);  	INIT_LIST_HEAD(&nfsi->access_cache_entry_lru);  	INIT_LIST_HEAD(&nfsi->access_cache_inode_lru); -	INIT_LIST_HEAD(&nfsi->commit_list); +	INIT_LIST_HEAD(&nfsi->commit_info.list);  	nfsi->npages = 0; -	nfsi->ncommit = 0; +	nfsi->commit_info.ncommit = 0;  	atomic_set(&nfsi->silly_count, 1);  	INIT_HLIST_HEAD(&nfsi->silly_list);  	init_waitqueue_head(&nfsi->waitqueue);  |