+/**
+ * nfs_revalidate_size - Revalidate the file size
+ * @inode - pointer to inode struct
+ * @file - pointer to struct file
+ *
+ * Revalidates the file length. This is basically a wrapper around
+ * nfs_revalidate_inode() that takes into account the fact that we may
+ * have cached writes (in which case we don't care about the server's
+ * idea of what the file length is), or O_DIRECT (in which case we
+ * shouldn't trust the cache).
+ */
+static int nfs_revalidate_file_size(struct inode *inode, struct file *filp)
+{
+ struct nfs_server *server = NFS_SERVER(inode);
+ struct nfs_inode *nfsi = NFS_I(inode);
+
+ if (server->flags & NFS_MOUNT_NOAC)
+ goto force_reval;
+ if (filp->f_flags & O_DIRECT)
+ goto force_reval;
+ if (nfsi->npages != 0)
+ return 0;
+ return nfs_revalidate_inode(server, inode);
+force_reval:
+ return __nfs_revalidate_inode(server, inode);
+}
+
+static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin)
+{
+ /* origin == SEEK_END => we must revalidate the cached file length */
+ if (origin == 2) {
+ struct inode *inode = filp->f_mapping->host;
+ int retval = nfs_revalidate_file_size(inode, filp);
+ if (retval < 0)
+ return (loff_t)retval;
+ }
+ return remote_llseek(filp, offset, origin);
+}
+