1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * NTFS block device I/O. 4 * 5 * Copyright (c) 2026 LG Electronics Co., Ltd. 6 */ 7 8 #include <linux/blkdev.h> 9 10 #include "ntfs.h" 11 12 /* 13 * ntfs_bdev_read - Read data directly from block device using bio 14 * @bdev: block device to read from 15 * @data: destination buffer 16 * @start: starting byte offset on the block device 17 * @size: number of bytes to read 18 * 19 * Reads @size bytes starting from byte offset @start directly from the block 20 * device using one or more BIOs. This function bypasses the page cache 21 * completely and performs synchronous I/O with REQ_META | REQ_SYNC flags set. 22 * 23 * The @start offset must be sector-aligned (512 bytes). If it is not aligned, 24 * the function will return -EINVAL. 25 * 26 * If the destination buffer @data is not a vmalloc address, it falls back 27 * to the more efficient bdev_rw_virt() helper. 28 * 29 * Return: 0 on success, negative error code on failure. 30 */ 31 int ntfs_bdev_read(struct block_device *bdev, char *data, loff_t start, size_t size) 32 { 33 unsigned int done = 0, added; 34 int error; 35 struct bio *bio; 36 enum req_op op; 37 sector_t sector = start >> SECTOR_SHIFT; 38 39 if (start & (SECTOR_SIZE - 1)) 40 return -EINVAL; 41 42 op = REQ_OP_READ | REQ_META | REQ_SYNC; 43 if (!is_vmalloc_addr(data)) 44 return bdev_rw_virt(bdev, sector, data, size, op); 45 46 bio = bio_alloc(bdev, 47 bio_max_segs(DIV_ROUND_UP(size, PAGE_SIZE)), 48 op, GFP_KERNEL); 49 bio->bi_iter.bi_sector = sector; 50 51 do { 52 added = bio_add_vmalloc_chunk(bio, data + done, size - done); 53 if (!added) { 54 struct bio *prev = bio; 55 56 bio = bio_alloc(prev->bi_bdev, 57 bio_max_segs(DIV_ROUND_UP(size - done, PAGE_SIZE)), 58 prev->bi_opf, GFP_KERNEL); 59 bio->bi_iter.bi_sector = bio_end_sector(prev); 60 bio_chain(prev, bio); 61 submit_bio(prev); 62 } 63 done += added; 64 } while (done < size); 65 66 error = submit_bio_wait(bio); 67 bio_put(bio); 68 69 if (op == REQ_OP_READ) 70 invalidate_kernel_vmap_range(data, size); 71 return error; 72 } 73 74 /* 75 * ntfs_bdev_write - Update block device contents via page cache 76 * @sb: super block of the mounted NTFS filesystem 77 * @buf: source buffer containing data to write 78 * @start: starting byte offset on the block device 79 * @size: number of bytes to write 80 * 81 * Writes @size bytes from @buf to the block device (sb->s_bdev) starting 82 * at byte offset @start. The write is performed entirely through the page 83 * cache of the block device's address space. 84 */ 85 int ntfs_bdev_write(struct super_block *sb, void *buf, loff_t start, size_t size) 86 { 87 pgoff_t idx, idx_end; 88 loff_t offset, end = start + size; 89 u32 from, to, buf_off = 0; 90 struct folio *folio; 91 92 idx = start >> PAGE_SHIFT; 93 idx_end = end >> PAGE_SHIFT; 94 from = start & ~PAGE_MASK; 95 96 if (idx == idx_end) 97 idx_end++; 98 99 for (; idx < idx_end; idx++, from = 0) { 100 folio = read_mapping_folio(sb->s_bdev->bd_mapping, idx, NULL); 101 if (IS_ERR(folio)) { 102 ntfs_error(sb, "Unable to read %ld page", idx); 103 return PTR_ERR(folio); 104 } 105 106 offset = (loff_t)idx << PAGE_SHIFT; 107 to = min_t(u32, end - offset, PAGE_SIZE); 108 109 memcpy_to_folio(folio, from, buf + buf_off, to); 110 buf_off += to; 111 folio_mark_uptodate(folio); 112 folio_mark_dirty(folio); 113 folio_put(folio); 114 } 115 116 return 0; 117 } 118