aboutsummaryrefslogtreecommitdiffstats
path: root/fs/logfs/dev_bdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/logfs/dev_bdev.c')
-rw-r--r--fs/logfs/dev_bdev.c88
1 files changed, 76 insertions, 12 deletions
diff --git a/fs/logfs/dev_bdev.c b/fs/logfs/dev_bdev.c
index 58a057b6e1af..9718c22f186d 100644
--- a/fs/logfs/dev_bdev.c
+++ b/fs/logfs/dev_bdev.c
@@ -167,27 +167,91 @@ static void bdev_writeseg(struct super_block *sb, u64 ofs, size_t len)
167 generic_unplug_device(bdev_get_queue(logfs_super(sb)->s_bdev)); 167 generic_unplug_device(bdev_get_queue(logfs_super(sb)->s_bdev));
168} 168}
169 169
170static int bdev_erase(struct super_block *sb, loff_t to, size_t len) 170
171static void erase_end_io(struct bio *bio, int err)
172{
173 const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
174 struct super_block *sb = bio->bi_private;
175 struct logfs_super *super = logfs_super(sb);
176
177 BUG_ON(!uptodate); /* FIXME: Retry io or write elsewhere */
178 BUG_ON(err);
179 BUG_ON(bio->bi_vcnt == 0);
180 bio_put(bio);
181 if (atomic_dec_and_test(&super->s_pending_writes))
182 wake_up(&wq);
183}
184
185static int do_erase(struct super_block *sb, u64 ofs, pgoff_t index,
186 size_t nr_pages)
187{
188 struct logfs_super *super = logfs_super(sb);
189 struct bio *bio;
190 struct request_queue *q = bdev_get_queue(sb->s_bdev);
191 unsigned int max_pages = queue_max_hw_sectors(q) >> (PAGE_SHIFT - 9);
192 int i;
193
194 bio = bio_alloc(GFP_NOFS, max_pages);
195 BUG_ON(!bio); /* FIXME: handle this */
196
197 for (i = 0; i < nr_pages; i++) {
198 if (i >= max_pages) {
199 /* Block layer cannot split bios :( */
200 bio->bi_vcnt = i;
201 bio->bi_idx = 0;
202 bio->bi_size = i * PAGE_SIZE;
203 bio->bi_bdev = super->s_bdev;
204 bio->bi_sector = ofs >> 9;
205 bio->bi_private = sb;
206 bio->bi_end_io = erase_end_io;
207 atomic_inc(&super->s_pending_writes);
208 submit_bio(WRITE, bio);
209
210 ofs += i * PAGE_SIZE;
211 index += i;
212 nr_pages -= i;
213 i = 0;
214
215 bio = bio_alloc(GFP_NOFS, max_pages);
216 BUG_ON(!bio);
217 }
218 bio->bi_io_vec[i].bv_page = super->s_erase_page;
219 bio->bi_io_vec[i].bv_len = PAGE_SIZE;
220 bio->bi_io_vec[i].bv_offset = 0;
221 }
222 bio->bi_vcnt = nr_pages;
223 bio->bi_idx = 0;
224 bio->bi_size = nr_pages * PAGE_SIZE;
225 bio->bi_bdev = super->s_bdev;
226 bio->bi_sector = ofs >> 9;
227 bio->bi_private = sb;
228 bio->bi_end_io = erase_end_io;
229 atomic_inc(&super->s_pending_writes);
230 submit_bio(WRITE, bio);
231 return 0;
232}
233
234static int bdev_erase(struct super_block *sb, loff_t to, size_t len,
235 int ensure_write)
171{ 236{
172 struct logfs_super *super = logfs_super(sb); 237 struct logfs_super *super = logfs_super(sb);
173 struct address_space *mapping = super->s_mapping_inode->i_mapping;
174 struct page *page;
175 pgoff_t index = to >> PAGE_SHIFT;
176 int i, nr_pages = len >> PAGE_SHIFT;
177 238
178 BUG_ON(to & (PAGE_SIZE - 1)); 239 BUG_ON(to & (PAGE_SIZE - 1));
179 BUG_ON(len & (PAGE_SIZE - 1)); 240 BUG_ON(len & (PAGE_SIZE - 1));
180 241
181 if (logfs_super(sb)->s_flags & LOGFS_SB_FLAG_RO) 242 if (super->s_flags & LOGFS_SB_FLAG_RO)
182 return -EROFS; 243 return -EROFS;
183 244
184 for (i = 0; i < nr_pages; i++) { 245 if (ensure_write) {
185 page = find_get_page(mapping, index + i); 246 /*
186 if (page) { 247 * Object store doesn't care whether erases happen or not.
187 memset(page_address(page), 0xFF, PAGE_SIZE); 248 * But for the journal they are required. Otherwise a scan
188 page_cache_release(page); 249 * can find an old commit entry and assume it is the current
189 } 250 * one, travelling back in time.
251 */
252 do_erase(sb, to, to >> PAGE_SHIFT, len >> PAGE_SHIFT);
190 } 253 }
254
191 return 0; 255 return 0;
192} 256}
193 257