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 11d7bdba1cSDavid Howells #include <linux/swap.h> 128ec442aeSDavid Howells #include <linux/nfs_fs.h> 138ec442aeSDavid Howells #include <linux/nfs_mount.h> 148ec442aeSDavid Howells #include <linux/nfs4_mount.h> 158ec442aeSDavid Howells #include <linux/fscache.h> 16a6b5a28eSDave Wysochanski #include <linux/iversion.h> 178ec442aeSDavid Howells 188ec442aeSDavid Howells #ifdef CONFIG_NFS_FSCACHE 198ec442aeSDavid Howells 208ec442aeSDavid Howells /* 21402cb8ddSDavid Howells * Definition of the auxiliary data attached to NFS inode storage objects 22402cb8ddSDavid Howells * within the cache. 23402cb8ddSDavid Howells * 24402cb8ddSDavid Howells * The contents of this struct are recorded in the on-disk local cache in the 25402cb8ddSDavid Howells * auxiliary data attached to the data storage object backing an inode. This 26402cb8ddSDavid Howells * permits coherency to be managed when a new inode binds to an already extant 27402cb8ddSDavid Howells * cache object. 28402cb8ddSDavid Howells */ 29402cb8ddSDavid Howells struct nfs_fscache_inode_auxdata { 306e31ded6SArnd Bergmann s64 mtime_sec; 316e31ded6SArnd Bergmann s64 mtime_nsec; 326e31ded6SArnd Bergmann s64 ctime_sec; 336e31ded6SArnd Bergmann s64 ctime_nsec; 34402cb8ddSDavid Howells u64 change_attr; 35402cb8ddSDavid Howells }; 36402cb8ddSDavid Howells 37402cb8ddSDavid Howells /* 3814727281SDavid Howells * fscache.c 3914727281SDavid Howells */ 40a6b5a28eSDave Wysochanski extern int nfs_fscache_get_super_cookie(struct super_block *, const char *, int); 4108734048SDavid Howells extern void nfs_fscache_release_super_cookie(struct super_block *); 4208734048SDavid Howells 43f1fe29b4SDavid Howells extern void nfs_fscache_init_inode(struct inode *); 44f1fe29b4SDavid Howells extern void nfs_fscache_clear_inode(struct inode *); 45f1fe29b4SDavid Howells extern void nfs_fscache_open_file(struct inode *, struct file *); 46a6b5a28eSDave Wysochanski extern void nfs_fscache_release_file(struct inode *, struct file *); 47ef79c097SDavid Howells 48fc1c5abfSDave Wysochanski extern int __nfs_fscache_read_page(struct inode *, struct page *); 49fc1c5abfSDave Wysochanski extern void __nfs_fscache_write_page(struct inode *, struct page *); 509a9fc1c0SDavid Howells 513577da4aSMatthew Wilcox (Oracle) static inline bool nfs_fscache_release_folio(struct folio *folio, gfp_t gfp) 52545db45fSDavid Howells { 533577da4aSMatthew Wilcox (Oracle) if (folio_test_fscache(folio)) { 54d7bdba1cSDavid Howells if (current_is_kswapd() || !(gfp & __GFP_FS)) 55a6b5a28eSDave Wysochanski return false; 563577da4aSMatthew Wilcox (Oracle) folio_wait_fscache(folio); 57*88a4d7bdSDave Wysochanski fscache_note_page_release(netfs_i_cookie(&NFS_I(folio->mapping->host)->netfs)); 583577da4aSMatthew Wilcox (Oracle) nfs_inc_fscache_stats(folio->mapping->host, 59a6b5a28eSDave Wysochanski NFSIOS_FSCACHE_PAGES_UNCACHED); 60545db45fSDavid Howells } 61a6b5a28eSDave Wysochanski return true; 62545db45fSDavid Howells } 63545db45fSDavid Howells 649a9fc1c0SDavid Howells /* 659a9fc1c0SDavid Howells * Retrieve a page from an inode data storage object. 669a9fc1c0SDavid Howells */ 67fc1c5abfSDave Wysochanski static inline int nfs_fscache_read_page(struct inode *inode, struct page *page) 689a9fc1c0SDavid Howells { 69*88a4d7bdSDave Wysochanski if (netfs_inode(inode)->cache) 70fc1c5abfSDave Wysochanski return __nfs_fscache_read_page(inode, page); 719a9fc1c0SDavid Howells return -ENOBUFS; 729a9fc1c0SDavid Howells } 73545db45fSDavid Howells 747f8e05f6SDavid Howells /* 757f8e05f6SDavid Howells * Store a page newly fetched from the server in an inode data storage object 767f8e05f6SDavid Howells * in the cache. 777f8e05f6SDavid Howells */ 78fc1c5abfSDave Wysochanski static inline void nfs_fscache_write_page(struct inode *inode, 7916f2f4e6SDavid Howells struct page *page) 807f8e05f6SDavid Howells { 81*88a4d7bdSDave Wysochanski if (netfs_inode(inode)->cache) 82fc1c5abfSDave Wysochanski __nfs_fscache_write_page(inode, page); 837f8e05f6SDavid Howells } 847f8e05f6SDavid Howells 85a6b5a28eSDave Wysochanski static inline void nfs_fscache_update_auxdata(struct nfs_fscache_inode_auxdata *auxdata, 8645f3a70bSDave Wysochanski struct inode *inode) 87de242c0bSDavid Howells { 88a6b5a28eSDave Wysochanski memset(auxdata, 0, sizeof(*auxdata)); 8945f3a70bSDave Wysochanski auxdata->mtime_sec = inode->i_mtime.tv_sec; 9045f3a70bSDave Wysochanski auxdata->mtime_nsec = inode->i_mtime.tv_nsec; 9145f3a70bSDave Wysochanski auxdata->ctime_sec = inode->i_ctime.tv_sec; 9245f3a70bSDave Wysochanski auxdata->ctime_nsec = inode->i_ctime.tv_nsec; 93a6b5a28eSDave Wysochanski 9445f3a70bSDave Wysochanski if (NFS_SERVER(inode)->nfs_client->rpc_ops->version == 4) 9545f3a70bSDave Wysochanski auxdata->change_attr = inode_peek_iversion_raw(inode); 96de242c0bSDavid Howells } 97de242c0bSDavid Howells 98de242c0bSDavid Howells /* 99a6b5a28eSDave Wysochanski * Invalidate the contents of fscache for this inode. This will not sleep. 100de242c0bSDavid Howells */ 101a6b5a28eSDave Wysochanski static inline void nfs_fscache_invalidate(struct inode *inode, int flags) 102de242c0bSDavid Howells { 103a6b5a28eSDave Wysochanski struct nfs_fscache_inode_auxdata auxdata; 104*88a4d7bdSDave Wysochanski struct fscache_cookie *cookie = netfs_i_cookie(&NFS_I(inode)->netfs); 105a6b5a28eSDave Wysochanski 10645f3a70bSDave Wysochanski nfs_fscache_update_auxdata(&auxdata, inode); 107*88a4d7bdSDave Wysochanski fscache_invalidate(cookie, &auxdata, i_size_read(inode), flags); 108de242c0bSDavid Howells } 109de242c0bSDavid Howells 110de242c0bSDavid Howells /* 1115d1acff1SDavid Howells * indicate the client caching state as readable text 1125d1acff1SDavid Howells */ 1135d1acff1SDavid Howells static inline const char *nfs_server_fscache_state(struct nfs_server *server) 1145d1acff1SDavid Howells { 115dea1bb35STrond Myklebust if (server->fscache) 1165d1acff1SDavid Howells return "yes"; 1175d1acff1SDavid Howells return "no "; 1185d1acff1SDavid Howells } 1195d1acff1SDavid Howells 1208ec442aeSDavid Howells #else /* CONFIG_NFS_FSCACHE */ 12108734048SDavid Howells static inline void nfs_fscache_release_super_cookie(struct super_block *sb) {} 12208734048SDavid Howells 123f1fe29b4SDavid Howells static inline void nfs_fscache_init_inode(struct inode *inode) {} 124f1fe29b4SDavid Howells static inline void nfs_fscache_clear_inode(struct inode *inode) {} 125f1fe29b4SDavid Howells static inline void nfs_fscache_open_file(struct inode *inode, 126ef79c097SDavid Howells struct file *filp) {} 127a6b5a28eSDave Wysochanski static inline void nfs_fscache_release_file(struct inode *inode, struct file *file) {} 128ef79c097SDavid Howells 1293577da4aSMatthew Wilcox (Oracle) static inline bool nfs_fscache_release_folio(struct folio *folio, gfp_t gfp) 130545db45fSDavid Howells { 1313577da4aSMatthew Wilcox (Oracle) return true; /* may release folio */ 132545db45fSDavid Howells } 133fc1c5abfSDave Wysochanski static inline int nfs_fscache_read_page(struct inode *inode, struct page *page) 1349a9fc1c0SDavid Howells { 1359a9fc1c0SDavid Howells return -ENOBUFS; 1369a9fc1c0SDavid Howells } 137fc1c5abfSDave Wysochanski static inline void nfs_fscache_write_page(struct inode *inode, struct page *page) {} 138a6b5a28eSDave Wysochanski static inline void nfs_fscache_invalidate(struct inode *inode, int flags) {} 139de242c0bSDavid Howells 1405d1acff1SDavid Howells static inline const char *nfs_server_fscache_state(struct nfs_server *server) 1415d1acff1SDavid Howells { 1425d1acff1SDavid Howells return "no "; 1435d1acff1SDavid Howells } 1445d1acff1SDavid Howells 1458ec442aeSDavid Howells #endif /* CONFIG_NFS_FSCACHE */ 1468ec442aeSDavid Howells #endif /* _NFS_FSCACHE_H */ 147