mirror of
https://github.com/torvalds/linux.git
synced 2024-12-13 14:43:03 +00:00
70431bfd82
Change the cifs filesystem to take account of the changes to fscache's indexing rewrite and reenable caching in cifs. 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 cifs, I've made it render the volume name string as: "cifs,<ipaddress>,<sharename>" where the sharename has '/' characters replaced with ';'. This probably needs rethinking a bit as the total name could exceed the maximum filename component length. Further, the coherency data is currently just set to 0. It needs something else doing with it - I wonder if it would suffice simply to sum the resource_id, vol_create_time and vol_serial_number or maybe hash them. (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) The functions to set/reset cookies are removed and fscache_use_cookie() and fscache_unuse_cookie() are used instead. fscache_use_cookie() is passed a flag to indicate if the cookie is opened for writing. fscache_unuse_cookie() is passed updates for the metadata if we changed it (ie. if the file was opened for writing). These are called when the file is opened or closed. (5) cifs_setattr_*() are made to call fscache_resize() to change the size of the cache object. (6) The functions to read and write data are stubbed out pending a conversion to use netfslib. Changes ======= ver #8: - Abstract cache invalidation into a helper function. - Fix some checkpatch warnings[3]. ver #7: - Removed the accidentally added-back call to get the super cookie in cifs_root_iget(). - Fixed the right call to cifs_fscache_get_super_cookie() to take account of the "-o fsc" mount flag. ver #6: - Moved the change of gfpflags_allow_blocking() to current_is_kswapd() for cifs here. - Fixed one of the error paths in cifs_atomic_open() to jump around the call to use the cookie. - Fixed an additional successful return in the middle of cifs_open() to use the cookie on the way out. - Only get a volume cookie (and thus inode cookies) when "-o fsc" is supplied to mount. ver #5: - Fixed a couple of bits of cookie handling[2]: - The cookie should be released in cifs_evict_inode(), not cifsFileInfo_put_final(). The cookie needs to persist beyond file closure so that writepages will be able to write to it. - fscache_use_cookie() needs to be called in cifs_atomic_open() as it is for cifs_open(). ver #4: - Fixed the use of sizeof with memset. - tcon->vol_create_time is __le64 so doesn't need cpu_to_le64(). ver #3: - Canonicalise the cifs coherency data to make the cache portable. - Set volume coherency data. ver #2: - Use gfpflags_allow_blocking() rather than using flag directly. - Upgraded to -rc4 to allow for upstream changes[1]. - fscache_acquire_volume() now returns errors. Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: Jeff Layton <jlayton@kernel.org> cc: Steve French <smfrench@gmail.com> cc: Shyam Prasad N <nspmangalore@gmail.com> cc: linux-cifs@vger.kernel.org cc: linux-cachefs@redhat.com Link: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=23b55d673d7527b093cd97b7c217c82e70cd1af0 [1] Link: https://lore.kernel.org/r/3419813.1641592362@warthog.procyon.org.uk/ [2] Link: https://lore.kernel.org/r/CAH2r5muTanw9pJqzAHd01d9A8keeChkzGsCEH6=0rHutVLAF-A@mail.gmail.com/ [3] Link: https://lore.kernel.org/r/163819671009.215744.11230627184193298714.stgit@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/163906982979.143852.10672081929614953210.stgit@warthog.procyon.org.uk/ # v2 Link: https://lore.kernel.org/r/163967187187.1823006.247415138444991444.stgit@warthog.procyon.org.uk/ # v3 Link: https://lore.kernel.org/r/164021579335.640689.2681324337038770579.stgit@warthog.procyon.org.uk/ # v4 Link: https://lore.kernel.org/r/3462849.1641593783@warthog.procyon.org.uk/ # v5 Link: https://lore.kernel.org/r/1318953.1642024578@warthog.procyon.org.uk/ # v6 Signed-off-by: Steve French <stfrench@microsoft.com>
171 lines
4.2 KiB
C
171 lines
4.2 KiB
C
// SPDX-License-Identifier: LGPL-2.1
|
|
/*
|
|
* CIFS filesystem cache interface
|
|
*
|
|
* Copyright (c) 2010 Novell, Inc.
|
|
* Author(s): Suresh Jayaraman <sjayaraman@suse.de>
|
|
*
|
|
*/
|
|
#include "fscache.h"
|
|
#include "cifsglob.h"
|
|
#include "cifs_debug.h"
|
|
#include "cifs_fs_sb.h"
|
|
#include "cifsproto.h"
|
|
|
|
static void cifs_fscache_fill_volume_coherency(
|
|
struct cifs_tcon *tcon,
|
|
struct cifs_fscache_volume_coherency_data *cd)
|
|
{
|
|
memset(cd, 0, sizeof(*cd));
|
|
cd->resource_id = cpu_to_le64(tcon->resource_id);
|
|
cd->vol_create_time = tcon->vol_create_time;
|
|
cd->vol_serial_number = cpu_to_le32(tcon->vol_serial_number);
|
|
}
|
|
|
|
int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
|
|
{
|
|
struct cifs_fscache_volume_coherency_data cd;
|
|
struct TCP_Server_Info *server = tcon->ses->server;
|
|
struct fscache_volume *vcookie;
|
|
const struct sockaddr *sa = (struct sockaddr *)&server->dstaddr;
|
|
size_t slen, i;
|
|
char *sharename;
|
|
char *key;
|
|
int ret = -ENOMEM;
|
|
|
|
tcon->fscache = NULL;
|
|
switch (sa->sa_family) {
|
|
case AF_INET:
|
|
case AF_INET6:
|
|
break;
|
|
default:
|
|
cifs_dbg(VFS, "Unknown network family '%d'\n", sa->sa_family);
|
|
return -EINVAL;
|
|
}
|
|
|
|
memset(&key, 0, sizeof(key));
|
|
|
|
sharename = extract_sharename(tcon->treeName);
|
|
if (IS_ERR(sharename)) {
|
|
cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
slen = strlen(sharename);
|
|
for (i = 0; i < slen; i++)
|
|
if (sharename[i] == '/')
|
|
sharename[i] = ';';
|
|
|
|
key = kasprintf(GFP_KERNEL, "cifs,%pISpc,%s", sa, sharename);
|
|
if (!key)
|
|
goto out;
|
|
|
|
cifs_fscache_fill_volume_coherency(tcon, &cd);
|
|
vcookie = fscache_acquire_volume(key,
|
|
NULL, /* preferred_cache */
|
|
&cd, sizeof(cd));
|
|
cifs_dbg(FYI, "%s: (%s/0x%p)\n", __func__, key, vcookie);
|
|
if (IS_ERR(vcookie)) {
|
|
if (vcookie != ERR_PTR(-EBUSY)) {
|
|
ret = PTR_ERR(vcookie);
|
|
goto out_2;
|
|
}
|
|
pr_err("Cache volume key already in use (%s)\n", key);
|
|
vcookie = NULL;
|
|
}
|
|
|
|
tcon->fscache = vcookie;
|
|
ret = 0;
|
|
out_2:
|
|
kfree(key);
|
|
out:
|
|
kfree(sharename);
|
|
return ret;
|
|
}
|
|
|
|
void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon)
|
|
{
|
|
struct cifs_fscache_volume_coherency_data cd;
|
|
|
|
cifs_dbg(FYI, "%s: (0x%p)\n", __func__, tcon->fscache);
|
|
|
|
cifs_fscache_fill_volume_coherency(tcon, &cd);
|
|
fscache_relinquish_volume(tcon->fscache, &cd, false);
|
|
tcon->fscache = NULL;
|
|
}
|
|
|
|
void cifs_fscache_get_inode_cookie(struct inode *inode)
|
|
{
|
|
struct cifs_fscache_inode_coherency_data cd;
|
|
struct cifsInodeInfo *cifsi = CIFS_I(inode);
|
|
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
|
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
|
|
|
cifs_fscache_fill_coherency(&cifsi->vfs_inode, &cd);
|
|
|
|
cifsi->fscache =
|
|
fscache_acquire_cookie(tcon->fscache, 0,
|
|
&cifsi->uniqueid, sizeof(cifsi->uniqueid),
|
|
&cd, sizeof(cd),
|
|
i_size_read(&cifsi->vfs_inode));
|
|
}
|
|
|
|
void cifs_fscache_unuse_inode_cookie(struct inode *inode, bool update)
|
|
{
|
|
if (update) {
|
|
struct cifs_fscache_inode_coherency_data cd;
|
|
loff_t i_size = i_size_read(inode);
|
|
|
|
cifs_fscache_fill_coherency(inode, &cd);
|
|
fscache_unuse_cookie(cifs_inode_cookie(inode), &cd, &i_size);
|
|
} else {
|
|
fscache_unuse_cookie(cifs_inode_cookie(inode), NULL, NULL);
|
|
}
|
|
}
|
|
|
|
void cifs_fscache_release_inode_cookie(struct inode *inode)
|
|
{
|
|
struct cifsInodeInfo *cifsi = CIFS_I(inode);
|
|
|
|
if (cifsi->fscache) {
|
|
cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache);
|
|
fscache_relinquish_cookie(cifsi->fscache, false);
|
|
cifsi->fscache = NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Retrieve a page from FS-Cache
|
|
*/
|
|
int __cifs_readpage_from_fscache(struct inode *inode, struct page *page)
|
|
{
|
|
cifs_dbg(FYI, "%s: (fsc:%p, p:%p, i:0x%p\n",
|
|
__func__, CIFS_I(inode)->fscache, page, inode);
|
|
return -ENOBUFS; // Needs conversion to using netfslib
|
|
}
|
|
|
|
/*
|
|
* Retrieve a set of pages from FS-Cache
|
|
*/
|
|
int __cifs_readpages_from_fscache(struct inode *inode,
|
|
struct address_space *mapping,
|
|
struct list_head *pages,
|
|
unsigned *nr_pages)
|
|
{
|
|
cifs_dbg(FYI, "%s: (0x%p/%u/0x%p)\n",
|
|
__func__, CIFS_I(inode)->fscache, *nr_pages, inode);
|
|
return -ENOBUFS; // Needs conversion to using netfslib
|
|
}
|
|
|
|
void __cifs_readpage_to_fscache(struct inode *inode, struct page *page)
|
|
{
|
|
struct cifsInodeInfo *cifsi = CIFS_I(inode);
|
|
|
|
WARN_ON(!cifsi->fscache);
|
|
|
|
cifs_dbg(FYI, "%s: (fsc: %p, p: %p, i: %p)\n",
|
|
__func__, cifsi->fscache, page, inode);
|
|
|
|
// Needs conversion to using netfslib
|
|
}
|