Skip to content

Commit 400e128

Browse files
jtlaytondhowells
authored andcommitted
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 <[email protected]> Signed-off-by: David Howells <[email protected]> Link: https://lore.kernel.org/r/[email protected]/ # v1 Link: https://lore.kernel.org/r/[email protected]/ # 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
1 parent 16f2f4e commit 400e128

File tree

9 files changed

+178
-224
lines changed

9 files changed

+178
-224
lines changed

fs/ceph/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ config CEPH_FS
2121
if CEPH_FS
2222
config CEPH_FSCACHE
2323
bool "Enable Ceph client caching support"
24-
depends on CEPH_FS=m && FSCACHE_OLD_API || CEPH_FS=y && FSCACHE_OLD_API=y
24+
depends on CEPH_FS=m && FSCACHE || CEPH_FS=y && FSCACHE=y
2525
help
2626
Choose Y here to enable persistent, read-only local
2727
caching support for Ceph clients using FS-Cache

fs/ceph/addr.c

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ static int ceph_set_page_dirty(struct page *page)
126126
BUG_ON(PagePrivate(page));
127127
attach_page_private(page, snapc);
128128

129-
return __set_page_dirty_nobuffers(page);
129+
return ceph_fscache_set_page_dirty(page);
130130
}
131131

132132
/*
@@ -141,8 +141,6 @@ static void ceph_invalidatepage(struct page *page, unsigned int offset,
141141
struct ceph_inode_info *ci;
142142
struct ceph_snap_context *snapc;
143143

144-
wait_on_page_fscache(page);
145-
146144
inode = page->mapping->host;
147145
ci = ceph_inode(inode);
148146

@@ -153,28 +151,36 @@ static void ceph_invalidatepage(struct page *page, unsigned int offset,
153151
}
154152

155153
WARN_ON(!PageLocked(page));
156-
if (!PagePrivate(page))
157-
return;
154+
if (PagePrivate(page)) {
155+
dout("%p invalidatepage %p idx %lu full dirty page\n",
156+
inode, page, page->index);
158157

159-
dout("%p invalidatepage %p idx %lu full dirty page\n",
160-
inode, page, page->index);
158+
snapc = detach_page_private(page);
159+
ceph_put_wrbuffer_cap_refs(ci, 1, snapc);
160+
ceph_put_snap_context(snapc);
161+
}
161162

162-
snapc = detach_page_private(page);
163-
ceph_put_wrbuffer_cap_refs(ci, 1, snapc);
164-
ceph_put_snap_context(snapc);
163+
wait_on_page_fscache(page);
165164
}
166165

167166
static int ceph_releasepage(struct page *page, gfp_t gfp)
168167
{
169-
dout("%p releasepage %p idx %lu (%sdirty)\n", page->mapping->host,
170-
page, page->index, PageDirty(page) ? "" : "not ");
168+
struct inode *inode = page->mapping->host;
169+
170+
dout("%llx:%llx releasepage %p idx %lu (%sdirty)\n",
171+
ceph_vinop(inode), page,
172+
page->index, PageDirty(page) ? "" : "not ");
173+
174+
if (PagePrivate(page))
175+
return 0;
171176

172177
if (PageFsCache(page)) {
173-
if (!(gfp & __GFP_DIRECT_RECLAIM) || !(gfp & __GFP_FS))
178+
if (!gfpflags_allow_blocking(gfp) || !(gfp & __GFP_FS))
174179
return 0;
175180
wait_on_page_fscache(page);
176181
}
177-
return !PagePrivate(page);
182+
ceph_fscache_note_page_release(inode);
183+
return 1;
178184
}
179185

180186
static void ceph_netfs_expand_readahead(struct netfs_read_request *rreq)

fs/ceph/cache.c

Lines changed: 59 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -12,199 +12,99 @@
1212
#include "super.h"
1313
#include "cache.h"
1414

15-
struct fscache_netfs ceph_cache_netfs = {
16-
.name = "ceph",
17-
.version = 0,
18-
};
19-
20-
static DEFINE_MUTEX(ceph_fscache_lock);
21-
static LIST_HEAD(ceph_fscache_list);
22-
23-
struct ceph_fscache_entry {
24-
struct list_head list;
25-
struct fscache_cookie *fscache;
26-
size_t uniq_len;
27-
/* The following members must be last */
28-
struct ceph_fsid fsid;
29-
char uniquifier[];
30-
};
31-
32-
static const struct fscache_cookie_def ceph_fscache_fsid_object_def = {
33-
.name = "CEPH.fsid",
34-
.type = FSCACHE_COOKIE_TYPE_INDEX,
35-
};
36-
37-
int __init ceph_fscache_register(void)
38-
{
39-
return fscache_register_netfs(&ceph_cache_netfs);
40-
}
41-
42-
void ceph_fscache_unregister(void)
43-
{
44-
fscache_unregister_netfs(&ceph_cache_netfs);
45-
}
46-
47-
int ceph_fscache_register_fs(struct ceph_fs_client* fsc, struct fs_context *fc)
15+
void ceph_fscache_register_inode_cookie(struct inode *inode)
4816
{
49-
const struct ceph_fsid *fsid = &fsc->client->fsid;
50-
const char *fscache_uniq = fsc->mount_options->fscache_uniq;
51-
size_t uniq_len = fscache_uniq ? strlen(fscache_uniq) : 0;
52-
struct ceph_fscache_entry *ent;
53-
int err = 0;
17+
struct ceph_inode_info *ci = ceph_inode(inode);
18+
struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
5419

55-
mutex_lock(&ceph_fscache_lock);
56-
list_for_each_entry(ent, &ceph_fscache_list, list) {
57-
if (memcmp(&ent->fsid, fsid, sizeof(*fsid)))
58-
continue;
59-
if (ent->uniq_len != uniq_len)
60-
continue;
61-
if (uniq_len && memcmp(ent->uniquifier, fscache_uniq, uniq_len))
62-
continue;
63-
64-
errorfc(fc, "fscache cookie already registered for fsid %pU, use fsc=<uniquifier> option",
65-
fsid);
66-
err = -EBUSY;
67-
goto out_unlock;
68-
}
20+
/* No caching for filesystem? */
21+
if (!fsc->fscache)
22+
return;
6923

70-
ent = kzalloc(sizeof(*ent) + uniq_len, GFP_KERNEL);
71-
if (!ent) {
72-
err = -ENOMEM;
73-
goto out_unlock;
74-
}
24+
/* Regular files only */
25+
if (!S_ISREG(inode->i_mode))
26+
return;
7527

76-
memcpy(&ent->fsid, fsid, sizeof(*fsid));
77-
if (uniq_len > 0) {
78-
memcpy(&ent->uniquifier, fscache_uniq, uniq_len);
79-
ent->uniq_len = uniq_len;
80-
}
28+
/* Only new inodes! */
29+
if (!(inode->i_state & I_NEW))
30+
return;
8131

82-
fsc->fscache = fscache_acquire_cookie(ceph_cache_netfs.primary_index,
83-
&ceph_fscache_fsid_object_def,
84-
&ent->fsid, sizeof(ent->fsid) + uniq_len,
85-
NULL, 0,
86-
fsc, 0, true);
32+
WARN_ON_ONCE(ci->fscache);
8733

88-
if (fsc->fscache) {
89-
ent->fscache = fsc->fscache;
90-
list_add_tail(&ent->list, &ceph_fscache_list);
91-
} else {
92-
kfree(ent);
93-
errorfc(fc, "unable to register fscache cookie for fsid %pU",
94-
fsid);
95-
/* all other fs ignore this error */
96-
}
97-
out_unlock:
98-
mutex_unlock(&ceph_fscache_lock);
99-
return err;
34+
ci->fscache = fscache_acquire_cookie(fsc->fscache, 0,
35+
&ci->i_vino, sizeof(ci->i_vino),
36+
&ci->i_version, sizeof(ci->i_version),
37+
i_size_read(inode));
10038
}
10139

102-
static enum fscache_checkaux ceph_fscache_inode_check_aux(
103-
void *cookie_netfs_data, const void *data, uint16_t dlen,
104-
loff_t object_size)
40+
void ceph_fscache_unregister_inode_cookie(struct ceph_inode_info* ci)
10541
{
106-
struct ceph_inode_info* ci = cookie_netfs_data;
107-
struct inode* inode = &ci->vfs_inode;
42+
struct fscache_cookie *cookie = ci->fscache;
10843

109-
if (dlen != sizeof(ci->i_version) ||
110-
i_size_read(inode) != object_size)
111-
return FSCACHE_CHECKAUX_OBSOLETE;
44+
fscache_relinquish_cookie(cookie, false);
45+
}
11246

113-
if (*(u64 *)data != ci->i_version)
114-
return FSCACHE_CHECKAUX_OBSOLETE;
47+
void ceph_fscache_use_cookie(struct inode *inode, bool will_modify)
48+
{
49+
struct ceph_inode_info *ci = ceph_inode(inode);
11550

116-
dout("ceph inode 0x%p cached okay\n", ci);
117-
return FSCACHE_CHECKAUX_OKAY;
51+
fscache_use_cookie(ci->fscache, will_modify);
11852
}
11953

120-
static const struct fscache_cookie_def ceph_fscache_inode_object_def = {
121-
.name = "CEPH.inode",
122-
.type = FSCACHE_COOKIE_TYPE_DATAFILE,
123-
.check_aux = ceph_fscache_inode_check_aux,
124-
};
125-
126-
void ceph_fscache_register_inode_cookie(struct inode *inode)
54+
void ceph_fscache_unuse_cookie(struct inode *inode, bool update)
12755
{
12856
struct ceph_inode_info *ci = ceph_inode(inode);
129-
struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
130-
131-
/* No caching for filesystem */
132-
if (!fsc->fscache)
133-
return;
13457

135-
/* Only cache for regular files that are read only */
136-
if (!S_ISREG(inode->i_mode))
137-
return;
58+
if (update) {
59+
loff_t i_size = i_size_read(inode);
13860

139-
inode_lock_nested(inode, I_MUTEX_CHILD);
140-
if (!ci->fscache) {
141-
ci->fscache = fscache_acquire_cookie(fsc->fscache,
142-
&ceph_fscache_inode_object_def,
143-
&ci->i_vino, sizeof(ci->i_vino),
144-
&ci->i_version, sizeof(ci->i_version),
145-
ci, i_size_read(inode), false);
61+
fscache_unuse_cookie(ci->fscache, &ci->i_version, &i_size);
62+
} else {
63+
fscache_unuse_cookie(ci->fscache, NULL, NULL);
14664
}
147-
inode_unlock(inode);
14865
}
14966

150-
void ceph_fscache_unregister_inode_cookie(struct ceph_inode_info* ci)
67+
void ceph_fscache_update(struct inode *inode)
15168
{
152-
struct fscache_cookie* cookie;
153-
154-
if ((cookie = ci->fscache) == NULL)
155-
return;
156-
157-
ci->fscache = NULL;
69+
struct ceph_inode_info *ci = ceph_inode(inode);
70+
loff_t i_size = i_size_read(inode);
15871

159-
fscache_relinquish_cookie(cookie, &ci->i_vino, false);
72+
fscache_update_cookie(ci->fscache, &ci->i_version, &i_size);
16073
}
16174

162-
static bool ceph_fscache_can_enable(void *data)
75+
void ceph_fscache_invalidate(struct inode *inode, bool dio_write)
16376
{
164-
struct inode *inode = data;
165-
return !inode_is_open_for_write(inode);
77+
struct ceph_inode_info *ci = ceph_inode(inode);
78+
79+
fscache_invalidate(ceph_inode(inode)->fscache,
80+
&ci->i_version, i_size_read(inode),
81+
dio_write ? FSCACHE_INVAL_DIO_WRITE : 0);
16682
}
16783

168-
void ceph_fscache_file_set_cookie(struct inode *inode, struct file *filp)
84+
int ceph_fscache_register_fs(struct ceph_fs_client* fsc, struct fs_context *fc)
16985
{
170-
struct ceph_inode_info *ci = ceph_inode(inode);
86+
const struct ceph_fsid *fsid = &fsc->client->fsid;
87+
const char *fscache_uniq = fsc->mount_options->fscache_uniq;
88+
size_t uniq_len = fscache_uniq ? strlen(fscache_uniq) : 0;
89+
char *name;
90+
int err = 0;
17191

172-
if (!fscache_cookie_valid(ci->fscache))
173-
return;
92+
name = kasprintf(GFP_KERNEL, "ceph,%pU%s%s", fsid, uniq_len ? "," : "",
93+
uniq_len ? fscache_uniq : "");
94+
if (!name)
95+
return -ENOMEM;
17496

175-
if (inode_is_open_for_write(inode)) {
176-
dout("fscache_file_set_cookie %p %p disabling cache\n",
177-
inode, filp);
178-
fscache_disable_cookie(ci->fscache, &ci->i_vino, false);
179-
} else {
180-
fscache_enable_cookie(ci->fscache, &ci->i_vino, i_size_read(inode),
181-
ceph_fscache_can_enable, inode);
182-
if (fscache_cookie_enabled(ci->fscache)) {
183-
dout("fscache_file_set_cookie %p %p enabling cache\n",
184-
inode, filp);
185-
}
97+
fsc->fscache = fscache_acquire_volume(name, NULL, NULL, 0);
98+
if (IS_ERR_OR_NULL(fsc->fscache)) {
99+
errorfc(fc, "Unable to register fscache cookie for %s", name);
100+
err = fsc->fscache ? PTR_ERR(fsc->fscache) : -EOPNOTSUPP;
101+
fsc->fscache = NULL;
186102
}
103+
kfree(name);
104+
return err;
187105
}
188106

189107
void ceph_fscache_unregister_fs(struct ceph_fs_client* fsc)
190108
{
191-
if (fscache_cookie_valid(fsc->fscache)) {
192-
struct ceph_fscache_entry *ent;
193-
bool found = false;
194-
195-
mutex_lock(&ceph_fscache_lock);
196-
list_for_each_entry(ent, &ceph_fscache_list, list) {
197-
if (ent->fscache == fsc->fscache) {
198-
list_del(&ent->list);
199-
kfree(ent);
200-
found = true;
201-
break;
202-
}
203-
}
204-
WARN_ON_ONCE(!found);
205-
mutex_unlock(&ceph_fscache_lock);
206-
207-
__fscache_relinquish_cookie(fsc->fscache, NULL, false);
208-
}
209-
fsc->fscache = NULL;
109+
fscache_relinquish_volume(fsc->fscache, NULL, false);
210110
}

0 commit comments

Comments
 (0)