Skip to content

Commit 7d828a0

Browse files
committed
netfs: Provide tools to create a buffer in an xarray
Provide tools to create a buffer in an xarray, with a function to add new folios with a mark. This will be used to create bounce buffer and can be used more easily to create a list of folios the span of which would require more than a page's worth of bio_vec structs. Signed-off-by: David Howells <[email protected]> Reviewed-by: Jeff Layton <[email protected]> cc: [email protected] cc: [email protected] cc: [email protected]
1 parent 21d706d commit 7d828a0

File tree

3 files changed

+98
-0
lines changed

3 files changed

+98
-0
lines changed

fs/netfs/internal.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,19 @@ static inline void netfs_proc_add_rreq(struct netfs_io_request *rreq) {}
5656
static inline void netfs_proc_del_rreq(struct netfs_io_request *rreq) {}
5757
#endif
5858

59+
/*
60+
* misc.c
61+
*/
62+
#define NETFS_FLAG_PUT_MARK BIT(0)
63+
#define NETFS_FLAG_PAGECACHE_MARK BIT(1)
64+
int netfs_xa_store_and_mark(struct xarray *xa, unsigned long index,
65+
struct folio *folio, unsigned int flags,
66+
gfp_t gfp_mask);
67+
int netfs_add_folios_to_buffer(struct xarray *buffer,
68+
struct address_space *mapping,
69+
pgoff_t index, pgoff_t to, gfp_t gfp_mask);
70+
void netfs_clear_buffer(struct xarray *buffer);
71+
5972
/*
6073
* objects.c
6174
*/

fs/netfs/misc.c

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,87 @@
88
#include <linux/swap.h>
99
#include "internal.h"
1010

11+
/*
12+
* Attach a folio to the buffer and maybe set marks on it to say that we need
13+
* to put the folio later and twiddle the pagecache flags.
14+
*/
15+
int netfs_xa_store_and_mark(struct xarray *xa, unsigned long index,
16+
struct folio *folio, unsigned int flags,
17+
gfp_t gfp_mask)
18+
{
19+
XA_STATE_ORDER(xas, xa, index, folio_order(folio));
20+
21+
retry:
22+
xas_lock(&xas);
23+
for (;;) {
24+
xas_store(&xas, folio);
25+
if (!xas_error(&xas))
26+
break;
27+
xas_unlock(&xas);
28+
if (!xas_nomem(&xas, gfp_mask))
29+
return xas_error(&xas);
30+
goto retry;
31+
}
32+
33+
if (flags & NETFS_FLAG_PUT_MARK)
34+
xas_set_mark(&xas, NETFS_BUF_PUT_MARK);
35+
if (flags & NETFS_FLAG_PAGECACHE_MARK)
36+
xas_set_mark(&xas, NETFS_BUF_PAGECACHE_MARK);
37+
xas_unlock(&xas);
38+
return xas_error(&xas);
39+
}
40+
41+
/*
42+
* Create the specified range of folios in the buffer attached to the read
43+
* request. The folios are marked with NETFS_BUF_PUT_MARK so that we know that
44+
* these need freeing later.
45+
*/
46+
int netfs_add_folios_to_buffer(struct xarray *buffer,
47+
struct address_space *mapping,
48+
pgoff_t index, pgoff_t to, gfp_t gfp_mask)
49+
{
50+
struct folio *folio;
51+
int ret;
52+
53+
if (to + 1 == index) /* Page range is inclusive */
54+
return 0;
55+
56+
do {
57+
/* TODO: Figure out what order folio can be allocated here */
58+
folio = filemap_alloc_folio(readahead_gfp_mask(mapping), 0);
59+
if (!folio)
60+
return -ENOMEM;
61+
folio->index = index;
62+
ret = netfs_xa_store_and_mark(buffer, index, folio,
63+
NETFS_FLAG_PUT_MARK, gfp_mask);
64+
if (ret < 0) {
65+
folio_put(folio);
66+
return ret;
67+
}
68+
69+
index += folio_nr_pages(folio);
70+
} while (index <= to && index != 0);
71+
72+
return 0;
73+
}
74+
75+
/*
76+
* Clear an xarray buffer, putting a ref on the folios that have
77+
* NETFS_BUF_PUT_MARK set.
78+
*/
79+
void netfs_clear_buffer(struct xarray *buffer)
80+
{
81+
struct folio *folio;
82+
XA_STATE(xas, buffer, 0);
83+
84+
rcu_read_lock();
85+
xas_for_each_marked(&xas, folio, ULONG_MAX, NETFS_BUF_PUT_MARK) {
86+
folio_put(folio);
87+
}
88+
rcu_read_unlock();
89+
xa_destroy(buffer);
90+
}
91+
1192
/**
1293
* netfs_dirty_folio - Mark folio dirty and pin a cache object for writeback
1394
* @mapping: The mapping the folio belongs to.

include/linux/netfs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ static inline int wait_on_page_fscache_killable(struct page *page)
109109
return folio_wait_private_2_killable(page_folio(page));
110110
}
111111

112+
/* Marks used on xarray-based buffers */
113+
#define NETFS_BUF_PUT_MARK XA_MARK_0 /* - Page needs putting */
114+
#define NETFS_BUF_PAGECACHE_MARK XA_MARK_1 /* - Page needs wb/dirty flag wrangling */
115+
112116
enum netfs_io_source {
113117
NETFS_FILL_WITH_ZEROES,
114118
NETFS_DOWNLOAD_FROM_SERVER,

0 commit comments

Comments
 (0)