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