Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

nfs: Convert to new fscache volume/cookie API

Change the nfs filesystem to support fscache's indexing rewrite and
reenable caching in nfs.

The following changes have been made:

(1) The fscache_netfs struct is no more, and there's no need to register
the filesystem as a whole.

(2) The session cookie is now an fscache_volume cookie, allocated with
fscache_acquire_volume(). That takes three parameters: a string
representing the "volume" in the index, a string naming the cache to
use (or NULL) and a u64 that conveys coherency metadata for the
volume.

For nfs, I've made it render the volume name string as:

"nfs,<ver>,<family>,<address>,<port>,<fsidH>,<fsidL>*<,param>[,<uniq>]"

(3) The fscache_cookie_def is no more and needed information is passed
directly to fscache_acquire_cookie(). The cache no longer calls back
into the filesystem, but rather metadata changes are indicated at
other times.

fscache_acquire_cookie() is passed the same keying and coherency
information as before.

(4) fscache_enable/disable_cookie() have been removed.

Call fscache_use_cookie() and fscache_unuse_cookie() when a file is
opened or closed to prevent a cache file from being culled and to keep
resources to hand that are needed to do I/O.

If a file is opened for writing, we invalidate it with
FSCACHE_INVAL_DIO_WRITE in lieu of doing writeback to the cache,
thereby making it cease caching until all currently open files are
closed. This should give the same behaviour as the uptream code.
Making the cache store local modifications isn't straightforward for
NFS, so that's left for future patches.

(5) fscache_invalidate() now needs to be given uptodate auxiliary data and
a file size. It also takes a flag to indicate if this was due to a
DIO write.

(6) Call nfs_fscache_invalidate() with FSCACHE_INVAL_DIO_WRITE on a file
to which a DIO write is made.

(7) Call fscache_note_page_release() from nfs_release_page().

(8) Use a killable wait in nfs_vm_page_mkwrite() when waiting for
PG_fscache to be cleared.

(9) The functions to read and write data to/from the cache are stubbed out
pending a conversion to use netfslib.

Changes
=======
ver #3:
- Added missing =n fallback for nfs_fscache_release_file()[1][2].

ver #2:
- Use gfpflags_allow_blocking() rather than using flag directly.
- fscache_acquire_volume() now returns errors.
- Remove NFS_INO_FSCACHE as it's no longer used.
- Need to unuse a cookie on file-release, not inode-clear.

Signed-off-by: Dave Wysochanski <dwysocha@redhat.com>
Co-developed-by: David Howells <dhowells@redhat.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Tested-by: Dave Wysochanski <dwysocha@redhat.com>
Acked-by: Jeff Layton <jlayton@kernel.org>
cc: Trond Myklebust <trond.myklebust@hammerspace.com>
cc: Anna Schumaker <anna.schumaker@netapp.com>
cc: linux-nfs@vger.kernel.org
cc: linux-cachefs@redhat.com
Link: https://lore.kernel.org/r/202112100804.nksO8K4u-lkp@intel.com/ [1]
Link: https://lore.kernel.org/r/202112100957.2oEDT20W-lkp@intel.com/ [2]
Link: https://lore.kernel.org/r/163819668938.215744.14448852181937731615.stgit@warthog.procyon.org.uk/ # v1
Link: https://lore.kernel.org/r/163906979003.143852.2601189243864854724.stgit@warthog.procyon.org.uk/ # v2
Link: https://lore.kernel.org/r/163967182112.1823006.7791504655391213379.stgit@warthog.procyon.org.uk/ # v3
Link: https://lore.kernel.org/r/164021575950.640689.12069642327533368467.stgit@warthog.procyon.org.uk/ # v4

authored by

Dave Wysochanski and committed by
David Howells
a6b5a28e 93c84614

