fileio.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2024, Alibaba Cloud
  4. */
  5. #include "internal.h"
  6. #include <trace/events/erofs.h>
  7. struct erofs_fileio_rq {
  8. struct bio_vec bvecs[16];
  9. struct bio bio;
  10. struct kiocb iocb;
  11. struct super_block *sb;
  12. refcount_t ref;
  13. };
  14. struct erofs_fileio {
  15. struct erofs_map_blocks map;
  16. struct erofs_map_dev dev;
  17. struct erofs_fileio_rq *rq;
  18. };
  19. static void erofs_fileio_ki_complete(struct kiocb *iocb, long ret)
  20. {
  21. struct erofs_fileio_rq *rq =
  22. container_of(iocb, struct erofs_fileio_rq, iocb);
  23. struct folio_iter fi;
  24. if (ret >= 0 && ret != rq->bio.bi_iter.bi_size)
  25. ret = -EIO;
  26. if (!rq->bio.bi_end_io) {
  27. bio_for_each_folio_all(fi, &rq->bio) {
  28. DBG_BUGON(folio_test_uptodate(fi.folio));
  29. erofs_onlinefolio_end(fi.folio, ret < 0, false);
  30. }
  31. } else if (ret < 0 && !rq->bio.bi_status) {
  32. rq->bio.bi_status = errno_to_blk_status(ret);
  33. }
  34. bio_endio(&rq->bio);
  35. bio_uninit(&rq->bio);
  36. if (refcount_dec_and_test(&rq->ref))
  37. kfree(rq);
  38. }
  39. static void erofs_fileio_rq_submit(struct erofs_fileio_rq *rq)
  40. {
  41. struct iov_iter iter;
  42. ssize_t ret;
  43. if (!rq)
  44. return;
  45. rq->iocb.ki_pos = rq->bio.bi_iter.bi_sector << SECTOR_SHIFT;
  46. rq->iocb.ki_ioprio = get_current_ioprio();
  47. rq->iocb.ki_complete = erofs_fileio_ki_complete;
  48. if (test_opt(&EROFS_SB(rq->sb)->opt, DIRECT_IO) &&
  49. rq->iocb.ki_filp->f_mode & FMODE_CAN_ODIRECT)
  50. rq->iocb.ki_flags = IOCB_DIRECT;
  51. iov_iter_bvec(&iter, ITER_DEST, rq->bvecs, rq->bio.bi_vcnt,
  52. rq->bio.bi_iter.bi_size);
  53. scoped_with_creds(rq->iocb.ki_filp->f_cred)
  54. ret = vfs_iocb_iter_read(rq->iocb.ki_filp, &rq->iocb, &iter);
  55. if (ret != -EIOCBQUEUED)
  56. erofs_fileio_ki_complete(&rq->iocb, ret);
  57. if (refcount_dec_and_test(&rq->ref))
  58. kfree(rq);
  59. }
  60. static struct erofs_fileio_rq *erofs_fileio_rq_alloc(struct erofs_map_dev *mdev)
  61. {
  62. struct erofs_fileio_rq *rq = kzalloc_obj(*rq, GFP_KERNEL | __GFP_NOFAIL);
  63. bio_init(&rq->bio, NULL, rq->bvecs, ARRAY_SIZE(rq->bvecs), REQ_OP_READ);
  64. rq->iocb.ki_filp = mdev->m_dif->file;
  65. rq->sb = mdev->m_sb;
  66. refcount_set(&rq->ref, 2);
  67. return rq;
  68. }
  69. struct bio *erofs_fileio_bio_alloc(struct erofs_map_dev *mdev)
  70. {
  71. return &erofs_fileio_rq_alloc(mdev)->bio;
  72. }
  73. void erofs_fileio_submit_bio(struct bio *bio)
  74. {
  75. return erofs_fileio_rq_submit(container_of(bio, struct erofs_fileio_rq,
  76. bio));
  77. }
  78. static int erofs_fileio_scan_folio(struct erofs_fileio *io,
  79. struct inode *inode, struct folio *folio)
  80. {
  81. struct erofs_map_blocks *map = &io->map;
  82. unsigned int cur = 0, end = folio_size(folio), len, attached = 0;
  83. loff_t pos = folio_pos(folio), ofs;
  84. int err = 0;
  85. erofs_onlinefolio_init(folio);
  86. while (cur < end) {
  87. if (!in_range(pos + cur, map->m_la, map->m_llen)) {
  88. map->m_la = pos + cur;
  89. map->m_llen = end - cur;
  90. err = erofs_map_blocks(inode, map);
  91. if (err)
  92. break;
  93. }
  94. ofs = folio_pos(folio) + cur - map->m_la;
  95. len = min_t(loff_t, map->m_llen - ofs, end - cur);
  96. if (map->m_flags & EROFS_MAP_META) {
  97. struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
  98. void *src;
  99. src = erofs_read_metabuf(&buf, inode->i_sb,
  100. map->m_pa + ofs, erofs_inode_in_metabox(inode));
  101. if (IS_ERR(src)) {
  102. err = PTR_ERR(src);
  103. break;
  104. }
  105. memcpy_to_folio(folio, cur, src, len);
  106. erofs_put_metabuf(&buf);
  107. } else if (!(map->m_flags & EROFS_MAP_MAPPED)) {
  108. folio_zero_segment(folio, cur, cur + len);
  109. attached = 0;
  110. } else {
  111. if (io->rq && (map->m_pa + ofs != io->dev.m_pa ||
  112. map->m_deviceid != io->dev.m_deviceid)) {
  113. io_retry:
  114. erofs_fileio_rq_submit(io->rq);
  115. io->rq = NULL;
  116. }
  117. if (!io->rq) {
  118. io->dev = (struct erofs_map_dev) {
  119. .m_pa = io->map.m_pa + ofs,
  120. .m_deviceid = io->map.m_deviceid,
  121. };
  122. err = erofs_map_dev(inode->i_sb, &io->dev);
  123. if (err)
  124. break;
  125. io->rq = erofs_fileio_rq_alloc(&io->dev);
  126. io->rq->bio.bi_iter.bi_sector =
  127. (io->dev.m_dif->fsoff + io->dev.m_pa) >> 9;
  128. attached = 0;
  129. }
  130. if (!bio_add_folio(&io->rq->bio, folio, len, cur))
  131. goto io_retry;
  132. if (!attached++)
  133. erofs_onlinefolio_split(folio);
  134. io->dev.m_pa += len;
  135. }
  136. cur += len;
  137. }
  138. erofs_onlinefolio_end(folio, err, false);
  139. return err;
  140. }
  141. static int erofs_fileio_read_folio(struct file *file, struct folio *folio)
  142. {
  143. bool need_iput;
  144. struct inode *realinode = erofs_real_inode(folio_inode(folio), &need_iput);
  145. struct erofs_fileio io = {};
  146. int err;
  147. trace_erofs_read_folio(realinode, folio, true);
  148. err = erofs_fileio_scan_folio(&io, realinode, folio);
  149. erofs_fileio_rq_submit(io.rq);
  150. if (need_iput)
  151. iput(realinode);
  152. return err;
  153. }
  154. static void erofs_fileio_readahead(struct readahead_control *rac)
  155. {
  156. bool need_iput;
  157. struct inode *realinode = erofs_real_inode(rac->mapping->host, &need_iput);
  158. struct erofs_fileio io = {};
  159. struct folio *folio;
  160. int err;
  161. trace_erofs_readahead(realinode, readahead_index(rac),
  162. readahead_count(rac), true);
  163. while ((folio = readahead_folio(rac))) {
  164. err = erofs_fileio_scan_folio(&io, realinode, folio);
  165. if (err && err != -EINTR)
  166. erofs_err(realinode->i_sb, "readahead error at folio %lu @ nid %llu",
  167. folio->index, EROFS_I(realinode)->nid);
  168. }
  169. erofs_fileio_rq_submit(io.rq);
  170. if (need_iput)
  171. iput(realinode);
  172. }
  173. const struct address_space_operations erofs_fileio_aops = {
  174. .read_folio = erofs_fileio_read_folio,
  175. .readahead = erofs_fileio_readahead,
  176. };