1414#include <linux/netfs.h>
1515#include "internal.h"
1616
17+ static int afs_writepages_region (struct address_space * mapping ,
18+ struct writeback_control * wbc ,
19+ loff_t start , loff_t end , loff_t * _next ,
20+ bool max_one_loop );
21+
1722static void afs_write_to_cache (struct afs_vnode * vnode , loff_t start , size_t len ,
1823 loff_t i_size , bool caching );
1924
@@ -38,6 +43,25 @@ static void afs_folio_start_fscache(bool caching, struct folio *folio)
3843}
3944#endif
4045
46+ /*
47+ * Flush out a conflicting write. This may extend the write to the surrounding
48+ * pages if also dirty and contiguous to the conflicting region..
49+ */
50+ static int afs_flush_conflicting_write (struct address_space * mapping ,
51+ struct folio * folio )
52+ {
53+ struct writeback_control wbc = {
54+ .sync_mode = WB_SYNC_ALL ,
55+ .nr_to_write = LONG_MAX ,
56+ .range_start = folio_pos (folio ),
57+ .range_end = LLONG_MAX ,
58+ };
59+ loff_t next ;
60+
61+ return afs_writepages_region (mapping , & wbc , folio_pos (folio ), LLONG_MAX ,
62+ & next , true);
63+ }
64+
4165/*
4266 * prepare to perform part of a write to a page
4367 */
@@ -80,7 +104,8 @@ int afs_write_begin(struct file *file, struct address_space *mapping,
80104
81105 if (folio_test_writeback (folio )) {
82106 trace_afs_folio_dirty (vnode , tracepoint_string ("alrdy" ), folio );
83- goto flush_conflicting_write ;
107+ folio_unlock (folio );
108+ goto wait_for_writeback ;
84109 }
85110 /* If the file is being filled locally, allow inter-write
86111 * spaces to be merged into writes. If it's not, only write
@@ -99,8 +124,15 @@ int afs_write_begin(struct file *file, struct address_space *mapping,
99124 * flush the page out.
100125 */
101126flush_conflicting_write :
102- _debug ("flush conflict" );
103- ret = folio_write_one (folio );
127+ trace_afs_folio_dirty (vnode , tracepoint_string ("confl" ), folio );
128+ folio_unlock (folio );
129+
130+ ret = afs_flush_conflicting_write (mapping , folio );
131+ if (ret < 0 )
132+ goto error ;
133+
134+ wait_for_writeback :
135+ ret = folio_wait_writeback_killable (folio );
104136 if (ret < 0 )
105137 goto error ;
106138
@@ -663,40 +695,13 @@ static ssize_t afs_write_back_from_locked_folio(struct address_space *mapping,
663695 return ret ;
664696}
665697
666- /*
667- * write a page back to the server
668- * - the caller locked the page for us
669- */
670- int afs_writepage (struct page * subpage , struct writeback_control * wbc )
671- {
672- struct folio * folio = page_folio (subpage );
673- ssize_t ret ;
674- loff_t start ;
675-
676- _enter ("{%lx}," , folio_index (folio ));
677-
678- #ifdef CONFIG_AFS_FSCACHE
679- folio_wait_fscache (folio );
680- #endif
681-
682- start = folio_index (folio ) * PAGE_SIZE ;
683- ret = afs_write_back_from_locked_folio (folio_mapping (folio ), wbc ,
684- folio , start , LLONG_MAX - start );
685- if (ret < 0 ) {
686- _leave (" = %zd" , ret );
687- return ret ;
688- }
689-
690- _leave (" = 0" );
691- return 0 ;
692- }
693-
694698/*
695699 * write a region of pages back to the server
696700 */
697701static int afs_writepages_region (struct address_space * mapping ,
698702 struct writeback_control * wbc ,
699- loff_t start , loff_t end , loff_t * _next )
703+ loff_t start , loff_t end , loff_t * _next ,
704+ bool max_one_loop )
700705{
701706 struct folio * folio ;
702707 struct page * head_page ;
@@ -775,6 +780,9 @@ static int afs_writepages_region(struct address_space *mapping,
775780
776781 start += ret ;
777782
783+ if (max_one_loop )
784+ break ;
785+
778786 cond_resched ();
779787 } while (wbc -> nr_to_write > 0 );
780788
@@ -806,24 +814,27 @@ int afs_writepages(struct address_space *mapping,
806814
807815 if (wbc -> range_cyclic ) {
808816 start = mapping -> writeback_index * PAGE_SIZE ;
809- ret = afs_writepages_region (mapping , wbc , start , LLONG_MAX , & next );
817+ ret = afs_writepages_region (mapping , wbc , start , LLONG_MAX ,
818+ & next , false);
810819 if (ret == 0 ) {
811820 mapping -> writeback_index = next / PAGE_SIZE ;
812821 if (start > 0 && wbc -> nr_to_write > 0 ) {
813822 ret = afs_writepages_region (mapping , wbc , 0 ,
814- start , & next );
823+ start , & next , false );
815824 if (ret == 0 )
816825 mapping -> writeback_index =
817826 next / PAGE_SIZE ;
818827 }
819828 }
820829 } else if (wbc -> range_start == 0 && wbc -> range_end == LLONG_MAX ) {
821- ret = afs_writepages_region (mapping , wbc , 0 , LLONG_MAX , & next );
830+ ret = afs_writepages_region (mapping , wbc , 0 , LLONG_MAX ,
831+ & next , false);
822832 if (wbc -> nr_to_write > 0 && ret == 0 )
823833 mapping -> writeback_index = next / PAGE_SIZE ;
824834 } else {
825835 ret = afs_writepages_region (mapping , wbc ,
826- wbc -> range_start , wbc -> range_end , & next );
836+ wbc -> range_start , wbc -> range_end ,
837+ & next , false);
827838 }
828839
829840 up_read (& vnode -> validate_lock );
0 commit comments