Skip to content

Commit 2ff1e97

Browse files
committed
netfs: Replace PG_fscache by setting folio->private and marking dirty
When dirty data is being written to the cache, setting/waiting on/clearing the fscache flag is always done in tandem with setting/waiting on/clearing the writeback flag. The netfslib buffered write routines wait on and set both flags and the write request cleanup clears both flags, so the fscache flag is almost superfluous. The reason it isn't superfluous is because the fscache flag is also used to indicate that data just read from the server is being written to the cache. The flag is used to prevent a race involving overlapping direct-I/O writes to the cache. Change this to indicate that a page is in need of being copied to the cache by placing a magic value in folio->private and marking the folios dirty. Then when the writeback code sees a folio marked in this way, it only writes it to the cache and not to the server. If a folio that has this magic value set is modified, the value is just replaced and the folio will then be uplodaded too. With this, PG_fscache is no longer required by the netfslib core, 9p and afs. Ceph and nfs, however, still need to use the old PG_fscache-based tracking. To deal with this, a flag, NETFS_ICTX_USE_PGPRIV2, now has to be set on the flags in the netfs_inode struct for those filesystems. This reenables the use of PG_fscache in that inode. 9p and afs use the netfslib write helpers so get switched over; cifs, for the moment, does page-by-page manual access to the cache, so doesn't use PG_fscache and is unaffected. Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> cc: Matthew Wilcox (Oracle) <willy@infradead.org> cc: Eric Van Hensbergen <ericvh@kernel.org> cc: Latchesar Ionkov <lucho@ionkov.net> cc: Dominique Martinet <asmadeus@codewreck.org> cc: Christian Schoenebeck <linux_oss@crudebyte.com> cc: Marc Dionne <marc.dionne@auristor.com> cc: Ilya Dryomov <idryomov@gmail.com> cc: Xiubo Li <xiubli@redhat.com> cc: Steve French <sfrench@samba.org> cc: Paulo Alcantara <pc@manguebit.com> cc: Ronnie Sahlberg <ronniesahlberg@gmail.com> cc: Shyam Prasad N <sprasad@microsoft.com> cc: Tom Talpey <tom@talpey.com> cc: Bharath SM <bharathsm@microsoft.com> cc: Trond Myklebust <trond.myklebust@hammerspace.com> cc: Anna Schumaker <anna@kernel.org> cc: netfs@lists.linux.dev cc: v9fs@lists.linux.dev cc: linux-afs@lists.infradead.org cc: ceph-devel@vger.kernel.org cc: linux-cifs@vger.kernel.org cc: linux-nfs@vger.kernel.org cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org
1 parent 5f24162 commit 2ff1e97

14 files changed

Lines changed: 143 additions & 97 deletions

File tree

fs/ceph/addr.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ static void ceph_fscache_write_to_cache(struct inode *inode, u64 off, u64 len, b
517517
struct fscache_cookie *cookie = ceph_fscache_cookie(ci);
518518

519519
fscache_write_to_cache(cookie, inode->i_mapping, off, len, i_size_read(inode),
520-
ceph_fscache_write_terminated, inode, caching);
520+
ceph_fscache_write_terminated, inode, true, caching);
521521
}
522522
#else
523523
static inline void ceph_set_page_fscache(struct page *page)

fs/ceph/inode.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,8 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
577577

578578
/* Set parameters for the netfs library */
579579
netfs_inode_init(&ci->netfs, &ceph_netfs_ops, false);
580+
/* [DEPRECATED] Use PG_private_2 to mark folio being written to the cache. */
581+
__set_bit(NETFS_ICTX_USE_PGPRIV2, &ci->netfs.flags);
580582

581583
spin_lock_init(&ci->i_ceph_lock);
582584

fs/netfs/buffered_read.c

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@
1010
#include "internal.h"
1111

