Skip to content

Commit ab75bff

Browse files
Trond Myklebustamschuma-ntap
authored andcommitted
NFS: Convert buffered reads to use folios
Perform a largely mechanical conversion of references to struct page and page-specific functions to use the folio equivalents. Note that the fscache functionality remains untouched. Instead we just pass in the folio page. This should be OK, as long as we use order 0 folios together with fscache. Signed-off-by: Trond Myklebust <[email protected]> Signed-off-by: Anna Schumaker <[email protected]>
1 parent 4b27232 commit ab75bff

File tree

5 files changed

+100
-50
lines changed

5 files changed

+100
-50
lines changed

fs/nfs/internal.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,24 @@ unsigned int nfs_page_length(struct page *page)
794794
return 0;
795795
}
796796

797+
/*
798+
* Determine the number of bytes of data the page contains
799+
*/
800+
static inline size_t nfs_folio_length(struct folio *folio)
801+
{
802+
loff_t i_size = i_size_read(folio_file_mapping(folio)->host);
803+
804+
if (i_size > 0) {
805+
pgoff_t index = folio_index(folio) >> folio_order(folio);
806+
pgoff_t end_index = (i_size - 1) >> folio_shift(folio);
807+
if (index < end_index)
808+
return folio_size(folio);
809+
if (index == end_index)
810+
return offset_in_folio(folio, i_size - 1) + 1;
811+
}
812+
return 0;
813+
}
814+
797815
/*
798816
* Convert a umode to a dirent->d_type
799817
*/

