xfs_bio_io.c 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2019 Christoph Hellwig.
  4. */
  5. #include "xfs.h"
  6. static inline unsigned int bio_max_vecs(unsigned int count)
  7. {
  8. return min_t(unsigned, howmany(count, PAGE_SIZE), BIO_MAX_PAGES);
  9. }
  10. int
  11. xfs_rw_bdev(
  12. struct block_device *bdev,
  13. sector_t sector,
  14. unsigned int count,
  15. char *data,
  16. unsigned int op)
  17. {
  18. unsigned int is_vmalloc = is_vmalloc_addr(data);
  19. unsigned int left = count;
  20. int error;
  21. struct bio *bio;
  22. if (is_vmalloc && op == REQ_OP_WRITE)
  23. flush_kernel_vmap_range(data, count);
  24. bio = bio_alloc(GFP_KERNEL, bio_max_vecs(left));
  25. bio_set_dev(bio, bdev);
  26. bio->bi_iter.bi_sector = sector;
  27. bio->bi_opf = op | REQ_META | REQ_SYNC;
  28. do {
  29. struct page *page = kmem_to_page(data);
  30. unsigned int off = offset_in_page(data);
  31. unsigned int len = min_t(unsigned, left, PAGE_SIZE - off);
  32. while (bio_add_page(bio, page, len, off) != len) {
  33. struct bio *prev = bio;
  34. bio = bio_alloc(GFP_KERNEL, bio_max_vecs(left));
  35. bio_copy_dev(bio, prev);
  36. bio->bi_iter.bi_sector = bio_end_sector(prev);
  37. bio->bi_opf = prev->bi_opf;
  38. bio_chain(prev, bio);
  39. submit_bio(prev);
  40. }
  41. data += len;
  42. left -= len;
  43. } while (left > 0);
  44. error = submit_bio_wait(bio);
  45. bio_put(bio);
  46. if (is_vmalloc && op == REQ_OP_READ)
  47. invalidate_kernel_vmap_range(data, count);
  48. return error;
  49. }