@@ -766,6 +766,7 @@ static void virtio_fs_request_complete(struct fuse_req *req,
struct fuse_args_pages *ap;
unsigned int len, i, thislen;
struct page *page;
+ struct folio *folio;
/*
* TODO verify that server properly follows FUSE protocol
@@ -777,15 +778,29 @@ static void virtio_fs_request_complete(struct fuse_req *req,
if (args->out_pages && args->page_zeroing) {
len = args->out_args[args->out_numargs - 1].size;
ap = container_of(args, typeof(*ap), args);
- for (i = 0; i < ap->num_pages; i++) {
- thislen = ap->descs[i].length;
- if (len < thislen) {
- WARN_ON(ap->descs[i].offset);
- page = ap->pages[i];
- zero_user_segment(page, len, thislen);
- len = 0;
- } else {
- len -= thislen;
+ if (ap->uses_folios) {
+ for (i = 0; i < ap->num_folios; i++) {
+ thislen = ap->folio_descs[i].length;
+ if (len < thislen) {
+ WARN_ON(ap->folio_descs[i].offset);
+ folio = ap->folios[i];
+ folio_zero_segment(folio, len, thislen);
+ len = 0;
+ } else {
+ len -= thislen;
+ }
+ }
+ } else {
+ for (i = 0; i < ap->num_pages; i++) {
+ thislen = ap->descs[i].length;
+ if (len < thislen) {
+ WARN_ON(ap->descs[i].offset);
+ page = ap->pages[i];
+ zero_user_segment(page, len, thislen);
+ len = 0;
+ } else {
+ len -= thislen;
+ }
}
}
}
@@ -1272,16 +1287,22 @@ static void virtio_fs_send_interrupt(struct fuse_iqueue *fiq, struct fuse_req *r
}
/* Count number of scatter-gather elements required */
-static unsigned int sg_count_fuse_pages(struct fuse_page_desc *page_descs,
- unsigned int num_pages,
- unsigned int total_len)
+static unsigned int sg_count_fuse_pages(struct fuse_args_pages *ap,
+ unsigned int total_len)
{
unsigned int i;
unsigned int this_len;
- for (i = 0; i < num_pages && total_len; i++) {
- this_len = min(page_descs[i].length, total_len);
- total_len -= this_len;
+ if (ap->uses_folios) {
+ for (i = 0; i < ap->num_folios && total_len; i++) {
+ this_len = min(ap->folio_descs[i].length, total_len);
+ total_len -= this_len;
+ }
+ } else {
+ for (i = 0; i < ap->num_pages && total_len; i++) {
+ this_len = min(ap->descs[i].length, total_len);
+ total_len -= this_len;
+ }
}
return i;
@@ -1299,8 +1320,7 @@ static unsigned int sg_count_fuse_req(struct fuse_req *req)
if (args->in_pages) {
size = args->in_args[args->in_numargs - 1].size;
- total_sgs += sg_count_fuse_pages(ap->descs, ap->num_pages,
- size);
+ total_sgs += sg_count_fuse_pages(ap, size);
}
if (!test_bit(FR_ISREPLY, &req->flags))
@@ -1313,28 +1333,35 @@ static unsigned int sg_count_fuse_req(struct fuse_req *req)
if (args->out_pages) {
size = args->out_args[args->out_numargs - 1].size;
- total_sgs += sg_count_fuse_pages(ap->descs, ap->num_pages,
- size);
+ total_sgs += sg_count_fuse_pages(ap, size);
}
return total_sgs;
}
-/* Add pages to scatter-gather list and return number of elements used */
+/* Add pages/folios to scatter-gather list and return number of elements used */
static unsigned int sg_init_fuse_pages(struct scatterlist *sg,
- struct page **pages,
- struct fuse_page_desc *page_descs,
- unsigned int num_pages,
+ struct fuse_args_pages *ap,
unsigned int total_len)
{
unsigned int i;
unsigned int this_len;
- for (i = 0; i < num_pages && total_len; i++) {
- sg_init_table(&sg[i], 1);
- this_len = min(page_descs[i].length, total_len);
- sg_set_page(&sg[i], pages[i], this_len, page_descs[i].offset);
- total_len -= this_len;
+ if (ap->uses_folios) {
+ for (i = 0; i < ap->num_folios && total_len; i++) {
+ sg_init_table(&sg[i], 1);
+ this_len = min(ap->folio_descs[i].length, total_len);
+ sg_set_folio(&sg[i], ap->folios[i], this_len,
+ ap->folio_descs[i].offset);
+ total_len -= this_len;
+ }
+ } else {
+ for (i = 0; i < ap->num_pages && total_len; i++) {
+ sg_init_table(&sg[i], 1);
+ this_len = min(ap->descs[i].length, total_len);
+ sg_set_page(&sg[i], ap->pages[i], this_len, ap->descs[i].offset);
+ total_len -= this_len;
+ }
}
return i;
@@ -1358,9 +1385,7 @@ static unsigned int sg_init_fuse_args(struct scatterlist *sg,
sg_init_one(&sg[total_sgs++], argbuf, len);
if (argpages)
- total_sgs += sg_init_fuse_pages(&sg[total_sgs],
- ap->pages, ap->descs,
- ap->num_pages,
+ total_sgs += sg_init_fuse_pages(&sg[total_sgs], ap,
args[numargs - 1].size);
if (len_used)