1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * fs/bfs/file.c 4 * BFS file operations. 5 * Copyright (C) 1999-2018 Tigran Aivazian <aivazian.tigran@gmail.com> 6 * 7 * Make the file block allocation algorithm understand the size 8 * of the underlying block device. 9 * Copyright (C) 2007 Dmitri Vorobiev <dmitri.vorobiev@gmail.com> 10 * 11 */ 12 13 #include <linux/fs.h> 14 #include <linux/buffer_head.h> 15 #include "bfs.h" 16 17 #undef DEBUG 18 19 #ifdef DEBUG 20 #define dprintf(x...) printf(x) 21 #else 22 #define dprintf(x...) 23 #endif 24 25 const struct file_operations bfs_file_operations = { 26 .llseek = generic_file_llseek, 27 .read_iter = generic_file_read_iter, 28 .write_iter = generic_file_write_iter, 29 .mmap = generic_file_mmap, 30 .splice_read = filemap_splice_read, 31 }; 32 33 static int bfs_move_block(unsigned long from, unsigned long to, 34 struct super_block *sb) 35 { 36 struct buffer_head *bh, *new; 37 38 bh = sb_bread(sb, from); 39 if (!bh) 40 return -EIO; 41 new = sb_getblk(sb, to); 42 memcpy(new->b_data, bh->b_data, bh->b_size); 43 mark_buffer_dirty(new); 44 bforget(bh); 45 brelse(new); 46 return 0; 47 } 48 49 static int bfs_move_blocks(struct super_block *sb, unsigned long start, 50 unsigned long end, unsigned long where) 51 { 52 unsigned long i; 53 54 dprintf("%08lx-%08lx->%08lx\n", start, end, where); 55 for (i = start; i <= end; i++) 56 if(bfs_move_block(i, where + i, sb)) { 57 dprintf("failed to move block %08lx -> %08lx\n", i, 58 where + i); 59 return -EIO; 60 } 61 return 0; 62 } 63 64 static int bfs_get_block(struct inode *inode, sector_t block, 65 struct buffer_head *bh_result, int create) 66 { 67 unsigned long phys; 68 int err; 69 struct super_block *sb = inode->i_sb; 70 struct bfs_sb_info *info = BFS_SB(sb); 71 struct bfs_inode_info *bi = BFS_I(inode); 72 73 phys = bi->i_sblock + block; 74 if (!create) { 75 if (phys <= bi->i_eblock) { 76 dprintf("c=%d, b=%08lx, phys=%09lx (granted)\n", 77 create, (unsigned long)block, phys); 78 map_bh(bh_result, sb, phys); 79 } 80 return 0; 81 } 82 83 /* 84 * If the file is not empty and the requested block is within the 85 * range of blocks allocated for this file, we can grant it. 86 */ 87 if (bi->i_sblock && (phys <= bi->i_eblock)) { 88 dprintf("c=%d, b=%08lx, phys=%08lx (interim block granted)\n", 89 create, (unsigned long)block, phys); 90 map_bh(bh_result, sb, phys); 91 return 0; 92 } 93 94 /* The file will be extended, so let's see if there is enough space. */ 95 if (phys >= info->si_blocks) 96 return -ENOSPC; 97 98 /* The rest has to be protected against itself. */ 99 mutex_lock(&info->bfs_lock); 100 101 /* 102 * If the last data block for this file is the last allocated 103 * block, we can extend the file trivially, without moving it 104 * anywhere. 105 */ 106 if (bi->i_eblock == info->si_lf_eblk) { 107 dprintf("c=%d, b=%08lx, phys=%08lx (simple extension)\n", 108 create, (unsigned long)block, phys); 109 map_bh(bh_result, sb, phys); 110 info->si_freeb -= phys - bi->i_eblock; 111 info->si_lf_eblk = bi->i_eblock = phys; 112 mark_inode_dirty(inode); 113 err = 0; 114 goto out; 115 } 116 117 /* Ok, we have to move this entire file to the next free block. */ 118 phys = info->si_lf_eblk + 1; 119 if (phys + block >= info->si_blocks) { 120 err = -ENOSPC; 121 goto out; 122 } 123 124 if (bi->i_sblock) { 125 err = bfs_move_blocks(inode->i_sb, bi->i_sblock, 126 bi->i_eblock, phys); 127 if (err) { 128 dprintf("failed to move ino=%08lx -> fs corruption\n", 129 inode->i_ino); 130 goto out; 131 } 132 } else 133 err = 0; 134 135 dprintf("c=%d, b=%08lx, phys=%08lx (moved)\n", 136 create, (unsigned long)block, phys); 137 bi->i_sblock = phys; 138 phys += block; 139 info->si_lf_eblk = bi->i_eblock = phys; 140 141 /* 142 * This assumes nothing can write the inode back while we are here 143 * and thus update inode->i_blocks! (XXX) 144 */ 145 info->si_freeb -= bi->i_eblock - bi->i_sblock + 1 - inode->i_blocks; 146 mark_inode_dirty(inode); 147 map_bh(bh_result, sb, phys); 148 out: 149 mutex_unlock(&info->bfs_lock); 150 return err; 151 } 152 153 static int bfs_writepage(struct page *page, struct writeback_control *wbc) 154 { 155 return block_write_full_page(page, bfs_get_block, wbc); 156 } 157 158 static int bfs_read_folio(struct file *file, struct folio *folio) 159 { 160 return block_read_full_folio(folio, bfs_get_block); 161 } 162 163 static void bfs_write_failed(struct address_space *mapping, loff_t to) 164 { 165 struct inode *inode = mapping->host; 166 167 if (to > inode->i_size) 168 truncate_pagecache(inode, inode->i_size); 169 } 170 171 static int bfs_write_begin(struct file *file, struct address_space *mapping, 172 loff_t pos, unsigned len, 173 struct page **pagep, void **fsdata) 174 { 175 int ret; 176 177 ret = block_write_begin(mapping, pos, len, pagep, bfs_get_block); 178 if (unlikely(ret)) 179 bfs_write_failed(mapping, pos + len); 180 181 return ret; 182 } 183 184 static sector_t bfs_bmap(struct address_space *mapping, sector_t block) 185 { 186 return generic_block_bmap(mapping, block, bfs_get_block); 187 } 188 189 const struct address_space_operations bfs_aops = { 190 .dirty_folio = block_dirty_folio, 191 .invalidate_folio = block_invalidate_folio, 192 .read_folio = bfs_read_folio, 193 .writepage = bfs_writepage, 194 .write_begin = bfs_write_begin, 195 .write_end = generic_write_end, 196 .bmap = bfs_bmap, 197 }; 198 199 const struct inode_operations bfs_file_inops; 200