1212
/*
13-
* Unlock the folios in a read operation. We need to set PG_fscache on any
13+
* Unlock the folios in a read operation. We need to set PG_writeback on any
1414
* folios we're going to write back before we unlock them.
15+
*
16+
* Note that if the deprecated NETFS_RREQ_USE_PGPRIV2 is set then we use
17+
* PG_private_2 and do a direct write to the cache from here instead.
1518
*/
1619
void netfs_rreq_unlock_folios(struct netfs_io_request *rreq)
1720
{
@@ -48,25 +51,31 @@ void netfs_rreq_unlock_folios(struct netfs_io_request *rreq)
4851
xas_for_each(&xas, folio, last_page) {
4952
loff_t pg_end;
5053
bool pg_failed = false;
51-
bool folio_started;
54+
bool wback_to_cache = false;
55+
bool folio_started = false;
5256

5357
if (xas_retry(&xas, folio))
5458
continue;
5559

5660
pg_end = folio_pos(folio) + folio_size(folio) - 1;
5761

58-
folio_started = false;
5962
for (;;) {
6063
loff_t sreq_end;
6164

6265
if (!subreq) {
6366
pg_failed = true;
6467
break;
6568
}
66-
if (!folio_started && test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags)) {
67-
trace_netfs_folio(folio, netfs_folio_trace_copy_to_cache);
68-
folio_start_fscache(folio);
69-
folio_started = true;
69+
if (test_bit(NETFS_RREQ_USE_PGPRIV2, &rreq->flags)) {
70+
if (!folio_started && test_bit(NETFS_SREQ_COPY_TO_CACHE,
71+
&subreq->flags)) {
72+
trace_netfs_folio(folio, netfs_folio_trace_copy_to_cache);
73+
folio_start_fscache(folio);
74+
folio_started = true;
75+
}
76+
} else {
77+
wback_to_cache |=
78+
test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags);
7079
}
7180
pg_failed |= subreq_failed;
7281
sreq_end = subreq->start + subreq->len - 1;
@@ -98,6 +107,11 @@ void netfs_rreq_unlock_folios(struct netfs_io_request *rreq)
98107
kfree(finfo);
99108
}
100109
folio_mark_uptodate(folio);
110+
if (wback_to_cache && !WARN_ON_ONCE(folio_get_private(folio) != NULL)) {
111+
trace_netfs_folio(folio, netfs_folio_trace_copy_to_cache);
112+
folio_attach_private(folio, NETFS_FOLIO_COPY_TO_CACHE);
113+
filemap_dirty_folio(folio->mapping, folio);
114+
}
101115
}
102116

