1b4d0d230SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */ 28ec442aeSDavid Howells /* NFS filesystem cache interface definitions 38ec442aeSDavid Howells * 48ec442aeSDavid Howells * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved. 58ec442aeSDavid Howells * Written by David Howells (dhowells@redhat.com) 68ec442aeSDavid Howells */ 78ec442aeSDavid Howells 88ec442aeSDavid Howells #ifndef _NFS_FSCACHE_H 98ec442aeSDavid Howells #define _NFS_FSCACHE_H 108ec442aeSDavid Howells 118ec442aeSDavid Howells #include <linux/nfs_fs.h> 128ec442aeSDavid Howells #include <linux/nfs_mount.h> 138ec442aeSDavid Howells #include <linux/nfs4_mount.h> 148ec442aeSDavid Howells #include <linux/fscache.h> 15a6b5a28eSDave Wysochanski #include <linux/iversion.h> 168ec442aeSDavid Howells 178ec442aeSDavid Howells #ifdef CONFIG_NFS_FSCACHE 188ec442aeSDavid Howells 198ec442aeSDavid Howells /* 20402cb8ddSDavid Howells * Definition of the auxiliary data attached to NFS inode storage objects 21402cb8ddSDavid Howells * within the cache. 22402cb8ddSDavid Howells * 23402cb8ddSDavid Howells * The contents of this struct are recorded in the on-disk local cache in the 24402cb8ddSDavid Howells * auxiliary data attached to the data storage object backing an inode. This 25402cb8ddSDavid Howells * permits coherency to be managed when a new inode binds to an already extant 26402cb8ddSDavid Howells * cache object. 27402cb8ddSDavid Howells */ 28402cb8ddSDavid Howells struct nfs_fscache_inode_auxdata { 296e31ded6SArnd Bergmann s64 mtime_sec; 306e31ded6SArnd Bergmann s64 mtime_nsec; 316e31ded6SArnd Bergmann s64 ctime_sec; 326e31ded6SArnd Bergmann s64 ctime_nsec; 33402cb8ddSDavid Howells u64 change_attr; 34402cb8ddSDavid Howells }; 35402cb8ddSDavid Howells 36402cb8ddSDavid Howells /* 3714727281SDavid Howells * fscache.c 3814727281SDavid Howells */ 39a6b5a28eSDave Wysochanski extern int nfs_fscache_get_super_cookie(struct super_block *, const char *, int); 4008734048SDavid Howells extern void nfs_fscache_release_super_cookie(struct super_block *); 4108734048SDavid Howells 42f1fe29b4SDavid Howells extern void nfs_fscache_init_inode(struct inode *); 43f1fe29b4SDavid Howells extern void nfs_fscache_clear_inode(struct inode *); 44f1fe29b4SDavid Howells extern void nfs_fscache_open_file(struct inode *, struct file *); 45a6b5a28eSDave Wysochanski extern void nfs_fscache_release_file(struct inode *, struct file *); 46ef79c097SDavid Howells 47*16f2f4e6SDavid Howells extern int __nfs_readpage_from_fscache(struct inode *, struct page *); 48*16f2f4e6SDavid Howells extern void __nfs_read_completion_to_fscache(struct nfs_pgio_header *hdr, 49*16f2f4e6SDavid Howells unsigned long bytes); 50*16f2f4e6SDavid Howells extern void __nfs_readpage_to_fscache(struct inode *, struct page *); 519a9fc1c0SDavid Howells 52a6b5a28eSDave Wysochanski static inline int nfs_fscache_release_page(struct page *page, gfp_t gfp) 53545db45fSDavid Howells { 54a6b5a28eSDave Wysochanski if (PageFsCache(page)) { 55a6b5a28eSDave Wysochanski if (!gfpflags_allow_blocking(gfp) || !(gfp & __GFP_FS)) 56a6b5a28eSDave Wysochanski return false; 57a6b5a28eSDave Wysochanski wait_on_page_fscache(page); 58a6b5a28eSDave Wysochanski fscache_note_page_release(nfs_i_fscache(page->mapping->host)); 59a6b5a28eSDave Wysochanski nfs_inc_fscache_stats(page->mapping->host, 60a6b5a28eSDave Wysochanski NFSIOS_FSCACHE_PAGES_UNCACHED); 61545db45fSDavid Howells } 62a6b5a28eSDave Wysochanski return true; 63545db45fSDavid Howells } 64545db45fSDavid Howells 659a9fc1c0SDavid Howells /* 669a9fc1c0SDavid Howells * Retrieve a page from an inode data storage object. 679a9fc1c0SDavid Howells */ 68*16f2f4e6SDavid Howells static inline int nfs_readpage_from_fscache(struct inode *inode, 699a9fc1c0SDavid Howells struct page *page) 709a9fc1c0SDavid Howells { 719a9fc1c0SDavid Howells if (NFS_I(inode)->fscache) 72*16f2f4e6SDavid Howells return __nfs_readpage_from_fscache(inode, page); 739a9fc1c0SDavid Howells return -ENOBUFS; 749a9fc1c0SDavid Howells } 75545db45fSDavid Howells 767f8e05f6SDavid Howells /* 777f8e05f6SDavid Howells * Store a page newly fetched from the server in an inode data storage object 787f8e05f6SDavid Howells * in the cache. 797f8e05f6SDavid Howells */ 807f8e05f6SDavid Howells static inline void nfs_readpage_to_fscache(struct inode *inode, 81*16f2f4e6SDavid Howells struct page *page) 827f8e05f6SDavid Howells { 83*16f2f4e6SDavid Howells if (NFS_I(inode)->fscache) 84*16f2f4e6SDavid Howells __nfs_readpage_to_fscache(inode, page); 857f8e05f6SDavid Howells } 867f8e05f6SDavid Howells 87a6b5a28eSDave Wysochanski static inline void nfs_fscache_update_auxdata(struct nfs_fscache_inode_auxdata *auxdata, 88a6b5a28eSDave Wysochanski struct nfs_inode *nfsi) 89de242c0bSDavid Howells { 90a6b5a28eSDave Wysochanski memset(auxdata, 0, sizeof(*auxdata)); 91a6b5a28eSDave Wysochanski auxdata->mtime_sec = nfsi->vfs_inode.i_mtime.tv_sec; 92a6b5a28eSDave Wysochanski auxdata->mtime_nsec = nfsi->vfs_inode.i_mtime.tv_nsec; 93a6b5a28eSDave Wysochanski auxdata->ctime_sec = nfsi->vfs_inode.i_ctime.tv_sec; 94a6b5a28eSDave Wysochanski auxdata->ctime_nsec = nfsi->vfs_inode.i_ctime.tv_nsec; 95a6b5a28eSDave Wysochanski 96a6b5a28eSDave Wysochanski if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4) 97a6b5a28eSDave Wysochanski auxdata->change_attr = inode_peek_iversion_raw(&nfsi->vfs_inode); 98de242c0bSDavid Howells } 99de242c0bSDavid Howells 100de242c0bSDavid Howells /* 101a6b5a28eSDave Wysochanski * Invalidate the contents of fscache for this inode. This will not sleep. 102de242c0bSDavid Howells */ 103a6b5a28eSDave Wysochanski static inline void nfs_fscache_invalidate(struct inode *inode, int flags) 104de242c0bSDavid Howells { 105a6b5a28eSDave Wysochanski struct nfs_fscache_inode_auxdata auxdata; 106a6b5a28eSDave Wysochanski struct nfs_inode *nfsi = NFS_I(inode); 107a6b5a28eSDave Wysochanski 108a6b5a28eSDave Wysochanski if (nfsi->fscache) { 109a6b5a28eSDave Wysochanski nfs_fscache_update_auxdata(&auxdata, nfsi); 110a6b5a28eSDave Wysochanski fscache_invalidate(nfsi->fscache, &auxdata, 111a6b5a28eSDave Wysochanski i_size_read(&nfsi->vfs_inode), flags); 112a6b5a28eSDave Wysochanski } 113de242c0bSDavid Howells } 114de242c0bSDavid Howells 115de242c0bSDavid Howells /* 1165d1acff1SDavid Howells * indicate the client caching state as readable text 1175d1acff1SDavid Howells */ 1185d1acff1SDavid Howells static inline const char *nfs_server_fscache_state(struct nfs_server *server) 1195d1acff1SDavid Howells { 120dea1bb35STrond Myklebust if (server->fscache) 1215d1acff1SDavid Howells return "yes"; 1225d1acff1SDavid Howells return "no "; 1235d1acff1SDavid Howells } 1245d1acff1SDavid Howells 1258ec442aeSDavid Howells #else /* CONFIG_NFS_FSCACHE */ 12608734048SDavid Howells static inline void nfs_fscache_release_super_cookie(struct super_block *sb) {} 12708734048SDavid Howells 128f1fe29b4SDavid Howells static inline void nfs_fscache_init_inode(struct inode *inode) {} 129f1fe29b4SDavid Howells static inline void nfs_fscache_clear_inode(struct inode *inode) {} 130f1fe29b4SDavid Howells static inline void nfs_fscache_open_file(struct inode *inode, 131ef79c097SDavid Howells struct file *filp) {} 132a6b5a28eSDave Wysochanski static inline void nfs_fscache_release_file(struct inode *inode, struct file *file) {} 133ef79c097SDavid Howells 134545db45fSDavid Howells static inline int nfs_fscache_release_page(struct page *page, gfp_t gfp) 135545db45fSDavid Howells { 136545db45fSDavid Howells return 1; /* True: may release page */ 137545db45fSDavid Howells } 138*16f2f4e6SDavid Howells static inline int nfs_readpage_from_fscache(struct inode *inode, 1399a9fc1c0SDavid Howells struct page *page) 1409a9fc1c0SDavid Howells { 1419a9fc1c0SDavid Howells return -ENOBUFS; 1429a9fc1c0SDavid Howells } 1437f8e05f6SDavid Howells static inline void nfs_readpage_to_fscache(struct inode *inode, 144*16f2f4e6SDavid Howells struct page *page) {} 1459a9fc1c0SDavid Howells 146de242c0bSDavid Howells 147a6b5a28eSDave Wysochanski static inline void nfs_fscache_invalidate(struct inode *inode, int flags) {} 148de242c0bSDavid Howells 1495d1acff1SDavid Howells static inline const char *nfs_server_fscache_state(struct nfs_server *server) 1505d1acff1SDavid Howells { 1515d1acff1SDavid Howells return "no "; 1525d1acff1SDavid Howells } 1535d1acff1SDavid Howells 1548ec442aeSDavid Howells #endif /* CONFIG_NFS_FSCACHE */ 1558ec442aeSDavid Howells #endif /* _NFS_FSCACHE_H */ 156