+170 -601
+1 -1
fs/nfs/Kconfig
··· 170 170 171 171 config NFS_FSCACHE 172 172 bool "Provide NFS client caching support" 173 - depends on NFS_FS=m && FSCACHE_OLD_API || NFS_FS=y && FSCACHE_OLD_API=y 173 + depends on NFS_FS=m && FSCACHE || NFS_FS=y && FSCACHE=y 174 174 help 175 175 Say Y here if you want NFS data to be cached locally on disc through 176 176 the general filesystem cache manager
+1 -1
fs/nfs/Makefile
··· 12 12 export.o sysfs.o fs_context.o 13 13 nfs-$(CONFIG_ROOT_NFS) += nfsroot.o 14 14 nfs-$(CONFIG_SYSCTL) += sysctl.o 15 - nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o 15 + nfs-$(CONFIG_NFS_FSCACHE) += fscache.o 16 16 17 17 obj-$(CONFIG_NFS_V2) += nfsv2.o 18 18 nfsv2-y := nfs2super.o proc.o nfs2xdr.o
-4
fs/nfs/client.c
··· 183 183 clp->cl_net = get_net(cl_init->net); 184 184 185 185 clp->cl_principal = "*"; 186 - nfs_fscache_get_client_cookie(clp); 187 - 188 186 return clp; 189 187 190 188 error_cleanup: ··· 236 238 */ 237 239 void nfs_free_client(struct nfs_client *clp) 238 240 { 239 - nfs_fscache_release_client_cookie(clp); 240 - 241 241 /* -EIO all pending I/O */ 242 242 if (!IS_ERR(clp->cl_rpcclient)) 243 243 rpc_shutdown_client(clp->cl_rpcclient);
+2
fs/nfs/direct.c
··· 59 59 #include "internal.h" 60 60 #include "iostat.h" 61 61 #include "pnfs.h" 62 + #include "fscache.h" 62 63 63 64 #define NFSDBG_FACILITY NFSDBG_VFS 64 65 ··· 960 959 } else { 961 960 result = requested; 962 961 } 962 + nfs_fscache_invalidate(inode, FSCACHE_INVAL_DIO_WRITE); 963 963 out_release: 964 964 nfs_direct_req_release(dreq); 965 965 out:
+8 -5
fs/nfs/file.c
··· 84 84 85 85 nfs_inc_stats(inode, NFSIOS_VFSRELEASE); 86 86 nfs_file_clear_open_context(filp); 87 + nfs_fscache_release_file(inode, filp); 87 88 return 0; 88 89 } 89 90 EXPORT_SYMBOL_GPL(nfs_file_release); ··· 416 415 return; 417 416 /* Cancel any unstarted writes on this page */ 418 417 nfs_wb_page_cancel(page_file_mapping(page)->host, page); 419 - 420 - nfs_fscache_invalidate_page(page, page->mapping->host); 418 + wait_on_page_fscache(page); 421 419 } 422 420 423 421 /* ··· 475 475 static int nfs_launder_page(struct page *page) 476 476 { 477 477 struct inode *inode = page_file_mapping(page)->host; 478 - struct nfs_inode *nfsi = NFS_I(inode); 479 478 480 479 dfprintk(PAGECACHE, "NFS: launder_page(%ld, %llu)\n", 481 480 inode->i_ino, (long long)page_offset(page)); 482 481 483 - nfs_fscache_wait_on_page_write(nfsi, page); 482 + wait_on_page_fscache(page); 484 483 return nfs_wb_page(inode, page); 485 484 } 486 485 ··· 554 555 sb_start_pagefault(inode->i_sb); 555 556 556 557 /* make sure the cache has finished storing the page */ 557 - nfs_fscache_wait_on_page_write(NFS_I(inode), page); 558 + if (PageFsCache(page) && 559 + wait_on_page_fscache_killable(vmf->page) < 0) { 560 + ret = VM_FAULT_RETRY; 561 + goto out; 562 + } 558 563 559 564 wait_on_bit_action(&NFS_I(inode)->flags, NFS_INO_INVALIDATING, 560 565 nfs_wait_bit_killable, TASK_KILLABLE);
-140
fs/nfs/fscache-index.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-or-later 2 - /* NFS FS-Cache index structure definition 3 - * 4 - * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved. 5 - * Written by David Howells (dhowells@redhat.com) 6 - */ 7 - 8 - #include <linux/init.h> 9 - #include <linux/kernel.h> 10 - #include <linux/sched.h> 11 - #include <linux/mm.h> 12 - #include <linux/nfs_fs.h> 13 - #include <linux/nfs_fs_sb.h> 14 - #include <linux/in6.h> 15 - #include <linux/iversion.h> 16 - 17 - #include "internal.h" 18 - #include "fscache.h" 19 - 20 - #define NFSDBG_FACILITY NFSDBG_FSCACHE 21 - 22 - /* 23 - * Define the NFS filesystem for FS-Cache. Upon registration FS-Cache sticks 24 - * the cookie for the top-level index object for NFS into here. The top-level 25 - * index can than have other cache objects inserted into it. 26 - */ 27 - struct fscache_netfs nfs_fscache_netfs = { 28 - .name = "nfs", 29 - .version = 0, 30 - }; 31 - 32 - /* 33 - * Register NFS for caching 34 - */ 35 - int nfs_fscache_register(void) 36 - { 37 - return fscache_register_netfs(&nfs_fscache_netfs); 38 - } 39 - 40 - /* 41 - * Unregister NFS for caching 42 - */ 43 - void nfs_fscache_unregister(void) 44 - { 45 - fscache_unregister_netfs(&nfs_fscache_netfs); 46 - } 47 - 48 - /* 49 - * Define the server object for FS-Cache. This is used to describe a server 50 - * object to fscache_acquire_cookie(). It is keyed by the NFS protocol and 51 - * server address parameters. 52 - */ 53 - const struct fscache_cookie_def nfs_fscache_server_index_def = { 54 - .name = "NFS.server", 55 - .type = FSCACHE_COOKIE_TYPE_INDEX, 56 - }; 57 - 58 - /* 59 - * Define the superblock object for FS-Cache. This is used to describe a 60 - * superblock object to fscache_acquire_cookie(). It is keyed by all the NFS 61 - * parameters that might cause a separate superblock. 62 - */ 63 - const struct fscache_cookie_def nfs_fscache_super_index_def = { 64 - .name = "NFS.super", 65 - .type = FSCACHE_COOKIE_TYPE_INDEX, 66 - }; 67 - 68 - /* 69 - * Consult the netfs about the state of an object 70 - * - This function can be absent if the index carries no state data 71 - * - The netfs data from the cookie being used as the target is 72 - * presented, as is the auxiliary data 73 - */ 74 - static 75 - enum fscache_checkaux nfs_fscache_inode_check_aux(void *cookie_netfs_data, 76 - const void *data, 77 - uint16_t datalen, 78 - loff_t object_size) 79 - { 80 - struct nfs_fscache_inode_auxdata auxdata; 81 - struct nfs_inode *nfsi = cookie_netfs_data; 82 - 83 - if (datalen != sizeof(auxdata)) 84 - return FSCACHE_CHECKAUX_OBSOLETE; 85 - 86 - memset(&auxdata, 0, sizeof(auxdata)); 87 - auxdata.mtime_sec = nfsi->vfs_inode.i_mtime.tv_sec; 88 - auxdata.mtime_nsec = nfsi->vfs_inode.i_mtime.tv_nsec; 89 - auxdata.ctime_sec = nfsi->vfs_inode.i_ctime.tv_sec; 90 - auxdata.ctime_nsec = nfsi->vfs_inode.i_ctime.tv_nsec; 91 - 92 - if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4) 93 - auxdata.change_attr = inode_peek_iversion_raw(&nfsi->vfs_inode); 94 - 95 - if (memcmp(data, &auxdata, datalen) != 0) 96 - return FSCACHE_CHECKAUX_OBSOLETE; 97 - 98 - return FSCACHE_CHECKAUX_OKAY; 99 - } 100 - 101 - /* 102 - * Get an extra reference on a read context. 103 - * - This function can be absent if the completion function doesn't require a 104 - * context. 105 - * - The read context is passed back to NFS in the event that a data read on the 106 - * cache fails with EIO - in which case the server must be contacted to 107 - * retrieve the data, which requires the read context for security. 108 - */ 109 - static void nfs_fh_get_context(void *cookie_netfs_data, void *context) 110 - { 111 - get_nfs_open_context(context); 112 - } 113 - 114 - /* 115 - * Release an extra reference on a read context. 116 - * - This function can be absent if the completion function doesn't require a 117 - * context. 118 - */ 119 - static void nfs_fh_put_context(void *cookie_netfs_data, void *context) 120 - { 121 - if (context) 122 - put_nfs_open_context(context); 123 - } 124 - 125 - /* 126 - * Define the inode object for FS-Cache. This is used to describe an inode 127 - * object to fscache_acquire_cookie(). It is keyed by the NFS file handle for 128 - * an inode. 129 - * 130 - * Coherency is managed by comparing the copies of i_size, i_mtime and i_ctime 131 - * held in the cache auxiliary data for the data storage object with those in 132 - * the inode struct in memory. 133 - */ 134 - const struct fscache_cookie_def nfs_fscache_inode_object_def = { 135 - .name = "NFS.fh", 136 - .type = FSCACHE_COOKIE_TYPE_DATAFILE, 137 - .check_aux = nfs_fscache_inode_check_aux, 138 - .get_context = nfs_fh_get_context, 139 - .put_context = nfs_fh_put_context, 140 - };
+103 -327
fs/nfs/fscache.c
··· 22 22 23 23 #define NFSDBG_FACILITY NFSDBG_FSCACHE 24 24 25 - static struct rb_root nfs_fscache_keys = RB_ROOT; 26 - static DEFINE_SPINLOCK(nfs_fscache_keys_lock); 25 + #define NFS_MAX_KEY_LEN 1000 27 26 28 - /* 29 - * Layout of the key for an NFS server cache object. 30 - */ 31 - struct nfs_server_key { 32 - struct { 33 - uint16_t nfsversion; /* NFS protocol version */ 34 - uint32_t minorversion; /* NFSv4 minor version */ 35 - uint16_t family; /* address family */ 36 - __be16 port; /* IP port */ 37 - } hdr; 38 - union { 39 - struct in_addr ipv4_addr; /* IPv4 address */ 40 - struct in6_addr ipv6_addr; /* IPv6 address */ 41 - }; 42 - } __packed; 27 + static bool nfs_append_int(char *key, int *_len, unsigned long long x) 28 + { 29 + if (*_len > NFS_MAX_KEY_LEN) 30 + return false; 31 + if (x == 0) 32 + key[(*_len)++] = ','; 33 + else 34 + *_len += sprintf(key + *_len, ",%llx", x); 35 + return true; 36 + } 43 37 44 38 /* 45 39 * Get the per-client index cookie for an NFS client if the appropriate mount ··· 41 47 * - We always try and get an index cookie for the client, but get filehandle 42 48 * cookies on a per-superblock basis, depending on the mount flags 43 49 */ 44 - void nfs_fscache_get_client_cookie(struct nfs_client *clp) 50 + static bool nfs_fscache_get_client_key(struct nfs_client *clp, 51 + char *key, int *_len) 45 52 { 46 53 const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &clp->cl_addr; 47 54 const struct sockaddr_in *sin = (struct sockaddr_in *) &clp->cl_addr; 48 - struct nfs_server_key key; 49 - uint16_t len = sizeof(key.hdr); 50 55 51 - memset(&key, 0, sizeof(key)); 52 - key.hdr.nfsversion = clp->rpc_ops->version; 53 - key.hdr.minorversion = clp->cl_minorversion; 54 - key.hdr.family = clp->cl_addr.ss_family; 56 + *_len += snprintf(key + *_len, NFS_MAX_KEY_LEN - *_len, 57 + ",%u.%u,%x", 58 + clp->rpc_ops->version, 59 + clp->cl_minorversion, 60 + clp->cl_addr.ss_family); 55 61 56 62 switch (clp->cl_addr.ss_family) { 57 63 case AF_INET: 58 - key.hdr.port = sin->sin_port; 59 - key.ipv4_addr = sin->sin_addr; 60 - len += sizeof(key.ipv4_addr); 61 - break; 64 + if (!nfs_append_int(key, _len, sin->sin_port) || 65 + !nfs_append_int(key, _len, sin->sin_addr.s_addr)) 66 + return false; 67 + return true; 62 68 63 69 case AF_INET6: 64 - key.hdr.port = sin6->sin6_port; 65 - key.ipv6_addr = sin6->sin6_addr; 66 - len += sizeof(key.ipv6_addr); 67 - break; 70 + if (!nfs_append_int(key, _len, sin6->sin6_port) || 71 + !nfs_append_int(key, _len, sin6->sin6_addr.s6_addr32[0]) || 72 + !nfs_append_int(key, _len, sin6->sin6_addr.s6_addr32[1]) || 73 + !nfs_append_int(key, _len, sin6->sin6_addr.s6_addr32[2]) || 74 + !nfs_append_int(key, _len, sin6->sin6_addr.s6_addr32[3])) 75 + return false; 76 + return true; 68 77 69 78 default: 70 79 printk(KERN_WARNING "NFS: Unknown network family '%d'\n", 71 80 clp->cl_addr.ss_family); 72 - clp->fscache = NULL; 73 - return; 81 + return false; 74 82 } 75 - 76 - /* create a cache index for looking up filehandles */ 77 - clp->fscache = fscache_acquire_cookie(nfs_fscache_netfs.primary_index, 78 - &nfs_fscache_server_index_def, 79 - &key, len, 80 - NULL, 0, 81 - clp, 0, true); 82 - dfprintk(FSCACHE, "NFS: get client cookie (0x%p/0x%p)\n", 83 - clp, clp->fscache); 84 83 } 85 84 86 85 /* 87 - * Dispose of a per-client cookie 88 - */ 89 - void nfs_fscache_release_client_cookie(struct nfs_client *clp) 90 - { 91 - dfprintk(FSCACHE, "NFS: releasing client cookie (0x%p/0x%p)\n", 92 - clp, clp->fscache); 93 - 94 - fscache_relinquish_cookie(clp->fscache, NULL, false); 95 - clp->fscache = NULL; 96 - } 97 - 98 - /* 99 - * Get the cache cookie for an NFS superblock. We have to handle 100 - * uniquification here because the cache doesn't do it for us. 86 + * Get the cache cookie for an NFS superblock. 101 87 * 102 88 * The default uniquifier is just an empty string, but it may be overridden 103 89 * either by the 'fsc=xxx' option to mount, or by inheriting it from the parent 104 90 * superblock across an automount point of some nature. 105 91 */ 106 - void nfs_fscache_get_super_cookie(struct super_block *sb, const char *uniq, int ulen) 92 + int nfs_fscache_get_super_cookie(struct super_block *sb, const char *uniq, int ulen) 107 93 { 108 - struct nfs_fscache_key *key, *xkey; 94 + struct fscache_volume *vcookie; 109 95 struct nfs_server *nfss = NFS_SB(sb); 110 - struct rb_node **p, *parent; 111 - int diff; 96 + unsigned int len = 3; 97 + char *key; 112 98 113 - nfss->fscache_key = NULL; 114 - nfss->fscache = NULL; 115 - if (!uniq) { 116 - uniq = ""; 117 - ulen = 1; 99 + if (uniq) { 100 + nfss->fscache_uniq = kmemdup_nul(uniq, ulen, GFP_KERNEL); 101 + if (!nfss->fscache_uniq) 102 + return -ENOMEM; 118 103 } 119 104 120 - key = kzalloc(sizeof(*key) + ulen, GFP_KERNEL); 105 + key = kmalloc(NFS_MAX_KEY_LEN + 24, GFP_KERNEL); 121 106 if (!key) 122 - return; 107 + return -ENOMEM; 123 108 124 - key->nfs_client = nfss->nfs_client; 125 - key->key.super.s_flags = sb->s_flags & NFS_SB_MASK; 126 - key->key.nfs_server.flags = nfss->flags; 127 - key->key.nfs_server.rsize = nfss->rsize; 128 - key->key.nfs_server.wsize = nfss->wsize; 129 - key->key.nfs_server.acregmin = nfss->acregmin; 130 - key->key.nfs_server.acregmax = nfss->acregmax; 131 - key->key.nfs_server.acdirmin = nfss->acdirmin; 132 - key->key.nfs_server.acdirmax = nfss->acdirmax; 133 - key->key.nfs_server.fsid = nfss->fsid; 134 - key->key.rpc_auth.au_flavor = nfss->client->cl_auth->au_flavor; 109 + memcpy(key, "nfs", 3); 110 + if (!nfs_fscache_get_client_key(nfss->nfs_client, key, &len) || 111 + !nfs_append_int(key, &len, nfss->fsid.major) || 112 + !nfs_append_int(key, &len, nfss->fsid.minor) || 113 + !nfs_append_int(key, &len, sb->s_flags & NFS_SB_MASK) || 114 + !nfs_append_int(key, &len, nfss->flags) || 115 + !nfs_append_int(key, &len, nfss->rsize) || 116 + !nfs_append_int(key, &len, nfss->wsize) || 117 + !nfs_append_int(key, &len, nfss->acregmin) || 118 + !nfs_append_int(key, &len, nfss->acregmax) || 119 + !nfs_append_int(key, &len, nfss->acdirmin) || 120 + !nfs_append_int(key, &len, nfss->acdirmax) || 121 + !nfs_append_int(key, &len, nfss->client->cl_auth->au_flavor)) 122 + goto out; 135 123 136 - key->key.uniq_len = ulen; 137 - memcpy(key->key.uniquifier, uniq, ulen); 138 - 139 - spin_lock(&nfs_fscache_keys_lock); 140 - p = &nfs_fscache_keys.rb_node; 141 - parent = NULL; 142 - while (*p) { 143 - parent = *p; 144 - xkey = rb_entry(parent, struct nfs_fscache_key, node); 145 - 146 - if (key->nfs_client < xkey->nfs_client) 147 - goto go_left; 148 - if (key->nfs_client > xkey->nfs_client) 149 - goto go_right; 150 - 151 - diff = memcmp(&key->key, &xkey->key, sizeof(key->key)); 152 - if (diff < 0) 153 - goto go_left; 154 - if (diff > 0) 155 - goto go_right; 156 - 157 - if (key->key.uniq_len == 0) 158 - goto non_unique; 159 - diff = memcmp(key->key.uniquifier, 160 - xkey->key.uniquifier, 161 - key->key.uniq_len); 162 - if (diff < 0) 163 - goto go_left; 164 - if (diff > 0) 165 - goto go_right; 166 - goto non_unique; 167 - 168 - go_left: 169 - p = &(*p)->rb_left; 170 - continue; 171 - go_right: 172 - p = &(*p)->rb_right; 124 + if (ulen > 0) { 125 + if (ulen > NFS_MAX_KEY_LEN - len) 126 + goto out; 127 + key[len++] = ','; 128 + memcpy(key + len, uniq, ulen); 129 + len += ulen; 173 130 } 174 - 175 - rb_link_node(&key->node, parent, p); 176 - rb_insert_color(&key->node, &nfs_fscache_keys); 177 - spin_unlock(&nfs_fscache_keys_lock); 178 - nfss->fscache_key = key; 131 + key[len] = 0; 179 132 180 133 /* create a cache index for looking up filehandles */ 181 - nfss->fscache = fscache_acquire_cookie(nfss->nfs_client->fscache, 182 - &nfs_fscache_super_index_def, 183 - &key->key, 184 - sizeof(key->key) + ulen, 185 - NULL, 0, 186 - nfss, 0, true); 134 + vcookie = fscache_acquire_volume(key, 135 + NULL, /* preferred_cache */ 136 + NULL, 0 /* coherency_data */); 187 137 dfprintk(FSCACHE, "NFS: get superblock cookie (0x%p/0x%p)\n", 188 - nfss, nfss->fscache); 189 - return; 138 + nfss, vcookie); 139 + if (IS_ERR(vcookie)) { 140 + if (vcookie != ERR_PTR(-EBUSY)) { 141 + kfree(key); 142 + return PTR_ERR(vcookie); 143 + } 144 + pr_err("NFS: Cache volume key already in use (%s)\n", key); 145 + vcookie = NULL; 146 + } 147 + nfss->fscache = vcookie; 190 148 191 - non_unique: 192 - spin_unlock(&nfs_fscache_keys_lock); 149 + out: 193 150 kfree(key); 194 - nfss->fscache_key = NULL; 195 - nfss->fscache = NULL; 196 - printk(KERN_WARNING "NFS:" 197 - " Cache request denied due to non-unique superblock keys\n"); 151 + return 0; 198 152 } 199 153 200 154 /* ··· 155 213 dfprintk(FSCACHE, "NFS: releasing superblock cookie (0x%p/0x%p)\n", 156 214 nfss, nfss->fscache); 157 215 158 - fscache_relinquish_cookie(nfss->fscache, NULL, false); 216 + fscache_relinquish_volume(nfss->fscache, NULL, false); 159 217 nfss->fscache = NULL; 160 - 161 - if (nfss->fscache_key) { 162 - spin_lock(&nfs_fscache_keys_lock); 163 - rb_erase(&nfss->fscache_key->node, &nfs_fscache_keys); 164 - spin_unlock(&nfs_fscache_keys_lock); 165 - kfree(nfss->fscache_key); 166 - nfss->fscache_key = NULL; 167 - } 168 - } 169 - 170 - static void nfs_fscache_update_auxdata(struct nfs_fscache_inode_auxdata *auxdata, 171 - struct nfs_inode *nfsi) 172 - { 173 - memset(auxdata, 0, sizeof(*auxdata)); 174 - auxdata->mtime_sec = nfsi->vfs_inode.i_mtime.tv_sec; 175 - auxdata->mtime_nsec = nfsi->vfs_inode.i_mtime.tv_nsec; 176 - auxdata->ctime_sec = nfsi->vfs_inode.i_ctime.tv_sec; 177 - auxdata->ctime_nsec = nfsi->vfs_inode.i_ctime.tv_nsec; 178 - 179 - if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4) 180 - auxdata->change_attr = inode_peek_iversion_raw(&nfsi->vfs_inode); 218 + kfree(nfss->fscache_uniq); 181 219 } 182 220 183 221 /* ··· 176 254 nfs_fscache_update_auxdata(&auxdata, nfsi); 177 255 178 256 nfsi->fscache = fscache_acquire_cookie(NFS_SB(inode->i_sb)->fscache, 179 - &nfs_fscache_inode_object_def, 180 - nfsi->fh.data, nfsi->fh.size, 181 - &auxdata, sizeof(auxdata), 182 - nfsi, nfsi->vfs_inode.i_size, false); 257 + 0, 258 + nfsi->fh.data, /* index_key */ 259 + nfsi->fh.size, 260 + &auxdata, /* aux_data */ 261 + sizeof(auxdata), 262 + i_size_read(&nfsi->vfs_inode)); 183 263 } 184 264 185 265 /* ··· 189 265 */ 190 266 void nfs_fscache_clear_inode(struct inode *inode) 191 267 { 192 - struct nfs_fscache_inode_auxdata auxdata; 193 268 struct nfs_inode *nfsi = NFS_I(inode); 194 269 struct fscache_cookie *cookie = nfs_i_fscache(inode); 195 270 196 271 dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n", nfsi, cookie); 197 272 198 - nfs_fscache_update_auxdata(&auxdata, nfsi); 199 - fscache_relinquish_cookie(cookie, &auxdata, false); 273 + fscache_relinquish_cookie(cookie, false); 200 274 nfsi->fscache = NULL; 201 - } 202 - 203 - static bool nfs_fscache_can_enable(void *data) 204 - { 205 - struct inode *inode = data; 206 - 207 - return !inode_is_open_for_write(inode); 208 275 } 209 276 210 277 /* ··· 222 307 struct nfs_fscache_inode_auxdata auxdata; 223 308 struct nfs_inode *nfsi = NFS_I(inode); 224 309 struct fscache_cookie *cookie = nfs_i_fscache(inode); 310 + bool open_for_write = inode_is_open_for_write(inode); 225 311 226 312 if (!fscache_cookie_valid(cookie)) 227 313 return; 228 314 229 - nfs_fscache_update_auxdata(&auxdata, nfsi); 230 - 231 - if (inode_is_open_for_write(inode)) { 315 + fscache_use_cookie(cookie, open_for_write); 316 + if (open_for_write) { 232 317 dfprintk(FSCACHE, "NFS: nfsi 0x%p disabling cache\n", nfsi); 233 - clear_bit(NFS_INO_FSCACHE, &nfsi->flags); 234 - fscache_disable_cookie(cookie, &auxdata, true); 235 - fscache_uncache_all_inode_pages(cookie, inode); 236 - } else { 237 - dfprintk(FSCACHE, "NFS: nfsi 0x%p enabling cache\n", nfsi); 238 - fscache_enable_cookie(cookie, &auxdata, nfsi->vfs_inode.i_size, 239 - nfs_fscache_can_enable, inode); 240 - if (fscache_cookie_enabled(cookie)) 241 - set_bit(NFS_INO_FSCACHE, &NFS_I(inode)->flags); 318 + nfs_fscache_update_auxdata(&auxdata, nfsi); 319 + fscache_invalidate(cookie, &auxdata, i_size_read(inode), 320 + FSCACHE_INVAL_DIO_WRITE); 242 321 } 243 322 } 244 323 EXPORT_SYMBOL_GPL(nfs_fscache_open_file); 245 324 246 - /* 247 - * Release the caching state associated with a page, if the page isn't busy 248 - * interacting with the cache. 249 - * - Returns true (can release page) or false (page busy). 250 - */ 251 - int nfs_fscache_release_page(struct page *page, gfp_t gfp) 325 + void nfs_fscache_release_file(struct inode *inode, struct file *filp) 252 326 { 253 - if (PageFsCache(page)) { 254 - struct fscache_cookie *cookie = nfs_i_fscache(page->mapping->host); 255 - 256 - BUG_ON(!cookie); 257 - dfprintk(FSCACHE, "NFS: fscache releasepage (0x%p/0x%p/0x%p)\n", 258 - cookie, page, NFS_I(page->mapping->host)); 259 - 260 - if (!fscache_maybe_release_page(cookie, page, gfp)) 261 - return 0; 262 - 263 - nfs_inc_fscache_stats(page->mapping->host, 264 - NFSIOS_FSCACHE_PAGES_UNCACHED); 265 - } 266 - 267 - return 1; 268 - } 269 - 270 - /* 271 - * Release the caching state associated with a page if undergoing complete page 272 - * invalidation. 273 - */ 274 - void __nfs_fscache_invalidate_page(struct page *page, struct inode *inode) 275 - { 327 + struct nfs_fscache_inode_auxdata auxdata; 328 + struct nfs_inode *nfsi = NFS_I(inode); 276 329 struct fscache_cookie *cookie = nfs_i_fscache(inode); 277 330 278 - BUG_ON(!cookie); 279 - 280 - dfprintk(FSCACHE, "NFS: fscache invalidatepage (0x%p/0x%p/0x%p)\n", 281 - cookie, page, NFS_I(inode)); 282 - 283 - fscache_wait_on_page_write(cookie, page); 284 - 285 - BUG_ON(!PageLocked(page)); 286 - fscache_uncache_page(cookie, page); 287 - nfs_inc_fscache_stats(page->mapping->host, 288 - NFSIOS_FSCACHE_PAGES_UNCACHED); 289 - } 290 - 291 - /* 292 - * Handle completion of a page being read from the cache. 293 - * - Called in process (keventd) context. 294 - */ 295 - static void nfs_readpage_from_fscache_complete(struct page *page, 296 - void *context, 297 - int error) 298 - { 299 - dfprintk(FSCACHE, 300 - "NFS: readpage_from_fscache_complete (0x%p/0x%p/%d)\n", 301 - page, context, error); 302 - 303 - /* 304 - * If the read completes with an error, mark the page with PG_checked, 305 - * unlock the page, and let the VM reissue the readpage. 306 - */ 307 - if (!error) 308 - SetPageUptodate(page); 309 - else 310 - SetPageChecked(page); 311 - unlock_page(page); 331 + if (fscache_cookie_valid(cookie)) { 332 + nfs_fscache_update_auxdata(&auxdata, nfsi); 333 + fscache_unuse_cookie(cookie, &auxdata, NULL); 334 + } 312 335 } 313 336 314 337 /* ··· 255 402 int __nfs_readpage_from_fscache(struct nfs_open_context *ctx, 256 403 struct inode *inode, struct page *page) 257 404 { 258 - int ret; 259 - 260 405 dfprintk(FSCACHE, 261 406 "NFS: readpage_from_fscache(fsc:%p/p:%p(i:%lx f:%lx)/0x%p)\n", 262 407 nfs_i_fscache(inode), page, page->index, page->flags, inode); ··· 264 413 return 1; 265 414 } 266 415 267 - ret = fscache_read_or_alloc_page(nfs_i_fscache(inode), 268 - page, 269 - nfs_readpage_from_fscache_complete, 270 - ctx, 271 - GFP_KERNEL); 272 - 273 - switch (ret) { 274 - case 0: /* read BIO submitted (page in fscache) */ 275 - dfprintk(FSCACHE, 276 - "NFS: readpage_from_fscache: BIO submitted\n"); 277 - nfs_inc_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_OK); 278 - return ret; 279 - 280 - case -ENOBUFS: /* inode not in cache */ 281 - case -ENODATA: /* page not in cache */ 282 - nfs_inc_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_FAIL); 283 - dfprintk(FSCACHE, 284 - "NFS: readpage_from_fscache %d\n", ret); 285 - return 1; 286 - 287 - default: 288 - dfprintk(FSCACHE, "NFS: readpage_from_fscache %d\n", ret); 289 - nfs_inc_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_FAIL); 290 - } 291 - return ret; 416 + return -ENOBUFS; // TODO: Use netfslib 292 417 } 293 418 294 419 /* ··· 276 449 struct list_head *pages, 277 450 unsigned *nr_pages) 278 451 { 279 - unsigned npages = *nr_pages; 280 - int ret; 281 - 282 452 dfprintk(FSCACHE, "NFS: nfs_getpages_from_fscache (0x%p/%u/0x%p)\n", 283 - nfs_i_fscache(inode), npages, inode); 453 + nfs_i_fscache(inode), *nr_pages, inode); 284 454 285 - ret = fscache_read_or_alloc_pages(nfs_i_fscache(inode), 286 - mapping, pages, nr_pages, 287 - nfs_readpage_from_fscache_complete, 288 - ctx, 289 - mapping_gfp_mask(mapping)); 290 - if (*nr_pages < npages) 291 - nfs_add_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_OK, 292 - npages); 293 - if (*nr_pages > 0) 294 - nfs_add_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_FAIL, 295 - *nr_pages); 296 - 297 - switch (ret) { 298 - case 0: /* read submitted to the cache for all pages */ 299 - BUG_ON(!list_empty(pages)); 300 - BUG_ON(*nr_pages != 0); 301 - dfprintk(FSCACHE, 302 - "NFS: nfs_getpages_from_fscache: submitted\n"); 303 - 304 - return ret; 305 - 306 - case -ENOBUFS: /* some pages aren't cached and can't be */ 307 - case -ENODATA: /* some pages aren't cached */ 308 - dfprintk(FSCACHE, 309 - "NFS: nfs_getpages_from_fscache: no page: %d\n", ret); 310 - return 1; 311 - 312 - default: 313 - dfprintk(FSCACHE, 314 - "NFS: nfs_getpages_from_fscache: ret %d\n", ret); 315 - } 316 - 317 - return ret; 455 + return -ENOBUFS; // TODO: Use netfslib 318 456 } 319 457 320 458 /* ··· 288 496 */ 289 497 void __nfs_readpage_to_fscache(struct inode *inode, struct page *page, int sync) 290 498 { 291 - int ret; 292 - 293 499 dfprintk(FSCACHE, 294 500 "NFS: readpage_to_fscache(fsc:%p/p:%p(i:%lx f:%lx)/%d)\n", 295 501 nfs_i_fscache(inode), page, page->index, page->flags, sync); 296 502 297 - ret = fscache_write_page(nfs_i_fscache(inode), page, 298 - inode->i_size, GFP_KERNEL); 299 - dfprintk(FSCACHE, 300 - "NFS: readpage_to_fscache: p:%p(i:%lu f:%lx) ret %d\n", 301 - page, page->index, page->flags, ret); 302 - 303 - if (ret != 0) { 304 - fscache_uncache_page(nfs_i_fscache(inode), page); 305 - nfs_inc_fscache_stats(inode, 306 - NFSIOS_FSCACHE_PAGES_WRITTEN_FAIL); 307 - nfs_inc_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_UNCACHED); 308 - } else { 309 - nfs_inc_fscache_stats(inode, 310 - NFSIOS_FSCACHE_PAGES_WRITTEN_OK); 311 - } 503 + return; // TODO: Use netfslib 312 504 }
+35 -92
fs/nfs/fscache.h
··· 12 12 #include <linux/nfs_mount.h> 13 13 #include <linux/nfs4_mount.h> 14 14 #include <linux/fscache.h> 15 + #include <linux/iversion.h> 15 16 16 17 #ifdef CONFIG_NFS_FSCACHE 17 - 18 - /* 19 - * set of NFS FS-Cache objects that form a superblock key 20 - */ 21 - struct nfs_fscache_key { 22 - struct rb_node node; 23 - struct nfs_client *nfs_client; /* the server */ 24 - 25 - /* the elements of the unique key - as used by nfs_compare_super() and 26 - * nfs_compare_mount_options() to distinguish superblocks */ 27 - struct { 28 - struct { 29 - unsigned long s_flags; /* various flags 30 - * (& NFS_MS_MASK) */ 31 - } super; 32 - 33 - struct { 34 - struct nfs_fsid fsid; 35 - int flags; 36 - unsigned int rsize; /* read size */ 37 - unsigned int wsize; /* write size */ 38 - unsigned int acregmin; /* attr cache timeouts */ 39 - unsigned int acregmax; 40 - unsigned int acdirmin; 41 - unsigned int acdirmax; 42 - } nfs_server; 43 - 44 - struct { 45 - rpc_authflavor_t au_flavor; 46 - } rpc_auth; 47 - 48 - /* uniquifier - can be used if nfs_server.flags includes 49 - * NFS_MOUNT_UNSHARED */ 50 - u8 uniq_len; 51 - char uniquifier[0]; 52 - } key; 53 - }; 54 18 55 19 /* 56 20 * Definition of the auxiliary data attached to NFS inode storage objects ··· 34 70 }; 35 71 36 72 /* 37 - * fscache-index.c 38 - */ 39 - extern struct fscache_netfs nfs_fscache_netfs; 40 - extern const struct fscache_cookie_def nfs_fscache_server_index_def; 41 - extern const struct fscache_cookie_def nfs_fscache_super_index_def; 42 - extern const struct fscache_cookie_def nfs_fscache_inode_object_def; 43 - 44 - extern int nfs_fscache_register(void); 45 - extern void nfs_fscache_unregister(void); 46 - 47 - /* 48 73 * fscache.c 49 74 */ 50 - extern void nfs_fscache_get_client_cookie(struct nfs_client *); 51 - extern void nfs_fscache_release_client_cookie(struct nfs_client *); 52 - 53 - extern void nfs_fscache_get_super_cookie(struct super_block *, const char *, int); 75 + extern int nfs_fscache_get_super_cookie(struct super_block *, const char *, int); 54 76 extern void nfs_fscache_release_super_cookie(struct super_block *); 55 77 56 78 extern void nfs_fscache_init_inode(struct inode *); 57 79 extern void nfs_fscache_clear_inode(struct inode *); 58 80 extern void nfs_fscache_open_file(struct inode *, struct file *); 81 + extern void nfs_fscache_release_file(struct inode *, struct file *); 59 82 60 83 extern void __nfs_fscache_invalidate_page(struct page *, struct inode *); 61 - extern int nfs_fscache_release_page(struct page *, gfp_t); 62 84 63 85 extern int __nfs_readpage_from_fscache(struct nfs_open_context *, 64 86 struct inode *, struct page *); ··· 53 103 struct list_head *, unsigned *); 54 104 extern void __nfs_readpage_to_fscache(struct inode *, struct page *, int); 55 105 56 - /* 57 - * wait for a page to complete writing to the cache 58 - */ 59 - static inline void nfs_fscache_wait_on_page_write(struct nfs_inode *nfsi, 60 - struct page *page) 106 + static inline int nfs_fscache_release_page(struct page *page, gfp_t gfp) 61 107 { 62 - if (PageFsCache(page)) 63 - fscache_wait_on_page_write(nfsi->fscache, page); 64 - } 65 - 66 - /* 67 - * release the caching state associated with a page if undergoing complete page 68 - * invalidation 69 - */ 70 - static inline void nfs_fscache_invalidate_page(struct page *page, 71 - struct inode *inode) 72 - { 73 - if (PageFsCache(page)) 74 - __nfs_fscache_invalidate_page(page, inode); 108 + if (PageFsCache(page)) { 109 + if (!gfpflags_allow_blocking(gfp) || !(gfp & __GFP_FS)) 110 + return false; 111 + wait_on_page_fscache(page); 112 + fscache_note_page_release(nfs_i_fscache(page->mapping->host)); 113 + nfs_inc_fscache_stats(page->mapping->host, 114 + NFSIOS_FSCACHE_PAGES_UNCACHED); 115 + } 116 + return true; 75 117 } 76 118 77 119 /* ··· 105 163 __nfs_readpage_to_fscache(inode, page, sync); 106 164 } 107 165 108 - /* 109 - * Invalidate the contents of fscache for this inode. This will not sleep. 110 - */ 111 - static inline void nfs_fscache_invalidate(struct inode *inode) 166 + static inline void nfs_fscache_update_auxdata(struct nfs_fscache_inode_auxdata *auxdata, 167 + struct nfs_inode *nfsi) 112 168 { 113 - fscache_invalidate(NFS_I(inode)->fscache); 169 + memset(auxdata, 0, sizeof(*auxdata)); 170 + auxdata->mtime_sec = nfsi->vfs_inode.i_mtime.tv_sec; 171 + auxdata->mtime_nsec = nfsi->vfs_inode.i_mtime.tv_nsec; 172 + auxdata->ctime_sec = nfsi->vfs_inode.i_ctime.tv_sec; 173 + auxdata->ctime_nsec = nfsi->vfs_inode.i_ctime.tv_nsec; 174 + 175 + if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4) 176 + auxdata->change_attr = inode_peek_iversion_raw(&nfsi->vfs_inode); 114 177 } 115 178 116 179 /* 117 - * Wait for an object to finish being invalidated. 180 + * Invalidate the contents of fscache for this inode. This will not sleep. 118 181 */ 119 - static inline void nfs_fscache_wait_on_invalidate(struct inode *inode) 182 + static inline void nfs_fscache_invalidate(struct inode *inode, int flags) 120 183 { 121 - fscache_wait_on_invalidate(NFS_I(inode)->fscache); 184 + struct nfs_fscache_inode_auxdata auxdata; 185 + struct nfs_inode *nfsi = NFS_I(inode); 186 + 187 + if (nfsi->fscache) { 188 + nfs_fscache_update_auxdata(&auxdata, nfsi); 189 + fscache_invalidate(nfsi->fscache, &auxdata, 190 + i_size_read(&nfsi->vfs_inode), flags); 191 + } 122 192 } 123 193 124 194 /* ··· 144 190 } 145 191 146 192 #else /* CONFIG_NFS_FSCACHE */ 147 - static inline int nfs_fscache_register(void) { return 0; } 148 - static inline void nfs_fscache_unregister(void) {} 149 - 150 - static inline void nfs_fscache_get_client_cookie(struct nfs_client *clp) {} 151 - static inline void nfs_fscache_release_client_cookie(struct nfs_client *clp) {} 152 - 153 193 static inline void nfs_fscache_release_super_cookie(struct super_block *sb) {} 154 194 155 195 static inline void nfs_fscache_init_inode(struct inode *inode) {} 156 196 static inline void nfs_fscache_clear_inode(struct inode *inode) {} 157 197 static inline void nfs_fscache_open_file(struct inode *inode, 158 198 struct file *filp) {} 199 + static inline void nfs_fscache_release_file(struct inode *inode, struct file *file) {} 159 200 160 201 static inline int nfs_fscache_release_page(struct page *page, gfp_t gfp) 161 202 { 162 203 return 1; /* True: may release page */ 163 204 } 164 - static inline void nfs_fscache_invalidate_page(struct page *page, 165 - struct inode *inode) {} 166 - static inline void nfs_fscache_wait_on_page_write(struct nfs_inode *nfsi, 167 - struct page *page) {} 168 - 169 205 static inline int nfs_readpage_from_fscache(struct nfs_open_context *ctx, 170 206 struct inode *inode, 171 207 struct page *page) ··· 174 230 struct page *page, int sync) {} 175 231 176 232 177 - static inline void nfs_fscache_invalidate(struct inode *inode) {} 178 - static inline void nfs_fscache_wait_on_invalidate(struct inode *inode) {} 233 + static inline void nfs_fscache_invalidate(struct inode *inode, int flags) {} 179 234 180 235 static inline const char *nfs_server_fscache_state(struct nfs_server *server) 181 236 {
+2 -9
fs/nfs/inode.c
··· 209 209 if (!nfs_has_xattr_cache(nfsi)) 210 210 flags &= ~NFS_INO_INVALID_XATTR; 211 211 if (flags & NFS_INO_INVALID_DATA) 212 - nfs_fscache_invalidate(inode); 212 + nfs_fscache_invalidate(inode, 0); 213 213 flags &= ~(NFS_INO_REVAL_PAGECACHE | NFS_INO_REVAL_FORCED); 214 214 215 215 nfsi->cache_validity |= flags; ··· 1289 1289 { 1290 1290 int ret; 1291 1291 1292 + nfs_fscache_invalidate(inode, 0); 1292 1293 if (mapping->nrpages != 0) { 1293 1294 if (S_ISREG(inode->i_mode)) { 1294 1295 ret = nfs_sync_mapping(mapping); ··· 1301 1300 return ret; 1302 1301 } 1303 1302 nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE); 1304 - nfs_fscache_wait_on_invalidate(inode); 1305 1303 1306 1304 dfprintk(PAGECACHE, "NFS: (%s/%Lu) data cache invalidated\n", 1307 1305 inode->i_sb->s_id, ··· 2374 2374 if (err < 0) 2375 2375 goto out9; 2376 2376 2377 - err = nfs_fscache_register(); 2378 - if (err < 0) 2379 - goto out8; 2380 - 2381 2377 err = nfsiod_start(); 2382 2378 if (err) 2383 2379 goto out7; ··· 2425 2429 out6: 2426 2430 nfsiod_stop(); 2427 2431 out7: 2428 - nfs_fscache_unregister(); 2429 - out8: 2430 2432 unregister_pernet_subsys(&nfs_net_ops); 2431 2433 out9: 2432 2434 nfs_sysfs_exit(); ··· 2439 2445 nfs_destroy_readpagecache(); 2440 2446 nfs_destroy_inodecache(); 2441 2447 nfs_destroy_nfspagecache(); 2442 - nfs_fscache_unregister(); 2443 2448 unregister_pernet_subsys(&nfs_net_ops); 2444 2449 rpc_proc_unregister(&init_net, "nfs"); 2445 2450 unregister_nfs_fs();
-1
fs/nfs/nfstrace.h
··· 42 42 { BIT(NFS_INO_ACL_LRU_SET), "ACL_LRU_SET" }, \ 43 43 { BIT(NFS_INO_INVALIDATING), "INVALIDATING" }, \ 44 44 { BIT(NFS_INO_FSCACHE), "FSCACHE" }, \ 45 - { BIT(NFS_INO_FSCACHE_LOCK), "FSCACHE_LOCK" }, \ 46 45 { BIT(NFS_INO_LAYOUTCOMMIT), "NEED_LAYOUTCOMMIT" }, \ 47 46 { BIT(NFS_INO_LAYOUTCOMMITTING), "LAYOUTCOMMIT" }, \ 48 47 { BIT(NFS_INO_LAYOUTSTATS), "LAYOUTSTATS" }, \
+15 -13
fs/nfs/super.c
··· 1204 1204 } 1205 1205 1206 1206 #ifdef CONFIG_NFS_FSCACHE 1207 - static void nfs_get_cache_cookie(struct super_block *sb, 1208 - struct nfs_fs_context *ctx) 1207 + static int nfs_get_cache_cookie(struct super_block *sb, 1208 + struct nfs_fs_context *ctx) 1209 1209 { 1210 1210 struct nfs_server *nfss = NFS_SB(sb); 1211 1211 char *uniq = NULL; 1212 1212 int ulen = 0; 1213 1213 1214 - nfss->fscache_key = NULL; 1215 1214 nfss->fscache = NULL; 1216 1215 1217 1216 if (!ctx) 1218 - return; 1217 + return 0; 1219 1218 1220 1219 if (ctx->clone_data.sb) { 1221 1220 struct nfs_server *mnt_s = NFS_SB(ctx->clone_data.sb); 1222 1221 if (!(mnt_s->options & NFS_OPTION_FSCACHE)) 1223 - return; 1224 - if (mnt_s->fscache_key) { 1225 - uniq = mnt_s->fscache_key->key.uniquifier; 1226 - ulen = mnt_s->fscache_key->key.uniq_len; 1222 + return 0; 1223 + if (mnt_s->fscache_uniq) { 1224 + uniq = mnt_s->fscache_uniq; 1225 + ulen = strlen(uniq); 1227 1226 } 1228 1227 } else { 1229 1228 if (!(ctx->options & NFS_OPTION_FSCACHE)) 1230 - return; 1229 + return 0; 1231 1230 if (ctx->fscache_uniq) { 1232 1231 uniq = ctx->fscache_uniq; 1233 1232 ulen = strlen(ctx->fscache_uniq); 1234 1233 } 1235 1234 } 1236 1235 1237 - nfs_fscache_get_super_cookie(sb, uniq, ulen); 1236 + return nfs_fscache_get_super_cookie(sb, uniq, ulen); 1238 1237 } 1239 1238 #else 1240 - static void nfs_get_cache_cookie(struct super_block *sb, 1241 - struct nfs_fs_context *ctx) 1239 + static int nfs_get_cache_cookie(struct super_block *sb, 1240 + struct nfs_fs_context *ctx) 1242 1241 { 1242 + return 0; 1243 1243 } 1244 1244 #endif 1245 1245 ··· 1299 1299 s->s_blocksize_bits = bsize; 1300 1300 s->s_blocksize = 1U << bsize; 1301 1301 } 1302 - nfs_get_cache_cookie(s, ctx); 1302 + error = nfs_get_cache_cookie(s, ctx); 1303 + if (error < 0) 1304 + goto error_splat_super; 1303 1305 } 1304 1306 1305 1307 error = nfs_get_root(s, fc);
+1
fs/nfs/write.c
··· 294 294 nfs_inc_stats(inode, NFSIOS_EXTENDWRITE); 295 295 out: 296 296 spin_unlock(&inode->i_lock); 297 + nfs_fscache_invalidate(inode, 0); 297 298 } 298 299 299 300 /* A writeback failed: mark the page as bad, and invalidate the page cache */
-1
include/linux/nfs_fs.h
··· 275 275 #define NFS_INO_ACL_LRU_SET (2) /* Inode is on the LRU list */ 276 276 #define NFS_INO_INVALIDATING (3) /* inode is being invalidated */ 277 277 #define NFS_INO_FSCACHE (5) /* inode can be cached by FS-Cache */ 278 - #define NFS_INO_FSCACHE_LOCK (6) /* FS-Cache cookie management lock */ 279 278 #define NFS_INO_FORCE_READDIR (7) /* force readdirplus */ 280 279 #define NFS_INO_LAYOUTCOMMIT (9) /* layoutcommit required */ 281 280 #define NFS_INO_LAYOUTCOMMITTING (10) /* layoutcommit inflight */
+2 -7
include/linux/nfs_fs_sb.h
··· 120 120 * This is used to generate the mv0 callback address. 121 121 */ 122 122 char cl_ipaddr[48]; 123 - 124 - #ifdef CONFIG_NFS_FSCACHE 125 - struct fscache_cookie *fscache; /* client index cache cookie */ 126 - #endif 127 - 128 123 struct net *cl_net; 129 124 struct list_head pending_cb_stateids; 130 125 }; ··· 189 194 struct nfs_auth_info auth_info; /* parsed auth flavors */ 190 195 191 196 #ifdef CONFIG_NFS_FSCACHE 192 - struct nfs_fscache_key *fscache_key; /* unique key for superblock */ 193 - struct fscache_cookie *fscache; /* superblock cookie */ 197 + struct fscache_volume *fscache; /* superblock cookie */ 198 + char *fscache_uniq; /* Uniquifier (or NULL) */ 194 199 #endif 195 200 196 201 u32 pnfs_blksize; /* layout_blksize attr */