fs/nfs/nfstrace.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -936,10 +936,10 @@ TRACE_EVENT(nfs_sillyrename_unlink,
936936
TRACE_EVENT(nfs_aop_readpage,
937937
TP_PROTO(
938938
const struct inode *inode,
939-
struct page *page
939+
struct folio *folio
940940
),
941941

942-
TP_ARGS(inode, page),
942+
TP_ARGS(inode, folio),
943943

944944
TP_STRUCT__entry(
945945
__field(dev_t, dev)
@@ -956,7 +956,7 @@ TRACE_EVENT(nfs_aop_readpage,
956956
__entry->fileid = nfsi->fileid;
957957
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
958958
__entry->version = inode_peek_iversion_raw(inode);
959-
__entry->offset = page_index(page) << PAGE_SHIFT;
959+
__entry->offset = folio_file_pos(folio);
960960
),
961961

962962
TP_printk(
@@ -971,11 +971,11 @@ TRACE_EVENT(nfs_aop_readpage,
971971
TRACE_EVENT(nfs_aop_readpage_done,
972972
TP_PROTO(
973973
const struct inode *inode,
974-
struct page *page,
974+
struct folio *folio,
975975
int ret
976976
),
977977

978-
TP_ARGS(inode, page, ret),
978+
TP_ARGS(inode, folio, ret),
979979

980980
TP_STRUCT__entry(
981981
__field(dev_t, dev)
@@ -993,7 +993,7 @@ TRACE_EVENT(nfs_aop_readpage_done,
993993
__entry->fileid = nfsi->fileid;
994994
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
995995
__entry->version = inode_peek_iversion_raw(inode);
996-
__entry->offset = page_index(page) << PAGE_SHIFT;
996+
__entry->offset = folio_file_pos(folio);
997997
__entry->ret = ret;
998998
),
999999

fs/nfs/pagelist.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,36 @@ nfs_create_request(struct nfs_open_context *ctx, struct page *page,
542542
return ret;
543543
}
544544

545+
/**
546+
* nfs_page_create_from_folio - Create an NFS read/write request.
547+
* @ctx: open context to use
548+
* @folio: folio to write
549+
* @offset: starting offset within the folio for the write
550+
* @count: number of bytes to read/write
551+
*
552+
* The page must be locked by the caller. This makes sure we never
553+
* create two different requests for the same page.
554+
* User should ensure it is safe to sleep in this function.
555+
*/
556+
struct nfs_page *nfs_page_create_from_folio(struct nfs_open_context *ctx,
557+
struct folio *folio,
558+
unsigned int offset,
559+
unsigned int count)
560+
{
561+
struct nfs_lock_context *l_ctx = nfs_get_lock_context(ctx);
562+
struct nfs_page *ret;
563+
564+
if (IS_ERR(l_ctx))
565+
return ERR_CAST(l_ctx);
566+
ret = nfs_page_create(l_ctx, offset, folio_index(folio), offset, count);
567+
if (!IS_ERR(ret)) {
568+
nfs_page_assign_folio(ret, folio);
569+
nfs_page_group_init(ret, NULL);
570+
}
571+
nfs_put_lock_context(l_ctx);
572+
return ret;
573+
}
574+
545575
static struct nfs_page *
546576
nfs_create_subreq(struct nfs_page *req,
547577
unsigned int pgbase,

fs/nfs/read.c

Lines changed: 42 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,11 @@ static void nfs_readhdr_free(struct nfs_pgio_header *rhdr)
4949
kmem_cache_free(nfs_rdata_cachep, rhdr);
5050
}
5151

52-
static
53-
int nfs_return_empty_page(struct page *page)
52+
static int nfs_return_empty_folio(struct folio *folio)
5453
{
55-
zero_user(page, 0, PAGE_SIZE);
56-
SetPageUptodate(page);
57-
unlock_page(page);
54+
folio_zero_segment(folio, 0, folio_size(folio));
55+
folio_mark_uptodate(folio);
56+
folio_unlock(folio);
5857
return 0;
5958
}
6059

@@ -111,18 +110,18 @@ EXPORT_SYMBOL_GPL(nfs_pageio_reset_read_mds);
111110
static void nfs_readpage_release(struct nfs_page *req, int error)
112111
{
113112
struct inode *inode = d_inode(nfs_req_openctx(req)->dentry);
114-
struct page *page = req->wb_page;
113+
struct folio *folio = nfs_page_to_folio(req);
115114

116115
dprintk("NFS: read done (%s/%llu %d@%lld)\n", inode->i_sb->s_id,
117116
(unsigned long long)NFS_FILEID(inode), req->wb_bytes,
118117
(long long)req_offset(req));
119118

120119
if (nfs_error_is_fatal_on_server(error) && error != -ETIMEDOUT)
121-
SetPageError(page);
120+
folio_set_error(folio);
122121
if (nfs_page_group_sync_on_bit(req, PG_UNLOCKPAGE)) {
123-
if (PageUptodate(page))
124-
nfs_fscache_write_page(inode, page);
125-
unlock_page(page);
122+
if (folio_test_uptodate(folio))
123+
nfs_fscache_write_page(inode, &folio->page);
124+
folio_unlock(folio);
126125
}
127126
nfs_release_request(req);
128127
}
@@ -135,7 +134,7 @@ struct nfs_readdesc {
135134
static void nfs_page_group_set_uptodate(struct nfs_page *req)
136135
{
137136
if (nfs_page_group_sync_on_bit(req, PG_UPTODATE))
138-
SetPageUptodate(req->wb_page);
137+
folio_mark_uptodate(nfs_page_to_folio(req));
139138
}
140139

141140
static void nfs_read_completion(struct nfs_pgio_header *hdr)
@@ -147,7 +146,7 @@ static void nfs_read_completion(struct nfs_pgio_header *hdr)
147146
goto out;
148147
while (!list_empty(&hdr->pages)) {
149148
struct nfs_page *req = nfs_list_entry(hdr->pages.next);
150-
struct page *page = req->wb_page;
149+
struct folio *folio = nfs_page_to_folio(req);
151150
unsigned long start = req->wb_pgbase;
152151
unsigned long end = req->wb_pgbase + req->wb_bytes;
153152

@@ -157,14 +156,14 @@ static void nfs_read_completion(struct nfs_pgio_header *hdr)
157156
if (bytes > hdr->good_bytes) {
158157
/* nothing in this request was good, so zero
159158
* the full extent of the request */
160-
zero_user_segment(page, start, end);
159+
folio_zero_segment(folio, start, end);
161160

162161
} else if (hdr->good_bytes - bytes < req->wb_bytes) {
163162
/* part of this request has good bytes, but
164163
* not all. zero the bad bytes */
165164
start += hdr->good_bytes - bytes;
166165
WARN_ON(start < req->wb_pgbase);
167-
zero_user_segment(page, start, end);
166+
folio_zero_segment(folio, start, end);
168167
}
169168
}
170169
error = 0;
@@ -281,33 +280,34 @@ static void nfs_readpage_result(struct rpc_task *task,
281280
nfs_readpage_retry(task, hdr);
282281
}
283282

284-
static int
285-
readpage_async_filler(struct nfs_readdesc *desc, struct page *page)
283+
static int readpage_async_filler(struct nfs_readdesc *desc, struct folio *folio)
286284
{
287-
struct inode *inode = page_file_mapping(page)->host;
288-
unsigned int rsize = NFS_SERVER(inode)->rsize;
285+
struct inode *inode = folio_file_mapping(folio)->host;
286+
struct nfs_server *server = NFS_SERVER(inode);
287+
size_t fsize = folio_size(folio);
288+
unsigned int rsize = server->rsize;
289289
struct nfs_page *new;
290290
unsigned int len, aligned_len;
291291
int error;
292292

293-
len = nfs_page_length(page);
293+
len = nfs_folio_length(folio);
294294
if (len == 0)
295-
return nfs_return_empty_page(page);
295+
return nfs_return_empty_folio(folio);
296296

297-
aligned_len = min_t(unsigned int, ALIGN(len, rsize), PAGE_SIZE);
297+
aligned_len = min_t(unsigned int, ALIGN(len, rsize), fsize);
298298

299-
if (!IS_SYNC(page->mapping->host)) {
300-
error = nfs_fscache_read_page(page->mapping->host, page);
299+
if (!IS_SYNC(inode)) {
300+
error = nfs_fscache_read_page(inode, &folio->page);
301301
if (error == 0)
302302
goto out_unlock;
303303
}
304304

305-
new = nfs_create_request(desc->ctx, page, 0, aligned_len);
305+
new = nfs_page_create_from_folio(desc->ctx, folio, 0, aligned_len);
306306
if (IS_ERR(new))
307307
goto out_error;
308308

309-
if (len < PAGE_SIZE)
310-
zero_user_segment(page, len, PAGE_SIZE);
309+
if (len < fsize)
310+
folio_zero_segment(folio, len, fsize);
311311
if (!nfs_pageio_add_request(&desc->pgio, new)) {
312312
nfs_list_remove_request(new);
313313
error = desc->pgio.pg_error;
@@ -318,7 +318,7 @@ readpage_async_filler(struct nfs_readdesc *desc, struct page *page)
318318
out_error:
319319
error = PTR_ERR(new);
320320
out_unlock:
321-
unlock_page(page);
321+
folio_unlock(folio);
322322
out:
323323
return error;
324324
}
@@ -331,25 +331,24 @@ readpage_async_filler(struct nfs_readdesc *desc, struct page *page)
331331
*/
332332
int nfs_read_folio(struct file *file, struct folio *folio)
333333
{
334-
struct page *page = &folio->page;
335334
struct nfs_readdesc desc;
336-
struct inode *inode = page_file_mapping(page)->host;
335+
struct inode *inode = file_inode(file);
337336
int ret;
338337

339-
trace_nfs_aop_readpage(inode, page);
338+
trace_nfs_aop_readpage(inode, folio);
340339
nfs_inc_stats(inode, NFSIOS_VFSREADPAGE);
341340

342341
/*
343342
* Try to flush any pending writes to the file..
344343
*
345-
* NOTE! Because we own the page lock, there cannot
344+
* NOTE! Because we own the folio lock, there cannot
346345
* be any new pending writes generated at this point
347-
* for this page (other pages can be written to).
346+
* for this folio (other folios can be written to).
348347
*/
349-
ret = nfs_wb_page(inode, page);
348+
ret = nfs_wb_folio(inode, folio);
350349
if (ret)
351350
goto out_unlock;
352-
if (PageUptodate(page))
351+
if (folio_test_uptodate(folio))
353352
goto out_unlock;
354353

355354
ret = -ESTALE;
@@ -368,24 +367,24 @@ int nfs_read_folio(struct file *file, struct folio *folio)
368367
nfs_pageio_init_read(&desc.pgio, inode, false,
369368
&nfs_async_read_completion_ops);
370369

371-
ret = readpage_async_filler(&desc, page);
370+
ret = readpage_async_filler(&desc, folio);
372371
if (ret)
373372
goto out;
374373

375374
nfs_pageio_complete_read(&desc.pgio);
376375
ret = desc.pgio.pg_error < 0 ? desc.pgio.pg_error : 0;
377376
if (!ret) {
378-
ret = wait_on_page_locked_killable(page);
379-
if (!PageUptodate(page) && !ret)
377+
ret = folio_wait_locked_killable(folio);
378+
if (!folio_test_uptodate(folio) && !ret)
380379
ret = xchg(&desc.ctx->error, 0);
381380
}
382381
out:
383382
put_nfs_open_context(desc.ctx);
384-
trace_nfs_aop_readpage_done(inode, page, ret);
383+
trace_nfs_aop_readpage_done(inode, folio, ret);
385384
return ret;
386385
out_unlock:
387-
unlock_page(page);
388-
trace_nfs_aop_readpage_done(inode, page, ret);
386+
folio_unlock(folio);
387+
trace_nfs_aop_readpage_done(inode, folio, ret);
389388
return ret;
390389
}
391390

@@ -395,7 +394,7 @@ void nfs_readahead(struct readahead_control *ractl)
395394
struct file *file = ractl->file;
396395
struct nfs_readdesc desc;
397396
struct inode *inode = ractl->mapping->host;
398-
struct page *page;
397+
struct folio *folio;
399398
int ret;
400399

401400
trace_nfs_aop_readahead(inode, readahead_pos(ractl), nr_pages);
@@ -416,9 +415,8 @@ void nfs_readahead(struct readahead_control *ractl)
416415
nfs_pageio_init_read(&desc.pgio, inode, false,
417416
&nfs_async_read_completion_ops);
418417

419-
while ((page = readahead_page(ractl)) != NULL) {
420-
ret = readpage_async_filler(&desc, page);
421-
put_page(page);
418+
while ((folio = readahead_folio(ractl)) != NULL) {
419+
ret = readpage_async_filler(&desc, folio);
422420
if (ret)
423421
break;
424422
}

include/linux/nfs_page.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ extern struct nfs_page *nfs_create_request(struct nfs_open_context *ctx,
125125
struct page *page,
126126
unsigned int offset,
127127
unsigned int count);
128+
extern struct nfs_page *nfs_page_create_from_folio(struct nfs_open_context *ctx,
129+
struct folio *folio,
130+
unsigned int offset,
131+
unsigned int count);
128132
extern void nfs_release_request(struct nfs_page *);
129133

130134

0 commit comments

Comments
 (0)