/* * A check for whether or not the parent directory has changed. * In the case it has, we assume that the dentries are untrustworthy * and may need to be looked up again. */ static inline int nfs_check_verifier(struct inode *dir, struct dentry *dentry) { if (IS_ROOT(dentry)) return 1; if ((NFS_FLAGS(dir) & NFS_INO_INVALID_ATTR) != 0 || nfs_attribute_timeout(dir)) return 0; return nfs_verify_change_attribute(dir, (unsigned long)dentry->d_fsdata); }
/** * 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) { struct nfs_inode *nfsi = NFS_I(inode); int retval = 0; if ((nfsi->cache_validity & 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; }
/* * Use the cached Readdirplus results in order to avoid a LOOKUP call * whenever we believe that the parent directory has not changed. * * We assume that any file creation/rename changes the directory mtime. * As this results in a page cache invalidation whenever it occurs, * we don't require any other tests for cache coherency. */ static int nfs_cached_lookup(struct inode *dir, struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr) { nfs_readdir_descriptor_t desc; struct nfs_server *server; struct nfs_entry entry; struct page *page; unsigned long timestamp; int res; if (!NFS_USE_READDIRPLUS(dir)) return -ENOENT; server = NFS_SERVER(dir); /* Don't use readdirplus unless the cache is stable */ if ((server->flags & NFS_MOUNT_NOAC) != 0 || nfs_caches_unstable(dir) || nfs_attribute_timeout(dir)) return -ENOENT; if ((NFS_FLAGS(dir) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA)) != 0) return -ENOENT; timestamp = NFS_I(dir)->readdir_timestamp; entry.fh = fh; entry.fattr = fattr; desc.decode = NFS_PROTO(dir)->decode_dirent; desc.entry = &entry; desc.page_index = 0; desc.plus = 1; for(;(page = find_get_page(dir->i_mapping, desc.page_index)); desc.page_index++) { res = -EIO; if (PageUptodate(page)) { void * kaddr = kmap_atomic(page, KM_USER0); desc.ptr = kaddr; res = find_dirent_name(&desc, page, dentry); kunmap_atomic(kaddr, KM_USER0); } page_cache_release(page); if (res == 0) goto out_found; if (res != -EAGAIN) break; } return -ENOENT; out_found: fattr->timestamp = timestamp; return 0; }
/** * 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; if (!(nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) && !nfs_attribute_timeout(inode)) return 0; force_reval: return __nfs_revalidate_inode(server, inode); }
/** * 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 (nfs_have_delegated_attributes(inode)) goto out_noreval; if (filp->f_flags & O_DIRECT) goto force_reval; if (nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) goto force_reval; if (nfs_attribute_timeout(inode)) goto force_reval; out_noreval: return 0; force_reval: return __nfs_revalidate_inode(server, inode); }