103117
if (!test_bit(NETFS_RREQ_DONT_UNLOCK_FOLIOS, &rreq->flags)) {
@@ -491,9 +505,11 @@ int netfs_write_begin(struct netfs_inode *ctx,
491505
netfs_put_request(rreq, false, netfs_rreq_trace_put_return);
492506

493507
have_folio:
494-
ret = folio_wait_fscache_killable(folio);
495-
if (ret < 0)
496-
goto error;
508+
if (test_bit(NETFS_ICTX_USE_PGPRIV2, &ctx->flags)) {
509+
ret = folio_wait_fscache_killable(folio);
510+
if (ret < 0)
511+
goto error;
512+
}
497513
have_folio_no_wait:
498514
*_folio = folio;
499515
_leave(" = 0");

fs/netfs/buffered_write.c

Lines changed: 44 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,13 @@ static void netfs_cleanup_buffered_write(struct netfs_io_request *wreq);
3030

3131
static void netfs_set_group(struct folio *folio, struct netfs_group *netfs_group)
3232
{
33-
if (netfs_group && !folio_get_private(folio))
34-
folio_attach_private(folio, netfs_get_group(netfs_group));
35-
}
33+
void *priv = folio_get_private(folio);
3634

37-
#if IS_ENABLED(CONFIG_FSCACHE)
38-
static void netfs_folio_start_fscache(bool caching, struct folio *folio)
39-
{
40-
if (caching)
41-
folio_start_fscache(folio);
42-
}
43-
#else
44-
static void netfs_folio_start_fscache(bool caching, struct folio *folio)
45-
{
35+
if (netfs_group && (!priv || priv == NETFS_FOLIO_COPY_TO_CACHE))
36+
folio_attach_private(folio, netfs_get_group(netfs_group));
37+
else if (!netfs_group && priv == NETFS_FOLIO_COPY_TO_CACHE)
38+
folio_detach_private(folio);
4639
}
47-
#endif
4840

4941
/*
5042
* Decide how we should modify a folio. We might be attempting to do
@@ -63,11 +55,12 @@ static enum netfs_how_to_modify netfs_how_to_modify(struct netfs_inode *ctx,
6355
bool maybe_trouble)
6456
{
6557
struct netfs_folio *finfo = netfs_folio_info(folio);
58+
struct netfs_group *group = netfs_folio_group(folio);
6659
loff_t pos = folio_file_pos(folio);
6760

6861
_enter("");
6962

70-
if (netfs_folio_group(folio) != netfs_group)
63+
if (group != netfs_group && group != NETFS_FOLIO_COPY_TO_CACHE)
7164
return NETFS_FLUSH_CONTENT;
7265

7366
if (folio_test_uptodate(folio))
@@ -396,9 +389,7 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter,
396389
folio_clear_dirty_for_io(folio);
397390
/* We make multiple writes to the folio... */
398391
if (!folio_test_writeback(folio)) {
399-
folio_wait_fscache(folio);
400392
folio_start_writeback(folio);
401-
folio_start_fscache(folio);
402393
if (wreq->iter.count == 0)
403394
trace_netfs_folio(folio, netfs_folio_trace_wthru);
404395
else
@@ -528,6 +519,7 @@ EXPORT_SYMBOL(netfs_file_write_iter);
528519
*/
529520
vm_fault_t netfs_page_mkwrite(struct vm_fault *vmf, struct netfs_group *netfs_group)
530521
{
522+
struct netfs_group *group;
531523
struct folio *folio = page_folio(vmf->page);
532524
struct file *file = vmf->vma->vm_file;
533525
struct inode *inode = file_inode(file);
@@ -550,7 +542,8 @@ vm_fault_t netfs_page_mkwrite(struct vm_fault *vmf, struct netfs_group *netfs_gr
550542
goto out;
551543
}
552544

553-
if (netfs_folio_group(folio) != netfs_group) {
545+
group = netfs_folio_group(folio);
546+
if (group != netfs_group && group != NETFS_FOLIO_COPY_TO_CACHE) {
554547
folio_unlock(folio);
555548
err = filemap_fdatawait_range(inode->i_mapping,
556549
folio_pos(folio),
@@ -606,8 +599,6 @@ static void netfs_kill_pages(struct address_space *mapping,
606599

607600
trace_netfs_folio(folio, netfs_folio_trace_kill);
608601
folio_clear_uptodate(folio);
609-
if (folio_test_fscache(folio))
610-
folio_end_fscache(folio);
611602
folio_end_writeback(folio);
612603
folio_lock(folio);
613604
generic_error_remove_folio(mapping, folio);
@@ -643,8 +634,6 @@ static void netfs_redirty_pages(struct address_space *mapping,
643634
next = folio_next_index(folio);
644635
trace_netfs_folio(folio, netfs_folio_trace_redirty);
645636
filemap_dirty_folio(mapping, folio);
646-
if (folio_test_fscache(folio))
647-
folio_end_fscache(folio);
648637
folio_end_writeback(folio);
649638
folio_put(folio);
650639
} while (index = next, index <= last);
@@ -700,7 +689,11 @@ static void netfs_pages_written_back(struct netfs_io_request *wreq)
700689
if (!folio_test_dirty(folio)) {
701690
folio_detach_private(folio);
702691
gcount++;
703-
trace_netfs_folio(folio, netfs_folio_trace_clear_g);
692+
if (group == NETFS_FOLIO_COPY_TO_CACHE)
693+
trace_netfs_folio(folio,
694+
netfs_folio_trace_end_copy);
695+
else
696+
trace_netfs_folio(folio, netfs_folio_trace_clear_g);
704697
} else {
705698
trace_netfs_folio(folio, netfs_folio_trace_redirtied);
706699
}
@@ -724,8 +717,6 @@ static void netfs_pages_written_back(struct netfs_io_request *wreq)
724717
trace_netfs_folio(folio, netfs_folio_trace_clear);
725718
}
726719
end_wb:
727-
if (folio_test_fscache(folio))
728-
folio_end_fscache(folio);
729720
xas_advance(&xas, folio_next_index(folio) - 1);
730721
folio_end_writeback(folio);
731722
}
@@ -795,7 +786,6 @@ static void netfs_extend_writeback(struct address_space *mapping,
795786
long *_count,
796787
loff_t start,
797788
loff_t max_len,
798-
bool caching,
799789
size_t *_len,
800790
size_t *_top)
801791
{
@@ -846,8 +836,7 @@ static void netfs_extend_writeback(struct address_space *mapping,
846836
break;
847837
}
848838
if (!folio_test_dirty(folio) ||
849-
folio_test_writeback(folio) ||
850-
folio_test_fscache(folio)) {
839+
folio_test_writeback(folio)) {
851840
folio_unlock(folio);
852841
folio_put(folio);
853842
xas_reset(xas);
@@ -860,7 +849,8 @@ static void netfs_extend_writeback(struct address_space *mapping,
860849
if ((const struct netfs_group *)priv != group) {
861850
stop = true;
862851
finfo = netfs_folio_info(folio);
863-
if (finfo->netfs_group != group ||
852+
if (!finfo ||
853+
finfo->netfs_group != group ||
864854
finfo->dirty_offset > 0) {
865855
folio_unlock(folio);
866856
folio_put(folio);
@@ -894,12 +884,14 @@ static void netfs_extend_writeback(struct address_space *mapping,
894884

895885
for (i = 0; i < folio_batch_count(&fbatch); i++) {
896886
folio = fbatch.folios[i];
897-
trace_netfs_folio(folio, netfs_folio_trace_store_plus);
887+
if (group == NETFS_FOLIO_COPY_TO_CACHE)
888+
trace_netfs_folio(folio, netfs_folio_trace_copy_plus);
889+
else
890+
trace_netfs_folio(folio, netfs_folio_trace_store_plus);
898891

899892
if (!folio_clear_dirty_for_io(folio))
900893
BUG();
901894
folio_start_writeback(folio);
902-
netfs_folio_start_fscache(caching, folio);
903895
folio_unlock(folio);
904896
}
905897

@@ -925,14 +917,14 @@ static ssize_t netfs_write_back_from_locked_folio(struct address_space *mapping,
925917
struct netfs_inode *ctx = netfs_inode(mapping->host);
926918
unsigned long long i_size = i_size_read(&ctx->inode);
927919
size_t len, max_len;
928-
bool caching = netfs_is_cache_enabled(ctx);
929920
long count = wbc->nr_to_write;
930921
int ret;
931922

932-
_enter(",%lx,%llx-%llx,%u", folio->index, start, end, caching);
923+
_enter(",%lx,%llx-%llx", folio->index, start, end);
933924

934925
wreq = netfs_alloc_request(mapping, NULL, start, folio_size(folio),
935-
NETFS_WRITEBACK);
926+
group == NETFS_FOLIO_COPY_TO_CACHE ?
927+
NETFS_COPY_TO_CACHE : NETFS_WRITEBACK);
936928
if (IS_ERR(wreq)) {
937929
folio_unlock(folio);
938930
return PTR_ERR(wreq);
@@ -941,7 +933,6 @@ static ssize_t netfs_write_back_from_locked_folio(struct address_space *mapping,
941933
if (!folio_clear_dirty_for_io(folio))
942934
BUG();
943935
folio_start_writeback(folio);
944-
netfs_folio_start_fscache(caching, folio);
945936

946937
count -= folio_nr_pages(folio);
947938

@@ -950,7 +941,10 @@ static ssize_t netfs_write_back_from_locked_folio(struct address_space *mapping,
950941
* immediately lockable, is not dirty or is missing, or we reach the
951942
* end of the range.
952943
*/
953-
trace_netfs_folio(folio, netfs_folio_trace_store);
944+
if (group == NETFS_FOLIO_COPY_TO_CACHE)
945+
trace_netfs_folio(folio, netfs_folio_trace_copy);
946+
else
947+
trace_netfs_folio(folio, netfs_folio_trace_store);
954948

955949
len = wreq->len;
956950
finfo = netfs_folio_info(folio);
@@ -973,7 +967,7 @@ static ssize_t netfs_write_back_from_locked_folio(struct address_space *mapping,
973967

974968
if (len < max_len)
975969
netfs_extend_writeback(mapping, group, xas, &count, start,
976-
max_len, caching, &len, &wreq->upper_len);
970+
max_len, &len, &wreq->upper_len);
977971
}
978972

979973
cant_expand:
@@ -997,15 +991,18 @@ static ssize_t netfs_write_back_from_locked_folio(struct address_space *mapping,
997991

998992
iov_iter_xarray(&wreq->iter, ITER_SOURCE, &mapping->i_pages, start,
999993
wreq->upper_len);
1000-
__set_bit(NETFS_RREQ_UPLOAD_TO_SERVER, &wreq->flags);
1001-
ret = netfs_begin_write(wreq, true, netfs_write_trace_writeback);
994+
if (group != NETFS_FOLIO_COPY_TO_CACHE) {
995+
__set_bit(NETFS_RREQ_UPLOAD_TO_SERVER, &wreq->flags);
996+
ret = netfs_begin_write(wreq, true, netfs_write_trace_writeback);
997+
} else {
998+
ret = netfs_begin_write(wreq, true, netfs_write_trace_copy_to_cache);
999+
}
10021000
if (ret == 0 || ret == -EIOCBQUEUED)
10031001
wbc->nr_to_write -= len / PAGE_SIZE;
10041002
} else {
10051003
_debug("write discard %zx @%llx [%llx]", len, start, i_size);
10061004

10071005
/* The dirty region was entirely beyond the EOF. */
1008-
fscache_clear_page_bits(mapping, start, len, caching);
10091006
netfs_pages_written_back(wreq);
10101007
ret = 0;
10111008
}
@@ -1058,9 +1055,11 @@ static ssize_t netfs_writepages_begin(struct address_space *mapping,
10581055

10591056
/* Skip any dirty folio that's not in the group of interest. */
10601057
priv = folio_get_private(folio);
1061-
if ((const struct netfs_group *)priv != group) {
1062-
finfo = netfs_folio_info(folio);
1063-
if (finfo->netfs_group != group) {
1058+
if ((const struct netfs_group *)priv == NETFS_FOLIO_COPY_TO_CACHE) {
1059+
group = NETFS_FOLIO_COPY_TO_CACHE;
1060+
} else if ((const struct netfs_group *)priv != group) {
1061+
finfo = __netfs_folio_info(priv);
1062+
if (!finfo || finfo->netfs_group != group) {
10641063
folio_put(folio);
10651064
continue;
10661065
}
@@ -1099,14 +1098,10 @@ static ssize_t netfs_writepages_begin(struct address_space *mapping,
10991098
goto search_again;
11001099
}
11011100

1102-
if (folio_test_writeback(folio) ||
1103-
folio_test_fscache(folio)) {
1101+
if (folio_test_writeback(folio)) {
11041102
folio_unlock(folio);
11051103
if (wbc->sync_mode != WB_SYNC_NONE) {
11061104
folio_wait_writeback(folio);
1107-
#ifdef CONFIG_FSCACHE
1108-
folio_wait_fscache(folio);
1109-
#endif
11101105
goto lock_again;
11111106
}
11121107

@@ -1265,7 +1260,8 @@ int netfs_launder_folio(struct folio *folio)
12651260

12661261
bvec_set_folio(&bvec, folio, len, offset);
12671262
iov_iter_bvec(&wreq->iter, ITER_SOURCE, &bvec, 1, len);
1268-
__set_bit(NETFS_RREQ_UPLOAD_TO_SERVER, &wreq->flags);
1263+
if (group != NETFS_FOLIO_COPY_TO_CACHE)
1264+
__set_bit(NETFS_RREQ_UPLOAD_TO_SERVER, &wreq->flags);
12691265
ret = netfs_begin_write(wreq, true, netfs_write_trace_launder);
12701266

12711267
out_put:
@@ -1274,7 +1270,6 @@ int netfs_launder_folio(struct folio *folio)
12741270
kfree(finfo);
12751271
netfs_put_request(wreq, false, netfs_rreq_trace_put_return);
12761272
out:
1277-
folio_wait_fscache(folio);
12781273
_leave(" = %d", ret);
12791274
return ret;
12801275
}

0 commit comments

Comments
 (0)