ceph: conversion to new fscache API
Now that the fscache API has been reworked and simplified, change ceph over to use it. With the old API, we would only instantiate a cookie when the file was open for reads. Change it to instantiate the cookie when the inode is instantiated and call use/unuse when the file is opened/closed. Also, ensure we resize the cached data on truncates, and invalidate the cache in response to the appropriate events. This will allow us to plumb in write support later. Signed-off-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: David Howells <dhowells@redhat.com> Link: https://lore.kernel.org/r/20211129162907.149445-2-jlayton@kernel.org/ # v1 Link: https://lore.kernel.org/r/20211207134451.66296-2-jlayton@kernel.org/ # v2 Link: https://lore.kernel.org/r/163906984277.143852.14697110691303589000.stgit@warthog.procyon.org.uk/ # v2 Link: https://lore.kernel.org/r/163967188351.1823006.5065634844099079351.stgit@warthog.procyon.org.uk/ # v3 Link: https://lore.kernel.org/r/164021581427.640689.14128682147127509264.stgit@warthog.procyon.org.uk/ # v4
This commit is contained in:
parent
16f2f4e679
commit
400e1286c0
9 changed files with 195 additions and 241 deletions
|
@ -21,7 +21,7 @@ config CEPH_FS
|
||||||
if CEPH_FS
|
if CEPH_FS
|
||||||
config CEPH_FSCACHE
|
config CEPH_FSCACHE
|
||||||
bool "Enable Ceph client caching support"
|
bool "Enable Ceph client caching support"
|
||||||
depends on CEPH_FS=m && FSCACHE_OLD_API || CEPH_FS=y && FSCACHE_OLD_API=y
|
depends on CEPH_FS=m && FSCACHE || CEPH_FS=y && FSCACHE=y
|
||||||
help
|
help
|
||||||
Choose Y here to enable persistent, read-only local
|
Choose Y here to enable persistent, read-only local
|
||||||
caching support for Ceph clients using FS-Cache
|
caching support for Ceph clients using FS-Cache
|
||||||
|
|
|
@ -126,7 +126,7 @@ static int ceph_set_page_dirty(struct page *page)
|
||||||
BUG_ON(PagePrivate(page));
|
BUG_ON(PagePrivate(page));
|
||||||
attach_page_private(page, snapc);
|
attach_page_private(page, snapc);
|
||||||
|
|
||||||
return __set_page_dirty_nobuffers(page);
|
return ceph_fscache_set_page_dirty(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -141,8 +141,6 @@ static void ceph_invalidatepage(struct page *page, unsigned int offset,
|
||||||
struct ceph_inode_info *ci;
|
struct ceph_inode_info *ci;
|
||||||
struct ceph_snap_context *snapc;
|
struct ceph_snap_context *snapc;
|
||||||
|
|
||||||
wait_on_page_fscache(page);
|
|
||||||
|
|
||||||
inode = page->mapping->host;
|
inode = page->mapping->host;
|
||||||
ci = ceph_inode(inode);
|
ci = ceph_inode(inode);
|
||||||
|
|
||||||
|
@ -153,28 +151,36 @@ static void ceph_invalidatepage(struct page *page, unsigned int offset,
|
||||||
}
|
}
|
||||||
|
|
||||||
WARN_ON(!PageLocked(page));
|
WARN_ON(!PageLocked(page));
|
||||||
if (!PagePrivate(page))
|
if (PagePrivate(page)) {
|
||||||
return;
|
dout("%p invalidatepage %p idx %lu full dirty page\n",
|
||||||
|
inode, page, page->index);
|
||||||
|
|
||||||
dout("%p invalidatepage %p idx %lu full dirty page\n",
|
snapc = detach_page_private(page);
|
||||||
inode, page, page->index);
|
ceph_put_wrbuffer_cap_refs(ci, 1, snapc);
|
||||||
|
ceph_put_snap_context(snapc);
|
||||||
|
}
|
||||||
|
|
||||||
snapc = detach_page_private(page);
|
wait_on_page_fscache(page);
|
||||||
ceph_put_wrbuffer_cap_refs(ci, 1, snapc);
|
|
||||||
ceph_put_snap_context(snapc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ceph_releasepage(struct page *page, gfp_t gfp)
|
static int ceph_releasepage(struct page *page, gfp_t gfp)
|
||||||
{
|
{
|
||||||
dout("%p releasepage %p idx %lu (%sdirty)\n", page->mapping->host,
|
struct inode *inode = page->mapping->host;
|
||||||
page, page->index, PageDirty(page) ? "" : "not ");
|
|
||||||
|
dout("%llx:%llx releasepage %p idx %lu (%sdirty)\n",
|
||||||
|
ceph_vinop(inode), page,
|
||||||
|
page->index, PageDirty(page) ? "" : "not ");
|
||||||
|
|
||||||
|
if (PagePrivate(page))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (PageFsCache(page)) {
|
if (PageFsCache(page)) {
|
||||||
if (!(gfp & __GFP_DIRECT_RECLAIM) || !(gfp & __GFP_FS))
|
if (!gfpflags_allow_blocking(gfp) || !(gfp & __GFP_FS))
|
||||||
return 0;
|
return 0;
|
||||||
wait_on_page_fscache(page);
|
wait_on_page_fscache(page);
|
||||||
}
|
}
|
||||||
return !PagePrivate(page);
|
ceph_fscache_note_page_release(inode);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ceph_netfs_expand_readahead(struct netfs_read_request *rreq)
|
static void ceph_netfs_expand_readahead(struct netfs_read_request *rreq)
|
||||||
|
|
250
fs/ceph/cache.c
250
fs/ceph/cache.c
|
@ -12,36 +12,73 @@
|
||||||
#include "super.h"
|
#include "super.h"
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
|
|
||||||
struct fscache_netfs ceph_cache_netfs = {
|
void ceph_fscache_register_inode_cookie(struct inode *inode)
|
||||||
.name = "ceph",
|
|
||||||
.version = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
static DEFINE_MUTEX(ceph_fscache_lock);
|
|
||||||
static LIST_HEAD(ceph_fscache_list);
|
|
||||||
|
|
||||||
struct ceph_fscache_entry {
|
|
||||||
struct list_head list;
|
|
||||||
struct fscache_cookie *fscache;
|
|
||||||
size_t uniq_len;
|
|
||||||
/* The following members must be last */
|
|
||||||
struct ceph_fsid fsid;
|
|
||||||
char uniquifier[];
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct fscache_cookie_def ceph_fscache_fsid_object_def = {
|
|
||||||
.name = "CEPH.fsid",
|
|
||||||
.type = FSCACHE_COOKIE_TYPE_INDEX,
|
|
||||||
};
|
|
||||||
|
|
||||||
int __init ceph_fscache_register(void)
|
|
||||||
{
|
{
|
||||||
return fscache_register_netfs(&ceph_cache_netfs);
|
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||||
|
struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
|
||||||
|
|
||||||
|
/* No caching for filesystem? */
|
||||||
|
if (!fsc->fscache)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Regular files only */
|
||||||
|
if (!S_ISREG(inode->i_mode))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Only new inodes! */
|
||||||
|
if (!(inode->i_state & I_NEW))
|
||||||
|
return;
|
||||||
|
|
||||||
|
WARN_ON_ONCE(ci->fscache);
|
||||||
|
|
||||||
|
ci->fscache = fscache_acquire_cookie(fsc->fscache, 0,
|
||||||
|
&ci->i_vino, sizeof(ci->i_vino),
|
||||||
|
&ci->i_version, sizeof(ci->i_version),
|
||||||
|
i_size_read(inode));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ceph_fscache_unregister(void)
|
void ceph_fscache_unregister_inode_cookie(struct ceph_inode_info* ci)
|
||||||
{
|
{
|
||||||
fscache_unregister_netfs(&ceph_cache_netfs);
|
struct fscache_cookie *cookie = ci->fscache;
|
||||||
|
|
||||||
|
fscache_relinquish_cookie(cookie, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ceph_fscache_use_cookie(struct inode *inode, bool will_modify)
|
||||||
|
{
|
||||||
|
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||||
|
|
||||||
|
fscache_use_cookie(ci->fscache, will_modify);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ceph_fscache_unuse_cookie(struct inode *inode, bool update)
|
||||||
|
{
|
||||||
|
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||||
|
|
||||||
|
if (update) {
|
||||||
|
loff_t i_size = i_size_read(inode);
|
||||||
|
|
||||||
|
fscache_unuse_cookie(ci->fscache, &ci->i_version, &i_size);
|
||||||
|
} else {
|
||||||
|
fscache_unuse_cookie(ci->fscache, NULL, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ceph_fscache_update(struct inode *inode)
|
||||||
|
{
|
||||||
|
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||||
|
loff_t i_size = i_size_read(inode);
|
||||||
|
|
||||||
|
fscache_update_cookie(ci->fscache, &ci->i_version, &i_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ceph_fscache_invalidate(struct inode *inode, bool dio_write)
|
||||||
|
{
|
||||||
|
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||||
|
|
||||||
|
fscache_invalidate(ceph_inode(inode)->fscache,
|
||||||
|
&ci->i_version, i_size_read(inode),
|
||||||
|
dio_write ? FSCACHE_INVAL_DIO_WRITE : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ceph_fscache_register_fs(struct ceph_fs_client* fsc, struct fs_context *fc)
|
int ceph_fscache_register_fs(struct ceph_fs_client* fsc, struct fs_context *fc)
|
||||||
|
@ -49,162 +86,25 @@ int ceph_fscache_register_fs(struct ceph_fs_client* fsc, struct fs_context *fc)
|
||||||
const struct ceph_fsid *fsid = &fsc->client->fsid;
|
const struct ceph_fsid *fsid = &fsc->client->fsid;
|
||||||
const char *fscache_uniq = fsc->mount_options->fscache_uniq;
|
const char *fscache_uniq = fsc->mount_options->fscache_uniq;
|
||||||
size_t uniq_len = fscache_uniq ? strlen(fscache_uniq) : 0;
|
size_t uniq_len = fscache_uniq ? strlen(fscache_uniq) : 0;
|
||||||
struct ceph_fscache_entry *ent;
|
char *name;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
mutex_lock(&ceph_fscache_lock);
|
name = kasprintf(GFP_KERNEL, "ceph,%pU%s%s", fsid, uniq_len ? "," : "",
|
||||||
list_for_each_entry(ent, &ceph_fscache_list, list) {
|
uniq_len ? fscache_uniq : "");
|
||||||
if (memcmp(&ent->fsid, fsid, sizeof(*fsid)))
|
if (!name)
|
||||||
continue;
|
return -ENOMEM;
|
||||||
if (ent->uniq_len != uniq_len)
|
|
||||||
continue;
|
|
||||||
if (uniq_len && memcmp(ent->uniquifier, fscache_uniq, uniq_len))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
errorfc(fc, "fscache cookie already registered for fsid %pU, use fsc=<uniquifier> option",
|
fsc->fscache = fscache_acquire_volume(name, NULL, NULL, 0);
|
||||||
fsid);
|
if (IS_ERR_OR_NULL(fsc->fscache)) {
|
||||||
err = -EBUSY;
|
errorfc(fc, "Unable to register fscache cookie for %s", name);
|
||||||
goto out_unlock;
|
err = fsc->fscache ? PTR_ERR(fsc->fscache) : -EOPNOTSUPP;
|
||||||
|
fsc->fscache = NULL;
|
||||||
}
|
}
|
||||||
|
kfree(name);
|
||||||
ent = kzalloc(sizeof(*ent) + uniq_len, GFP_KERNEL);
|
|
||||||
if (!ent) {
|
|
||||||
err = -ENOMEM;
|
|
||||||
goto out_unlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(&ent->fsid, fsid, sizeof(*fsid));
|
|
||||||
if (uniq_len > 0) {
|
|
||||||
memcpy(&ent->uniquifier, fscache_uniq, uniq_len);
|
|
||||||
ent->uniq_len = uniq_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
fsc->fscache = fscache_acquire_cookie(ceph_cache_netfs.primary_index,
|
|
||||||
&ceph_fscache_fsid_object_def,
|
|
||||||
&ent->fsid, sizeof(ent->fsid) + uniq_len,
|
|
||||||
NULL, 0,
|
|
||||||
fsc, 0, true);
|
|
||||||
|
|
||||||
if (fsc->fscache) {
|
|
||||||
ent->fscache = fsc->fscache;
|
|
||||||
list_add_tail(&ent->list, &ceph_fscache_list);
|
|
||||||
} else {
|
|
||||||
kfree(ent);
|
|
||||||
errorfc(fc, "unable to register fscache cookie for fsid %pU",
|
|
||||||
fsid);
|
|
||||||
/* all other fs ignore this error */
|
|
||||||
}
|
|
||||||
out_unlock:
|
|
||||||
mutex_unlock(&ceph_fscache_lock);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum fscache_checkaux ceph_fscache_inode_check_aux(
|
|
||||||
void *cookie_netfs_data, const void *data, uint16_t dlen,
|
|
||||||
loff_t object_size)
|
|
||||||
{
|
|
||||||
struct ceph_inode_info* ci = cookie_netfs_data;
|
|
||||||
struct inode* inode = &ci->vfs_inode;
|
|
||||||
|
|
||||||
if (dlen != sizeof(ci->i_version) ||
|
|
||||||
i_size_read(inode) != object_size)
|
|
||||||
return FSCACHE_CHECKAUX_OBSOLETE;
|
|
||||||
|
|
||||||
if (*(u64 *)data != ci->i_version)
|
|
||||||
return FSCACHE_CHECKAUX_OBSOLETE;
|
|
||||||
|
|
||||||
dout("ceph inode 0x%p cached okay\n", ci);
|
|
||||||
return FSCACHE_CHECKAUX_OKAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct fscache_cookie_def ceph_fscache_inode_object_def = {
|
|
||||||
.name = "CEPH.inode",
|
|
||||||
.type = FSCACHE_COOKIE_TYPE_DATAFILE,
|
|
||||||
.check_aux = ceph_fscache_inode_check_aux,
|
|
||||||
};
|
|
||||||
|
|
||||||
void ceph_fscache_register_inode_cookie(struct inode *inode)
|
|
||||||
{
|
|
||||||
struct ceph_inode_info *ci = ceph_inode(inode);
|
|
||||||
struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
|
|
||||||
|
|
||||||
/* No caching for filesystem */
|
|
||||||
if (!fsc->fscache)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Only cache for regular files that are read only */
|
|
||||||
if (!S_ISREG(inode->i_mode))
|
|
||||||
return;
|
|
||||||
|
|
||||||
inode_lock_nested(inode, I_MUTEX_CHILD);
|
|
||||||
if (!ci->fscache) {
|
|
||||||
ci->fscache = fscache_acquire_cookie(fsc->fscache,
|
|
||||||
&ceph_fscache_inode_object_def,
|
|
||||||
&ci->i_vino, sizeof(ci->i_vino),
|
|
||||||
&ci->i_version, sizeof(ci->i_version),
|
|
||||||
ci, i_size_read(inode), false);
|
|
||||||
}
|
|
||||||
inode_unlock(inode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ceph_fscache_unregister_inode_cookie(struct ceph_inode_info* ci)
|
|
||||||
{
|
|
||||||
struct fscache_cookie* cookie;
|
|
||||||
|
|
||||||
if ((cookie = ci->fscache) == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ci->fscache = NULL;
|
|
||||||
|
|
||||||
fscache_relinquish_cookie(cookie, &ci->i_vino, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool ceph_fscache_can_enable(void *data)
|
|
||||||
{
|
|
||||||
struct inode *inode = data;
|
|
||||||
return !inode_is_open_for_write(inode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ceph_fscache_file_set_cookie(struct inode *inode, struct file *filp)
|
|
||||||
{
|
|
||||||
struct ceph_inode_info *ci = ceph_inode(inode);
|
|
||||||
|
|
||||||
if (!fscache_cookie_valid(ci->fscache))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (inode_is_open_for_write(inode)) {
|
|
||||||
dout("fscache_file_set_cookie %p %p disabling cache\n",
|
|
||||||
inode, filp);
|
|
||||||
fscache_disable_cookie(ci->fscache, &ci->i_vino, false);
|
|
||||||
} else {
|
|
||||||
fscache_enable_cookie(ci->fscache, &ci->i_vino, i_size_read(inode),
|
|
||||||
ceph_fscache_can_enable, inode);
|
|
||||||
if (fscache_cookie_enabled(ci->fscache)) {
|
|
||||||
dout("fscache_file_set_cookie %p %p enabling cache\n",
|
|
||||||
inode, filp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ceph_fscache_unregister_fs(struct ceph_fs_client* fsc)
|
void ceph_fscache_unregister_fs(struct ceph_fs_client* fsc)
|
||||||
{
|
{
|
||||||
if (fscache_cookie_valid(fsc->fscache)) {
|
fscache_relinquish_volume(fsc->fscache, NULL, false);
|
||||||
struct ceph_fscache_entry *ent;
|
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
mutex_lock(&ceph_fscache_lock);
|
|
||||||
list_for_each_entry(ent, &ceph_fscache_list, list) {
|
|
||||||
if (ent->fscache == fsc->fscache) {
|
|
||||||
list_del(&ent->list);
|
|
||||||
kfree(ent);
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WARN_ON_ONCE(!found);
|
|
||||||
mutex_unlock(&ceph_fscache_lock);
|
|
||||||
|
|
||||||
__fscache_relinquish_cookie(fsc->fscache, NULL, false);
|
|
||||||
}
|
|
||||||
fsc->fscache = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,19 +12,19 @@
|
||||||
#include <linux/netfs.h>
|
#include <linux/netfs.h>
|
||||||
|
|
||||||
#ifdef CONFIG_CEPH_FSCACHE
|
#ifdef CONFIG_CEPH_FSCACHE
|
||||||
|
#include <linux/fscache.h>
|
||||||
extern struct fscache_netfs ceph_cache_netfs;
|
|
||||||
|
|
||||||
int ceph_fscache_register(void);
|
|
||||||
void ceph_fscache_unregister(void);
|
|
||||||
|
|
||||||
int ceph_fscache_register_fs(struct ceph_fs_client* fsc, struct fs_context *fc);
|
int ceph_fscache_register_fs(struct ceph_fs_client* fsc, struct fs_context *fc);
|
||||||
void ceph_fscache_unregister_fs(struct ceph_fs_client* fsc);
|
void ceph_fscache_unregister_fs(struct ceph_fs_client* fsc);
|
||||||
|
|
||||||
void ceph_fscache_register_inode_cookie(struct inode *inode);
|
void ceph_fscache_register_inode_cookie(struct inode *inode);
|
||||||
void ceph_fscache_unregister_inode_cookie(struct ceph_inode_info* ci);
|
void ceph_fscache_unregister_inode_cookie(struct ceph_inode_info* ci);
|
||||||
void ceph_fscache_file_set_cookie(struct inode *inode, struct file *filp);
|
|
||||||
void ceph_fscache_revalidate_cookie(struct ceph_inode_info *ci);
|
void ceph_fscache_use_cookie(struct inode *inode, bool will_modify);
|
||||||
|
void ceph_fscache_unuse_cookie(struct inode *inode, bool update);
|
||||||
|
|
||||||
|
void ceph_fscache_update(struct inode *inode);
|
||||||
|
void ceph_fscache_invalidate(struct inode *inode, bool dio_write);
|
||||||
|
|
||||||
static inline void ceph_fscache_inode_init(struct ceph_inode_info *ci)
|
static inline void ceph_fscache_inode_init(struct ceph_inode_info *ci)
|
||||||
{
|
{
|
||||||
|
@ -36,37 +36,51 @@ static inline struct fscache_cookie *ceph_fscache_cookie(struct ceph_inode_info
|
||||||
return ci->fscache;
|
return ci->fscache;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ceph_fscache_invalidate(struct inode *inode)
|
static inline void ceph_fscache_resize(struct inode *inode, loff_t to)
|
||||||
{
|
{
|
||||||
fscache_invalidate(ceph_inode(inode)->fscache);
|
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||||
|
struct fscache_cookie *cookie = ceph_fscache_cookie(ci);
|
||||||
|
|
||||||
|
if (cookie) {
|
||||||
|
ceph_fscache_use_cookie(inode, true);
|
||||||
|
fscache_resize_cookie(cookie, to);
|
||||||
|
ceph_fscache_unuse_cookie(inode, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool ceph_is_cache_enabled(struct inode *inode)
|
static inline void ceph_fscache_unpin_writeback(struct inode *inode,
|
||||||
|
struct writeback_control *wbc)
|
||||||
{
|
{
|
||||||
struct fscache_cookie *cookie = ceph_fscache_cookie(ceph_inode(inode));
|
fscache_unpin_writeback(wbc, ceph_fscache_cookie(ceph_inode(inode)));
|
||||||
|
}
|
||||||
|
|
||||||
if (!cookie)
|
static inline int ceph_fscache_set_page_dirty(struct page *page)
|
||||||
return false;
|
{
|
||||||
return fscache_cookie_enabled(cookie);
|
struct inode *inode = page->mapping->host;
|
||||||
|
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||||
|
|
||||||
|
return fscache_set_page_dirty(page, ceph_fscache_cookie(ci));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ceph_begin_cache_operation(struct netfs_read_request *rreq)
|
static inline int ceph_begin_cache_operation(struct netfs_read_request *rreq)
|
||||||
{
|
{
|
||||||
struct fscache_cookie *cookie = ceph_fscache_cookie(ceph_inode(rreq->inode));
|
struct fscache_cookie *cookie = ceph_fscache_cookie(ceph_inode(rreq->inode));
|
||||||
|
|
||||||
return fscache_begin_read_operation(rreq, cookie);
|
return fscache_begin_read_operation(&rreq->cache_resources, cookie);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
|
|
||||||
static inline int ceph_fscache_register(void)
|
static inline bool ceph_is_cache_enabled(struct inode *inode)
|
||||||
{
|
{
|
||||||
return 0;
|
return fscache_cookie_enabled(ceph_fscache_cookie(ceph_inode(inode)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ceph_fscache_unregister(void)
|
static inline void ceph_fscache_note_page_release(struct inode *inode)
|
||||||
{
|
{
|
||||||
}
|
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||||
|
|
||||||
|
fscache_note_page_release(ceph_fscache_cookie(ci));
|
||||||
|
}
|
||||||
|
#else /* CONFIG_CEPH_FSCACHE */
|
||||||
static inline int ceph_fscache_register_fs(struct ceph_fs_client* fsc,
|
static inline int ceph_fscache_register_fs(struct ceph_fs_client* fsc,
|
||||||
struct fs_context *fc)
|
struct fs_context *fc)
|
||||||
{
|
{
|
||||||
|
@ -81,11 +95,6 @@ static inline void ceph_fscache_inode_init(struct ceph_inode_info *ci)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct fscache_cookie *ceph_fscache_cookie(struct ceph_inode_info *ci)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void ceph_fscache_register_inode_cookie(struct inode *inode)
|
static inline void ceph_fscache_register_inode_cookie(struct inode *inode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -94,15 +103,41 @@ static inline void ceph_fscache_unregister_inode_cookie(struct ceph_inode_info*
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ceph_fscache_file_set_cookie(struct inode *inode,
|
static inline void ceph_fscache_use_cookie(struct inode *inode, bool will_modify)
|
||||||
struct file *filp)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ceph_fscache_invalidate(struct inode *inode)
|
static inline void ceph_fscache_unuse_cookie(struct inode *inode, bool update)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void ceph_fscache_update(struct inode *inode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ceph_fscache_invalidate(struct inode *inode, bool dio_write)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct fscache_cookie *ceph_fscache_cookie(struct ceph_inode_info *ci)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ceph_fscache_resize(struct inode *inode, loff_t to)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ceph_fscache_unpin_writeback(struct inode *inode,
|
||||||
|
struct writeback_control *wbc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ceph_fscache_set_page_dirty(struct page *page)
|
||||||
|
{
|
||||||
|
return __set_page_dirty_nobuffers(page);
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool ceph_is_cache_enabled(struct inode *inode)
|
static inline bool ceph_is_cache_enabled(struct inode *inode)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -112,6 +147,10 @@ static inline int ceph_begin_cache_operation(struct netfs_read_request *rreq)
|
||||||
{
|
{
|
||||||
return -ENOBUFS;
|
return -ENOBUFS;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* _CEPH_CACHE_H */
|
static inline void ceph_fscache_note_page_release(struct inode *inode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_CEPH_FSCACHE */
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -1856,7 +1856,7 @@ static int try_nonblocking_invalidate(struct inode *inode)
|
||||||
u32 invalidating_gen = ci->i_rdcache_gen;
|
u32 invalidating_gen = ci->i_rdcache_gen;
|
||||||
|
|
||||||
spin_unlock(&ci->i_ceph_lock);
|
spin_unlock(&ci->i_ceph_lock);
|
||||||
ceph_fscache_invalidate(inode);
|
ceph_fscache_invalidate(inode, false);
|
||||||
invalidate_mapping_pages(&inode->i_data, 0, -1);
|
invalidate_mapping_pages(&inode->i_data, 0, -1);
|
||||||
spin_lock(&ci->i_ceph_lock);
|
spin_lock(&ci->i_ceph_lock);
|
||||||
|
|
||||||
|
@ -2388,6 +2388,7 @@ int ceph_write_inode(struct inode *inode, struct writeback_control *wbc)
|
||||||
int wait = (wbc->sync_mode == WB_SYNC_ALL && !wbc->for_sync);
|
int wait = (wbc->sync_mode == WB_SYNC_ALL && !wbc->for_sync);
|
||||||
|
|
||||||
dout("write_inode %p wait=%d\n", inode, wait);
|
dout("write_inode %p wait=%d\n", inode, wait);
|
||||||
|
ceph_fscache_unpin_writeback(inode, wbc);
|
||||||
if (wait) {
|
if (wait) {
|
||||||
dirty = try_flush_caps(inode, &flush_tid);
|
dirty = try_flush_caps(inode, &flush_tid);
|
||||||
if (dirty)
|
if (dirty)
|
||||||
|
|
|
@ -248,8 +248,7 @@ static int ceph_init_file(struct inode *inode, struct file *file, int fmode)
|
||||||
|
|
||||||
switch (inode->i_mode & S_IFMT) {
|
switch (inode->i_mode & S_IFMT) {
|
||||||
case S_IFREG:
|
case S_IFREG:
|
||||||
ceph_fscache_register_inode_cookie(inode);
|
ceph_fscache_use_cookie(inode, file->f_mode & FMODE_WRITE);
|
||||||
ceph_fscache_file_set_cookie(inode, file);
|
|
||||||
fallthrough;
|
fallthrough;
|
||||||
case S_IFDIR:
|
case S_IFDIR:
|
||||||
ret = ceph_init_file_info(inode, file, fmode,
|
ret = ceph_init_file_info(inode, file, fmode,
|
||||||
|
@ -810,6 +809,7 @@ int ceph_release(struct inode *inode, struct file *file)
|
||||||
dout("release inode %p regular file %p\n", inode, file);
|
dout("release inode %p regular file %p\n", inode, file);
|
||||||
WARN_ON(!list_empty(&fi->rw_contexts));
|
WARN_ON(!list_empty(&fi->rw_contexts));
|
||||||
|
|
||||||
|
ceph_fscache_unuse_cookie(inode, file->f_mode & FMODE_WRITE);
|
||||||
ceph_put_fmode(ci, fi->fmode, 1);
|
ceph_put_fmode(ci, fi->fmode, 1);
|
||||||
|
|
||||||
kmem_cache_free(ceph_file_cachep, fi);
|
kmem_cache_free(ceph_file_cachep, fi);
|
||||||
|
@ -1206,7 +1206,11 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
|
||||||
snapc, snapc ? snapc->seq : 0);
|
snapc, snapc ? snapc->seq : 0);
|
||||||
|
|
||||||
if (write) {
|
if (write) {
|
||||||
int ret2 = invalidate_inode_pages2_range(inode->i_mapping,
|
int ret2;
|
||||||
|
|
||||||
|
ceph_fscache_invalidate(inode, true);
|
||||||
|
|
||||||
|
ret2 = invalidate_inode_pages2_range(inode->i_mapping,
|
||||||
pos >> PAGE_SHIFT,
|
pos >> PAGE_SHIFT,
|
||||||
(pos + count - 1) >> PAGE_SHIFT);
|
(pos + count - 1) >> PAGE_SHIFT);
|
||||||
if (ret2 < 0)
|
if (ret2 < 0)
|
||||||
|
@ -1417,6 +1421,7 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
ceph_fscache_invalidate(inode, false);
|
||||||
ret = invalidate_inode_pages2_range(inode->i_mapping,
|
ret = invalidate_inode_pages2_range(inode->i_mapping,
|
||||||
pos >> PAGE_SHIFT,
|
pos >> PAGE_SHIFT,
|
||||||
(pos + count - 1) >> PAGE_SHIFT);
|
(pos + count - 1) >> PAGE_SHIFT);
|
||||||
|
@ -2101,6 +2106,7 @@ static long ceph_fallocate(struct file *file, int mode,
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
filemap_invalidate_lock(inode->i_mapping);
|
filemap_invalidate_lock(inode->i_mapping);
|
||||||
|
ceph_fscache_invalidate(inode, false);
|
||||||
ceph_zero_pagecache_range(inode, offset, length);
|
ceph_zero_pagecache_range(inode, offset, length);
|
||||||
ret = ceph_zero_objects(inode, offset, length);
|
ret = ceph_zero_objects(inode, offset, length);
|
||||||
|
|
||||||
|
@ -2425,6 +2431,7 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off,
|
||||||
goto out_caps;
|
goto out_caps;
|
||||||
|
|
||||||
/* Drop dst file cached pages */
|
/* Drop dst file cached pages */
|
||||||
|
ceph_fscache_invalidate(dst_inode, false);
|
||||||
ret = invalidate_inode_pages2_range(dst_inode->i_mapping,
|
ret = invalidate_inode_pages2_range(dst_inode->i_mapping,
|
||||||
dst_off >> PAGE_SHIFT,
|
dst_off >> PAGE_SHIFT,
|
||||||
(dst_off + len) >> PAGE_SHIFT);
|
(dst_off + len) >> PAGE_SHIFT);
|
||||||
|
|
|
@ -564,6 +564,8 @@ void ceph_evict_inode(struct inode *inode)
|
||||||
percpu_counter_dec(&mdsc->metric.total_inodes);
|
percpu_counter_dec(&mdsc->metric.total_inodes);
|
||||||
|
|
||||||
truncate_inode_pages_final(&inode->i_data);
|
truncate_inode_pages_final(&inode->i_data);
|
||||||
|
if (inode->i_state & I_PINNING_FSCACHE_WB)
|
||||||
|
ceph_fscache_unuse_cookie(inode, true);
|
||||||
clear_inode(inode);
|
clear_inode(inode);
|
||||||
|
|
||||||
ceph_fscache_unregister_inode_cookie(ci);
|
ceph_fscache_unregister_inode_cookie(ci);
|
||||||
|
@ -634,6 +636,12 @@ int ceph_fill_file_size(struct inode *inode, int issued,
|
||||||
}
|
}
|
||||||
i_size_write(inode, size);
|
i_size_write(inode, size);
|
||||||
inode->i_blocks = calc_inode_blocks(size);
|
inode->i_blocks = calc_inode_blocks(size);
|
||||||
|
/*
|
||||||
|
* If we're expanding, then we should be able to just update
|
||||||
|
* the existing cookie.
|
||||||
|
*/
|
||||||
|
if (size > isize)
|
||||||
|
ceph_fscache_update(inode);
|
||||||
ci->i_reported_size = size;
|
ci->i_reported_size = size;
|
||||||
if (truncate_seq != ci->i_truncate_seq) {
|
if (truncate_seq != ci->i_truncate_seq) {
|
||||||
dout("truncate_seq %u -> %u\n",
|
dout("truncate_seq %u -> %u\n",
|
||||||
|
@ -666,10 +674,6 @@ int ceph_fill_file_size(struct inode *inode, int issued,
|
||||||
truncate_size);
|
truncate_size);
|
||||||
ci->i_truncate_size = truncate_size;
|
ci->i_truncate_size = truncate_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (queue_trunc)
|
|
||||||
ceph_fscache_invalidate(inode);
|
|
||||||
|
|
||||||
return queue_trunc;
|
return queue_trunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1053,6 +1057,8 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,
|
||||||
|
|
||||||
spin_unlock(&ci->i_ceph_lock);
|
spin_unlock(&ci->i_ceph_lock);
|
||||||
|
|
||||||
|
ceph_fscache_register_inode_cookie(inode);
|
||||||
|
|
||||||
if (fill_inline)
|
if (fill_inline)
|
||||||
ceph_fill_inline_data(inode, locked_page,
|
ceph_fill_inline_data(inode, locked_page,
|
||||||
iinfo->inline_data, iinfo->inline_len);
|
iinfo->inline_data, iinfo->inline_len);
|
||||||
|
@ -1814,11 +1820,13 @@ bool ceph_inode_set_size(struct inode *inode, loff_t size)
|
||||||
spin_lock(&ci->i_ceph_lock);
|
spin_lock(&ci->i_ceph_lock);
|
||||||
dout("set_size %p %llu -> %llu\n", inode, i_size_read(inode), size);
|
dout("set_size %p %llu -> %llu\n", inode, i_size_read(inode), size);
|
||||||
i_size_write(inode, size);
|
i_size_write(inode, size);
|
||||||
|
ceph_fscache_update(inode);
|
||||||
inode->i_blocks = calc_inode_blocks(size);
|
inode->i_blocks = calc_inode_blocks(size);
|
||||||
|
|
||||||
ret = __ceph_should_report_size(ci);
|
ret = __ceph_should_report_size(ci);
|
||||||
|
|
||||||
spin_unlock(&ci->i_ceph_lock);
|
spin_unlock(&ci->i_ceph_lock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1844,6 +1852,8 @@ static void ceph_do_invalidate_pages(struct inode *inode)
|
||||||
u32 orig_gen;
|
u32 orig_gen;
|
||||||
int check = 0;
|
int check = 0;
|
||||||
|
|
||||||
|
ceph_fscache_invalidate(inode, false);
|
||||||
|
|
||||||
mutex_lock(&ci->i_truncate_mutex);
|
mutex_lock(&ci->i_truncate_mutex);
|
||||||
|
|
||||||
if (ceph_inode_is_shutdown(inode)) {
|
if (ceph_inode_is_shutdown(inode)) {
|
||||||
|
@ -1868,7 +1878,7 @@ static void ceph_do_invalidate_pages(struct inode *inode)
|
||||||
orig_gen = ci->i_rdcache_gen;
|
orig_gen = ci->i_rdcache_gen;
|
||||||
spin_unlock(&ci->i_ceph_lock);
|
spin_unlock(&ci->i_ceph_lock);
|
||||||
|
|
||||||
ceph_fscache_invalidate(inode);
|
ceph_fscache_invalidate(inode, false);
|
||||||
if (invalidate_inode_pages2(inode->i_mapping) < 0) {
|
if (invalidate_inode_pages2(inode->i_mapping) < 0) {
|
||||||
pr_err("invalidate_inode_pages2 %llx.%llx failed\n",
|
pr_err("invalidate_inode_pages2 %llx.%llx failed\n",
|
||||||
ceph_vinop(inode));
|
ceph_vinop(inode));
|
||||||
|
@ -1937,6 +1947,7 @@ retry:
|
||||||
ci->i_truncate_pending, to);
|
ci->i_truncate_pending, to);
|
||||||
spin_unlock(&ci->i_ceph_lock);
|
spin_unlock(&ci->i_ceph_lock);
|
||||||
|
|
||||||
|
ceph_fscache_resize(inode, to);
|
||||||
truncate_pagecache(inode, to);
|
truncate_pagecache(inode, to);
|
||||||
|
|
||||||
spin_lock(&ci->i_ceph_lock);
|
spin_lock(&ci->i_ceph_lock);
|
||||||
|
@ -2184,7 +2195,6 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
|
||||||
if (inode_dirty_flags)
|
if (inode_dirty_flags)
|
||||||
__mark_inode_dirty(inode, inode_dirty_flags);
|
__mark_inode_dirty(inode, inode_dirty_flags);
|
||||||
|
|
||||||
|
|
||||||
if (mask) {
|
if (mask) {
|
||||||
req->r_inode = inode;
|
req->r_inode = inode;
|
||||||
ihold(inode);
|
ihold(inode);
|
||||||
|
|
|
@ -787,16 +787,10 @@ static int __init init_caches(void)
|
||||||
if (!ceph_wb_pagevec_pool)
|
if (!ceph_wb_pagevec_pool)
|
||||||
goto bad_pagevec_pool;
|
goto bad_pagevec_pool;
|
||||||
|
|
||||||
error = ceph_fscache_register();
|
|
||||||
if (error)
|
|
||||||
goto bad_fscache;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
bad_fscache:
|
|
||||||
kmem_cache_destroy(ceph_mds_request_cachep);
|
|
||||||
bad_pagevec_pool:
|
bad_pagevec_pool:
|
||||||
mempool_destroy(ceph_wb_pagevec_pool);
|
kmem_cache_destroy(ceph_mds_request_cachep);
|
||||||
bad_mds_req:
|
bad_mds_req:
|
||||||
kmem_cache_destroy(ceph_dir_file_cachep);
|
kmem_cache_destroy(ceph_dir_file_cachep);
|
||||||
bad_dir_file:
|
bad_dir_file:
|
||||||
|
@ -828,8 +822,6 @@ static void destroy_caches(void)
|
||||||
kmem_cache_destroy(ceph_dir_file_cachep);
|
kmem_cache_destroy(ceph_dir_file_cachep);
|
||||||
kmem_cache_destroy(ceph_mds_request_cachep);
|
kmem_cache_destroy(ceph_mds_request_cachep);
|
||||||
mempool_destroy(ceph_wb_pagevec_pool);
|
mempool_destroy(ceph_wb_pagevec_pool);
|
||||||
|
|
||||||
ceph_fscache_unregister();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __ceph_umount_begin(struct ceph_fs_client *fsc)
|
static void __ceph_umount_begin(struct ceph_fs_client *fsc)
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
#include <linux/ceph/libceph.h>
|
#include <linux/ceph/libceph.h>
|
||||||
|
|
||||||
#ifdef CONFIG_CEPH_FSCACHE
|
#ifdef CONFIG_CEPH_FSCACHE
|
||||||
#define FSCACHE_USE_NEW_IO_API
|
|
||||||
#include <linux/fscache.h>
|
#include <linux/fscache.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -135,7 +134,7 @@ struct ceph_fs_client {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_CEPH_FSCACHE
|
#ifdef CONFIG_CEPH_FSCACHE
|
||||||
struct fscache_cookie *fscache;
|
struct fscache_volume *fscache;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue