Skip to content

Commit 93c8461

Browse files
committed
9p: Copy local writes to the cache when writing to the server
When writing to the server from v9fs_vfs_writepage(), copy the data to the cache object too. To make this possible, the cookie must have its active users count incremented when the page is dirtied and kept incremented until we manage to clean up all the pages. This allows the writeback to take place after the last file struct is released. This is done by taking a use on the cookie in v9fs_set_page_dirty() if we haven't already done so (controlled by the I_PINNING_FSCACHE_WB flag) and dropping the pin in v9fs_write_inode() if __writeback_single_inode() clears all the outstanding dirty pages (conveyed by the unpinned_fscache_wb flag in the writeback_control struct). Inode eviction must also clear the flag after truncating away all the outstanding pages. In the future this will be handled more gracefully by netfslib. Changes ======= ver #3: - Canonicalise the coherency data to make it endianness-independent. ver #2: - Fix an unused-var warning due to CONFIG_9P_FSCACHE=n[1]. Signed-off-by: David Howells <[email protected]> Acked-by: Jeff Layton <[email protected]> Tested-by: Dominique Martinet <[email protected]> cc: Eric Van Hensbergen <[email protected]> cc: Latchesar Ionkov <[email protected]> cc: [email protected] cc: [email protected] Link: https://lore.kernel.org/r/163819667027.215744.13815687931204222995.stgit@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/163906978015.143852.10646669694345706328.stgit@warthog.procyon.org.uk/ # v2 Link: https://lore.kernel.org/r/163967180760.1823006.5831751873616248910.stgit@warthog.procyon.org.uk/ # v3 Link: https://lore.kernel.org/r/164021574522.640689.13849966660182529125.stgit@warthog.procyon.org.uk/ # v4
1 parent 24e42e3 commit 93c8461

File tree

3 files changed

+52
-1
lines changed

3 files changed

+52
-1
lines changed

fs/9p/vfs_addr.c

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ static void v9fs_vfs_readahead(struct readahead_control *ractl)
137137
static int v9fs_release_page(struct page *page, gfp_t gfp)
138138
{
139139
struct folio *folio = page_folio(page);
140+
struct inode *inode = folio_inode(folio);
140141

141142
if (folio_test_private(folio))
142143
return 0;
@@ -147,6 +148,7 @@ static int v9fs_release_page(struct page *page, gfp_t gfp)
147148
folio_wait_fscache(folio);
148149
}
149150
#endif
151+
fscache_note_page_release(v9fs_inode_cookie(V9FS_I(inode)));
150152
return 1;
151153
}
152154

@@ -165,10 +167,25 @@ static void v9fs_invalidate_page(struct page *page, unsigned int offset,
165167
folio_wait_fscache(folio);
166168
}
167169

170+
static void v9fs_write_to_cache_done(void *priv, ssize_t transferred_or_error,
171+
bool was_async)
172+
{
173+
struct v9fs_inode *v9inode = priv;
174+
__le32 version;
175+
176+
if (IS_ERR_VALUE(transferred_or_error) &&
177+
transferred_or_error != -ENOBUFS) {
178+
version = cpu_to_le32(v9inode->qid.version);
179+
fscache_invalidate(v9fs_inode_cookie(v9inode), &version,
180+
i_size_read(&v9inode->vfs_inode), 0);
181+
}
182+
}
183+
168184
static int v9fs_vfs_write_folio_locked(struct folio *folio)
169185
{
170186
struct inode *inode = folio_inode(folio);
171187
struct v9fs_inode *v9inode = V9FS_I(inode);
188+
struct fscache_cookie *cookie = v9fs_inode_cookie(v9inode);
172189
loff_t start = folio_pos(folio);
173190
loff_t i_size = i_size_read(inode);
174191
struct iov_iter from;
@@ -185,10 +202,21 @@ static int v9fs_vfs_write_folio_locked(struct folio *folio)
185202
/* We should have writeback_fid always set */
186203
BUG_ON(!v9inode->writeback_fid);
187204

205+
folio_wait_fscache(folio);
188206
folio_start_writeback(folio);
189207

190208
p9_client_write(v9inode->writeback_fid, start, &from, &err);
191209

210+
if (err == 0 &&
211+
fscache_cookie_enabled(cookie) &&
212+
test_bit(FSCACHE_COOKIE_IS_CACHING, &cookie->flags)) {
213+
folio_start_fscache(folio);
214+
fscache_write_to_cache(v9fs_inode_cookie(v9inode),
215+
folio_mapping(folio), start, len, i_size,
216+
v9fs_write_to_cache_done, v9inode,
217+
true);
218+
}
219+
192220
folio_end_writeback(folio);
193221
return err;
194222
}
@@ -307,6 +335,7 @@ static int v9fs_write_end(struct file *filp, struct address_space *mapping,
307335
loff_t last_pos = pos + copied;
308336
struct folio *folio = page_folio(subpage);
309337
struct inode *inode = mapping->host;
338+
struct v9fs_inode *v9inode = V9FS_I(inode);
310339

311340
p9_debug(P9_DEBUG_VFS, "filp %p, mapping %p\n", filp, mapping);
312341

@@ -326,6 +355,7 @@ static int v9fs_write_end(struct file *filp, struct address_space *mapping,
326355
if (last_pos > inode->i_size) {
327356
inode_add_bytes(inode, last_pos - inode->i_size);
328357
i_size_write(inode, last_pos);
358+
fscache_update_cookie(v9fs_inode_cookie(v9inode), NULL, &last_pos);
329359
}
330360
folio_mark_dirty(folio);
331361
out:
@@ -335,11 +365,25 @@ static int v9fs_write_end(struct file *filp, struct address_space *mapping,
335365
return copied;
336366
}
337367

368+
#ifdef CONFIG_9P_FSCACHE
369+
/*
370+
* Mark a page as having been made dirty and thus needing writeback. We also
371+
* need to pin the cache object to write back to.
372+
*/
373+
static int v9fs_set_page_dirty(struct page *page)
374+
{
375+
struct v9fs_inode *v9inode = V9FS_I(page->mapping->host);
376+
377+
return fscache_set_page_dirty(page, v9fs_inode_cookie(v9inode));
378+
}
379+
#else
380+
#define v9fs_set_page_dirty __set_page_dirty_nobuffers
381+
#endif
338382

339383
const struct address_space_operations v9fs_addr_operations = {
340384
.readpage = v9fs_vfs_readpage,
341385
.readahead = v9fs_vfs_readahead,
342-
.set_page_dirty = __set_page_dirty_nobuffers,
386+
.set_page_dirty = v9fs_set_page_dirty,
343387
.writepage = v9fs_vfs_writepage,
344388
.write_begin = v9fs_write_begin,
345389
.write_end = v9fs_write_end,

fs/9p/vfs_inode.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,8 +380,12 @@ struct inode *v9fs_get_inode(struct super_block *sb, umode_t mode, dev_t rdev)
380380
void v9fs_evict_inode(struct inode *inode)
381381
{
382382
struct v9fs_inode *v9inode = V9FS_I(inode);
383+
__le32 version;
383384

384385
truncate_inode_pages_final(&inode->i_data);
386+
version = cpu_to_le32(v9inode->qid.version);
387+
fscache_clear_inode_writeback(v9fs_inode_cookie(v9inode), inode,
388+
&version);
385389
clear_inode(inode);
386390
filemap_fdatawrite(&inode->i_data);
387391

fs/9p/vfs_super.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <linux/slab.h>
2121
#include <linux/statfs.h>
2222
#include <linux/magic.h>
23+
#include <linux/fscache.h>
2324
#include <net/9p/9p.h>
2425
#include <net/9p/client.h>
2526

@@ -309,6 +310,7 @@ static int v9fs_write_inode(struct inode *inode,
309310
__mark_inode_dirty(inode, I_DIRTY_DATASYNC);
310311
return ret;
311312
}
313+
fscache_unpin_writeback(wbc, v9fs_inode_cookie(v9inode));
312314
return 0;
313315
}
314316

@@ -332,6 +334,7 @@ static int v9fs_write_inode_dotl(struct inode *inode,
332334
__mark_inode_dirty(inode, I_DIRTY_DATASYNC);
333335
return ret;
334336
}
337+
fscache_unpin_writeback(wbc, v9fs_inode_cookie(v9inode));
335338
return 0;
336339
}
337340

0 commit comments

Comments
 (0)