Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fe51beec authored by Trond Myklebust's avatar Trond Myklebust
Browse files

[PATCH] NFS: Ensure that fstat() always returns the correct mtime



 Even if the file is open for writes.

 Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 7d52e862
Loading
Loading
Loading
Loading
+22 −6
Original line number Original line Diff line number Diff line
@@ -127,6 +127,21 @@ nfs_file_release(struct inode *inode, struct file *filp)
	return NFS_PROTO(inode)->file_release(inode, filp);
	return NFS_PROTO(inode)->file_release(inode, filp);
}
}


/**
 * nfs_revalidate_file - Revalidate the page cache & related metadata
 * @inode - pointer to inode struct
 * @file - pointer to file
 */
static int nfs_revalidate_file(struct inode *inode, struct file *filp)
{
	int retval = 0;

	if ((NFS_FLAGS(inode) & NFS_INO_REVAL_PAGECACHE) || nfs_attribute_timeout(inode))
		retval = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
	nfs_revalidate_mapping(inode, filp->f_mapping);
	return 0;
}

/**
/**
 * nfs_revalidate_size - Revalidate the file size
 * nfs_revalidate_size - Revalidate the file size
 * @inode - pointer to inode struct
 * @inode - pointer to inode struct
@@ -149,7 +164,8 @@ static int nfs_revalidate_file_size(struct inode *inode, struct file *filp)
		goto force_reval;
		goto force_reval;
	if (nfsi->npages != 0)
	if (nfsi->npages != 0)
		return 0;
		return 0;
	return nfs_revalidate_inode(server, inode);
	if (!(NFS_FLAGS(inode) & NFS_INO_REVAL_PAGECACHE) && !nfs_attribute_timeout(inode))
		return 0;
force_reval:
force_reval:
	return __nfs_revalidate_inode(server, inode);
	return __nfs_revalidate_inode(server, inode);
}
}
@@ -210,7 +226,7 @@ nfs_file_read(struct kiocb *iocb, char __user * buf, size_t count, loff_t pos)
		dentry->d_parent->d_name.name, dentry->d_name.name,
		dentry->d_parent->d_name.name, dentry->d_name.name,
		(unsigned long) count, (unsigned long) pos);
		(unsigned long) count, (unsigned long) pos);


	result = nfs_revalidate_inode(NFS_SERVER(inode), inode);
	result = nfs_revalidate_file(inode, iocb->ki_filp);
	if (!result)
	if (!result)
		result = generic_file_aio_read(iocb, buf, count, pos);
		result = generic_file_aio_read(iocb, buf, count, pos);
	return result;
	return result;
@@ -228,7 +244,7 @@ nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count,
		dentry->d_parent->d_name.name, dentry->d_name.name,
		dentry->d_parent->d_name.name, dentry->d_name.name,
		(unsigned long) count, (unsigned long long) *ppos);
		(unsigned long) count, (unsigned long long) *ppos);


	res = nfs_revalidate_inode(NFS_SERVER(inode), inode);
	res = nfs_revalidate_file(inode, filp);
	if (!res)
	if (!res)
		res = generic_file_sendfile(filp, ppos, count, actor, target);
		res = generic_file_sendfile(filp, ppos, count, actor, target);
	return res;
	return res;
@@ -244,7 +260,7 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
	dfprintk(VFS, "nfs: mmap(%s/%s)\n",
	dfprintk(VFS, "nfs: mmap(%s/%s)\n",
		dentry->d_parent->d_name.name, dentry->d_name.name);
		dentry->d_parent->d_name.name, dentry->d_name.name);


	status = nfs_revalidate_inode(NFS_SERVER(inode), inode);
	status = nfs_revalidate_file(inode, file);
	if (!status)
	if (!status)
		status = generic_file_mmap(file, vma);
		status = generic_file_mmap(file, vma);
	return status;
	return status;
@@ -340,7 +356,7 @@ nfs_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t
		result = nfs_revalidate_file_size(inode, iocb->ki_filp);
		result = nfs_revalidate_file_size(inode, iocb->ki_filp);
		if (result)
		if (result)
			goto out;
			goto out;
	} else
	}
	nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
	nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);


	result = count;
	result = count;
+16 −8
Original line number Original line Diff line number Diff line
@@ -620,9 +620,9 @@ nfs_zap_caches(struct inode *inode)


	memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
	memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
	if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))
	if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))
		nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
		nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
	else
	else
		nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
		nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
}
}


static void nfs_zap_acl_cache(struct inode *inode)
static void nfs_zap_acl_cache(struct inode *inode)
@@ -1055,6 +1055,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
		goto out;
		goto out;
	}
	}
	flags = nfsi->flags;
	flags = nfsi->flags;
	nfsi->flags &= ~NFS_INO_REVAL_PAGECACHE;
	/*
	/*
	 * We may need to keep the attributes marked as invalid if
	 * We may need to keep the attributes marked as invalid if
	 * we raced with nfs_end_attr_update().
	 * we raced with nfs_end_attr_update().
@@ -1187,8 +1188,11 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
		if ((fattr->valid & NFS_ATTR_PRE_CHANGE) != 0
		if ((fattr->valid & NFS_ATTR_PRE_CHANGE) != 0
				&& nfsi->change_attr == fattr->pre_change_attr)
				&& nfsi->change_attr == fattr->pre_change_attr)
			nfsi->change_attr = fattr->change_attr;
			nfsi->change_attr = fattr->change_attr;
		if (!data_unstable && nfsi->change_attr != fattr->change_attr)
		if (nfsi->change_attr != fattr->change_attr) {
			nfsi->flags |= NFS_INO_INVALID_ATTR;
			nfsi->flags |= NFS_INO_INVALID_ATTR;
			if (!data_unstable)
				nfsi->flags |= NFS_INO_REVAL_PAGECACHE;
		}
	}
	}


	if ((fattr->valid & NFS_ATTR_FATTR) == 0)
	if ((fattr->valid & NFS_ATTR_FATTR) == 0)
@@ -1211,12 +1215,16 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
	}
	}


	/* Verify a few of the more important attributes */
	/* Verify a few of the more important attributes */
	if (!data_unstable) {
	if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) {
		if (!timespec_equal(&inode->i_mtime, &fattr->mtime)
				|| cur_size != new_isize)
		nfsi->flags |= NFS_INO_INVALID_ATTR;
		nfsi->flags |= NFS_INO_INVALID_ATTR;
	} else if (new_isize != cur_size && nfsi->npages == 0)
		if (!data_unstable)
			nfsi->flags |= NFS_INO_REVAL_PAGECACHE;
	}
	if (cur_size != new_isize) {
		nfsi->flags |= NFS_INO_INVALID_ATTR;
		nfsi->flags |= NFS_INO_INVALID_ATTR;
		if (nfsi->npages == 0)
			nfsi->flags |= NFS_INO_REVAL_PAGECACHE;
	}


	/* Have any file permissions changed? */
	/* Have any file permissions changed? */
	if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)
	if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)
+1 −0
Original line number Original line Diff line number Diff line
@@ -198,6 +198,7 @@ struct nfs_inode {
#define NFS_INO_INVALID_ATIME	0x0020		/* cached atime is invalid */
#define NFS_INO_INVALID_ATIME	0x0020		/* cached atime is invalid */
#define NFS_INO_INVALID_ACCESS	0x0040		/* cached access cred invalid */
#define NFS_INO_INVALID_ACCESS	0x0040		/* cached access cred invalid */
#define NFS_INO_INVALID_ACL	0x0080		/* cached acls are invalid */
#define NFS_INO_INVALID_ACL	0x0080		/* cached acls are invalid */
#define NFS_INO_REVAL_PAGECACHE	0x1000		/* must revalidate pagecache */


static inline struct nfs_inode *NFS_I(struct inode *inode)
static inline struct nfs_inode *NFS_I(struct inode *inode)
{
{