Blame view
fs/f2fs/data.c
79.3 KB
7c1a000d4 f2fs: add SPDX li... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
0a8165d7c f2fs: adjust kern... |
2 |
/* |
eb47b8009 f2fs: add address... |
3 4 5 6 |
* fs/f2fs/data.c * * Copyright (c) 2012 Samsung Electronics Co., Ltd. * http://www.samsung.com/ |
eb47b8009 f2fs: add address... |
7 8 9 10 11 12 13 |
*/ #include <linux/fs.h> #include <linux/f2fs_fs.h> #include <linux/buffer_head.h> #include <linux/mpage.h> #include <linux/writeback.h> #include <linux/backing-dev.h> |
8f46dcaea f2fs: expose f2fs... |
14 |
#include <linux/pagevec.h> |
eb47b8009 f2fs: add address... |
15 16 |
#include <linux/blkdev.h> #include <linux/bio.h> |
4969c06a0 f2fs: support swa... |
17 |
#include <linux/swap.h> |
690e4a3ea f2fs: add missing... |
18 |
#include <linux/prefetch.h> |
e2e40f2c1 fs: move struct k... |
19 |
#include <linux/uio.h> |
f1e886601 f2fs: expose f2fs... |
20 |
#include <linux/cleancache.h> |
174cd4b1e sched/headers: Pr... |
21 |
#include <linux/sched/signal.h> |
eb47b8009 f2fs: add address... |
22 23 24 25 |
#include "f2fs.h" #include "node.h" #include "segment.h" |
db9f7c1a9 f2fs: activate f2... |
26 |
#include "trace.h" |
848753aa3 f2fs: add tracepo... |
27 |
#include <trace/events/f2fs.h> |
eb47b8009 f2fs: add address... |
28 |
|
6dbb17961 f2fs: refactor re... |
29 30 31 |
#define NUM_PREALLOC_POST_READ_CTXS 128 static struct kmem_cache *bio_post_read_ctx_cache; |
0b20fcec8 f2fs: cache globa... |
32 |
static struct kmem_cache *bio_entry_slab; |
6dbb17961 f2fs: refactor re... |
33 |
static mempool_t *bio_post_read_ctx_pool; |
36951b38d f2fs: don't wait ... |
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
static bool __is_cp_guaranteed(struct page *page) { struct address_space *mapping = page->mapping; struct inode *inode; struct f2fs_sb_info *sbi; if (!mapping) return false; inode = mapping->host; sbi = F2FS_I_SB(inode); if (inode->i_ino == F2FS_META_INO(sbi) || inode->i_ino == F2FS_NODE_INO(sbi) || S_ISDIR(inode->i_mode) || |
e7a4feb0a f2fs: fix to let ... |
49 |
(S_ISREG(inode->i_mode) && |
af033b2aa f2fs: guarantee j... |
50 |
(f2fs_is_atomic_file(inode) || IS_NOQUOTA(inode))) || |
36951b38d f2fs: don't wait ... |
51 52 53 54 |
is_cold_data(page)) return true; return false; } |
5f9abab42 f2fs: account rea... |
55 56 |
static enum count_type __read_io_type(struct page *page) { |
4969c06a0 f2fs: support swa... |
57 |
struct address_space *mapping = page_file_mapping(page); |
5f9abab42 f2fs: account rea... |
58 59 60 61 62 63 64 65 66 67 68 69 70 |
if (mapping) { struct inode *inode = mapping->host; struct f2fs_sb_info *sbi = F2FS_I_SB(inode); if (inode->i_ino == F2FS_META_INO(sbi)) return F2FS_RD_META; if (inode->i_ino == F2FS_NODE_INO(sbi)) return F2FS_RD_NODE; } return F2FS_RD_DATA; } |
6dbb17961 f2fs: refactor re... |
71 72 73 74 |
/* postprocessing steps for read bios */ enum bio_post_read_step { STEP_INITIAL = 0, STEP_DECRYPT, |
95ae251fe f2fs: add fs-veri... |
75 |
STEP_VERITY, |
6dbb17961 f2fs: refactor re... |
76 77 78 79 80 81 82 83 84 85 |
}; struct bio_post_read_ctx { struct bio *bio; struct work_struct work; unsigned int cur_step; unsigned int enabled_steps; }; static void __read_end_io(struct bio *bio) |
93dfe2ac5 f2fs: refactor bi... |
86 |
{ |
6dbb17961 f2fs: refactor re... |
87 88 |
struct page *page; struct bio_vec *bv; |
6dc4f100c block: allow bio_... |
89 |
struct bvec_iter_all iter_all; |
93dfe2ac5 f2fs: refactor bi... |
90 |
|
2b070cfe5 block: remove the... |
91 |
bio_for_each_segment_all(bv, bio, iter_all) { |
6dbb17961 f2fs: refactor re... |
92 93 94 95 96 |
page = bv->bv_page; /* PG_error was set if any post_read step failed */ if (bio->bi_status || PageError(page)) { ClearPageUptodate(page); |
fb7d70db3 f2fs: clear PageE... |
97 98 |
/* will re-read again later */ ClearPageError(page); |
6dbb17961 f2fs: refactor re... |
99 100 101 |
} else { SetPageUptodate(page); } |
5f9abab42 f2fs: account rea... |
102 |
dec_page_count(F2FS_P_SB(page), __read_io_type(page)); |
6dbb17961 f2fs: refactor re... |
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
unlock_page(page); } if (bio->bi_private) mempool_free(bio->bi_private, bio_post_read_ctx_pool); bio_put(bio); } static void bio_post_read_processing(struct bio_post_read_ctx *ctx); static void decrypt_work(struct work_struct *work) { struct bio_post_read_ctx *ctx = container_of(work, struct bio_post_read_ctx, work); fscrypt_decrypt_bio(ctx->bio); bio_post_read_processing(ctx); } |
95ae251fe f2fs: add fs-veri... |
121 122 123 124 125 126 127 128 129 |
static void verity_work(struct work_struct *work) { struct bio_post_read_ctx *ctx = container_of(work, struct bio_post_read_ctx, work); fsverity_verify_bio(ctx->bio); bio_post_read_processing(ctx); } |
6dbb17961 f2fs: refactor re... |
130 131 |
static void bio_post_read_processing(struct bio_post_read_ctx *ctx) { |
95ae251fe f2fs: add fs-veri... |
132 133 134 135 136 |
/* * We use different work queues for decryption and for verity because * verity may require reading metadata pages that need decryption, and * we shouldn't recurse to the same workqueue. */ |
6dbb17961 f2fs: refactor re... |
137 138 139 140 141 142 143 144 145 |
switch (++ctx->cur_step) { case STEP_DECRYPT: if (ctx->enabled_steps & (1 << STEP_DECRYPT)) { INIT_WORK(&ctx->work, decrypt_work); fscrypt_enqueue_decrypt_work(&ctx->work); return; } ctx->cur_step++; /* fall-through */ |
95ae251fe f2fs: add fs-veri... |
146 147 148 149 150 151 152 153 |
case STEP_VERITY: if (ctx->enabled_steps & (1 << STEP_VERITY)) { INIT_WORK(&ctx->work, verity_work); fsverity_enqueue_verify_work(&ctx->work); return; } ctx->cur_step++; /* fall-through */ |
6dbb17961 f2fs: refactor re... |
154 155 156 157 158 159 160 161 162 163 164 165 |
default: __read_end_io(ctx->bio); } } static bool f2fs_bio_post_read_required(struct bio *bio) { return bio->bi_private && !bio->bi_status; } static void f2fs_read_end_io(struct bio *bio) { |
c45d6002f f2fs: show f2fs i... |
166 167 168 169 |
struct f2fs_sb_info *sbi = F2FS_P_SB(bio_first_page_all(bio)); if (time_to_inject(sbi, FAULT_READ_IO)) { f2fs_show_injection_info(sbi, FAULT_READ_IO); |
4e4cbee93 block: switch bio... |
170 |
bio->bi_status = BLK_STS_IOERR; |
55523519b f2fs: show simple... |
171 |
} |
8b038c70d f2fs: support IO ... |
172 |
|
6dbb17961 f2fs: refactor re... |
173 174 |
if (f2fs_bio_post_read_required(bio)) { struct bio_post_read_ctx *ctx = bio->bi_private; |
f1e886601 f2fs: expose f2fs... |
175 |
|
6dbb17961 f2fs: refactor re... |
176 177 178 |
ctx->cur_step = STEP_INITIAL; bio_post_read_processing(ctx); return; |
f1e886601 f2fs: expose f2fs... |
179 |
} |
6dbb17961 f2fs: refactor re... |
180 181 |
__read_end_io(bio); |
f1e886601 f2fs: expose f2fs... |
182 |
} |
4246a0b63 block: add a bi_e... |
183 |
static void f2fs_write_end_io(struct bio *bio) |
93dfe2ac5 f2fs: refactor bi... |
184 |
{ |
1b1f559fc f2fs: remove the ... |
185 |
struct f2fs_sb_info *sbi = bio->bi_private; |
f568849ed Merge branch 'for... |
186 |
struct bio_vec *bvec; |
6dc4f100c block: allow bio_... |
187 |
struct bvec_iter_all iter_all; |
93dfe2ac5 f2fs: refactor bi... |
188 |
|
6f5c2ed0a f2fs: split IO er... |
189 |
if (time_to_inject(sbi, FAULT_WRITE_IO)) { |
c45d6002f f2fs: show f2fs i... |
190 |
f2fs_show_injection_info(sbi, FAULT_WRITE_IO); |
6f5c2ed0a f2fs: split IO er... |
191 192 |
bio->bi_status = BLK_STS_IOERR; } |
2b070cfe5 block: remove the... |
193 |
bio_for_each_segment_all(bvec, bio, iter_all) { |
93dfe2ac5 f2fs: refactor bi... |
194 |
struct page *page = bvec->bv_page; |
36951b38d f2fs: don't wait ... |
195 |
enum count_type type = WB_DATA_TYPE(page); |
93dfe2ac5 f2fs: refactor bi... |
196 |
|
0a595ebaa f2fs: support IO ... |
197 198 199 200 201 |
if (IS_DUMMY_WRITTEN_PAGE(page)) { set_page_private(page, (unsigned long)NULL); ClearPagePrivate(page); unlock_page(page); mempool_free(page, sbi->write_io_dummy); |
4e4cbee93 block: switch bio... |
202 |
if (unlikely(bio->bi_status)) |
0a595ebaa f2fs: support IO ... |
203 204 205 |
f2fs_stop_checkpoint(sbi, true); continue; } |
d2d0727b1 fscrypt: simplify... |
206 |
fscrypt_finalize_bounce_page(&page); |
4375a3366 f2fs crypto: add ... |
207 |
|
4e4cbee93 block: switch bio... |
208 |
if (unlikely(bio->bi_status)) { |
5114a97a8 fs: use mapping_s... |
209 |
mapping_set_error(page->mapping, -EIO); |
b1ca321d1 f2fs: skip stop_c... |
210 211 |
if (type == F2FS_WB_CP_DATA) f2fs_stop_checkpoint(sbi, true); |
93dfe2ac5 f2fs: refactor bi... |
212 |
} |
7dff55d27 f2fs: check node ... |
213 214 215 |
f2fs_bug_on(sbi, page->mapping == NODE_MAPPING(sbi) && page->index != nid_of_node(page)); |
36951b38d f2fs: don't wait ... |
216 |
dec_page_count(sbi, type); |
50fa53ecc f2fs: fix to avoi... |
217 218 |
if (f2fs_in_warm_node_list(sbi, page)) f2fs_del_fsync_node_entry(sbi, page); |
36951b38d f2fs: don't wait ... |
219 |
clear_cold_data(page); |
93dfe2ac5 f2fs: refactor bi... |
220 |
end_page_writeback(page); |
f568849ed Merge branch 'for... |
221 |
} |
36951b38d f2fs: don't wait ... |
222 |
if (!get_pages(sbi, F2FS_WB_CP_DATA) && |
f57301849 f2fs: use bio cou... |
223 |
wq_has_sleeper(&sbi->cp_wait)) |
93dfe2ac5 f2fs: refactor bi... |
224 225 226 227 |
wake_up(&sbi->cp_wait); bio_put(bio); } |
940a6d34b f2fs: move all th... |
228 |
/* |
3c62be17d f2fs: support mul... |
229 230 231 232 233 234 235 |
* Return true, if pre_bio's bdev is same as its target device. */ struct block_device *f2fs_target_device(struct f2fs_sb_info *sbi, block_t blk_addr, struct bio *bio) { struct block_device *bdev = sbi->sb->s_bdev; int i; |
0916878da f2fs: Fix use of ... |
236 237 238 239 240 241 242 243 |
if (f2fs_is_multi_device(sbi)) { for (i = 0; i < sbi->s_ndevs; i++) { if (FDEV(i).start_blk <= blk_addr && FDEV(i).end_blk >= blk_addr) { blk_addr -= FDEV(i).start_blk; bdev = FDEV(i).bdev; break; } |
3c62be17d f2fs: support mul... |
244 245 246 |
} } if (bio) { |
74d46992e block: replace bi... |
247 |
bio_set_dev(bio, bdev); |
3c62be17d f2fs: support mul... |
248 249 250 251 252 253 254 255 |
bio->bi_iter.bi_sector = SECTOR_FROM_BLOCK(blk_addr); } return bdev; } int f2fs_target_device_index(struct f2fs_sb_info *sbi, block_t blkaddr) { int i; |
0916878da f2fs: Fix use of ... |
256 257 |
if (!f2fs_is_multi_device(sbi)) return 0; |
3c62be17d f2fs: support mul... |
258 259 260 261 262 263 264 265 266 |
for (i = 0; i < sbi->s_ndevs; i++) if (FDEV(i).start_blk <= blkaddr && FDEV(i).end_blk >= blkaddr) return i; return 0; } static bool __same_bdev(struct f2fs_sb_info *sbi, block_t blk_addr, struct bio *bio) { |
74d46992e block: replace bi... |
267 268 |
struct block_device *b = f2fs_target_device(sbi, blk_addr, NULL); return bio->bi_disk == b->bd_disk && bio->bi_partno == b->bd_partno; |
3c62be17d f2fs: support mul... |
269 270 271 |
} /* |
940a6d34b f2fs: move all th... |
272 273 |
* Low-level block read/write IO operations. */ |
b757f6edb f2fs: clean up __... |
274 |
static struct bio *__bio_alloc(struct f2fs_io_info *fio, int npages) |
940a6d34b f2fs: move all th... |
275 |
{ |
b757f6edb f2fs: clean up __... |
276 |
struct f2fs_sb_info *sbi = fio->sbi; |
940a6d34b f2fs: move all th... |
277 |
struct bio *bio; |
d62fe9714 f2fs: support bio... |
278 |
bio = f2fs_bio_alloc(sbi, npages, true); |
940a6d34b f2fs: move all th... |
279 |
|
b757f6edb f2fs: clean up __... |
280 281 |
f2fs_target_device(sbi, fio->new_blkaddr, bio); if (is_read_io(fio->op)) { |
0cdd31953 f2fs: support pas... |
282 283 284 285 286 |
bio->bi_end_io = f2fs_read_end_io; bio->bi_private = NULL; } else { bio->bi_end_io = f2fs_write_end_io; bio->bi_private = sbi; |
b757f6edb f2fs: clean up __... |
287 288 |
bio->bi_write_hint = f2fs_io_type_to_rw_hint(sbi, fio->type, fio->temp); |
0cdd31953 f2fs: support pas... |
289 |
} |
b757f6edb f2fs: clean up __... |
290 291 |
if (fio->io_wbc) wbc_init_bio(fio->io_wbc, bio); |
940a6d34b f2fs: move all th... |
292 293 294 |
return bio; } |
4fc29c1aa Merge tag 'for-f2... |
295 296 |
static inline void __submit_bio(struct f2fs_sb_info *sbi, struct bio *bio, enum page_type type) |
f57301849 f2fs: use bio cou... |
297 |
{ |
4fc29c1aa Merge tag 'for-f2... |
298 |
if (!is_read_io(bio_op(bio))) { |
0a595ebaa f2fs: support IO ... |
299 |
unsigned int start; |
0a595ebaa f2fs: support IO ... |
300 301 |
if (type != DATA && type != NODE) goto submit_io; |
66415cee3 f2fs: blk_finish_... |
302 |
if (test_opt(sbi, LFS) && current->plug) |
3bb09a0e7 f2fs: remove redu... |
303 |
blk_finish_plug(current->plug); |
8223ecc45 f2fs: fix to add ... |
304 305 |
if (F2FS_IO_ALIGNED(sbi)) goto submit_io; |
0a595ebaa f2fs: support IO ... |
306 307 308 309 310 311 312 313 314 315 |
start = bio->bi_iter.bi_size >> F2FS_BLKSIZE_BITS; start %= F2FS_IO_SIZE(sbi); if (start == 0) goto submit_io; /* fill dummy pages */ for (; start < F2FS_IO_SIZE(sbi); start++) { struct page *page = mempool_alloc(sbi->write_io_dummy, |
bc73a4b24 f2fs: silence VM_... |
316 |
GFP_NOIO | __GFP_NOFAIL); |
0a595ebaa f2fs: support IO ... |
317 |
f2fs_bug_on(sbi, !page); |
bc73a4b24 f2fs: silence VM_... |
318 |
zero_user_segment(page, 0, PAGE_SIZE); |
0a595ebaa f2fs: support IO ... |
319 320 321 322 323 324 325 326 327 328 329 330 |
SetPagePrivate(page); set_page_private(page, (unsigned long)DUMMY_WRITTEN_PAGE); lock_page(page); if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) f2fs_bug_on(sbi, 1); } /* * In the NODE case, we lose next block address chain. So, we * need to do checkpoint in f2fs_sync_file. */ if (type == NODE) set_sbi_flag(sbi, SBI_NEED_CP); |
19a5f5e2e f2fs: drop any bl... |
331 |
} |
0a595ebaa f2fs: support IO ... |
332 |
submit_io: |
554b5125f f2fs: add submit_... |
333 334 335 336 |
if (is_read_io(bio_op(bio))) trace_f2fs_submit_read_bio(sbi->sb, type, bio); else trace_f2fs_submit_write_bio(sbi->sb, type, bio); |
4e49ea4a3 block/fs/drivers:... |
337 |
submit_bio(bio); |
f57301849 f2fs: use bio cou... |
338 |
} |
458e6197c f2fs: refactor bi... |
339 |
static void __submit_merged_bio(struct f2fs_bio_info *io) |
93dfe2ac5 f2fs: refactor bi... |
340 |
{ |
458e6197c f2fs: refactor bi... |
341 |
struct f2fs_io_info *fio = &io->fio; |
93dfe2ac5 f2fs: refactor bi... |
342 343 344 |
if (!io->bio) return; |
554b5125f f2fs: add submit_... |
345 |
bio_set_op_attrs(io->bio, fio->op, fio->op_flags); |
04d328def f2fs: use bio op ... |
346 |
if (is_read_io(fio->op)) |
554b5125f f2fs: add submit_... |
347 |
trace_f2fs_prepare_read_bio(io->sbi->sb, fio->type, io->bio); |
6a8f8ca58 f2fs: avoid race ... |
348 |
else |
554b5125f f2fs: add submit_... |
349 |
trace_f2fs_prepare_write_bio(io->sbi->sb, fio->type, io->bio); |
04d328def f2fs: use bio op ... |
350 |
|
4fc29c1aa Merge tag 'for-f2... |
351 |
__submit_bio(io->sbi, io->bio, fio->type); |
93dfe2ac5 f2fs: refactor bi... |
352 353 |
io->bio = NULL; } |
8648de2c5 f2fs: add bio cac... |
354 |
static bool __has_merged_page(struct bio *bio, struct inode *inode, |
bab475c54 Revert: "f2fs: ch... |
355 |
struct page *page, nid_t ino) |
0fd785eb9 f2fs: relocate is... |
356 |
{ |
0fd785eb9 f2fs: relocate is... |
357 358 |
struct bio_vec *bvec; struct page *target; |
6dc4f100c block: allow bio_... |
359 |
struct bvec_iter_all iter_all; |
0fd785eb9 f2fs: relocate is... |
360 |
|
8648de2c5 f2fs: add bio cac... |
361 |
if (!bio) |
0fd785eb9 f2fs: relocate is... |
362 |
return false; |
0c3a57975 f2fs: introduce f... |
363 |
|
bab475c54 Revert: "f2fs: ch... |
364 |
if (!inode && !page && !ino) |
0c3a57975 f2fs: introduce f... |
365 |
return true; |
0fd785eb9 f2fs: relocate is... |
366 |
|
8648de2c5 f2fs: add bio cac... |
367 |
bio_for_each_segment_all(bvec, bio, iter_all) { |
0fd785eb9 f2fs: relocate is... |
368 |
|
d2d0727b1 fscrypt: simplify... |
369 370 371 |
target = bvec->bv_page; if (fscrypt_is_bounce_page(target)) target = fscrypt_pagecache_page(target); |
0fd785eb9 f2fs: relocate is... |
372 |
|
0c3a57975 f2fs: introduce f... |
373 374 |
if (inode && inode == target->mapping->host) return true; |
bab475c54 Revert: "f2fs: ch... |
375 376 |
if (page && page == target) return true; |
0c3a57975 f2fs: introduce f... |
377 |
if (ino && ino == ino_of_node(target)) |
0fd785eb9 f2fs: relocate is... |
378 |
return true; |
0fd785eb9 f2fs: relocate is... |
379 |
} |
0fd785eb9 f2fs: relocate is... |
380 381 |
return false; } |
b9109b0e4 f2fs: remove unne... |
382 |
static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi, |
a912b54d3 f2fs: split bio c... |
383 |
enum page_type type, enum temp_type temp) |
93dfe2ac5 f2fs: refactor bi... |
384 385 |
{ enum page_type btype = PAGE_TYPE_OF_BIO(type); |
a912b54d3 f2fs: split bio c... |
386 |
struct f2fs_bio_info *io = sbi->write_io[btype] + temp; |
93dfe2ac5 f2fs: refactor bi... |
387 |
|
df0f8dc0e f2fs: avoid unnec... |
388 |
down_write(&io->io_rwsem); |
458e6197c f2fs: refactor bi... |
389 390 391 392 |
/* change META to META_FLUSH in the checkpoint procedure */ if (type >= META_FLUSH) { io->fio.type = META_FLUSH; |
04d328def f2fs: use bio op ... |
393 |
io->fio.op = REQ_OP_WRITE; |
3adc5fcb7 f2fs: Make flush ... |
394 |
io->fio.op_flags = REQ_META | REQ_PRIO | REQ_SYNC; |
70fd76140 block,fs: use REQ... |
395 |
if (!test_opt(sbi, NOBARRIER)) |
7f54f51f4 f2fs: remove pref... |
396 |
io->fio.op_flags |= REQ_PREFLUSH | REQ_FUA; |
458e6197c f2fs: refactor bi... |
397 398 |
} __submit_merged_bio(io); |
df0f8dc0e f2fs: avoid unnec... |
399 |
up_write(&io->io_rwsem); |
93dfe2ac5 f2fs: refactor bi... |
400 |
} |
a912b54d3 f2fs: split bio c... |
401 |
static void __submit_merged_write_cond(struct f2fs_sb_info *sbi, |
bab475c54 Revert: "f2fs: ch... |
402 403 |
struct inode *inode, struct page *page, nid_t ino, enum page_type type, bool force) |
0c3a57975 f2fs: introduce f... |
404 |
{ |
a912b54d3 f2fs: split bio c... |
405 |
enum temp_type temp; |
1e771e83c f2fs: only flush ... |
406 |
bool ret = true; |
a912b54d3 f2fs: split bio c... |
407 408 |
for (temp = HOT; temp < NR_TEMP_TYPE; temp++) { |
1e771e83c f2fs: only flush ... |
409 410 411 |
if (!force) { enum page_type btype = PAGE_TYPE_OF_BIO(type); struct f2fs_bio_info *io = sbi->write_io[btype] + temp; |
a912b54d3 f2fs: split bio c... |
412 |
|
1e771e83c f2fs: only flush ... |
413 |
down_read(&io->io_rwsem); |
8648de2c5 f2fs: add bio cac... |
414 |
ret = __has_merged_page(io->bio, inode, page, ino); |
1e771e83c f2fs: only flush ... |
415 416 417 418 |
up_read(&io->io_rwsem); } if (ret) __f2fs_submit_merged_write(sbi, type, temp); |
a912b54d3 f2fs: split bio c... |
419 420 421 422 423 |
/* TODO: use HOT temp only for meta pages now. */ if (type >= META) break; } |
0c3a57975 f2fs: introduce f... |
424 |
} |
b9109b0e4 f2fs: remove unne... |
425 |
void f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type) |
0c3a57975 f2fs: introduce f... |
426 |
{ |
adcc00f7d f2fs: data: fix w... |
427 |
__submit_merged_write_cond(sbi, NULL, NULL, 0, type, true); |
0c3a57975 f2fs: introduce f... |
428 |
} |
b9109b0e4 f2fs: remove unne... |
429 |
void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi, |
bab475c54 Revert: "f2fs: ch... |
430 431 |
struct inode *inode, struct page *page, nid_t ino, enum page_type type) |
0c3a57975 f2fs: introduce f... |
432 |
{ |
bab475c54 Revert: "f2fs: ch... |
433 |
__submit_merged_write_cond(sbi, inode, page, ino, type, false); |
0c3a57975 f2fs: introduce f... |
434 |
} |
b9109b0e4 f2fs: remove unne... |
435 |
void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi) |
406657dd1 f2fs: introduce f... |
436 |
{ |
b9109b0e4 f2fs: remove unne... |
437 438 439 |
f2fs_submit_merged_write(sbi, DATA); f2fs_submit_merged_write(sbi, NODE); f2fs_submit_merged_write(sbi, META); |
406657dd1 f2fs: introduce f... |
440 |
} |
93dfe2ac5 f2fs: refactor bi... |
441 442 |
/* * Fill the locked page with data located in the block address. |
771a9a717 f2fs: fix comment... |
443 |
* A caller needs to unlock the page on failure. |
93dfe2ac5 f2fs: refactor bi... |
444 |
*/ |
05ca3632e f2fs: add sbi and... |
445 |
int f2fs_submit_page_bio(struct f2fs_io_info *fio) |
93dfe2ac5 f2fs: refactor bi... |
446 |
{ |
93dfe2ac5 f2fs: refactor bi... |
447 |
struct bio *bio; |
0b81d0779 fs crypto: move p... |
448 449 |
struct page *page = fio->encrypted_page ? fio->encrypted_page : fio->page; |
93dfe2ac5 f2fs: refactor bi... |
450 |
|
c9b60788f f2fs: fix to do s... |
451 |
if (!f2fs_is_valid_blkaddr(fio->sbi, fio->new_blkaddr, |
93770ab7a f2fs: introduce D... |
452 453 |
fio->is_por ? META_POR : (__is_meta_io(fio) ? META_GENERIC : DATA_GENERIC_ENHANCE))) |
10f966bbf f2fs: use generic... |
454 |
return -EFSCORRUPTED; |
c9b60788f f2fs: fix to do s... |
455 |
|
2ace38e00 f2fs: cleanup par... |
456 |
trace_f2fs_submit_page_bio(page, fio); |
05ca3632e f2fs: add sbi and... |
457 |
f2fs_trace_ios(fio, 0); |
93dfe2ac5 f2fs: refactor bi... |
458 459 |
/* Allocate a new bio */ |
b757f6edb f2fs: clean up __... |
460 |
bio = __bio_alloc(fio, 1); |
93dfe2ac5 f2fs: refactor bi... |
461 |
|
09cbfeaf1 mm, fs: get rid o... |
462 |
if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { |
93dfe2ac5 f2fs: refactor bi... |
463 |
bio_put(bio); |
93dfe2ac5 f2fs: refactor bi... |
464 465 |
return -EFAULT; } |
78efac537 f2fs: fix to acco... |
466 467 |
if (fio->io_wbc && !is_read_io(fio->op)) |
34e51a5e1 blkcg, writeback:... |
468 |
wbc_account_cgroup_owner(fio->io_wbc, page, PAGE_SIZE); |
78efac537 f2fs: fix to acco... |
469 |
|
04d328def f2fs: use bio op ... |
470 |
bio_set_op_attrs(bio, fio->op, fio->op_flags); |
93dfe2ac5 f2fs: refactor bi... |
471 |
|
5f9abab42 f2fs: account rea... |
472 473 |
inc_page_count(fio->sbi, is_read_io(fio->op) ? __read_io_type(page): WB_DATA_TYPE(fio->page)); |
4c58ed076 f2fs: fix to acco... |
474 475 |
__submit_bio(fio->sbi, bio, fio->type); |
93dfe2ac5 f2fs: refactor bi... |
476 477 |
return 0; } |
8896cbdfe f2fs: introduce {... |
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 |
static bool page_is_mergeable(struct f2fs_sb_info *sbi, struct bio *bio, block_t last_blkaddr, block_t cur_blkaddr) { if (last_blkaddr + 1 != cur_blkaddr) return false; return __same_bdev(sbi, cur_blkaddr, bio); } static bool io_type_is_mergeable(struct f2fs_bio_info *io, struct f2fs_io_info *fio) { if (io->fio.op != fio->op) return false; return io->fio.op_flags == fio->op_flags; } static bool io_is_mergeable(struct f2fs_sb_info *sbi, struct bio *bio, struct f2fs_bio_info *io, struct f2fs_io_info *fio, block_t last_blkaddr, block_t cur_blkaddr) { |
c72db71ed f2fs: fix panic o... |
500 501 502 503 504 505 506 507 508 509 |
if (F2FS_IO_ALIGNED(sbi) && (fio->type == DATA || fio->type == NODE)) { unsigned int filled_blocks = F2FS_BYTES_TO_BLK(bio->bi_iter.bi_size); unsigned int io_size = F2FS_IO_SIZE(sbi); unsigned int left_vecs = bio->bi_max_vecs - bio->bi_vcnt; /* IOs in bio is aligned and left space of vectors is not enough */ if (!(filled_blocks % io_size) && left_vecs < io_size) return false; } |
8896cbdfe f2fs: introduce {... |
510 511 512 513 |
if (!page_is_mergeable(sbi, bio, last_blkaddr, cur_blkaddr)) return false; return io_type_is_mergeable(io, fio); } |
0b20fcec8 f2fs: cache globa... |
514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 |
static void add_bio_entry(struct f2fs_sb_info *sbi, struct bio *bio, struct page *page, enum temp_type temp) { struct f2fs_bio_info *io = sbi->write_io[DATA] + temp; struct bio_entry *be; be = f2fs_kmem_cache_alloc(bio_entry_slab, GFP_NOFS); be->bio = bio; bio_get(bio); if (bio_add_page(bio, page, PAGE_SIZE, 0) != PAGE_SIZE) f2fs_bug_on(sbi, 1); down_write(&io->bio_list_lock); list_add_tail(&be->list, &io->bio_list); up_write(&io->bio_list_lock); } static void del_bio_entry(struct bio_entry *be) { list_del(&be->list); kmem_cache_free(bio_entry_slab, be); } static int add_ipu_page(struct f2fs_sb_info *sbi, struct bio **bio, struct page *page) { enum temp_type temp; bool found = false; int ret = -EAGAIN; for (temp = HOT; temp < NR_TEMP_TYPE && !found; temp++) { struct f2fs_bio_info *io = sbi->write_io[DATA] + temp; struct list_head *head = &io->bio_list; struct bio_entry *be; down_write(&io->bio_list_lock); list_for_each_entry(be, head, list) { if (be->bio != *bio) continue; found = true; if (bio_add_page(*bio, page, PAGE_SIZE, 0) == PAGE_SIZE) { ret = 0; break; } /* bio is full */ del_bio_entry(be); __submit_bio(sbi, *bio, DATA); break; } up_write(&io->bio_list_lock); } if (ret) { bio_put(*bio); *bio = NULL; } return ret; } void f2fs_submit_merged_ipu_write(struct f2fs_sb_info *sbi, struct bio **bio, struct page *page) { enum temp_type temp; bool found = false; struct bio *target = bio ? *bio : NULL; for (temp = HOT; temp < NR_TEMP_TYPE && !found; temp++) { struct f2fs_bio_info *io = sbi->write_io[DATA] + temp; struct list_head *head = &io->bio_list; struct bio_entry *be; if (list_empty(head)) continue; down_read(&io->bio_list_lock); list_for_each_entry(be, head, list) { if (target) found = (target == be->bio); else found = __has_merged_page(be->bio, NULL, page, 0); if (found) break; } up_read(&io->bio_list_lock); if (!found) continue; found = false; down_write(&io->bio_list_lock); list_for_each_entry(be, head, list) { if (target) found = (target == be->bio); else found = __has_merged_page(be->bio, NULL, page, 0); if (found) { target = be->bio; del_bio_entry(be); break; } } up_write(&io->bio_list_lock); } if (found) __submit_bio(sbi, target, DATA); if (bio && *bio) { bio_put(*bio); *bio = NULL; } } |
8648de2c5 f2fs: add bio cac... |
633 634 635 636 637 638 639 640 |
int f2fs_merge_page_bio(struct f2fs_io_info *fio) { struct bio *bio = *fio->bio; struct page *page = fio->encrypted_page ? fio->encrypted_page : fio->page; if (!f2fs_is_valid_blkaddr(fio->sbi, fio->new_blkaddr, __is_meta_io(fio) ? META_GENERIC : DATA_GENERIC)) |
10f966bbf f2fs: use generic... |
641 |
return -EFSCORRUPTED; |
8648de2c5 f2fs: add bio cac... |
642 643 644 |
trace_f2fs_submit_page_bio(page, fio); f2fs_trace_ios(fio, 0); |
8896cbdfe f2fs: introduce {... |
645 |
if (bio && !page_is_mergeable(fio->sbi, bio, *fio->last_block, |
0b20fcec8 f2fs: cache globa... |
646 647 |
fio->new_blkaddr)) f2fs_submit_merged_ipu_write(fio->sbi, &bio, NULL); |
8648de2c5 f2fs: add bio cac... |
648 649 |
alloc_new: if (!bio) { |
b757f6edb f2fs: clean up __... |
650 |
bio = __bio_alloc(fio, BIO_MAX_PAGES); |
8648de2c5 f2fs: add bio cac... |
651 |
bio_set_op_attrs(bio, fio->op, fio->op_flags); |
8648de2c5 f2fs: add bio cac... |
652 |
|
0b20fcec8 f2fs: cache globa... |
653 654 655 656 |
add_bio_entry(fio->sbi, bio, page, fio->temp); } else { if (add_ipu_page(fio->sbi, &bio, page)) goto alloc_new; |
8648de2c5 f2fs: add bio cac... |
657 658 659 |
} if (fio->io_wbc) |
9637d5173 Merge tag 'for-li... |
660 |
wbc_account_cgroup_owner(fio->io_wbc, page, PAGE_SIZE); |
8648de2c5 f2fs: add bio cac... |
661 662 663 664 665 666 667 668 |
inc_page_count(fio->sbi, WB_DATA_TYPE(page)); *fio->last_block = fio->new_blkaddr; *fio->bio = bio; return 0; } |
fe16efe6a f2fs: fix to let ... |
669 |
void f2fs_submit_page_write(struct f2fs_io_info *fio) |
93dfe2ac5 f2fs: refactor bi... |
670 |
{ |
05ca3632e f2fs: add sbi and... |
671 |
struct f2fs_sb_info *sbi = fio->sbi; |
458e6197c f2fs: refactor bi... |
672 |
enum page_type btype = PAGE_TYPE_OF_BIO(fio->type); |
a912b54d3 f2fs: split bio c... |
673 |
struct f2fs_bio_info *io = sbi->write_io[btype] + fio->temp; |
4375a3366 f2fs crypto: add ... |
674 |
struct page *bio_page; |
93dfe2ac5 f2fs: refactor bi... |
675 |
|
b9109b0e4 f2fs: remove unne... |
676 |
f2fs_bug_on(sbi, is_read_io(fio->op)); |
93dfe2ac5 f2fs: refactor bi... |
677 |
|
fb830fc5c f2fs: introduce i... |
678 679 680 681 682 683 |
down_write(&io->io_rwsem); next: if (fio->in_list) { spin_lock(&io->io_lock); if (list_empty(&io->io_list)) { spin_unlock(&io->io_lock); |
fe16efe6a f2fs: fix to let ... |
684 |
goto out; |
fb830fc5c f2fs: introduce i... |
685 686 687 688 689 690 |
} fio = list_first_entry(&io->io_list, struct f2fs_io_info, list); list_del(&fio->list); spin_unlock(&io->io_lock); } |
93dfe2ac5 f2fs: refactor bi... |
691 |
|
93770ab7a f2fs: introduce D... |
692 |
verify_fio_blkaddr(fio); |
93dfe2ac5 f2fs: refactor bi... |
693 |
|
36951b38d f2fs: don't wait ... |
694 |
bio_page = fio->encrypted_page ? fio->encrypted_page : fio->page; |
ebf7c522f f2fs: Fix bool in... |
695 696 |
/* set submitted = true as a return value */ fio->submitted = true; |
d68f735b3 f2fs: check io su... |
697 |
|
b9109b0e4 f2fs: remove unne... |
698 |
inc_page_count(sbi, WB_DATA_TYPE(bio_page)); |
93dfe2ac5 f2fs: refactor bi... |
699 |
|
8896cbdfe f2fs: introduce {... |
700 701 |
if (io->bio && !io_is_mergeable(sbi, io->bio, io, fio, io->last_block_in_bio, fio->new_blkaddr)) |
458e6197c f2fs: refactor bi... |
702 |
__submit_merged_bio(io); |
93dfe2ac5 f2fs: refactor bi... |
703 704 |
alloc_new: if (io->bio == NULL) { |
8223ecc45 f2fs: fix to add ... |
705 706 |
if (F2FS_IO_ALIGNED(sbi) && (fio->type == DATA || fio->type == NODE) && |
0a595ebaa f2fs: support IO ... |
707 |
fio->new_blkaddr & F2FS_IO_SIZE_MASK(sbi)) { |
b9109b0e4 f2fs: remove unne... |
708 |
dec_page_count(sbi, WB_DATA_TYPE(bio_page)); |
fe16efe6a f2fs: fix to let ... |
709 710 |
fio->retry = true; goto skip; |
0a595ebaa f2fs: support IO ... |
711 |
} |
b757f6edb f2fs: clean up __... |
712 |
io->bio = __bio_alloc(fio, BIO_MAX_PAGES); |
458e6197c f2fs: refactor bi... |
713 |
io->fio = *fio; |
93dfe2ac5 f2fs: refactor bi... |
714 |
} |
a912b54d3 f2fs: split bio c... |
715 |
if (bio_add_page(io->bio, bio_page, PAGE_SIZE, 0) < PAGE_SIZE) { |
458e6197c f2fs: refactor bi... |
716 |
__submit_merged_bio(io); |
93dfe2ac5 f2fs: refactor bi... |
717 718 |
goto alloc_new; } |
578c64787 f2fs: implement c... |
719 |
if (fio->io_wbc) |
34e51a5e1 blkcg, writeback:... |
720 |
wbc_account_cgroup_owner(fio->io_wbc, bio_page, PAGE_SIZE); |
578c64787 f2fs: implement c... |
721 |
|
7a9d75481 f2fs: trace old b... |
722 |
io->last_block_in_bio = fio->new_blkaddr; |
05ca3632e f2fs: add sbi and... |
723 |
f2fs_trace_ios(fio, 0); |
fb830fc5c f2fs: introduce i... |
724 725 |
trace_f2fs_submit_page_write(fio->page, fio); |
fe16efe6a f2fs: fix to let ... |
726 |
skip: |
fb830fc5c f2fs: introduce i... |
727 728 |
if (fio->in_list) goto next; |
fe16efe6a f2fs: fix to let ... |
729 |
out: |
4354994f0 f2fs: checkpoint ... |
730 |
if (is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN) || |
00e09c0bc f2fs: enhance f2f... |
731 |
!f2fs_is_checkpoint_ready(sbi)) |
5ce805869 f2fs: submit bio ... |
732 |
__submit_merged_bio(io); |
df0f8dc0e f2fs: avoid unnec... |
733 |
up_write(&io->io_rwsem); |
93dfe2ac5 f2fs: refactor bi... |
734 |
} |
95ae251fe f2fs: add fs-veri... |
735 736 737 738 739 |
static inline bool f2fs_need_verity(const struct inode *inode, pgoff_t idx) { return fsverity_active(inode) && idx < DIV_ROUND_UP(inode->i_size, PAGE_SIZE); } |
13ba41e34 f2fs: make get_lo... |
740 |
static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr, |
95ae251fe f2fs: add fs-veri... |
741 742 |
unsigned nr_pages, unsigned op_flag, pgoff_t first_idx) |
13ba41e34 f2fs: make get_lo... |
743 744 |
{ struct f2fs_sb_info *sbi = F2FS_I_SB(inode); |
13ba41e34 f2fs: make get_lo... |
745 |
struct bio *bio; |
6dbb17961 f2fs: refactor re... |
746 747 |
struct bio_post_read_ctx *ctx; unsigned int post_read_steps = 0; |
13ba41e34 f2fs: make get_lo... |
748 |
|
d62fe9714 f2fs: support bio... |
749 |
bio = f2fs_bio_alloc(sbi, min_t(int, nr_pages, BIO_MAX_PAGES), false); |
6dbb17961 f2fs: refactor re... |
750 |
if (!bio) |
13ba41e34 f2fs: make get_lo... |
751 |
return ERR_PTR(-ENOMEM); |
13ba41e34 f2fs: make get_lo... |
752 753 |
f2fs_target_device(sbi, blkaddr, bio); bio->bi_end_io = f2fs_read_end_io; |
e2e59414a f2fs: assign REQ_... |
754 |
bio_set_op_attrs(bio, REQ_OP_READ, op_flag); |
13ba41e34 f2fs: make get_lo... |
755 |
|
6dbb17961 f2fs: refactor re... |
756 757 |
if (f2fs_encrypted_file(inode)) post_read_steps |= 1 << STEP_DECRYPT; |
95ae251fe f2fs: add fs-veri... |
758 759 760 |
if (f2fs_need_verity(inode, first_idx)) post_read_steps |= 1 << STEP_VERITY; |
6dbb17961 f2fs: refactor re... |
761 762 763 764 765 766 767 768 769 |
if (post_read_steps) { ctx = mempool_alloc(bio_post_read_ctx_pool, GFP_NOFS); if (!ctx) { bio_put(bio); return ERR_PTR(-ENOMEM); } ctx->bio = bio; ctx->enabled_steps = post_read_steps; bio->bi_private = ctx; |
6dbb17961 f2fs: refactor re... |
770 |
} |
13ba41e34 f2fs: make get_lo... |
771 772 773 774 775 776 777 |
return bio; } /* This can handle encryption stuffs */ static int f2fs_submit_page_read(struct inode *inode, struct page *page, block_t blkaddr) { |
93770ab7a f2fs: introduce D... |
778 779 |
struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct bio *bio; |
13ba41e34 f2fs: make get_lo... |
780 |
|
95ae251fe f2fs: add fs-veri... |
781 |
bio = f2fs_grab_read_bio(inode, blkaddr, 1, 0, page->index); |
13ba41e34 f2fs: make get_lo... |
782 783 |
if (IS_ERR(bio)) return PTR_ERR(bio); |
0ded69f63 f2fs: avoid wrong... |
784 785 |
/* wait for GCed page writeback via META_MAPPING */ f2fs_wait_on_block_writeback(inode, blkaddr); |
13ba41e34 f2fs: make get_lo... |
786 787 788 789 |
if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { bio_put(bio); return -EFAULT; } |
fb7d70db3 f2fs: clear PageE... |
790 |
ClearPageError(page); |
93770ab7a f2fs: introduce D... |
791 792 |
inc_page_count(sbi, F2FS_RD_DATA); __submit_bio(sbi, bio, DATA); |
13ba41e34 f2fs: make get_lo... |
793 794 |
return 0; } |
46008c6d4 f2fs: support in ... |
795 796 797 798 |
static void __set_data_blkaddr(struct dnode_of_data *dn) { struct f2fs_node *rn = F2FS_NODE(dn->node_page); __le32 *addr_array; |
7a2af766a f2fs: enhance on-... |
799 800 801 802 |
int base = 0; if (IS_INODE(dn->node_page) && f2fs_has_extra_attr(dn->inode)) base = get_extra_isize(dn->inode); |
46008c6d4 f2fs: support in ... |
803 804 805 |
/* Get physical address of data block */ addr_array = blkaddr_in_node(rn); |
7a2af766a f2fs: enhance on-... |
806 |
addr_array[base + dn->ofs_in_node] = cpu_to_le32(dn->data_blkaddr); |
46008c6d4 f2fs: support in ... |
807 |
} |
93dfe2ac5 f2fs: refactor bi... |
808 |
/* |
eb47b8009 f2fs: add address... |
809 810 811 812 813 |
* Lock ordering for the change of data block address: * ->data_page * ->node_page * update block addresses in the node page */ |
4d57b86dd f2fs: clean up sy... |
814 |
void f2fs_set_data_blkaddr(struct dnode_of_data *dn) |
eb47b8009 f2fs: add address... |
815 |
{ |
bae0ee7a7 f2fs: check PageW... |
816 |
f2fs_wait_on_page_writeback(dn->node_page, NODE, true, true); |
46008c6d4 f2fs: support in ... |
817 818 |
__set_data_blkaddr(dn); if (set_page_dirty(dn->node_page)) |
12719ae14 f2fs: avoid unnec... |
819 |
dn->node_changed = true; |
eb47b8009 f2fs: add address... |
820 |
} |
f28b3434a f2fs: introduce f... |
821 822 823 |
void f2fs_update_data_blkaddr(struct dnode_of_data *dn, block_t blkaddr) { dn->data_blkaddr = blkaddr; |
4d57b86dd f2fs: clean up sy... |
824 |
f2fs_set_data_blkaddr(dn); |
f28b3434a f2fs: introduce f... |
825 826 |
f2fs_update_extent_cache(dn); } |
46008c6d4 f2fs: support in ... |
827 |
/* dn->ofs_in_node will be returned with up-to-date last block pointer */ |
4d57b86dd f2fs: clean up sy... |
828 |
int f2fs_reserve_new_blocks(struct dnode_of_data *dn, blkcnt_t count) |
eb47b8009 f2fs: add address... |
829 |
{ |
4081363fb f2fs: introduce F... |
830 |
struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); |
0abd675e9 f2fs: support pla... |
831 |
int err; |
eb47b8009 f2fs: add address... |
832 |
|
46008c6d4 f2fs: support in ... |
833 834 |
if (!count) return 0; |
91942321e f2fs: use inode p... |
835 |
if (unlikely(is_inode_flag_set(dn->inode, FI_NO_ALLOC))) |
eb47b8009 f2fs: add address... |
836 |
return -EPERM; |
0abd675e9 f2fs: support pla... |
837 838 |
if (unlikely((err = inc_valid_block_count(sbi, dn->inode, &count)))) return err; |
eb47b8009 f2fs: add address... |
839 |
|
46008c6d4 f2fs: support in ... |
840 841 |
trace_f2fs_reserve_new_blocks(dn->inode, dn->nid, dn->ofs_in_node, count); |
bae0ee7a7 f2fs: check PageW... |
842 |
f2fs_wait_on_page_writeback(dn->node_page, NODE, true, true); |
46008c6d4 f2fs: support in ... |
843 844 |
for (; count > 0; dn->ofs_in_node++) { |
7a2af766a f2fs: enhance on-... |
845 846 |
block_t blkaddr = datablock_addr(dn->inode, dn->node_page, dn->ofs_in_node); |
46008c6d4 f2fs: support in ... |
847 848 849 850 851 852 853 854 855 |
if (blkaddr == NULL_ADDR) { dn->data_blkaddr = NEW_ADDR; __set_data_blkaddr(dn); count--; } } if (set_page_dirty(dn->node_page)) dn->node_changed = true; |
eb47b8009 f2fs: add address... |
856 857 |
return 0; } |
46008c6d4 f2fs: support in ... |
858 |
/* Should keep dn->ofs_in_node unchanged */ |
4d57b86dd f2fs: clean up sy... |
859 |
int f2fs_reserve_new_block(struct dnode_of_data *dn) |
46008c6d4 f2fs: support in ... |
860 861 862 |
{ unsigned int ofs_in_node = dn->ofs_in_node; int ret; |
4d57b86dd f2fs: clean up sy... |
863 |
ret = f2fs_reserve_new_blocks(dn, 1); |
46008c6d4 f2fs: support in ... |
864 865 866 |
dn->ofs_in_node = ofs_in_node; return ret; } |
b600965c4 f2fs: add a new f... |
867 868 869 870 |
int f2fs_reserve_block(struct dnode_of_data *dn, pgoff_t index) { bool need_put = dn->inode_page ? false : true; int err; |
4d57b86dd f2fs: clean up sy... |
871 |
err = f2fs_get_dnode_of_data(dn, index, ALLOC_NODE); |
b600965c4 f2fs: add a new f... |
872 873 |
if (err) return err; |
a8865372a f2fs: handle erro... |
874 |
|
b600965c4 f2fs: add a new f... |
875 |
if (dn->data_blkaddr == NULL_ADDR) |
4d57b86dd f2fs: clean up sy... |
876 |
err = f2fs_reserve_new_block(dn); |
a8865372a f2fs: handle erro... |
877 |
if (err || need_put) |
b600965c4 f2fs: add a new f... |
878 879 880 |
f2fs_put_dnode(dn); return err; } |
759af1c9c f2fs: use extent ... |
881 |
int f2fs_get_block(struct dnode_of_data *dn, pgoff_t index) |
eb47b8009 f2fs: add address... |
882 |
{ |
e15882b6c f2fs: init local ... |
883 |
struct extent_info ei = {0,0,0}; |
759af1c9c f2fs: use extent ... |
884 |
struct inode *inode = dn->inode; |
028a41e89 f2fs: initialize ... |
885 |
|
759af1c9c f2fs: use extent ... |
886 887 888 |
if (f2fs_lookup_extent_cache(inode, index, &ei)) { dn->data_blkaddr = ei.blk + index - ei.fofs; return 0; |
429511cdf f2fs: add core fu... |
889 |
} |
028a41e89 f2fs: initialize ... |
890 |
|
759af1c9c f2fs: use extent ... |
891 |
return f2fs_reserve_block(dn, index); |
eb47b8009 f2fs: add address... |
892 |
} |
4d57b86dd f2fs: clean up sy... |
893 |
struct page *f2fs_get_read_data_page(struct inode *inode, pgoff_t index, |
04d328def f2fs: use bio op ... |
894 |
int op_flags, bool for_write) |
eb47b8009 f2fs: add address... |
895 |
{ |
eb47b8009 f2fs: add address... |
896 897 898 |
struct address_space *mapping = inode->i_mapping; struct dnode_of_data dn; struct page *page; |
e15882b6c f2fs: init local ... |
899 |
struct extent_info ei = {0,0,0}; |
eb47b8009 f2fs: add address... |
900 |
int err; |
4375a3366 f2fs crypto: add ... |
901 |
|
a56c7c6fb f2fs: set GFP_NOF... |
902 |
page = f2fs_grab_cache_page(mapping, index, for_write); |
650495ded f2fs: fix the inc... |
903 904 |
if (!page) return ERR_PTR(-ENOMEM); |
cb3bc9ee0 f2fs: use extent ... |
905 906 |
if (f2fs_lookup_extent_cache(inode, index, &ei)) { dn.data_blkaddr = ei.blk + index - ei.fofs; |
93770ab7a f2fs: introduce D... |
907 908 |
if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), dn.data_blkaddr, DATA_GENERIC_ENHANCE_READ)) { |
10f966bbf f2fs: use generic... |
909 |
err = -EFSCORRUPTED; |
93770ab7a f2fs: introduce D... |
910 911 |
goto put_err; } |
cb3bc9ee0 f2fs: use extent ... |
912 913 |
goto got_it; } |
eb47b8009 f2fs: add address... |
914 |
set_new_dnode(&dn, inode, NULL, NULL, 0); |
4d57b86dd f2fs: clean up sy... |
915 |
err = f2fs_get_dnode_of_data(&dn, index, LOOKUP_NODE); |
86531d6b8 f2fs: callers tak... |
916 917 |
if (err) goto put_err; |
eb47b8009 f2fs: add address... |
918 |
f2fs_put_dnode(&dn); |
6bacf52fb f2fs: add unlikel... |
919 |
if (unlikely(dn.data_blkaddr == NULL_ADDR)) { |
86531d6b8 f2fs: callers tak... |
920 921 |
err = -ENOENT; goto put_err; |
650495ded f2fs: fix the inc... |
922 |
} |
93770ab7a f2fs: introduce D... |
923 924 925 926 |
if (dn.data_blkaddr != NEW_ADDR && !f2fs_is_valid_blkaddr(F2FS_I_SB(inode), dn.data_blkaddr, DATA_GENERIC_ENHANCE)) { |
10f966bbf f2fs: use generic... |
927 |
err = -EFSCORRUPTED; |
93770ab7a f2fs: introduce D... |
928 929 |
goto put_err; } |
cb3bc9ee0 f2fs: use extent ... |
930 |
got_it: |
43f3eae1d f2fs: split find_... |
931 932 |
if (PageUptodate(page)) { unlock_page(page); |
eb47b8009 f2fs: add address... |
933 |
return page; |
43f3eae1d f2fs: split find_... |
934 |
} |
eb47b8009 f2fs: add address... |
935 |
|
d59ff4df7 f2fs: fix wrong B... |
936 937 938 939 |
/* * A new dentry page is allocated but not able to be written, since its * new inode page couldn't be allocated due to -ENOSPC. * In such the case, its blkaddr can be remained as NEW_ADDR. |
4d57b86dd f2fs: clean up sy... |
940 941 |
* see, f2fs_add_link -> f2fs_get_new_data_page -> * f2fs_init_inode_metadata. |
d59ff4df7 f2fs: fix wrong B... |
942 943 |
*/ if (dn.data_blkaddr == NEW_ADDR) { |
09cbfeaf1 mm, fs: get rid o... |
944 |
zero_user_segment(page, 0, PAGE_SIZE); |
237c0790e f2fs: call SetPag... |
945 946 |
if (!PageUptodate(page)) SetPageUptodate(page); |
43f3eae1d f2fs: split find_... |
947 |
unlock_page(page); |
d59ff4df7 f2fs: fix wrong B... |
948 949 |
return page; } |
eb47b8009 f2fs: add address... |
950 |
|
13ba41e34 f2fs: make get_lo... |
951 |
err = f2fs_submit_page_read(inode, page, dn.data_blkaddr); |
393ff91f5 f2fs: reduce unnc... |
952 |
if (err) |
86531d6b8 f2fs: callers tak... |
953 |
goto put_err; |
43f3eae1d f2fs: split find_... |
954 |
return page; |
86531d6b8 f2fs: callers tak... |
955 956 957 958 |
put_err: f2fs_put_page(page, 1); return ERR_PTR(err); |
43f3eae1d f2fs: split find_... |
959 |
} |
4d57b86dd f2fs: clean up sy... |
960 |
struct page *f2fs_find_data_page(struct inode *inode, pgoff_t index) |
43f3eae1d f2fs: split find_... |
961 962 963 964 965 966 967 968 |
{ struct address_space *mapping = inode->i_mapping; struct page *page; page = find_get_page(mapping, index); if (page && PageUptodate(page)) return page; f2fs_put_page(page, 0); |
4d57b86dd f2fs: clean up sy... |
969 |
page = f2fs_get_read_data_page(inode, index, 0, false); |
43f3eae1d f2fs: split find_... |
970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 |
if (IS_ERR(page)) return page; if (PageUptodate(page)) return page; wait_on_page_locked(page); if (unlikely(!PageUptodate(page))) { f2fs_put_page(page, 0); return ERR_PTR(-EIO); } return page; } /* * If it tries to access a hole, return an error. * Because, the callers, functions in dir.c and GC, should be able to know * whether this page exists or not. */ |
4d57b86dd f2fs: clean up sy... |
989 |
struct page *f2fs_get_lock_data_page(struct inode *inode, pgoff_t index, |
a56c7c6fb f2fs: set GFP_NOF... |
990 |
bool for_write) |
43f3eae1d f2fs: split find_... |
991 992 993 994 |
{ struct address_space *mapping = inode->i_mapping; struct page *page; repeat: |
4d57b86dd f2fs: clean up sy... |
995 |
page = f2fs_get_read_data_page(inode, index, 0, for_write); |
43f3eae1d f2fs: split find_... |
996 997 |
if (IS_ERR(page)) return page; |
393ff91f5 f2fs: reduce unnc... |
998 |
|
43f3eae1d f2fs: split find_... |
999 |
/* wait for read completion */ |
393ff91f5 f2fs: reduce unnc... |
1000 |
lock_page(page); |
6bacf52fb f2fs: add unlikel... |
1001 |
if (unlikely(page->mapping != mapping)) { |
afcb7ca01 f2fs: check trunc... |
1002 1003 |
f2fs_put_page(page, 1); goto repeat; |
eb47b8009 f2fs: add address... |
1004 |
} |
1563ac75e f2fs: fix to dete... |
1005 1006 1007 1008 |
if (unlikely(!PageUptodate(page))) { f2fs_put_page(page, 1); return ERR_PTR(-EIO); } |
eb47b8009 f2fs: add address... |
1009 1010 |
return page; } |
0a8165d7c f2fs: adjust kern... |
1011 |
/* |
eb47b8009 f2fs: add address... |
1012 1013 |
* Caller ensures that this data page is never allocated. * A new zero-filled data page is allocated in the page cache. |
399368372 f2fs: introduce a... |
1014 |
* |
4f4124d0b f2fs: update seve... |
1015 1016 |
* Also, caller should grab and release a rwsem by calling f2fs_lock_op() and * f2fs_unlock_op(). |
470f00e96 f2fs: fix to rele... |
1017 1018 |
* Note that, ipage is set only by make_empty_dir, and if any error occur, * ipage should be released by this function. |
eb47b8009 f2fs: add address... |
1019 |
*/ |
4d57b86dd f2fs: clean up sy... |
1020 |
struct page *f2fs_get_new_data_page(struct inode *inode, |
a8865372a f2fs: handle erro... |
1021 |
struct page *ipage, pgoff_t index, bool new_i_size) |
eb47b8009 f2fs: add address... |
1022 |
{ |
eb47b8009 f2fs: add address... |
1023 1024 1025 1026 |
struct address_space *mapping = inode->i_mapping; struct page *page; struct dnode_of_data dn; int err; |
7612118ae f2fs: check the p... |
1027 |
|
a56c7c6fb f2fs: set GFP_NOF... |
1028 |
page = f2fs_grab_cache_page(mapping, index, true); |
470f00e96 f2fs: fix to rele... |
1029 1030 1031 1032 1033 1034 |
if (!page) { /* * before exiting, we should make sure ipage will be released * if any error occur. */ f2fs_put_page(ipage, 1); |
01f28610a f2fs: fix race on... |
1035 |
return ERR_PTR(-ENOMEM); |
470f00e96 f2fs: fix to rele... |
1036 |
} |
eb47b8009 f2fs: add address... |
1037 |
|
a8865372a f2fs: handle erro... |
1038 |
set_new_dnode(&dn, inode, ipage, NULL, 0); |
b600965c4 f2fs: add a new f... |
1039 |
err = f2fs_reserve_block(&dn, index); |
01f28610a f2fs: fix race on... |
1040 1041 |
if (err) { f2fs_put_page(page, 1); |
eb47b8009 f2fs: add address... |
1042 |
return ERR_PTR(err); |
a8865372a f2fs: handle erro... |
1043 |
} |
01f28610a f2fs: fix race on... |
1044 1045 |
if (!ipage) f2fs_put_dnode(&dn); |
eb47b8009 f2fs: add address... |
1046 1047 |
if (PageUptodate(page)) |
01f28610a f2fs: fix race on... |
1048 |
goto got_it; |
eb47b8009 f2fs: add address... |
1049 1050 |
if (dn.data_blkaddr == NEW_ADDR) { |
09cbfeaf1 mm, fs: get rid o... |
1051 |
zero_user_segment(page, 0, PAGE_SIZE); |
237c0790e f2fs: call SetPag... |
1052 1053 |
if (!PageUptodate(page)) SetPageUptodate(page); |
eb47b8009 f2fs: add address... |
1054 |
} else { |
4375a3366 f2fs crypto: add ... |
1055 |
f2fs_put_page(page, 1); |
a8865372a f2fs: handle erro... |
1056 |
|
7612118ae f2fs: check the p... |
1057 1058 |
/* if ipage exists, blkaddr should be NEW_ADDR */ f2fs_bug_on(F2FS_I_SB(inode), ipage); |
4d57b86dd f2fs: clean up sy... |
1059 |
page = f2fs_get_lock_data_page(inode, index, true); |
4375a3366 f2fs crypto: add ... |
1060 |
if (IS_ERR(page)) |
7612118ae f2fs: check the p... |
1061 |
return page; |
eb47b8009 f2fs: add address... |
1062 |
} |
01f28610a f2fs: fix race on... |
1063 |
got_it: |
9edcdabf3 f2fs: fix overflo... |
1064 |
if (new_i_size && i_size_read(inode) < |
ee6d182f2 f2fs: remove sync... |
1065 |
((loff_t)(index + 1) << PAGE_SHIFT)) |
fc9581c80 f2fs: introduce f... |
1066 |
f2fs_i_size_write(inode, ((loff_t)(index + 1) << PAGE_SHIFT)); |
eb47b8009 f2fs: add address... |
1067 1068 |
return page; } |
d5097be55 f2fs: apply write... |
1069 |
static int __allocate_data_block(struct dnode_of_data *dn, int seg_type) |
bfad7c2d4 f2fs: introduce a... |
1070 |
{ |
4081363fb f2fs: introduce F... |
1071 |
struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); |
bfad7c2d4 f2fs: introduce a... |
1072 |
struct f2fs_summary sum; |
bfad7c2d4 f2fs: introduce a... |
1073 |
struct node_info ni; |
6aa58d8ad f2fs: readahead e... |
1074 |
block_t old_blkaddr; |
46008c6d4 f2fs: support in ... |
1075 |
blkcnt_t count = 1; |
0abd675e9 f2fs: support pla... |
1076 |
int err; |
bfad7c2d4 f2fs: introduce a... |
1077 |
|
91942321e f2fs: use inode p... |
1078 |
if (unlikely(is_inode_flag_set(dn->inode, FI_NO_ALLOC))) |
bfad7c2d4 f2fs: introduce a... |
1079 |
return -EPERM; |
df6136ef5 f2fs: preallocate... |
1080 |
|
7735730d3 f2fs: fix to prop... |
1081 1082 1083 |
err = f2fs_get_node_info(sbi, dn->nid, &ni); if (err) return err; |
7a2af766a f2fs: enhance on-... |
1084 1085 |
dn->data_blkaddr = datablock_addr(dn->inode, dn->node_page, dn->ofs_in_node); |
f847c699c f2fs: allow out-p... |
1086 |
if (dn->data_blkaddr != NULL_ADDR) |
df6136ef5 f2fs: preallocate... |
1087 |
goto alloc; |
0abd675e9 f2fs: support pla... |
1088 1089 |
if (unlikely((err = inc_valid_block_count(sbi, dn->inode, &count)))) return err; |
bfad7c2d4 f2fs: introduce a... |
1090 |
|
df6136ef5 f2fs: preallocate... |
1091 |
alloc: |
bfad7c2d4 f2fs: introduce a... |
1092 |
set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version); |
6aa58d8ad f2fs: readahead e... |
1093 1094 |
old_blkaddr = dn->data_blkaddr; f2fs_allocate_data_block(sbi, NULL, old_blkaddr, &dn->data_blkaddr, |
d5097be55 f2fs: apply write... |
1095 |
&sum, seg_type, NULL, false); |
6aa58d8ad f2fs: readahead e... |
1096 1097 1098 |
if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO) invalidate_mapping_pages(META_MAPPING(sbi), old_blkaddr, old_blkaddr); |
86f35dc39 f2fs: fix extent ... |
1099 |
f2fs_update_data_blkaddr(dn, dn->data_blkaddr); |
bfad7c2d4 f2fs: introduce a... |
1100 |
|
0a4daae5f f2fs: update i_si... |
1101 1102 1103 1104 |
/* * i_size will be updated by direct_IO. Otherwise, we'll get stale * data from unwritten block via dio_read. */ |
bfad7c2d4 f2fs: introduce a... |
1105 1106 |
return 0; } |
a7de60869 f2fs: use err for... |
1107 |
int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *from) |
59b802e5a f2fs: allocate da... |
1108 |
{ |
b439b103a f2fs: move dio pr... |
1109 |
struct inode *inode = file_inode(iocb->ki_filp); |
5b8db7fad f2fs: simplify __... |
1110 |
struct f2fs_map_blocks map; |
d6d478a14 f2fs: continue to... |
1111 |
int flag; |
a7de60869 f2fs: use err for... |
1112 |
int err = 0; |
d6d478a14 f2fs: continue to... |
1113 |
bool direct_io = iocb->ki_flags & IOCB_DIRECT; |
59b802e5a f2fs: allocate da... |
1114 |
|
71ad682c1 f2fs: convert inl... |
1115 |
/* convert inline data for Direct I/O*/ |
d6d478a14 f2fs: continue to... |
1116 |
if (direct_io) { |
71ad682c1 f2fs: convert inl... |
1117 1118 1119 1120 |
err = f2fs_convert_inline_inode(inode); if (err) return err; } |
f9d6d0597 f2fs: fix out-pla... |
1121 1122 |
if (direct_io && allow_outplace_dio(inode, iocb, from)) return 0; |
dc91de78e f2fs: do not prea... |
1123 1124 |
if (is_inode_flag_set(inode, FI_NO_PREALLOC)) return 0; |
0080c5076 f2fs: do not prea... |
1125 |
map.m_lblk = F2FS_BLK_ALIGN(iocb->ki_pos); |
dfd02e4de f2fs: fix to prea... |
1126 1127 1128 1129 1130 |
map.m_len = F2FS_BYTES_TO_BLK(iocb->ki_pos + iov_iter_count(from)); if (map.m_len > map.m_lblk) map.m_len -= map.m_lblk; else map.m_len = 0; |
da85985c6 f2fs: speed up ha... |
1131 |
map.m_next_pgofs = NULL; |
c4020b2da f2fs: support F2F... |
1132 |
map.m_next_extent = NULL; |
d5097be55 f2fs: apply write... |
1133 |
map.m_seg_type = NO_CHECK_TYPE; |
f9d6d0597 f2fs: fix out-pla... |
1134 |
map.m_may_create = true; |
2a3407607 f2fs: call f2fs_b... |
1135 |
|
d6d478a14 f2fs: continue to... |
1136 |
if (direct_io) { |
4d57b86dd f2fs: clean up sy... |
1137 |
map.m_seg_type = f2fs_rw_hint_to_seg_type(iocb->ki_hint); |
f847c699c f2fs: allow out-p... |
1138 |
flag = f2fs_force_buffered_io(inode, iocb, from) ? |
d6d478a14 f2fs: continue to... |
1139 1140 1141 |
F2FS_GET_BLOCK_PRE_AIO : F2FS_GET_BLOCK_PRE_DIO; goto map_blocks; |
d5097be55 f2fs: apply write... |
1142 |
} |
f24703712 f2fs: make max in... |
1143 |
if (iocb->ki_pos + iov_iter_count(from) > MAX_INLINE_DATA(inode)) { |
a7de60869 f2fs: use err for... |
1144 1145 1146 |
err = f2fs_convert_inline_inode(inode); if (err) return err; |
b439b103a f2fs: move dio pr... |
1147 |
} |
d6d478a14 f2fs: continue to... |
1148 |
if (f2fs_has_inline_data(inode)) |
25006645d f2fs: still write... |
1149 |
return err; |
d6d478a14 f2fs: continue to... |
1150 1151 1152 1153 1154 1155 1156 1157 1158 |
flag = F2FS_GET_BLOCK_PRE_AIO; map_blocks: err = f2fs_map_blocks(inode, &map, 1, flag); if (map.m_len > 0 && err == -ENOSPC) { if (!direct_io) set_inode_flag(inode, FI_NO_PREALLOC); err = 0; |
25006645d f2fs: still write... |
1159 |
} |
a7de60869 f2fs: use err for... |
1160 |
return err; |
59b802e5a f2fs: allocate da... |
1161 |
} |
39a869582 f2fs: refactor ->... |
1162 |
void __do_map_lock(struct f2fs_sb_info *sbi, int flag, bool lock) |
59c9081bc f2fs: allow write... |
1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 |
{ if (flag == F2FS_GET_BLOCK_PRE_AIO) { if (lock) down_read(&sbi->node_change); else up_read(&sbi->node_change); } else { if (lock) f2fs_lock_op(sbi); else f2fs_unlock_op(sbi); } } |
0a8165d7c f2fs: adjust kern... |
1176 |
/* |
003a3e1d6 f2fs: add f2fs_ma... |
1177 1178 |
* f2fs_map_blocks() now supported readahead/bmap/rw direct_IO with * f2fs_map_blocks structure. |
4f4124d0b f2fs: update seve... |
1179 1180 1181 1182 1183 |
* If original data blocks are allocated, then give them to blockdev. * Otherwise, * a. preallocate requested block addresses * b. do not use extent cache for better performance * c. give the block addresses to blockdev |
eb47b8009 f2fs: add address... |
1184 |
*/ |
d323d005a f2fs: support fil... |
1185 |
int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, |
e2b4e2bc8 f2fs: fix incorre... |
1186 |
int create, int flag) |
eb47b8009 f2fs: add address... |
1187 |
{ |
003a3e1d6 f2fs: add f2fs_ma... |
1188 |
unsigned int maxblocks = map->m_len; |
eb47b8009 f2fs: add address... |
1189 |
struct dnode_of_data dn; |
f9811703f f2fs: fix to hand... |
1190 |
struct f2fs_sb_info *sbi = F2FS_I_SB(inode); |
f9d6d0597 f2fs: fix out-pla... |
1191 |
int mode = map->m_may_create ? ALLOC_NODE : LOOKUP_NODE; |
46008c6d4 f2fs: support in ... |
1192 |
pgoff_t pgofs, end_offset, end; |
bfad7c2d4 f2fs: introduce a... |
1193 |
int err = 0, ofs = 1; |
46008c6d4 f2fs: support in ... |
1194 1195 |
unsigned int ofs_in_node, last_ofs_in_node; blkcnt_t prealloc; |
e15882b6c f2fs: init local ... |
1196 |
struct extent_info ei = {0,0,0}; |
7df3a4318 f2fs: optimize th... |
1197 |
block_t blkaddr; |
c4020b2da f2fs: support F2F... |
1198 |
unsigned int start_pgofs; |
eb47b8009 f2fs: add address... |
1199 |
|
dfd02e4de f2fs: fix to prea... |
1200 1201 |
if (!maxblocks) return 0; |
003a3e1d6 f2fs: add f2fs_ma... |
1202 1203 1204 1205 1206 |
map->m_len = 0; map->m_flags = 0; /* it only supports block size == page size */ pgofs = (pgoff_t)map->m_lblk; |
46008c6d4 f2fs: support in ... |
1207 |
end = pgofs + maxblocks; |
eb47b8009 f2fs: add address... |
1208 |
|
24b849125 f2fs: preallocate... |
1209 |
if (!create && f2fs_lookup_extent_cache(inode, pgofs, &ei)) { |
f4f0b6777 f2fs: fix m_may_c... |
1210 1211 1212 |
if (test_opt(sbi, LFS) && flag == F2FS_GET_BLOCK_DIO && map->m_may_create) goto next_dnode; |
003a3e1d6 f2fs: add f2fs_ma... |
1213 1214 1215 |
map->m_pblk = ei.blk + pgofs - ei.fofs; map->m_len = min((pgoff_t)maxblocks, ei.fofs + ei.len - pgofs); map->m_flags = F2FS_MAP_MAPPED; |
c4020b2da f2fs: support F2F... |
1216 1217 |
if (map->m_next_extent) *map->m_next_extent = pgofs + map->m_len; |
1e78e8bd9 f2fs: fix data co... |
1218 1219 1220 1221 1222 |
/* for hardware encryption, but to avoid potential issue in future */ if (flag == F2FS_GET_BLOCK_DIO) f2fs_wait_on_block_writeback_range(inode, map->m_pblk, map->m_len); |
bfad7c2d4 f2fs: introduce a... |
1223 |
goto out; |
a2e7d1bfe f2fs: introduce f... |
1224 |
} |
bfad7c2d4 f2fs: introduce a... |
1225 |
|
4fe71e88b f2fs: simplify f2... |
1226 |
next_dnode: |
f9d6d0597 f2fs: fix out-pla... |
1227 |
if (map->m_may_create) |
59c9081bc f2fs: allow write... |
1228 |
__do_map_lock(sbi, flag, true); |
eb47b8009 f2fs: add address... |
1229 1230 1231 |
/* When reading holes, we need its node page */ set_new_dnode(&dn, inode, NULL, NULL, 0); |
4d57b86dd f2fs: clean up sy... |
1232 |
err = f2fs_get_dnode_of_data(&dn, pgofs, mode); |
1ec79083b f2fs: should put ... |
1233 |
if (err) { |
43473f964 f2fs: fix incorre... |
1234 1235 |
if (flag == F2FS_GET_BLOCK_BMAP) map->m_pblk = 0; |
da85985c6 f2fs: speed up ha... |
1236 |
if (err == -ENOENT) { |
bfad7c2d4 f2fs: introduce a... |
1237 |
err = 0; |
da85985c6 f2fs: speed up ha... |
1238 1239 |
if (map->m_next_pgofs) *map->m_next_pgofs = |
4d57b86dd f2fs: clean up sy... |
1240 |
f2fs_get_next_page_offset(&dn, pgofs); |
c4020b2da f2fs: support F2F... |
1241 1242 |
if (map->m_next_extent) *map->m_next_extent = |
4d57b86dd f2fs: clean up sy... |
1243 |
f2fs_get_next_page_offset(&dn, pgofs); |
da85985c6 f2fs: speed up ha... |
1244 |
} |
bfad7c2d4 f2fs: introduce a... |
1245 |
goto unlock_out; |
848753aa3 f2fs: add tracepo... |
1246 |
} |
973163fc0 f2fs: reorganize ... |
1247 |
|
c4020b2da f2fs: support F2F... |
1248 |
start_pgofs = pgofs; |
46008c6d4 f2fs: support in ... |
1249 |
prealloc = 0; |
230436b3e f2fs: hide a mayb... |
1250 |
last_ofs_in_node = ofs_in_node = dn.ofs_in_node; |
81ca7350c f2fs: remove unne... |
1251 |
end_offset = ADDRS_PER_PAGE(dn.node_page, inode); |
4fe71e88b f2fs: simplify f2... |
1252 1253 |
next_block: |
7a2af766a f2fs: enhance on-... |
1254 |
blkaddr = datablock_addr(dn.inode, dn.node_page, dn.ofs_in_node); |
4fe71e88b f2fs: simplify f2... |
1255 |
|
c9b60788f f2fs: fix to do s... |
1256 |
if (__is_valid_data_blkaddr(blkaddr) && |
93770ab7a f2fs: introduce D... |
1257 |
!f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC_ENHANCE)) { |
10f966bbf f2fs: use generic... |
1258 |
err = -EFSCORRUPTED; |
c9b60788f f2fs: fix to do s... |
1259 1260 |
goto sync_out; } |
93770ab7a f2fs: introduce D... |
1261 |
if (__is_valid_data_blkaddr(blkaddr)) { |
f847c699c f2fs: allow out-p... |
1262 |
/* use out-place-update for driect IO under LFS mode */ |
f9d6d0597 f2fs: fix out-pla... |
1263 1264 |
if (test_opt(sbi, LFS) && flag == F2FS_GET_BLOCK_DIO && map->m_may_create) { |
f847c699c f2fs: allow out-p... |
1265 |
err = __allocate_data_block(&dn, map->m_seg_type); |
05e360061 f2fs: fix to hand... |
1266 1267 1268 1269 |
if (err) goto sync_out; blkaddr = dn.data_blkaddr; set_inode_flag(inode, FI_APPEND_WRITE); |
f847c699c f2fs: allow out-p... |
1270 1271 |
} } else { |
973163fc0 f2fs: reorganize ... |
1272 |
if (create) { |
f9811703f f2fs: fix to hand... |
1273 1274 |
if (unlikely(f2fs_cp_error(sbi))) { err = -EIO; |
4fe71e88b f2fs: simplify f2... |
1275 |
goto sync_out; |
f9811703f f2fs: fix to hand... |
1276 |
} |
24b849125 f2fs: preallocate... |
1277 |
if (flag == F2FS_GET_BLOCK_PRE_AIO) { |
46008c6d4 f2fs: support in ... |
1278 1279 1280 1281 |
if (blkaddr == NULL_ADDR) { prealloc++; last_ofs_in_node = dn.ofs_in_node; } |
24b849125 f2fs: preallocate... |
1282 |
} else { |
0a4daae5f f2fs: update i_si... |
1283 1284 |
WARN_ON(flag != F2FS_GET_BLOCK_PRE_DIO && flag != F2FS_GET_BLOCK_DIO); |
d5097be55 f2fs: apply write... |
1285 1286 |
err = __allocate_data_block(&dn, map->m_seg_type); |
6f2d8ed65 f2fs: don't miss ... |
1287 |
if (!err) |
91942321e f2fs: use inode p... |
1288 |
set_inode_flag(inode, FI_APPEND_WRITE); |
24b849125 f2fs: preallocate... |
1289 |
} |
973163fc0 f2fs: reorganize ... |
1290 |
if (err) |
4fe71e88b f2fs: simplify f2... |
1291 |
goto sync_out; |
3f2be0430 f2fs: avoid m_fla... |
1292 |
map->m_flags |= F2FS_MAP_NEW; |
4fe71e88b f2fs: simplify f2... |
1293 |
blkaddr = dn.data_blkaddr; |
973163fc0 f2fs: reorganize ... |
1294 |
} else { |
43473f964 f2fs: fix incorre... |
1295 1296 1297 1298 |
if (flag == F2FS_GET_BLOCK_BMAP) { map->m_pblk = 0; goto sync_out; } |
c4020b2da f2fs: support F2F... |
1299 1300 |
if (flag == F2FS_GET_BLOCK_PRECACHE) goto sync_out; |
da85985c6 f2fs: speed up ha... |
1301 1302 1303 1304 |
if (flag == F2FS_GET_BLOCK_FIEMAP && blkaddr == NULL_ADDR) { if (map->m_next_pgofs) *map->m_next_pgofs = pgofs + 1; |
4c2ac6a86 f2fs: clean up f2... |
1305 |
goto sync_out; |
da85985c6 f2fs: speed up ha... |
1306 |
} |
f3d98e74f f2fs: speed up de... |
1307 1308 1309 1310 |
if (flag != F2FS_GET_BLOCK_FIEMAP) { /* for defragment case */ if (map->m_next_pgofs) *map->m_next_pgofs = pgofs + 1; |
4fe71e88b f2fs: simplify f2... |
1311 |
goto sync_out; |
f3d98e74f f2fs: speed up de... |
1312 |
} |
e2b4e2bc8 f2fs: fix incorre... |
1313 |
} |
e2b4e2bc8 f2fs: fix incorre... |
1314 |
} |
eb47b8009 f2fs: add address... |
1315 |
|
46008c6d4 f2fs: support in ... |
1316 1317 |
if (flag == F2FS_GET_BLOCK_PRE_AIO) goto skip; |
4fe71e88b f2fs: simplify f2... |
1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 |
if (map->m_len == 0) { /* preallocated unwritten block should be mapped for fiemap. */ if (blkaddr == NEW_ADDR) map->m_flags |= F2FS_MAP_UNWRITTEN; map->m_flags |= F2FS_MAP_MAPPED; map->m_pblk = blkaddr; map->m_len = 1; } else if ((map->m_pblk != NEW_ADDR && blkaddr == (map->m_pblk + ofs)) || |
b439b103a f2fs: move dio pr... |
1328 |
(map->m_pblk == NEW_ADDR && blkaddr == NEW_ADDR) || |
46008c6d4 f2fs: support in ... |
1329 |
flag == F2FS_GET_BLOCK_PRE_DIO) { |
4fe71e88b f2fs: simplify f2... |
1330 1331 1332 1333 1334 |
ofs++; map->m_len++; } else { goto sync_out; } |
bfad7c2d4 f2fs: introduce a... |
1335 |
|
46008c6d4 f2fs: support in ... |
1336 |
skip: |
bfad7c2d4 f2fs: introduce a... |
1337 1338 |
dn.ofs_in_node++; pgofs++; |
46008c6d4 f2fs: support in ... |
1339 1340 1341 |
/* preallocate blocks in batch for one dnode page */ if (flag == F2FS_GET_BLOCK_PRE_AIO && (pgofs == end || dn.ofs_in_node == end_offset)) { |
7df3a4318 f2fs: optimize th... |
1342 |
|
46008c6d4 f2fs: support in ... |
1343 |
dn.ofs_in_node = ofs_in_node; |
4d57b86dd f2fs: clean up sy... |
1344 |
err = f2fs_reserve_new_blocks(&dn, prealloc); |
46008c6d4 f2fs: support in ... |
1345 1346 |
if (err) goto sync_out; |
bfad7c2d4 f2fs: introduce a... |
1347 |
|
46008c6d4 f2fs: support in ... |
1348 1349 1350 1351 |
map->m_len += dn.ofs_in_node - ofs_in_node; if (prealloc && dn.ofs_in_node != last_ofs_in_node + 1) { err = -ENOSPC; goto sync_out; |
3104af35e f2fs: reduce cove... |
1352 |
} |
46008c6d4 f2fs: support in ... |
1353 1354 1355 1356 1357 1358 1359 |
dn.ofs_in_node = end_offset; } if (pgofs >= end) goto sync_out; else if (dn.ofs_in_node < end_offset) goto next_block; |
c4020b2da f2fs: support F2F... |
1360 1361 1362 1363 1364 1365 1366 1367 1368 |
if (flag == F2FS_GET_BLOCK_PRECACHE) { if (map->m_flags & F2FS_MAP_MAPPED) { unsigned int ofs = start_pgofs - map->m_lblk; f2fs_update_extent_cache_range(&dn, start_pgofs, map->m_pblk + ofs, map->m_len - ofs); } } |
46008c6d4 f2fs: support in ... |
1369 |
f2fs_put_dnode(&dn); |
f9d6d0597 f2fs: fix out-pla... |
1370 |
if (map->m_may_create) { |
59c9081bc f2fs: allow write... |
1371 |
__do_map_lock(sbi, flag, false); |
6f2d8ed65 f2fs: don't miss ... |
1372 |
f2fs_balance_fs(sbi, dn.node_changed); |
eb47b8009 f2fs: add address... |
1373 |
} |
46008c6d4 f2fs: support in ... |
1374 |
goto next_dnode; |
7df3a4318 f2fs: optimize th... |
1375 |
|
bfad7c2d4 f2fs: introduce a... |
1376 |
sync_out: |
1e78e8bd9 f2fs: fix data co... |
1377 1378 1379 1380 1381 |
/* for hardware encryption, but to avoid potential issue in future */ if (flag == F2FS_GET_BLOCK_DIO && map->m_flags & F2FS_MAP_MAPPED) f2fs_wait_on_block_writeback_range(inode, map->m_pblk, map->m_len); |
c4020b2da f2fs: support F2F... |
1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 |
if (flag == F2FS_GET_BLOCK_PRECACHE) { if (map->m_flags & F2FS_MAP_MAPPED) { unsigned int ofs = start_pgofs - map->m_lblk; f2fs_update_extent_cache_range(&dn, start_pgofs, map->m_pblk + ofs, map->m_len - ofs); } if (map->m_next_extent) *map->m_next_extent = pgofs + 1; } |
eb47b8009 f2fs: add address... |
1393 |
f2fs_put_dnode(&dn); |
bfad7c2d4 f2fs: introduce a... |
1394 |
unlock_out: |
f9d6d0597 f2fs: fix out-pla... |
1395 |
if (map->m_may_create) { |
59c9081bc f2fs: allow write... |
1396 |
__do_map_lock(sbi, flag, false); |
6f2d8ed65 f2fs: don't miss ... |
1397 |
f2fs_balance_fs(sbi, dn.node_changed); |
2a3407607 f2fs: call f2fs_b... |
1398 |
} |
bfad7c2d4 f2fs: introduce a... |
1399 |
out: |
003a3e1d6 f2fs: add f2fs_ma... |
1400 |
trace_f2fs_map_blocks(inode, map, err); |
bfad7c2d4 f2fs: introduce a... |
1401 |
return err; |
eb47b8009 f2fs: add address... |
1402 |
} |
b91050a80 f2fs: add nowait ... |
1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 |
bool f2fs_overwrite_io(struct inode *inode, loff_t pos, size_t len) { struct f2fs_map_blocks map; block_t last_lblk; int err; if (pos + len > i_size_read(inode)) return false; map.m_lblk = F2FS_BYTES_TO_BLK(pos); map.m_next_pgofs = NULL; map.m_next_extent = NULL; map.m_seg_type = NO_CHECK_TYPE; |
f4f0b6777 f2fs: fix m_may_c... |
1416 |
map.m_may_create = false; |
b91050a80 f2fs: add nowait ... |
1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 |
last_lblk = F2FS_BLK_ALIGN(pos + len); while (map.m_lblk < last_lblk) { map.m_len = last_lblk - map.m_lblk; err = f2fs_map_blocks(inode, &map, 0, F2FS_GET_BLOCK_DEFAULT); if (err || map.m_len == 0) return false; map.m_lblk += map.m_len; } return true; } |
003a3e1d6 f2fs: add f2fs_ma... |
1428 |
static int __get_data_block(struct inode *inode, sector_t iblock, |
da85985c6 f2fs: speed up ha... |
1429 |
struct buffer_head *bh, int create, int flag, |
f9d6d0597 f2fs: fix out-pla... |
1430 |
pgoff_t *next_pgofs, int seg_type, bool may_write) |
003a3e1d6 f2fs: add f2fs_ma... |
1431 1432 |
{ struct f2fs_map_blocks map; |
a7de60869 f2fs: use err for... |
1433 |
int err; |
003a3e1d6 f2fs: add f2fs_ma... |
1434 1435 1436 |
map.m_lblk = iblock; map.m_len = bh->b_size >> inode->i_blkbits; |
da85985c6 f2fs: speed up ha... |
1437 |
map.m_next_pgofs = next_pgofs; |
c4020b2da f2fs: support F2F... |
1438 |
map.m_next_extent = NULL; |
d5097be55 f2fs: apply write... |
1439 |
map.m_seg_type = seg_type; |
f9d6d0597 f2fs: fix out-pla... |
1440 |
map.m_may_create = may_write; |
003a3e1d6 f2fs: add f2fs_ma... |
1441 |
|
a7de60869 f2fs: use err for... |
1442 1443 |
err = f2fs_map_blocks(inode, &map, create, flag); if (!err) { |
003a3e1d6 f2fs: add f2fs_ma... |
1444 1445 |
map_bh(bh, inode->i_sb, map.m_pblk); bh->b_state = (bh->b_state & ~F2FS_MAP_FLAGS) | map.m_flags; |
b86e33075 f2fs: fix a dead ... |
1446 |
bh->b_size = (u64)map.m_len << inode->i_blkbits; |
003a3e1d6 f2fs: add f2fs_ma... |
1447 |
} |
a7de60869 f2fs: use err for... |
1448 |
return err; |
003a3e1d6 f2fs: add f2fs_ma... |
1449 |
} |
ccfb30001 f2fs: fix to repo... |
1450 |
static int get_data_block(struct inode *inode, sector_t iblock, |
da85985c6 f2fs: speed up ha... |
1451 1452 |
struct buffer_head *bh_result, int create, int flag, pgoff_t *next_pgofs) |
e2b4e2bc8 f2fs: fix incorre... |
1453 |
{ |
da85985c6 f2fs: speed up ha... |
1454 |
return __get_data_block(inode, iblock, bh_result, create, |
d5097be55 f2fs: apply write... |
1455 |
flag, next_pgofs, |
f9d6d0597 f2fs: fix out-pla... |
1456 1457 1458 1459 1460 1461 1462 1463 1464 |
NO_CHECK_TYPE, create); } static int get_data_block_dio_write(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create) { return __get_data_block(inode, iblock, bh_result, create, F2FS_GET_BLOCK_DIO, NULL, f2fs_rw_hint_to_seg_type(inode->i_write_hint), |
75a037f36 f2fs: fix liveloc... |
1465 |
IS_SWAPFILE(inode) ? false : true); |
e2b4e2bc8 f2fs: fix incorre... |
1466 1467 1468 |
} static int get_data_block_dio(struct inode *inode, sector_t iblock, |
ccfb30001 f2fs: fix to repo... |
1469 1470 |
struct buffer_head *bh_result, int create) { |
e2b4e2bc8 f2fs: fix incorre... |
1471 |
return __get_data_block(inode, iblock, bh_result, create, |
f9d6d0597 f2fs: fix out-pla... |
1472 1473 1474 |
F2FS_GET_BLOCK_DIO, NULL, f2fs_rw_hint_to_seg_type(inode->i_write_hint), false); |
ccfb30001 f2fs: fix to repo... |
1475 |
} |
e2b4e2bc8 f2fs: fix incorre... |
1476 |
static int get_data_block_bmap(struct inode *inode, sector_t iblock, |
ccfb30001 f2fs: fix to repo... |
1477 1478 |
struct buffer_head *bh_result, int create) { |
179448bfe f2fs: add a max b... |
1479 |
/* Block number less than F2FS MAX BLOCKS */ |
e0afc4d6d f2fs: introduce m... |
1480 |
if (unlikely(iblock >= F2FS_I_SB(inode)->max_file_blocks)) |
179448bfe f2fs: add a max b... |
1481 |
return -EFBIG; |
e2b4e2bc8 f2fs: fix incorre... |
1482 |
return __get_data_block(inode, iblock, bh_result, create, |
d5097be55 f2fs: apply write... |
1483 |
F2FS_GET_BLOCK_BMAP, NULL, |
f9d6d0597 f2fs: fix out-pla... |
1484 |
NO_CHECK_TYPE, create); |
ccfb30001 f2fs: fix to repo... |
1485 |
} |
7f63eb77a f2fs: report unwr... |
1486 1487 1488 1489 1490 1491 1492 1493 1494 |
static inline sector_t logical_to_blk(struct inode *inode, loff_t offset) { return (offset >> inode->i_blkbits); } static inline loff_t blk_to_logical(struct inode *inode, sector_t blk) { return (blk << inode->i_blkbits); } |
442a9dbd5 f2fs: support FIE... |
1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 |
static int f2fs_xattr_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct page *page; struct node_info ni; __u64 phys = 0, len; __u32 flags; nid_t xnid = F2FS_I(inode)->i_xattr_nid; int err = 0; if (f2fs_has_inline_xattr(inode)) { int offset; page = f2fs_grab_cache_page(NODE_MAPPING(sbi), inode->i_ino, false); if (!page) return -ENOMEM; |
7735730d3 f2fs: fix to prop... |
1513 1514 1515 1516 1517 |
err = f2fs_get_node_info(sbi, inode->i_ino, &ni); if (err) { f2fs_put_page(page, 1); return err; } |
442a9dbd5 f2fs: support FIE... |
1518 1519 1520 1521 |
phys = (__u64)blk_to_logical(inode, ni.blk_addr); offset = offsetof(struct f2fs_inode, i_addr) + sizeof(__le32) * (DEF_ADDRS_PER_INODE - |
b323fd28b f2fs: kill F2FS_I... |
1522 |
get_inline_xattr_addrs(inode)); |
442a9dbd5 f2fs: support FIE... |
1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 |
phys += offset; len = inline_xattr_size(inode); f2fs_put_page(page, 1); flags = FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_NOT_ALIGNED; if (!xnid) flags |= FIEMAP_EXTENT_LAST; err = fiemap_fill_next_extent(fieinfo, 0, phys, len, flags); if (err || err == 1) return err; } if (xnid) { page = f2fs_grab_cache_page(NODE_MAPPING(sbi), xnid, false); if (!page) return -ENOMEM; |
7735730d3 f2fs: fix to prop... |
1543 1544 1545 1546 1547 |
err = f2fs_get_node_info(sbi, xnid, &ni); if (err) { f2fs_put_page(page, 1); return err; } |
442a9dbd5 f2fs: support FIE... |
1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 |
phys = (__u64)blk_to_logical(inode, ni.blk_addr); len = inode->i_sb->s_blocksize; f2fs_put_page(page, 1); flags = FIEMAP_EXTENT_LAST; } if (phys) err = fiemap_fill_next_extent(fieinfo, 0, phys, len, flags); return (err < 0 ? err : 0); } |
9ab701349 f2fs: support f2f... |
1562 1563 1564 |
int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, u64 start, u64 len) { |
7f63eb77a f2fs: report unwr... |
1565 1566 |
struct buffer_head map_bh; sector_t start_blk, last_blk; |
da85985c6 f2fs: speed up ha... |
1567 |
pgoff_t next_pgofs; |
7f63eb77a f2fs: report unwr... |
1568 1569 |
u64 logical = 0, phys = 0, size = 0; u32 flags = 0; |
7f63eb77a f2fs: report unwr... |
1570 |
int ret = 0; |
c4020b2da f2fs: support F2F... |
1571 1572 1573 1574 1575 |
if (fieinfo->fi_flags & FIEMAP_FLAG_CACHE) { ret = f2fs_precache_extents(inode); if (ret) return ret; } |
442a9dbd5 f2fs: support FIE... |
1576 |
ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC | FIEMAP_FLAG_XATTR); |
7f63eb77a f2fs: report unwr... |
1577 1578 |
if (ret) return ret; |
f1b43d4cd f2fs: fix to cove... |
1579 |
inode_lock(inode); |
442a9dbd5 f2fs: support FIE... |
1580 1581 1582 1583 |
if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) { ret = f2fs_xattr_fiemap(inode, fieinfo); goto out; } |
7975f3498 f2fs: support fie... |
1584 |
if (f2fs_has_inline_data(inode) || f2fs_has_inline_dentry(inode)) { |
67f8cf3ce f2fs: support fie... |
1585 1586 |
ret = f2fs_inline_data_fiemap(inode, fieinfo, start, len); if (ret != -EAGAIN) |
f1b43d4cd f2fs: fix to cove... |
1587 |
goto out; |
67f8cf3ce f2fs: support fie... |
1588 |
} |
7f63eb77a f2fs: report unwr... |
1589 1590 1591 1592 1593 |
if (logical_to_blk(inode, len) == 0) len = blk_to_logical(inode, 1); start_blk = logical_to_blk(inode, start); last_blk = logical_to_blk(inode, start + len - 1); |
9a950d52b f2fs: fix bugs an... |
1594 |
|
7f63eb77a f2fs: report unwr... |
1595 1596 1597 |
next: memset(&map_bh, 0, sizeof(struct buffer_head)); map_bh.b_size = len; |
e2b4e2bc8 f2fs: fix incorre... |
1598 |
ret = get_data_block(inode, start_blk, &map_bh, 0, |
da85985c6 f2fs: speed up ha... |
1599 |
F2FS_GET_BLOCK_FIEMAP, &next_pgofs); |
7f63eb77a f2fs: report unwr... |
1600 1601 1602 1603 1604 |
if (ret) goto out; /* HOLE */ if (!buffer_mapped(&map_bh)) { |
da85985c6 f2fs: speed up ha... |
1605 |
start_blk = next_pgofs; |
58736fa60 f2fs: be aware of... |
1606 1607 1608 |
if (blk_to_logical(inode, start_blk) < blk_to_logical(inode, F2FS_I_SB(inode)->max_file_blocks)) |
9a950d52b f2fs: fix bugs an... |
1609 |
goto prep_next; |
58736fa60 f2fs: be aware of... |
1610 |
|
9a950d52b f2fs: fix bugs an... |
1611 1612 |
flags |= FIEMAP_EXTENT_LAST; } |
7f63eb77a f2fs: report unwr... |
1613 |
|
da5af127a f2fs: recognize e... |
1614 |
if (size) { |
62230e0d7 f2fs: use IS_ENCR... |
1615 |
if (IS_ENCRYPTED(inode)) |
da5af127a f2fs: recognize e... |
1616 |
flags |= FIEMAP_EXTENT_DATA_ENCRYPTED; |
9a950d52b f2fs: fix bugs an... |
1617 1618 |
ret = fiemap_fill_next_extent(fieinfo, logical, phys, size, flags); |
da5af127a f2fs: recognize e... |
1619 |
} |
7f63eb77a f2fs: report unwr... |
1620 |
|
9a950d52b f2fs: fix bugs an... |
1621 1622 |
if (start_blk > last_blk || ret) goto out; |
7f63eb77a f2fs: report unwr... |
1623 |
|
9a950d52b f2fs: fix bugs an... |
1624 1625 1626 1627 1628 1629 |
logical = blk_to_logical(inode, start_blk); phys = blk_to_logical(inode, map_bh.b_blocknr); size = map_bh.b_size; flags = 0; if (buffer_unwritten(&map_bh)) flags = FIEMAP_EXTENT_UNWRITTEN; |
7f63eb77a f2fs: report unwr... |
1630 |
|
9a950d52b f2fs: fix bugs an... |
1631 |
start_blk += logical_to_blk(inode, size); |
7f63eb77a f2fs: report unwr... |
1632 |
|
9a950d52b f2fs: fix bugs an... |
1633 |
prep_next: |
7f63eb77a f2fs: report unwr... |
1634 1635 1636 1637 1638 1639 1640 1641 |
cond_resched(); if (fatal_signal_pending(current)) ret = -EINTR; else goto next; out: if (ret == 1) ret = 0; |
5955102c9 wrappers for ->i_... |
1642 |
inode_unlock(inode); |
7f63eb77a f2fs: report unwr... |
1643 |
return ret; |
9ab701349 f2fs: support f2f... |
1644 |
} |
95ae251fe f2fs: add fs-veri... |
1645 1646 1647 1648 1649 1650 1651 1652 |
static inline loff_t f2fs_readpage_limit(struct inode *inode) { if (IS_ENABLED(CONFIG_FS_VERITY) && (IS_VERITY(inode) || f2fs_verity_in_progress(inode))) return inode->i_sb->s_maxbytes; return i_size_read(inode); } |
2df0ab045 f2fs: introduce f... |
1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 |
static int f2fs_read_single_page(struct inode *inode, struct page *page, unsigned nr_pages, struct f2fs_map_blocks *map, struct bio **bio_ret, sector_t *last_block_in_bio, bool is_readahead) { struct bio *bio = *bio_ret; const unsigned blkbits = inode->i_blkbits; const unsigned blocksize = 1 << blkbits; sector_t block_in_file; sector_t last_block; sector_t last_block_in_file; sector_t block_nr; int ret = 0; |
4969c06a0 f2fs: support swa... |
1668 |
block_in_file = (sector_t)page_index(page); |
2df0ab045 f2fs: introduce f... |
1669 |
last_block = block_in_file + nr_pages; |
95ae251fe f2fs: add fs-veri... |
1670 |
last_block_in_file = (f2fs_readpage_limit(inode) + blocksize - 1) >> |
2df0ab045 f2fs: introduce f... |
1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 |
blkbits; if (last_block > last_block_in_file) last_block = last_block_in_file; /* just zeroing out page which is beyond EOF */ if (block_in_file >= last_block) goto zero_out; /* * Map blocks using the previous result first. */ if ((map->m_flags & F2FS_MAP_MAPPED) && block_in_file > map->m_lblk && block_in_file < (map->m_lblk + map->m_len)) goto got_it; /* * Then do more f2fs_map_blocks() calls until we are * done with this page. */ map->m_lblk = block_in_file; map->m_len = last_block - block_in_file; ret = f2fs_map_blocks(inode, map, 0, F2FS_GET_BLOCK_DEFAULT); if (ret) goto out; got_it: if ((map->m_flags & F2FS_MAP_MAPPED)) { block_nr = map->m_pblk + block_in_file - map->m_lblk; SetPageMappedToDisk(page); |
4969c06a0 f2fs: support swa... |
1700 1701 |
if (!PageUptodate(page) && (!PageSwapCache(page) && !cleancache_get_page(page))) { |
2df0ab045 f2fs: introduce f... |
1702 1703 1704 1705 1706 |
SetPageUptodate(page); goto confused; } if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), block_nr, |
93770ab7a f2fs: introduce D... |
1707 |
DATA_GENERIC_ENHANCE_READ)) { |
10f966bbf f2fs: use generic... |
1708 |
ret = -EFSCORRUPTED; |
2df0ab045 f2fs: introduce f... |
1709 1710 1711 1712 1713 |
goto out; } } else { zero_out: zero_user_segment(page, 0, PAGE_SIZE); |
95ae251fe f2fs: add fs-veri... |
1714 1715 1716 1717 1718 |
if (f2fs_need_verity(inode, page->index) && !fsverity_verify_page(page)) { ret = -EIO; goto out; } |
2df0ab045 f2fs: introduce f... |
1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 |
if (!PageUptodate(page)) SetPageUptodate(page); unlock_page(page); goto out; } /* * This page will go to BIO. Do we need to send this * BIO off first? */ |
8896cbdfe f2fs: introduce {... |
1729 1730 |
if (bio && !page_is_mergeable(F2FS_I_SB(inode), bio, *last_block_in_bio, block_nr)) { |
2df0ab045 f2fs: introduce f... |
1731 1732 1733 1734 1735 1736 |
submit_and_realloc: __submit_bio(F2FS_I_SB(inode), bio, DATA); bio = NULL; } if (bio == NULL) { bio = f2fs_grab_read_bio(inode, block_nr, nr_pages, |
95ae251fe f2fs: add fs-veri... |
1737 |
is_readahead ? REQ_RAHEAD : 0, page->index); |
2df0ab045 f2fs: introduce f... |
1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 |
if (IS_ERR(bio)) { ret = PTR_ERR(bio); bio = NULL; goto out; } } /* * If the page is under writeback, we need to wait for * its completion to see the correct decrypted data. */ f2fs_wait_on_block_writeback(inode, block_nr); if (bio_add_page(bio, page, blocksize, 0) < blocksize) goto submit_and_realloc; inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA); ClearPageError(page); *last_block_in_bio = block_nr; goto out; confused: if (bio) { __submit_bio(F2FS_I_SB(inode), bio, DATA); bio = NULL; } unlock_page(page); out: *bio_ret = bio; return ret; } |
f1e886601 f2fs: expose f2fs... |
1768 1769 1770 |
/* * This function was originally taken from fs/mpage.c, and customized for f2fs. * Major change was from block_size == page_size in f2fs by default. |
e2e59414a f2fs: assign REQ_... |
1771 1772 1773 1774 1775 |
* * Note that the aops->readpages() function is ONLY used for read-ahead. If * this function ever deviates from doing just read-ahead, it should either * use ->readpage() or do the necessary surgery to decouple ->readpages() * from read-ahead. |
f1e886601 f2fs: expose f2fs... |
1776 1777 1778 |
*/ static int f2fs_mpage_readpages(struct address_space *mapping, struct list_head *pages, struct page *page, |
e2e59414a f2fs: assign REQ_... |
1779 |
unsigned nr_pages, bool is_readahead) |
f1e886601 f2fs: expose f2fs... |
1780 1781 |
{ struct bio *bio = NULL; |
f1e886601 f2fs: expose f2fs... |
1782 1783 |
sector_t last_block_in_bio = 0; struct inode *inode = mapping->host; |
f1e886601 f2fs: expose f2fs... |
1784 |
struct f2fs_map_blocks map; |
2df0ab045 f2fs: introduce f... |
1785 |
int ret = 0; |
f1e886601 f2fs: expose f2fs... |
1786 1787 1788 1789 1790 |
map.m_pblk = 0; map.m_lblk = 0; map.m_len = 0; map.m_flags = 0; |
da85985c6 f2fs: speed up ha... |
1791 |
map.m_next_pgofs = NULL; |
c4020b2da f2fs: support F2F... |
1792 |
map.m_next_extent = NULL; |
d5097be55 f2fs: apply write... |
1793 |
map.m_seg_type = NO_CHECK_TYPE; |
f9d6d0597 f2fs: fix out-pla... |
1794 |
map.m_may_create = false; |
f1e886601 f2fs: expose f2fs... |
1795 |
|
736c0a748 f2fs: remove an e... |
1796 |
for (; nr_pages; nr_pages--) { |
f1e886601 f2fs: expose f2fs... |
1797 |
if (pages) { |
939afa943 f2fs: clean up wi... |
1798 |
page = list_last_entry(pages, struct page, lru); |
a83d50bc1 f2fs: fix bad pre... |
1799 1800 |
prefetchw(&page->flags); |
f1e886601 f2fs: expose f2fs... |
1801 1802 |
list_del(&page->lru); if (add_to_page_cache_lru(page, mapping, |
4969c06a0 f2fs: support swa... |
1803 |
page_index(page), |
8a5c743e3 mm, memcg: use co... |
1804 |
readahead_gfp_mask(mapping))) |
f1e886601 f2fs: expose f2fs... |
1805 1806 |
goto next_page; } |
2df0ab045 f2fs: introduce f... |
1807 1808 1809 1810 |
ret = f2fs_read_single_page(inode, page, nr_pages, &map, &bio, &last_block_in_bio, is_readahead); if (ret) { SetPageError(page); |
09cbfeaf1 mm, fs: get rid o... |
1811 |
zero_user_segment(page, 0, PAGE_SIZE); |
f1e886601 f2fs: expose f2fs... |
1812 |
unlock_page(page); |
f1e886601 f2fs: expose f2fs... |
1813 |
} |
f1e886601 f2fs: expose f2fs... |
1814 1815 |
next_page: if (pages) |
09cbfeaf1 mm, fs: get rid o... |
1816 |
put_page(page); |
f1e886601 f2fs: expose f2fs... |
1817 1818 1819 |
} BUG_ON(pages && !list_empty(pages)); if (bio) |
4fc29c1aa Merge tag 'for-f2... |
1820 |
__submit_bio(F2FS_I_SB(inode), bio, DATA); |
2df0ab045 f2fs: introduce f... |
1821 |
return pages ? 0 : ret; |
f1e886601 f2fs: expose f2fs... |
1822 |
} |
eb47b8009 f2fs: add address... |
1823 1824 |
static int f2fs_read_data_page(struct file *file, struct page *page) { |
4969c06a0 f2fs: support swa... |
1825 |
struct inode *inode = page_file_mapping(page)->host; |
b3d208f96 f2fs: revisit inl... |
1826 |
int ret = -EAGAIN; |
9ffe0fb5f f2fs: handle inli... |
1827 |
|
c20e89cde f2fs: add a trace... |
1828 |
trace_f2fs_readpage(page, DATA); |
e1c420452 f2fs: fix typo |
1829 |
/* If the file has inline data, try to read it directly */ |
9ffe0fb5f f2fs: handle inli... |
1830 1831 |
if (f2fs_has_inline_data(inode)) ret = f2fs_read_inline_data(inode, page); |
b3d208f96 f2fs: revisit inl... |
1832 |
if (ret == -EAGAIN) |
4969c06a0 f2fs: support swa... |
1833 1834 |
ret = f2fs_mpage_readpages(page_file_mapping(page), NULL, page, 1, false); |
9ffe0fb5f f2fs: handle inli... |
1835 |
return ret; |
eb47b8009 f2fs: add address... |
1836 1837 1838 1839 1840 1841 |
} static int f2fs_read_data_pages(struct file *file, struct address_space *mapping, struct list_head *pages, unsigned nr_pages) { |
71cb4afff f2fs: allow readp... |
1842 |
struct inode *inode = mapping->host; |
939afa943 f2fs: clean up wi... |
1843 |
struct page *page = list_last_entry(pages, struct page, lru); |
b8c294004 f2fs: add a trace... |
1844 1845 |
trace_f2fs_readpages(inode, page, nr_pages); |
9ffe0fb5f f2fs: handle inli... |
1846 1847 1848 1849 |
/* If the file has inline data, skip readpages */ if (f2fs_has_inline_data(inode)) return 0; |
e2e59414a f2fs: assign REQ_... |
1850 |
return f2fs_mpage_readpages(mapping, pages, NULL, nr_pages, true); |
eb47b8009 f2fs: add address... |
1851 |
} |
7eab0c0df f2fs: reconstruct... |
1852 1853 1854 |
static int encrypt_one_page(struct f2fs_io_info *fio) { struct inode *inode = fio->page->mapping->host; |
6aa58d8ad f2fs: readahead e... |
1855 |
struct page *mpage; |
7eab0c0df f2fs: reconstruct... |
1856 |
gfp_t gfp_flags = GFP_NOFS; |
1958593e4 f2fs: introduce f... |
1857 |
if (!f2fs_encrypted_file(inode)) |
7eab0c0df f2fs: reconstruct... |
1858 |
return 0; |
6dbb17961 f2fs: refactor re... |
1859 |
/* wait for GCed page writeback via META_MAPPING */ |
0ded69f63 f2fs: avoid wrong... |
1860 |
f2fs_wait_on_block_writeback(inode, fio->old_blkaddr); |
7eab0c0df f2fs: reconstruct... |
1861 1862 |
retry_encrypt: |
53bc1d854 fscrypt: support ... |
1863 1864 1865 |
fio->encrypted_page = fscrypt_encrypt_pagecache_blocks(fio->page, PAGE_SIZE, 0, gfp_flags); |
6aa58d8ad f2fs: readahead e... |
1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 |
if (IS_ERR(fio->encrypted_page)) { /* flush pending IOs and wait for a while in the ENOMEM case */ if (PTR_ERR(fio->encrypted_page) == -ENOMEM) { f2fs_flush_merged_writes(fio->sbi); congestion_wait(BLK_RW_ASYNC, HZ/50); gfp_flags |= __GFP_NOFAIL; goto retry_encrypt; } return PTR_ERR(fio->encrypted_page); } |
7eab0c0df f2fs: reconstruct... |
1876 |
|
6aa58d8ad f2fs: readahead e... |
1877 1878 1879 1880 1881 1882 |
mpage = find_lock_page(META_MAPPING(fio->sbi), fio->old_blkaddr); if (mpage) { if (PageUptodate(mpage)) memcpy(page_address(mpage), page_address(fio->encrypted_page), PAGE_SIZE); f2fs_put_page(mpage, 1); |
7eab0c0df f2fs: reconstruct... |
1883 |
} |
6aa58d8ad f2fs: readahead e... |
1884 |
return 0; |
7eab0c0df f2fs: reconstruct... |
1885 |
} |
bb9e3bb8d f2fs: split need_... |
1886 1887 |
static inline bool check_inplace_update_policy(struct inode *inode, struct f2fs_io_info *fio) |
7eab0c0df f2fs: reconstruct... |
1888 |
{ |
bb9e3bb8d f2fs: split need_... |
1889 1890 |
struct f2fs_sb_info *sbi = F2FS_I_SB(inode); unsigned int policy = SM_I(sbi)->ipu_policy; |
7eab0c0df f2fs: reconstruct... |
1891 |
|
bb9e3bb8d f2fs: split need_... |
1892 1893 |
if (policy & (0x1 << F2FS_IPU_FORCE)) return true; |
4d57b86dd f2fs: clean up sy... |
1894 |
if (policy & (0x1 << F2FS_IPU_SSR) && f2fs_need_SSR(sbi)) |
bb9e3bb8d f2fs: split need_... |
1895 1896 1897 1898 |
return true; if (policy & (0x1 << F2FS_IPU_UTIL) && utilization(sbi) > SM_I(sbi)->min_ipu_util) return true; |
4d57b86dd f2fs: clean up sy... |
1899 |
if (policy & (0x1 << F2FS_IPU_SSR_UTIL) && f2fs_need_SSR(sbi) && |
bb9e3bb8d f2fs: split need_... |
1900 1901 1902 1903 1904 1905 1906 1907 1908 |
utilization(sbi) > SM_I(sbi)->min_ipu_util) return true; /* * IPU for rewrite async pages */ if (policy & (0x1 << F2FS_IPU_ASYNC) && fio && fio->op == REQ_OP_WRITE && !(fio->op_flags & REQ_SYNC) && |
62230e0d7 f2fs: use IS_ENCR... |
1909 |
!IS_ENCRYPTED(inode)) |
bb9e3bb8d f2fs: split need_... |
1910 1911 1912 1913 1914 1915 |
return true; /* this is only set during fdatasync */ if (policy & (0x1 << F2FS_IPU_FSYNC) && is_inode_flag_set(inode, FI_NEED_IPU)) return true; |
4354994f0 f2fs: checkpoint ... |
1916 1917 1918 |
if (unlikely(fio && is_sbi_flag_set(sbi, SBI_CP_DISABLED) && !f2fs_is_checkpointed_data(sbi, fio->old_blkaddr))) return true; |
bb9e3bb8d f2fs: split need_... |
1919 1920 |
return false; } |
4d57b86dd f2fs: clean up sy... |
1921 |
bool f2fs_should_update_inplace(struct inode *inode, struct f2fs_io_info *fio) |
bb9e3bb8d f2fs: split need_... |
1922 |
{ |
1ad71a271 f2fs: add an ioct... |
1923 1924 |
if (f2fs_is_pinned_file(inode)) return true; |
bb9e3bb8d f2fs: split need_... |
1925 1926 1927 1928 1929 1930 1931 |
/* if this is cold file, we should overwrite to avoid fragmentation */ if (file_is_cold(inode)) return true; return check_inplace_update_policy(inode, fio); } |
4d57b86dd f2fs: clean up sy... |
1932 |
bool f2fs_should_update_outplace(struct inode *inode, struct f2fs_io_info *fio) |
bb9e3bb8d f2fs: split need_... |
1933 1934 1935 1936 1937 1938 1939 |
{ struct f2fs_sb_info *sbi = F2FS_I_SB(inode); if (test_opt(sbi, LFS)) return true; if (S_ISDIR(inode->i_mode)) return true; |
af033b2aa f2fs: guarantee j... |
1940 1941 |
if (IS_NOQUOTA(inode)) return true; |
bb9e3bb8d f2fs: split need_... |
1942 1943 1944 1945 1946 1947 1948 |
if (f2fs_is_atomic_file(inode)) return true; if (fio) { if (is_cold_data(fio->page)) return true; if (IS_ATOMIC_WRITTEN_PAGE(fio->page)) return true; |
4354994f0 f2fs: checkpoint ... |
1949 1950 1951 |
if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED) && f2fs_is_checkpointed_data(sbi, fio->old_blkaddr))) return true; |
bb9e3bb8d f2fs: split need_... |
1952 1953 1954 |
} return false; } |
7eab0c0df f2fs: reconstruct... |
1955 1956 1957 |
static inline bool need_inplace_update(struct f2fs_io_info *fio) { struct inode *inode = fio->page->mapping->host; |
4d57b86dd f2fs: clean up sy... |
1958 |
if (f2fs_should_update_outplace(inode, fio)) |
7eab0c0df f2fs: reconstruct... |
1959 |
return false; |
4d57b86dd f2fs: clean up sy... |
1960 |
return f2fs_should_update_inplace(inode, fio); |
7eab0c0df f2fs: reconstruct... |
1961 |
} |
4d57b86dd f2fs: clean up sy... |
1962 |
int f2fs_do_write_data_page(struct f2fs_io_info *fio) |
eb47b8009 f2fs: add address... |
1963 |
{ |
05ca3632e f2fs: add sbi and... |
1964 |
struct page *page = fio->page; |
eb47b8009 f2fs: add address... |
1965 |
struct inode *inode = page->mapping->host; |
eb47b8009 f2fs: add address... |
1966 |
struct dnode_of_data dn; |
e959c8f54 f2fs: lookup exte... |
1967 |
struct extent_info ei = {0,0,0}; |
7735730d3 f2fs: fix to prop... |
1968 |
struct node_info ni; |
e959c8f54 f2fs: lookup exte... |
1969 |
bool ipu_force = false; |
eb47b8009 f2fs: add address... |
1970 1971 1972 |
int err = 0; set_new_dnode(&dn, inode, NULL, NULL, 0); |
e959c8f54 f2fs: lookup exte... |
1973 1974 1975 |
if (need_inplace_update(fio) && f2fs_lookup_extent_cache(inode, page->index, &ei)) { fio->old_blkaddr = ei.blk + page->index - ei.fofs; |
a817737e8 f2fs: introduce v... |
1976 |
|
c9b60788f f2fs: fix to do s... |
1977 |
if (!f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr, |
93770ab7a f2fs: introduce D... |
1978 |
DATA_GENERIC_ENHANCE)) |
10f966bbf f2fs: use generic... |
1979 |
return -EFSCORRUPTED; |
c9b60788f f2fs: fix to do s... |
1980 1981 1982 1983 |
ipu_force = true; fio->need_lock = LOCK_DONE; goto got_it; |
e959c8f54 f2fs: lookup exte... |
1984 |
} |
279d6df20 f2fs: release cp ... |
1985 |
|
d29460e5c f2fs: avoid deadl... |
1986 1987 1988 |
/* Deadlock due to between page->lock and f2fs_lock_op */ if (fio->need_lock == LOCK_REQ && !f2fs_trylock_op(fio->sbi)) return -EAGAIN; |
279d6df20 f2fs: release cp ... |
1989 |
|
4d57b86dd f2fs: clean up sy... |
1990 |
err = f2fs_get_dnode_of_data(&dn, page->index, LOOKUP_NODE); |
eb47b8009 f2fs: add address... |
1991 |
if (err) |
279d6df20 f2fs: release cp ... |
1992 |
goto out; |
eb47b8009 f2fs: add address... |
1993 |
|
28bc106b2 f2fs: support rev... |
1994 |
fio->old_blkaddr = dn.data_blkaddr; |
eb47b8009 f2fs: add address... |
1995 1996 |
/* This page is already truncated */ |
7a9d75481 f2fs: trace old b... |
1997 |
if (fio->old_blkaddr == NULL_ADDR) { |
2bca1e238 f2fs: clear page'... |
1998 |
ClearPageUptodate(page); |
2baf07818 f2fs: fix to spre... |
1999 |
clear_cold_data(page); |
eb47b8009 f2fs: add address... |
2000 |
goto out_writepage; |
2bca1e238 f2fs: clear page'... |
2001 |
} |
e959c8f54 f2fs: lookup exte... |
2002 |
got_it: |
c9b60788f f2fs: fix to do s... |
2003 2004 |
if (__is_valid_data_blkaddr(fio->old_blkaddr) && !f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr, |
93770ab7a f2fs: introduce D... |
2005 |
DATA_GENERIC_ENHANCE)) { |
10f966bbf f2fs: use generic... |
2006 |
err = -EFSCORRUPTED; |
c9b60788f f2fs: fix to do s... |
2007 2008 |
goto out_writepage; } |
eb47b8009 f2fs: add address... |
2009 2010 2011 2012 |
/* * If current allocation needs SSR, * it had better in-place writes for updated data. */ |
93770ab7a f2fs: introduce D... |
2013 2014 |
if (ipu_force || (__is_valid_data_blkaddr(fio->old_blkaddr) && |
7b525dd01 f2fs: clean up wi... |
2015 |
need_inplace_update(fio))) { |
cc15620bc f2fs: avoid f2fs_... |
2016 2017 2018 2019 2020 |
err = encrypt_one_page(fio); if (err) goto out_writepage; set_page_writeback(page); |
17c500350 f2fs: clear PageE... |
2021 |
ClearPageError(page); |
279d6df20 f2fs: release cp ... |
2022 |
f2fs_put_dnode(&dn); |
cc15620bc f2fs: avoid f2fs_... |
2023 |
if (fio->need_lock == LOCK_REQ) |
279d6df20 f2fs: release cp ... |
2024 |
f2fs_unlock_op(fio->sbi); |
4d57b86dd f2fs: clean up sy... |
2025 |
err = f2fs_inplace_write_data(fio); |
6492a335f f2fs: fix encrypt... |
2026 2027 |
if (err) { if (f2fs_encrypted_file(inode)) |
d2d0727b1 fscrypt: simplify... |
2028 |
fscrypt_finalize_bounce_page(&fio->encrypted_page); |
6492a335f f2fs: fix encrypt... |
2029 2030 |
if (PageWriteback(page)) end_page_writeback(page); |
cd23ffa9f f2fs: fix to set ... |
2031 2032 |
} else { set_inode_flag(inode, FI_UPDATE_WRITE); |
6492a335f f2fs: fix encrypt... |
2033 |
} |
7eab0c0df f2fs: reconstruct... |
2034 |
trace_f2fs_do_write_data_page(fio->page, IPU); |
279d6df20 f2fs: release cp ... |
2035 |
return err; |
eb47b8009 f2fs: add address... |
2036 |
} |
279d6df20 f2fs: release cp ... |
2037 |
|
cc15620bc f2fs: avoid f2fs_... |
2038 2039 2040 2041 2042 2043 2044 |
if (fio->need_lock == LOCK_RETRY) { if (!f2fs_trylock_op(fio->sbi)) { err = -EAGAIN; goto out_writepage; } fio->need_lock = LOCK_REQ; } |
7735730d3 f2fs: fix to prop... |
2045 2046 2047 2048 2049 |
err = f2fs_get_node_info(fio->sbi, dn.nid, &ni); if (err) goto out_writepage; fio->version = ni.version; |
cc15620bc f2fs: avoid f2fs_... |
2050 2051 2052 2053 2054 |
err = encrypt_one_page(fio); if (err) goto out_writepage; set_page_writeback(page); |
17c500350 f2fs: clear PageE... |
2055 |
ClearPageError(page); |
cc15620bc f2fs: avoid f2fs_... |
2056 |
|
279d6df20 f2fs: release cp ... |
2057 |
/* LFS mode write path */ |
4d57b86dd f2fs: clean up sy... |
2058 |
f2fs_outplace_write_data(&dn, fio); |
279d6df20 f2fs: release cp ... |
2059 2060 2061 2062 |
trace_f2fs_do_write_data_page(page, OPU); set_inode_flag(inode, FI_APPEND_WRITE); if (page->index == 0) set_inode_flag(inode, FI_FIRST_BLOCK_WRITTEN); |
eb47b8009 f2fs: add address... |
2063 2064 |
out_writepage: f2fs_put_dnode(&dn); |
279d6df20 f2fs: release cp ... |
2065 |
out: |
cc15620bc f2fs: avoid f2fs_... |
2066 |
if (fio->need_lock == LOCK_REQ) |
279d6df20 f2fs: release cp ... |
2067 |
f2fs_unlock_op(fio->sbi); |
eb47b8009 f2fs: add address... |
2068 2069 |
return err; } |
d68f735b3 f2fs: check io su... |
2070 |
static int __write_data_page(struct page *page, bool *submitted, |
8648de2c5 f2fs: add bio cac... |
2071 2072 |
struct bio **bio, sector_t *last_block, |
b0af6d491 f2fs: add app/fs ... |
2073 2074 |
struct writeback_control *wbc, enum iostat_type io_type) |
eb47b8009 f2fs: add address... |
2075 2076 |
{ struct inode *inode = page->mapping->host; |
4081363fb f2fs: introduce F... |
2077 |
struct f2fs_sb_info *sbi = F2FS_I_SB(inode); |
eb47b8009 f2fs: add address... |
2078 2079 |
loff_t i_size = i_size_read(inode); const pgoff_t end_index = ((unsigned long long) i_size) |
09cbfeaf1 mm, fs: get rid o... |
2080 |
>> PAGE_SHIFT; |
1f0d5c911 f2fs: fix potenti... |
2081 |
loff_t psize = (loff_t)(page->index + 1) << PAGE_SHIFT; |
9ffe0fb5f f2fs: handle inli... |
2082 |
unsigned offset = 0; |
399368372 f2fs: introduce a... |
2083 |
bool need_balance_fs = false; |
eb47b8009 f2fs: add address... |
2084 |
int err = 0; |
458e6197c f2fs: refactor bi... |
2085 |
struct f2fs_io_info fio = { |
05ca3632e f2fs: add sbi and... |
2086 |
.sbi = sbi, |
39d787bec f2fs: enhance mul... |
2087 |
.ino = inode->i_ino, |
458e6197c f2fs: refactor bi... |
2088 |
.type = DATA, |
04d328def f2fs: use bio op ... |
2089 |
.op = REQ_OP_WRITE, |
7637241e6 writeback: add wb... |
2090 |
.op_flags = wbc_to_write_flags(wbc), |
e959c8f54 f2fs: lookup exte... |
2091 |
.old_blkaddr = NULL_ADDR, |
05ca3632e f2fs: add sbi and... |
2092 |
.page = page, |
4375a3366 f2fs crypto: add ... |
2093 |
.encrypted_page = NULL, |
d68f735b3 f2fs: check io su... |
2094 |
.submitted = false, |
cc15620bc f2fs: avoid f2fs_... |
2095 |
.need_lock = LOCK_RETRY, |
b0af6d491 f2fs: add app/fs ... |
2096 |
.io_type = io_type, |
578c64787 f2fs: implement c... |
2097 |
.io_wbc = wbc, |
8648de2c5 f2fs: add bio cac... |
2098 2099 |
.bio = bio, .last_block = last_block, |
458e6197c f2fs: refactor bi... |
2100 |
}; |
eb47b8009 f2fs: add address... |
2101 |
|
ecda0de34 f2fs: add a trace... |
2102 |
trace_f2fs_writepage(page, DATA); |
db198ae0f f2fs: drop page c... |
2103 2104 2105 |
/* we should bypass data pages to proceed the kworkder jobs */ if (unlikely(f2fs_cp_error(sbi))) { mapping_set_error(page->mapping, -EIO); |
1174abfd8 f2fs: don't drop ... |
2106 2107 2108 2109 2110 2111 |
/* * don't drop any dirty dentry pages for keeping lastest * directory structure. */ if (S_ISDIR(inode->i_mode)) goto redirty_out; |
db198ae0f f2fs: drop page c... |
2112 2113 |
goto out; } |
0771fcc71 f2fs: skip ->writ... |
2114 2115 |
if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) goto redirty_out; |
95ae251fe f2fs: add fs-veri... |
2116 |
if (page->index < end_index || f2fs_verity_in_progress(inode)) |
399368372 f2fs: introduce a... |
2117 |
goto write; |
eb47b8009 f2fs: add address... |
2118 2119 2120 2121 2122 |
/* * If the offset is out-of-range of file size, * this page does not have to be written to disk. */ |
09cbfeaf1 mm, fs: get rid o... |
2123 |
offset = i_size & (PAGE_SIZE - 1); |
76f60268e f2fs: call redirt... |
2124 |
if ((page->index >= end_index + 1) || !offset) |
399368372 f2fs: introduce a... |
2125 |
goto out; |
eb47b8009 f2fs: add address... |
2126 |
|
09cbfeaf1 mm, fs: get rid o... |
2127 |
zero_user_segment(page, offset, PAGE_SIZE); |
399368372 f2fs: introduce a... |
2128 |
write: |
1e84371ff f2fs: change atom... |
2129 2130 |
if (f2fs_is_drop_cache(inode)) goto out; |
e6e5f5610 f2fs: avoid writi... |
2131 2132 2133 |
/* we should not write 0'th page having journal header */ if (f2fs_is_volatile_file(inode) && (!page->index || (!wbc->for_reclaim && |
4d57b86dd f2fs: clean up sy... |
2134 |
f2fs_available_free_memory(sbi, BASE_CHECK)))) |
1e84371ff f2fs: change atom... |
2135 |
goto redirty_out; |
eb47b8009 f2fs: add address... |
2136 |
|
399368372 f2fs: introduce a... |
2137 |
/* Dentry blocks are controlled by checkpoint */ |
eb47b8009 f2fs: add address... |
2138 |
if (S_ISDIR(inode->i_mode)) { |
cc15620bc f2fs: avoid f2fs_... |
2139 |
fio.need_lock = LOCK_DONE; |
4d57b86dd f2fs: clean up sy... |
2140 |
err = f2fs_do_write_data_page(&fio); |
8618b881e f2fs: fix not to ... |
2141 2142 |
goto done; } |
9ffe0fb5f f2fs: handle inli... |
2143 |
|
8618b881e f2fs: fix not to ... |
2144 |
if (!wbc->for_reclaim) |
399368372 f2fs: introduce a... |
2145 |
need_balance_fs = true; |
7f3037a5e f2fs: check free_... |
2146 |
else if (has_not_enough_free_secs(sbi, 0, 0)) |
399368372 f2fs: introduce a... |
2147 |
goto redirty_out; |
ef095d19e f2fs: write small... |
2148 2149 |
else set_inode_flag(inode, FI_HOT_DATA); |
eb47b8009 f2fs: add address... |
2150 |
|
b3d208f96 f2fs: revisit inl... |
2151 |
err = -EAGAIN; |
dd7b2333e f2fs: no need loc... |
2152 |
if (f2fs_has_inline_data(inode)) { |
b3d208f96 f2fs: revisit inl... |
2153 |
err = f2fs_write_inline_data(inode, page); |
dd7b2333e f2fs: no need loc... |
2154 2155 2156 |
if (!err) goto out; } |
279d6df20 f2fs: release cp ... |
2157 |
|
cc15620bc f2fs: avoid f2fs_... |
2158 |
if (err == -EAGAIN) { |
4d57b86dd f2fs: clean up sy... |
2159 |
err = f2fs_do_write_data_page(&fio); |
cc15620bc f2fs: avoid f2fs_... |
2160 2161 |
if (err == -EAGAIN) { fio.need_lock = LOCK_REQ; |
4d57b86dd f2fs: clean up sy... |
2162 |
err = f2fs_do_write_data_page(&fio); |
cc15620bc f2fs: avoid f2fs_... |
2163 2164 |
} } |
a0d00fad3 f2fs: fix to avoi... |
2165 |
|
eb4497975 f2fs: fix to upda... |
2166 2167 2168 2169 2170 2171 2172 2173 |
if (err) { file_set_keep_isize(inode); } else { down_write(&F2FS_I(inode)->i_sem); if (F2FS_I(inode)->last_disk_size < psize) F2FS_I(inode)->last_disk_size = psize; up_write(&F2FS_I(inode)->i_sem); } |
279d6df20 f2fs: release cp ... |
2174 |
|
8618b881e f2fs: fix not to ... |
2175 2176 2177 |
done: if (err && err != -ENOENT) goto redirty_out; |
eb47b8009 f2fs: add address... |
2178 |
|
399368372 f2fs: introduce a... |
2179 |
out: |
a7ffdbe22 f2fs: expand coun... |
2180 |
inode_dec_dirty_pages(inode); |
2baf07818 f2fs: fix to spre... |
2181 |
if (err) { |
2bca1e238 f2fs: clear page'... |
2182 |
ClearPageUptodate(page); |
2baf07818 f2fs: fix to spre... |
2183 2184 |
clear_cold_data(page); } |
0c3a57975 f2fs: introduce f... |
2185 2186 |
if (wbc->for_reclaim) { |
bab475c54 Revert: "f2fs: ch... |
2187 |
f2fs_submit_merged_write_cond(sbi, NULL, page, 0, DATA); |
ef095d19e f2fs: write small... |
2188 |
clear_inode_flag(inode, FI_HOT_DATA); |
4d57b86dd f2fs: clean up sy... |
2189 |
f2fs_remove_dirty_inode(inode); |
d68f735b3 f2fs: check io su... |
2190 |
submitted = NULL; |
0c3a57975 f2fs: introduce f... |
2191 |
} |
eb47b8009 f2fs: add address... |
2192 |
unlock_page(page); |
186857c5a f2fs: fix potenti... |
2193 |
if (!S_ISDIR(inode->i_mode) && !IS_NOQUOTA(inode) && |
0b20fcec8 f2fs: cache globa... |
2194 |
!F2FS_I(inode)->cp_task) |
a78818930 f2fs: fix out-of ... |
2195 |
f2fs_balance_fs(sbi, need_balance_fs); |
0c3a57975 f2fs: introduce f... |
2196 |
|
d68f735b3 f2fs: check io su... |
2197 |
if (unlikely(f2fs_cp_error(sbi))) { |
b9109b0e4 f2fs: remove unne... |
2198 |
f2fs_submit_merged_write(sbi, DATA); |
0b20fcec8 f2fs: cache globa... |
2199 |
f2fs_submit_merged_ipu_write(sbi, bio, NULL); |
d68f735b3 f2fs: check io su... |
2200 2201 2202 2203 2204 |
submitted = NULL; } if (submitted) *submitted = fio.submitted; |
0c3a57975 f2fs: introduce f... |
2205 |
|
eb47b8009 f2fs: add address... |
2206 |
return 0; |
eb47b8009 f2fs: add address... |
2207 |
redirty_out: |
76f60268e f2fs: call redirt... |
2208 |
redirty_page_for_writepage(wbc, page); |
5b19d284f f2fs: avoid fsync... |
2209 2210 2211 2212 2213 2214 2215 |
/* * pageout() in MM traslates EAGAIN, so calls handle_write_error() * -> mapping_set_error() -> set_bit(AS_EIO, ...). * file_write_and_wait_range() will see EIO error, which is critical * to return value of fsync() followed by atomic_write failure to user. */ if (!err || wbc->for_reclaim) |
0002b61bd f2fs: return AOP_... |
2216 |
return AOP_WRITEPAGE_ACTIVATE; |
b230e6cab f2fs: handle writ... |
2217 2218 |
unlock_page(page); return err; |
fa9150a84 f2fs: remove the ... |
2219 |
} |
f566bae84 f2fs: call intern... |
2220 2221 2222 |
static int f2fs_write_data_page(struct page *page, struct writeback_control *wbc) { |
8648de2c5 f2fs: add bio cac... |
2223 |
return __write_data_page(page, NULL, NULL, NULL, wbc, FS_DATA_IO); |
f566bae84 f2fs: call intern... |
2224 |
} |
8f46dcaea f2fs: expose f2fs... |
2225 2226 2227 2228 2229 2230 |
/* * This function was copied from write_cche_pages from mm/page-writeback.c. * The major change is making write step of cold data page separately from * warm/hot data page. */ static int f2fs_write_cache_pages(struct address_space *mapping, |
b0af6d491 f2fs: add app/fs ... |
2231 2232 |
struct writeback_control *wbc, enum iostat_type io_type) |
8f46dcaea f2fs: expose f2fs... |
2233 2234 2235 2236 |
{ int ret = 0; int done = 0; struct pagevec pvec; |
c29fd0c0e f2fs: let sync no... |
2237 |
struct f2fs_sb_info *sbi = F2FS_M_SB(mapping); |
8648de2c5 f2fs: add bio cac... |
2238 2239 |
struct bio *bio = NULL; sector_t last_block; |
8f46dcaea f2fs: expose f2fs... |
2240 2241 2242 2243 2244 2245 2246 |
int nr_pages; pgoff_t uninitialized_var(writeback_index); pgoff_t index; pgoff_t end; /* Inclusive */ pgoff_t done_index; int cycled; int range_whole = 0; |
10bbd2358 pagevec: Use xa_m... |
2247 |
xa_mark_t tag; |
bab475c54 Revert: "f2fs: ch... |
2248 |
int nwritten = 0; |
8f46dcaea f2fs: expose f2fs... |
2249 |
|
866798201 mm, pagevec: remo... |
2250 |
pagevec_init(&pvec); |
46ae957f9 f2fs: remove two ... |
2251 |
|
ef095d19e f2fs: write small... |
2252 2253 2254 2255 2256 |
if (get_dirty_pages(mapping->host) <= SM_I(F2FS_M_SB(mapping))->min_hot_blocks) set_inode_flag(mapping->host, FI_HOT_DATA); else clear_inode_flag(mapping->host, FI_HOT_DATA); |
8f46dcaea f2fs: expose f2fs... |
2257 2258 2259 2260 2261 2262 2263 2264 2265 |
if (wbc->range_cyclic) { writeback_index = mapping->writeback_index; /* prev offset */ index = writeback_index; if (index == 0) cycled = 1; else cycled = 0; end = -1; } else { |
09cbfeaf1 mm, fs: get rid o... |
2266 2267 |
index = wbc->range_start >> PAGE_SHIFT; end = wbc->range_end >> PAGE_SHIFT; |
8f46dcaea f2fs: expose f2fs... |
2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 |
if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) range_whole = 1; cycled = 1; /* ignore range_cyclic tests */ } if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages) tag = PAGECACHE_TAG_TOWRITE; else tag = PAGECACHE_TAG_DIRTY; retry: if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages) tag_pages_for_writeback(mapping, index, end); done_index = index; while (!done && (index <= end)) { int i; |
69c4f35d2 f2fs: use pagevec... |
2282 |
nr_pages = pagevec_lookup_range_tag(&pvec, mapping, &index, end, |
67fd707f4 mm: remove nr_pag... |
2283 |
tag); |
8f46dcaea f2fs: expose f2fs... |
2284 2285 2286 2287 2288 |
if (nr_pages == 0) break; for (i = 0; i < nr_pages; i++) { struct page *page = pvec.pages[i]; |
d68f735b3 f2fs: check io su... |
2289 |
bool submitted = false; |
8f46dcaea f2fs: expose f2fs... |
2290 |
|
f8de43312 f2fs: detect sync... |
2291 |
/* give a priority to WB_SYNC threads */ |
c29fd0c0e f2fs: let sync no... |
2292 |
if (atomic_read(&sbi->wb_sync_req[DATA]) && |
f8de43312 f2fs: detect sync... |
2293 2294 2295 2296 |
wbc->sync_mode == WB_SYNC_NONE) { done = 1; break; } |
8f46dcaea f2fs: expose f2fs... |
2297 |
done_index = page->index; |
d29460e5c f2fs: avoid deadl... |
2298 |
retry_write: |
8f46dcaea f2fs: expose f2fs... |
2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 |
lock_page(page); if (unlikely(page->mapping != mapping)) { continue_unlock: unlock_page(page); continue; } if (!PageDirty(page)) { /* someone wrote it for us */ goto continue_unlock; } |
8f46dcaea f2fs: expose f2fs... |
2311 |
if (PageWriteback(page)) { |
0b20fcec8 f2fs: cache globa... |
2312 |
if (wbc->sync_mode != WB_SYNC_NONE) |
fec1d6576 f2fs: use wait_fo... |
2313 |
f2fs_wait_on_page_writeback(page, |
bae0ee7a7 f2fs: check PageW... |
2314 |
DATA, true, true); |
0b20fcec8 f2fs: cache globa... |
2315 |
else |
8f46dcaea f2fs: expose f2fs... |
2316 2317 |
goto continue_unlock; } |
8f46dcaea f2fs: expose f2fs... |
2318 2319 |
if (!clear_page_dirty_for_io(page)) goto continue_unlock; |
8648de2c5 f2fs: add bio cac... |
2320 2321 |
ret = __write_data_page(page, &submitted, &bio, &last_block, wbc, io_type); |
8f46dcaea f2fs: expose f2fs... |
2322 |
if (unlikely(ret)) { |
0002b61bd f2fs: return AOP_... |
2323 2324 2325 2326 2327 2328 2329 2330 |
/* * keep nr_to_write, since vfs uses this to * get # of written pages. */ if (ret == AOP_WRITEPAGE_ACTIVATE) { unlock_page(page); ret = 0; continue; |
d29460e5c f2fs: avoid deadl... |
2331 2332 2333 2334 2335 2336 2337 2338 2339 |
} else if (ret == -EAGAIN) { ret = 0; if (wbc->sync_mode == WB_SYNC_ALL) { cond_resched(); congestion_wait(BLK_RW_ASYNC, HZ/50); goto retry_write; } continue; |
0002b61bd f2fs: return AOP_... |
2340 |
} |
b230e6cab f2fs: handle writ... |
2341 2342 2343 |
done_index = page->index + 1; done = 1; break; |
d68f735b3 f2fs: check io su... |
2344 |
} else if (submitted) { |
bab475c54 Revert: "f2fs: ch... |
2345 |
nwritten++; |
8f46dcaea f2fs: expose f2fs... |
2346 |
} |
f8de43312 f2fs: detect sync... |
2347 |
if (--wbc->nr_to_write <= 0 && |
687de7f10 f2fs: avoid IO sp... |
2348 |
wbc->sync_mode == WB_SYNC_NONE) { |
8f46dcaea f2fs: expose f2fs... |
2349 2350 2351 2352 2353 2354 2355 |
done = 1; break; } } pagevec_release(&pvec); cond_resched(); } |
8f46dcaea f2fs: expose f2fs... |
2356 2357 2358 2359 2360 2361 2362 2363 |
if (!cycled && !done) { cycled = 1; index = 0; end = writeback_index - 1; goto retry; } if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) mapping->writeback_index = done_index; |
bab475c54 Revert: "f2fs: ch... |
2364 |
if (nwritten) |
b9109b0e4 f2fs: remove unne... |
2365 |
f2fs_submit_merged_write_cond(F2FS_M_SB(mapping), mapping->host, |
bab475c54 Revert: "f2fs: ch... |
2366 |
NULL, 0, DATA); |
8648de2c5 f2fs: add bio cac... |
2367 2368 |
/* submit cached bio of IPU write */ if (bio) |
0b20fcec8 f2fs: cache globa... |
2369 |
f2fs_submit_merged_ipu_write(sbi, &bio, NULL); |
6ca56ca42 f2fs: don't submi... |
2370 |
|
8f46dcaea f2fs: expose f2fs... |
2371 2372 |
return ret; } |
853137cef f2fs: fix perform... |
2373 2374 2375 2376 2377 |
static inline bool __should_serialize_io(struct inode *inode, struct writeback_control *wbc) { if (!S_ISREG(inode->i_mode)) return false; |
af033b2aa f2fs: guarantee j... |
2378 2379 |
if (IS_NOQUOTA(inode)) return false; |
040d2bb31 f2fs: fix to avoi... |
2380 2381 2382 |
/* to avoid deadlock in path of data flush */ if (F2FS_I(inode)->cp_task) return false; |
853137cef f2fs: fix perform... |
2383 2384 2385 2386 2387 2388 |
if (wbc->sync_mode != WB_SYNC_ALL) return true; if (get_dirty_pages(inode) >= SM_I(F2FS_I_SB(inode))->min_seq_blocks) return true; return false; } |
fc99fe27b f2fs: make __f2fs... |
2389 |
static int __f2fs_write_data_pages(struct address_space *mapping, |
b0af6d491 f2fs: add app/fs ... |
2390 2391 |
struct writeback_control *wbc, enum iostat_type io_type) |
eb47b8009 f2fs: add address... |
2392 2393 |
{ struct inode *inode = mapping->host; |
4081363fb f2fs: introduce F... |
2394 |
struct f2fs_sb_info *sbi = F2FS_I_SB(inode); |
9dfa1baff f2fs: use blk_plu... |
2395 |
struct blk_plug plug; |
eb47b8009 f2fs: add address... |
2396 |
int ret; |
853137cef f2fs: fix perform... |
2397 |
bool locked = false; |
eb47b8009 f2fs: add address... |
2398 |
|
cfb185a14 f2fs: add NULL po... |
2399 2400 2401 |
/* deal with chardevs and other special file */ if (!mapping->a_ops->writepage) return 0; |
6a2905443 f2fs: skip writin... |
2402 2403 2404 |
/* skip writing if there is no dirty page in this inode */ if (!get_dirty_pages(inode) && wbc->sync_mode == WB_SYNC_NONE) return 0; |
0771fcc71 f2fs: skip ->writ... |
2405 2406 2407 |
/* during POR, we don't need to trigger writepage at all. */ if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) goto skip_write; |
af033b2aa f2fs: guarantee j... |
2408 2409 |
if ((S_ISDIR(inode->i_mode) || IS_NOQUOTA(inode)) && wbc->sync_mode == WB_SYNC_NONE && |
a12570232 Revert "f2fs: do ... |
2410 |
get_dirty_pages(inode) < nr_pages_to_skip(sbi, DATA) && |
4d57b86dd f2fs: clean up sy... |
2411 |
f2fs_available_free_memory(sbi, DIRTY_DENTS)) |
a12570232 Revert "f2fs: do ... |
2412 |
goto skip_write; |
d323d005a f2fs: support fil... |
2413 |
/* skip writing during file defragment */ |
91942321e f2fs: use inode p... |
2414 |
if (is_inode_flag_set(inode, FI_DO_DEFRAG)) |
d323d005a f2fs: support fil... |
2415 |
goto skip_write; |
d31c7c3f0 f2fs: fix missing... |
2416 |
trace_f2fs_writepages(mapping->host, wbc, DATA); |
687de7f10 f2fs: avoid IO sp... |
2417 2418 |
/* to avoid spliting IOs due to mixed WB_SYNC_ALL and WB_SYNC_NONE */ if (wbc->sync_mode == WB_SYNC_ALL) |
c29fd0c0e f2fs: let sync no... |
2419 2420 |
atomic_inc(&sbi->wb_sync_req[DATA]); else if (atomic_read(&sbi->wb_sync_req[DATA])) |
687de7f10 f2fs: avoid IO sp... |
2421 |
goto skip_write; |
853137cef f2fs: fix perform... |
2422 2423 2424 2425 |
if (__should_serialize_io(inode, wbc)) { mutex_lock(&sbi->writepages); locked = true; } |
9dfa1baff f2fs: use blk_plu... |
2426 |
blk_start_plug(&plug); |
b0af6d491 f2fs: add app/fs ... |
2427 |
ret = f2fs_write_cache_pages(mapping, wbc, io_type); |
9dfa1baff f2fs: use blk_plu... |
2428 |
blk_finish_plug(&plug); |
687de7f10 f2fs: avoid IO sp... |
2429 |
|
853137cef f2fs: fix perform... |
2430 2431 |
if (locked) mutex_unlock(&sbi->writepages); |
687de7f10 f2fs: avoid IO sp... |
2432 |
if (wbc->sync_mode == WB_SYNC_ALL) |
c29fd0c0e f2fs: let sync no... |
2433 |
atomic_dec(&sbi->wb_sync_req[DATA]); |
28ea6162e f2fs: do not skip... |
2434 2435 2436 2437 |
/* * if some pages were truncated, we cannot guarantee its mapping->host * to detect pending bios. */ |
458e6197c f2fs: refactor bi... |
2438 |
|
4d57b86dd f2fs: clean up sy... |
2439 |
f2fs_remove_dirty_inode(inode); |
eb47b8009 f2fs: add address... |
2440 |
return ret; |
d3baf95da f2fs: increase pa... |
2441 2442 |
skip_write: |
a7ffdbe22 f2fs: expand coun... |
2443 |
wbc->pages_skipped += get_dirty_pages(inode); |
d31c7c3f0 f2fs: fix missing... |
2444 |
trace_f2fs_writepages(mapping->host, wbc, DATA); |
d3baf95da f2fs: increase pa... |
2445 |
return 0; |
eb47b8009 f2fs: add address... |
2446 |
} |
b0af6d491 f2fs: add app/fs ... |
2447 2448 2449 2450 2451 2452 2453 2454 2455 |
static int f2fs_write_data_pages(struct address_space *mapping, struct writeback_control *wbc) { struct inode *inode = mapping->host; return __f2fs_write_data_pages(mapping, wbc, F2FS_I(inode)->cp_task == current ? FS_CP_DATA_IO : FS_DATA_IO); } |
3aab8f828 f2fs: introduce f... |
2456 2457 2458 |
static void f2fs_write_failed(struct address_space *mapping, loff_t to) { struct inode *inode = mapping->host; |
819d9153d f2fs: use i_size_... |
2459 |
loff_t i_size = i_size_read(inode); |
3aab8f828 f2fs: introduce f... |
2460 |
|
95ae251fe f2fs: add fs-veri... |
2461 2462 |
/* In the fs-verity case, f2fs_end_enable_verity() does the truncate */ if (to > i_size && !f2fs_verity_in_progress(inode)) { |
a33c15023 f2fs: fix avoid r... |
2463 |
down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); |
6f8d44550 f2fs: avoid fi->i... |
2464 |
down_write(&F2FS_I(inode)->i_mmap_sem); |
a33c15023 f2fs: fix avoid r... |
2465 |
|
819d9153d f2fs: use i_size_... |
2466 |
truncate_pagecache(inode, i_size); |
c42d28ce3 f2fs: fix potenti... |
2467 2468 |
if (!IS_NOQUOTA(inode)) f2fs_truncate_blocks(inode, i_size, true); |
a33c15023 f2fs: fix avoid r... |
2469 |
|
5a3a2d83c f2fs: dax: fix ra... |
2470 |
up_write(&F2FS_I(inode)->i_mmap_sem); |
6f8d44550 f2fs: avoid fi->i... |
2471 |
up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); |
3aab8f828 f2fs: introduce f... |
2472 2473 |
} } |
2aadac085 f2fs: introduce p... |
2474 2475 2476 2477 2478 2479 2480 2481 |
static int prepare_write_begin(struct f2fs_sb_info *sbi, struct page *page, loff_t pos, unsigned len, block_t *blk_addr, bool *node_changed) { struct inode *inode = page->mapping->host; pgoff_t index = page->index; struct dnode_of_data dn; struct page *ipage; |
b4d07a3e1 f2fs: avoid f2fs_... |
2482 |
bool locked = false; |
e15882b6c f2fs: init local ... |
2483 |
struct extent_info ei = {0,0,0}; |
2aadac085 f2fs: introduce p... |
2484 |
int err = 0; |
2866fb16d f2fs: fix race be... |
2485 |
int flag; |
2aadac085 f2fs: introduce p... |
2486 |
|
24b849125 f2fs: preallocate... |
2487 2488 2489 2490 |
/* * we already allocated all the blocks, so we don't need to get * the block addresses when there is no need to fill the page. */ |
dc91de78e f2fs: do not prea... |
2491 |
if (!f2fs_has_inline_data(inode) && len == PAGE_SIZE && |
95ae251fe f2fs: add fs-veri... |
2492 2493 |
!is_inode_flag_set(inode, FI_NO_PREALLOC) && !f2fs_verity_in_progress(inode)) |
24b849125 f2fs: preallocate... |
2494 |
return 0; |
2866fb16d f2fs: fix race be... |
2495 2496 2497 2498 2499 |
/* f2fs_lock_op avoids race between write CP and convert_inline_page */ if (f2fs_has_inline_data(inode) && pos + len > MAX_INLINE_DATA(inode)) flag = F2FS_GET_BLOCK_DEFAULT; else flag = F2FS_GET_BLOCK_PRE_AIO; |
b4d07a3e1 f2fs: avoid f2fs_... |
2500 |
if (f2fs_has_inline_data(inode) || |
09cbfeaf1 mm, fs: get rid o... |
2501 |
(pos & PAGE_MASK) >= i_size_read(inode)) { |
2866fb16d f2fs: fix race be... |
2502 |
__do_map_lock(sbi, flag, true); |
b4d07a3e1 f2fs: avoid f2fs_... |
2503 2504 2505 |
locked = true; } restart: |
2aadac085 f2fs: introduce p... |
2506 |
/* check inline_data */ |
4d57b86dd f2fs: clean up sy... |
2507 |
ipage = f2fs_get_node_page(sbi, inode->i_ino); |
2aadac085 f2fs: introduce p... |
2508 2509 2510 2511 2512 2513 2514 2515 |
if (IS_ERR(ipage)) { err = PTR_ERR(ipage); goto unlock_out; } set_new_dnode(&dn, inode, ipage, ipage, 0); if (f2fs_has_inline_data(inode)) { |
f24703712 f2fs: make max in... |
2516 |
if (pos + len <= MAX_INLINE_DATA(inode)) { |
4d57b86dd f2fs: clean up sy... |
2517 |
f2fs_do_read_inline_data(page, ipage); |
91942321e f2fs: use inode p... |
2518 |
set_inode_flag(inode, FI_DATA_EXIST); |
ab47036d8 f2fs: fix deadloc... |
2519 2520 |
if (inode->i_nlink) set_inline_node(ipage); |
2aadac085 f2fs: introduce p... |
2521 2522 2523 |
} else { err = f2fs_convert_inline_page(&dn, page); if (err) |
b4d07a3e1 f2fs: avoid f2fs_... |
2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 |
goto out; if (dn.data_blkaddr == NULL_ADDR) err = f2fs_get_block(&dn, index); } } else if (locked) { err = f2fs_get_block(&dn, index); } else { if (f2fs_lookup_extent_cache(inode, index, &ei)) { dn.data_blkaddr = ei.blk + index - ei.fofs; } else { |
b4d07a3e1 f2fs: avoid f2fs_... |
2534 |
/* hole case */ |
4d57b86dd f2fs: clean up sy... |
2535 |
err = f2fs_get_dnode_of_data(&dn, index, LOOKUP_NODE); |
4da7bf5a4 f2fs: remove redu... |
2536 |
if (err || dn.data_blkaddr == NULL_ADDR) { |
b4d07a3e1 f2fs: avoid f2fs_... |
2537 |
f2fs_put_dnode(&dn); |
59c9081bc f2fs: allow write... |
2538 2539 |
__do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, true); |
2866fb16d f2fs: fix race be... |
2540 |
WARN_ON(flag != F2FS_GET_BLOCK_PRE_AIO); |
b4d07a3e1 f2fs: avoid f2fs_... |
2541 2542 2543 |
locked = true; goto restart; } |
2aadac085 f2fs: introduce p... |
2544 2545 |
} } |
b4d07a3e1 f2fs: avoid f2fs_... |
2546 |
|
2aadac085 f2fs: introduce p... |
2547 2548 2549 |
/* convert_inline_page can make node_changed */ *blk_addr = dn.data_blkaddr; *node_changed = dn.node_changed; |
b4d07a3e1 f2fs: avoid f2fs_... |
2550 |
out: |
2aadac085 f2fs: introduce p... |
2551 2552 |
f2fs_put_dnode(&dn); unlock_out: |
b4d07a3e1 f2fs: avoid f2fs_... |
2553 |
if (locked) |
2866fb16d f2fs: fix race be... |
2554 |
__do_map_lock(sbi, flag, false); |
2aadac085 f2fs: introduce p... |
2555 2556 |
return err; } |
eb47b8009 f2fs: add address... |
2557 2558 2559 2560 2561 |
static int f2fs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { struct inode *inode = mapping->host; |
4081363fb f2fs: introduce F... |
2562 |
struct f2fs_sb_info *sbi = F2FS_I_SB(inode); |
86531d6b8 f2fs: callers tak... |
2563 |
struct page *page = NULL; |
09cbfeaf1 mm, fs: get rid o... |
2564 |
pgoff_t index = ((unsigned long long) pos) >> PAGE_SHIFT; |
a2e2e76b2 f2fs: fix to drop... |
2565 |
bool need_balance = false, drop_atomic = false; |
2aadac085 f2fs: introduce p... |
2566 |
block_t blkaddr = NULL_ADDR; |
eb47b8009 f2fs: add address... |
2567 |
int err = 0; |
62aed044e f2fs: add a trace... |
2568 |
trace_f2fs_write_begin(inode, pos, len, flags); |
00e09c0bc f2fs: enhance f2f... |
2569 2570 |
if (!f2fs_is_checkpoint_ready(sbi)) { err = -ENOSPC; |
4354994f0 f2fs: checkpoint ... |
2571 |
goto fail; |
00e09c0bc f2fs: enhance f2f... |
2572 |
} |
4354994f0 f2fs: checkpoint ... |
2573 |
|
455e3a588 f2fs: don't allow... |
2574 2575 2576 |
if ((f2fs_is_atomic_file(inode) && !f2fs_available_free_memory(sbi, INMEM_PAGES)) || is_inode_flag_set(inode, FI_ATOMIC_REVOKE_REQUEST)) { |
57864ae5c f2fs: limit # of ... |
2577 |
err = -ENOMEM; |
a2e2e76b2 f2fs: fix to drop... |
2578 |
drop_atomic = true; |
57864ae5c f2fs: limit # of ... |
2579 2580 |
goto fail; } |
5f7273958 f2fs: fix deadloc... |
2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 |
/* * We should check this at this moment to avoid deadlock on inode page * and #0 page. The locking rule for inline_data conversion should be: * lock_page(page #0) -> lock_page(inode_page) */ if (index != 0) { err = f2fs_convert_inline_inode(inode); if (err) goto fail; } |
afcb7ca01 f2fs: check trunc... |
2591 |
repeat: |
86d54795c f2fs: do not wait... |
2592 2593 2594 2595 |
/* * Do not use grab_cache_page_write_begin() to avoid deadlock due to * wait_for_stable_page. Will wait that below with our IO control. */ |
01eccef79 f2fs: support get... |
2596 |
page = f2fs_pagecache_get_page(mapping, index, |
86d54795c f2fs: do not wait... |
2597 |
FGP_LOCK | FGP_WRITE | FGP_CREAT, GFP_NOFS); |
3aab8f828 f2fs: introduce f... |
2598 2599 2600 2601 |
if (!page) { err = -ENOMEM; goto fail; } |
d5f66990b f2fs: decrease th... |
2602 |
|
eb47b8009 f2fs: add address... |
2603 |
*pagep = page; |
2aadac085 f2fs: introduce p... |
2604 2605 |
err = prepare_write_begin(sbi, page, pos, len, &blkaddr, &need_balance); |
9ba69cf98 f2fs: avoid to al... |
2606 |
if (err) |
2aadac085 f2fs: introduce p... |
2607 |
goto fail; |
9ba69cf98 f2fs: avoid to al... |
2608 |
|
af033b2aa f2fs: guarantee j... |
2609 2610 |
if (need_balance && !IS_NOQUOTA(inode) && has_not_enough_free_secs(sbi, 0, 0)) { |
2a3407607 f2fs: call f2fs_b... |
2611 |
unlock_page(page); |
2c4db1a6f f2fs: clean up f2... |
2612 |
f2fs_balance_fs(sbi, true); |
2a3407607 f2fs: call f2fs_b... |
2613 2614 2615 2616 2617 2618 2619 |
lock_page(page); if (page->mapping != mapping) { /* The page got truncated from under us */ f2fs_put_page(page, 1); goto repeat; } } |
bae0ee7a7 f2fs: check PageW... |
2620 |
f2fs_wait_on_page_writeback(page, DATA, false, true); |
b3d208f96 f2fs: revisit inl... |
2621 |
|
649d7df29 f2fs: fix to set ... |
2622 2623 |
if (len == PAGE_SIZE || PageUptodate(page)) return 0; |
eb47b8009 f2fs: add address... |
2624 |
|
95ae251fe f2fs: add fs-veri... |
2625 2626 |
if (!(pos & (PAGE_SIZE - 1)) && (pos + len) >= i_size_read(inode) && !f2fs_verity_in_progress(inode)) { |
746e24039 f2fs: add a case ... |
2627 2628 2629 |
zero_user_segment(page, len, PAGE_SIZE); return 0; } |
2aadac085 f2fs: introduce p... |
2630 |
if (blkaddr == NEW_ADDR) { |
09cbfeaf1 mm, fs: get rid o... |
2631 |
zero_user_segment(page, 0, PAGE_SIZE); |
649d7df29 f2fs: fix to set ... |
2632 |
SetPageUptodate(page); |
eb47b8009 f2fs: add address... |
2633 |
} else { |
93770ab7a f2fs: introduce D... |
2634 2635 |
if (!f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC_ENHANCE_READ)) { |
10f966bbf f2fs: use generic... |
2636 |
err = -EFSCORRUPTED; |
93770ab7a f2fs: introduce D... |
2637 2638 |
goto fail; } |
13ba41e34 f2fs: make get_lo... |
2639 2640 |
err = f2fs_submit_page_read(inode, page, blkaddr); if (err) |
78682f794 f2fs: fix to avoi... |
2641 |
goto fail; |
d54c795b4 f2fs: fix error p... |
2642 |
|
393ff91f5 f2fs: reduce unnc... |
2643 |
lock_page(page); |
6bacf52fb f2fs: add unlikel... |
2644 |
if (unlikely(page->mapping != mapping)) { |
afcb7ca01 f2fs: check trunc... |
2645 2646 |
f2fs_put_page(page, 1); goto repeat; |
eb47b8009 f2fs: add address... |
2647 |
} |
1563ac75e f2fs: fix to dete... |
2648 2649 2650 |
if (unlikely(!PageUptodate(page))) { err = -EIO; goto fail; |
4375a3366 f2fs crypto: add ... |
2651 |
} |
eb47b8009 f2fs: add address... |
2652 |
} |
eb47b8009 f2fs: add address... |
2653 |
return 0; |
9ba69cf98 f2fs: avoid to al... |
2654 |
|
3aab8f828 f2fs: introduce f... |
2655 |
fail: |
86531d6b8 f2fs: callers tak... |
2656 |
f2fs_put_page(page, 1); |
3aab8f828 f2fs: introduce f... |
2657 |
f2fs_write_failed(mapping, pos + len); |
a2e2e76b2 f2fs: fix to drop... |
2658 |
if (drop_atomic) |
4d57b86dd f2fs: clean up sy... |
2659 |
f2fs_drop_inmem_pages_all(sbi, false); |
3aab8f828 f2fs: introduce f... |
2660 |
return err; |
eb47b8009 f2fs: add address... |
2661 |
} |
a1dd3c13c f2fs: fix to reco... |
2662 2663 2664 2665 2666 2667 |
static int f2fs_write_end(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned copied, struct page *page, void *fsdata) { struct inode *inode = page->mapping->host; |
dfb2bf38b f2fs: add a trace... |
2668 |
trace_f2fs_write_end(inode, pos, len, copied); |
649d7df29 f2fs: fix to set ... |
2669 2670 2671 2672 2673 2674 |
/* * This should be come from len == PAGE_SIZE, and we expect copied * should be PAGE_SIZE. Otherwise, we treat it with zero copied and * let generic_perform_write() try to copy data again through copied=0. */ if (!PageUptodate(page)) { |
746e24039 f2fs: add a case ... |
2675 |
if (unlikely(copied != len)) |
649d7df29 f2fs: fix to set ... |
2676 2677 2678 2679 2680 2681 |
copied = 0; else SetPageUptodate(page); } if (!copied) goto unlock_out; |
34ba94bac f2fs: do not make... |
2682 |
set_page_dirty(page); |
a1dd3c13c f2fs: fix to reco... |
2683 |
|
95ae251fe f2fs: add fs-veri... |
2684 2685 |
if (pos + copied > i_size_read(inode) && !f2fs_verity_in_progress(inode)) |
fc9581c80 f2fs: introduce f... |
2686 |
f2fs_i_size_write(inode, pos + copied); |
649d7df29 f2fs: fix to set ... |
2687 |
unlock_out: |
3024c9a1f Revert "f2fs: mov... |
2688 |
f2fs_put_page(page, 1); |
d0239e1bf f2fs: detect idle... |
2689 |
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); |
a1dd3c13c f2fs: fix to reco... |
2690 2691 |
return copied; } |
6f6737631 direct_IO: use io... |
2692 2693 |
static int check_direct_IO(struct inode *inode, struct iov_iter *iter, loff_t offset) |
944fcfc18 f2fs: check the b... |
2694 |
{ |
8a56dd968 f2fs: allow wrong... |
2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 |
unsigned i_blkbits = READ_ONCE(inode->i_blkbits); unsigned blkbits = i_blkbits; unsigned blocksize_mask = (1 << blkbits) - 1; unsigned long align = offset | iov_iter_alignment(iter); struct block_device *bdev = inode->i_sb->s_bdev; if (align & blocksize_mask) { if (bdev) blkbits = blksize_bits(bdev_logical_block_size(bdev)); blocksize_mask = (1 << blkbits) - 1; if (align & blocksize_mask) return -EINVAL; return 1; } |
944fcfc18 f2fs: check the b... |
2709 2710 |
return 0; } |
02b16d0a3 f2fs: add to acco... |
2711 2712 2713 2714 2715 2716 2717 2718 2719 |
static void f2fs_dio_end_io(struct bio *bio) { struct f2fs_private_dio *dio = bio->bi_private; dec_page_count(F2FS_I_SB(dio->inode), dio->write ? F2FS_DIO_WRITE : F2FS_DIO_READ); bio->bi_private = dio->orig_private; bio->bi_end_io = dio->orig_end_io; |
5222595d0 f2fs: use kvmallo... |
2720 |
kvfree(dio); |
02b16d0a3 f2fs: add to acco... |
2721 2722 2723 2724 2725 2726 2727 2728 2729 |
bio_endio(bio); } static void f2fs_dio_submit_bio(struct bio *bio, struct inode *inode, loff_t file_offset) { struct f2fs_private_dio *dio; bool write = (bio_op(bio) == REQ_OP_WRITE); |
02b16d0a3 f2fs: add to acco... |
2730 2731 2732 |
dio = f2fs_kzalloc(F2FS_I_SB(inode), sizeof(struct f2fs_private_dio), GFP_NOFS); |
8e1140387 f2fs: remove set ... |
2733 |
if (!dio) |
02b16d0a3 f2fs: add to acco... |
2734 |
goto out; |
02b16d0a3 f2fs: add to acco... |
2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 |
dio->inode = inode; dio->orig_end_io = bio->bi_end_io; dio->orig_private = bio->bi_private; dio->write = write; bio->bi_end_io = f2fs_dio_end_io; bio->bi_private = dio; inc_page_count(F2FS_I_SB(inode), write ? F2FS_DIO_WRITE : F2FS_DIO_READ); submit_bio(bio); return; out: bio->bi_status = BLK_STS_IOERR; bio_endio(bio); } |
c8b8e32d7 direct-io: elimin... |
2753 |
static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) |
eb47b8009 f2fs: add address... |
2754 |
{ |
b439b103a f2fs: move dio pr... |
2755 |
struct address_space *mapping = iocb->ki_filp->f_mapping; |
3aab8f828 f2fs: introduce f... |
2756 |
struct inode *inode = mapping->host; |
0cdd31953 f2fs: support pas... |
2757 |
struct f2fs_sb_info *sbi = F2FS_I_SB(inode); |
f847c699c f2fs: allow out-p... |
2758 |
struct f2fs_inode_info *fi = F2FS_I(inode); |
3aab8f828 f2fs: introduce f... |
2759 |
size_t count = iov_iter_count(iter); |
c8b8e32d7 direct-io: elimin... |
2760 |
loff_t offset = iocb->ki_pos; |
82e0a5aa5 f2fs: fix to avoi... |
2761 |
int rw = iov_iter_rw(iter); |
3aab8f828 f2fs: introduce f... |
2762 |
int err; |
0cdd31953 f2fs: support pas... |
2763 |
enum rw_hint hint = iocb->ki_hint; |
63189b785 f2fs: wrap all op... |
2764 |
int whint_mode = F2FS_OPTION(sbi).whint_mode; |
f847c699c f2fs: allow out-p... |
2765 |
bool do_opu; |
944fcfc18 f2fs: check the b... |
2766 |
|
b439b103a f2fs: move dio pr... |
2767 |
err = check_direct_IO(inode, iter, offset); |
b9d777b85 f2fs: check inlin... |
2768 |
if (err) |
8a56dd968 f2fs: allow wrong... |
2769 |
return err < 0 ? err : 0; |
9ffe0fb5f f2fs: handle inli... |
2770 |
|
f847c699c f2fs: allow out-p... |
2771 |
if (f2fs_force_buffered_io(inode, iocb, iter)) |
36abef4e7 f2fs: introduce m... |
2772 |
return 0; |
fcc85a4d8 f2fs crypto: acti... |
2773 |
|
f847c699c f2fs: allow out-p... |
2774 |
do_opu = allow_outplace_dio(inode, iocb, iter); |
5302fb000 f2fs: clean up co... |
2775 |
trace_f2fs_direct_IO_enter(inode, offset, count, rw); |
70407fad8 f2fs: add tracepo... |
2776 |
|
0cdd31953 f2fs: support pas... |
2777 2778 |
if (rw == WRITE && whint_mode == WHINT_MODE_OFF) iocb->ki_hint = WRITE_LIFE_NOT_SET; |
f847c699c f2fs: allow out-p... |
2779 2780 2781 2782 2783 2784 2785 2786 |
if (iocb->ki_flags & IOCB_NOWAIT) { if (!down_read_trylock(&fi->i_gc_rwsem[rw])) { iocb->ki_hint = hint; err = -EAGAIN; goto out; } if (do_opu && !down_read_trylock(&fi->i_gc_rwsem[READ])) { up_read(&fi->i_gc_rwsem[rw]); |
b91050a80 f2fs: add nowait ... |
2787 2788 2789 2790 |
iocb->ki_hint = hint; err = -EAGAIN; goto out; } |
f847c699c f2fs: allow out-p... |
2791 2792 2793 2794 |
} else { down_read(&fi->i_gc_rwsem[rw]); if (do_opu) down_read(&fi->i_gc_rwsem[READ]); |
b91050a80 f2fs: add nowait ... |
2795 |
} |
02b16d0a3 f2fs: add to acco... |
2796 |
err = __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev, |
f9d6d0597 f2fs: fix out-pla... |
2797 2798 |
iter, rw == WRITE ? get_data_block_dio_write : get_data_block_dio, NULL, f2fs_dio_submit_bio, |
02b16d0a3 f2fs: add to acco... |
2799 |
DIO_LOCKING | DIO_SKIP_HOLES); |
f847c699c f2fs: allow out-p... |
2800 2801 2802 2803 2804 |
if (do_opu) up_read(&fi->i_gc_rwsem[READ]); up_read(&fi->i_gc_rwsem[rw]); |
82e0a5aa5 f2fs: fix to avoi... |
2805 2806 |
if (rw == WRITE) { |
0cdd31953 f2fs: support pas... |
2807 2808 |
if (whint_mode == WHINT_MODE_OFF) iocb->ki_hint = hint; |
b0af6d491 f2fs: add app/fs ... |
2809 2810 2811 |
if (err > 0) { f2fs_update_iostat(F2FS_I_SB(inode), APP_DIRECT_IO, err); |
f847c699c f2fs: allow out-p... |
2812 2813 |
if (!do_opu) set_inode_flag(inode, FI_UPDATE_WRITE); |
b0af6d491 f2fs: add app/fs ... |
2814 |
} else if (err < 0) { |
6bfc49197 f2fs: issue cache... |
2815 |
f2fs_write_failed(mapping, offset + count); |
b0af6d491 f2fs: add app/fs ... |
2816 |
} |
6bfc49197 f2fs: issue cache... |
2817 |
} |
70407fad8 f2fs: add tracepo... |
2818 |
|
b91050a80 f2fs: add nowait ... |
2819 |
out: |
5302fb000 f2fs: clean up co... |
2820 |
trace_f2fs_direct_IO_exit(inode, offset, count, rw, err); |
70407fad8 f2fs: add tracepo... |
2821 |
|
3aab8f828 f2fs: introduce f... |
2822 |
return err; |
eb47b8009 f2fs: add address... |
2823 |
} |
487261f39 f2fs: merge {inva... |
2824 2825 |
void f2fs_invalidate_page(struct page *page, unsigned int offset, unsigned int length) |
eb47b8009 f2fs: add address... |
2826 2827 |
{ struct inode *inode = page->mapping->host; |
487261f39 f2fs: merge {inva... |
2828 |
struct f2fs_sb_info *sbi = F2FS_I_SB(inode); |
a7ffdbe22 f2fs: expand coun... |
2829 |
|
487261f39 f2fs: merge {inva... |
2830 |
if (inode->i_ino >= F2FS_ROOT_INO(sbi) && |
09cbfeaf1 mm, fs: get rid o... |
2831 |
(offset % PAGE_SIZE || length != PAGE_SIZE)) |
a7ffdbe22 f2fs: expand coun... |
2832 |
return; |
487261f39 f2fs: merge {inva... |
2833 |
if (PageDirty(page)) { |
933439c8f f2fs: give a chan... |
2834 |
if (inode->i_ino == F2FS_META_INO(sbi)) { |
487261f39 f2fs: merge {inva... |
2835 |
dec_page_count(sbi, F2FS_DIRTY_META); |
933439c8f f2fs: give a chan... |
2836 |
} else if (inode->i_ino == F2FS_NODE_INO(sbi)) { |
487261f39 f2fs: merge {inva... |
2837 |
dec_page_count(sbi, F2FS_DIRTY_NODES); |
933439c8f f2fs: give a chan... |
2838 |
} else { |
487261f39 f2fs: merge {inva... |
2839 |
inode_dec_dirty_pages(inode); |
4d57b86dd f2fs: clean up sy... |
2840 |
f2fs_remove_dirty_inode(inode); |
933439c8f f2fs: give a chan... |
2841 |
} |
487261f39 f2fs: merge {inva... |
2842 |
} |
decd36b6c f2fs: remove inme... |
2843 |
|
2baf07818 f2fs: fix to spre... |
2844 |
clear_cold_data(page); |
decd36b6c f2fs: remove inme... |
2845 |
if (IS_ATOMIC_WRITTEN_PAGE(page)) |
4d57b86dd f2fs: clean up sy... |
2846 |
return f2fs_drop_inmem_page(inode, page); |
decd36b6c f2fs: remove inme... |
2847 |
|
240a59156 f2fs: fix to add ... |
2848 |
f2fs_clear_page_private(page); |
eb47b8009 f2fs: add address... |
2849 |
} |
487261f39 f2fs: merge {inva... |
2850 |
int f2fs_release_page(struct page *page, gfp_t wait) |
eb47b8009 f2fs: add address... |
2851 |
{ |
f68daeebb f2fs: keep PagePr... |
2852 2853 2854 |
/* If this is dirty page, keep PagePrivate */ if (PageDirty(page)) return 0; |
decd36b6c f2fs: remove inme... |
2855 2856 2857 |
/* This is atomic written page, keep Private */ if (IS_ATOMIC_WRITTEN_PAGE(page)) return 0; |
2baf07818 f2fs: fix to spre... |
2858 |
clear_cold_data(page); |
240a59156 f2fs: fix to add ... |
2859 |
f2fs_clear_page_private(page); |
c3850aa1c f2fs: fix return ... |
2860 |
return 1; |
eb47b8009 f2fs: add address... |
2861 2862 2863 2864 |
} static int f2fs_set_data_page_dirty(struct page *page) { |
4969c06a0 f2fs: support swa... |
2865 |
struct inode *inode = page_file_mapping(page)->host; |
eb47b8009 f2fs: add address... |
2866 |
|
26c6b8879 f2fs: add tracepo... |
2867 |
trace_f2fs_set_page_dirty(page, DATA); |
237c0790e f2fs: call SetPag... |
2868 2869 |
if (!PageUptodate(page)) SetPageUptodate(page); |
4969c06a0 f2fs: support swa... |
2870 2871 |
if (PageSwapCache(page)) return __set_page_dirty_nobuffers(page); |
34ba94bac f2fs: do not make... |
2872 |
|
5fe457430 f2fs: introduce F... |
2873 |
if (f2fs_is_atomic_file(inode) && !f2fs_is_commit_atomic_write(inode)) { |
decd36b6c f2fs: remove inme... |
2874 |
if (!IS_ATOMIC_WRITTEN_PAGE(page)) { |
4d57b86dd f2fs: clean up sy... |
2875 |
f2fs_register_inmem_page(inode, page); |
decd36b6c f2fs: remove inme... |
2876 2877 2878 2879 2880 2881 2882 |
return 1; } /* * Previously, this page has been registered, we just * return here. */ return 0; |
34ba94bac f2fs: do not make... |
2883 |
} |
eb47b8009 f2fs: add address... |
2884 |
if (!PageDirty(page)) { |
b87078ad3 Revert "f2fs: int... |
2885 |
__set_page_dirty_nobuffers(page); |
4d57b86dd f2fs: clean up sy... |
2886 |
f2fs_update_dirty_page(inode, page); |
eb47b8009 f2fs: add address... |
2887 2888 2889 2890 |
return 1; } return 0; } |
c01e54b77 f2fs: support swa... |
2891 2892 |
static sector_t f2fs_bmap(struct address_space *mapping, sector_t block) { |
454ae7e51 f2fs: handle inli... |
2893 |
struct inode *inode = mapping->host; |
1d373a0ef f2fs: flush dirty... |
2894 2895 2896 2897 2898 2899 |
if (f2fs_has_inline_data(inode)) return 0; /* make sure allocating whole blocks */ if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) filemap_write_and_wait(mapping); |
e2b4e2bc8 f2fs: fix incorre... |
2900 |
return generic_block_bmap(mapping, block, get_data_block_bmap); |
429511cdf f2fs: add core fu... |
2901 |
} |
5b7a487cf f2fs: add customi... |
2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 |
#ifdef CONFIG_MIGRATION #include <linux/migrate.h> int f2fs_migrate_page(struct address_space *mapping, struct page *newpage, struct page *page, enum migrate_mode mode) { int rc, extra_count; struct f2fs_inode_info *fi = F2FS_I(mapping->host); bool atomic_written = IS_ATOMIC_WRITTEN_PAGE(page); BUG_ON(PageWriteback(page)); /* migrating an atomic written page is safe with the inmem_lock hold */ |
ff1048e7d f2fs: relax migra... |
2915 2916 2917 2918 2919 2920 |
if (atomic_written) { if (mode != MIGRATE_SYNC) return -EBUSY; if (!mutex_trylock(&fi->inmem_lock)) return -EAGAIN; } |
5b7a487cf f2fs: add customi... |
2921 |
|
240a59156 f2fs: fix to add ... |
2922 2923 |
/* one extra reference was held for atomic_write page */ extra_count = atomic_written ? 1 : 0; |
5b7a487cf f2fs: add customi... |
2924 |
rc = migrate_page_move_mapping(mapping, newpage, |
371096949 mm: migrate: remo... |
2925 |
page, extra_count); |
5b7a487cf f2fs: add customi... |
2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 |
if (rc != MIGRATEPAGE_SUCCESS) { if (atomic_written) mutex_unlock(&fi->inmem_lock); return rc; } if (atomic_written) { struct inmem_pages *cur; list_for_each_entry(cur, &fi->inmem_pages, list) if (cur->page == page) { cur->page = newpage; break; } mutex_unlock(&fi->inmem_lock); put_page(page); get_page(newpage); } |
240a59156 f2fs: fix to add ... |
2943 2944 2945 2946 |
if (PagePrivate(page)) { f2fs_set_page_private(newpage, page_private(page)); f2fs_clear_page_private(page); } |
5b7a487cf f2fs: add customi... |
2947 |
|
2916ecc0f mm/migrate: new m... |
2948 2949 2950 2951 |
if (mode != MIGRATE_SYNC_NO_COPY) migrate_page_copy(newpage, page); else migrate_page_states(newpage, page); |
5b7a487cf f2fs: add customi... |
2952 2953 2954 2955 |
return MIGRATEPAGE_SUCCESS; } #endif |
4969c06a0 f2fs: support swa... |
2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 |
#ifdef CONFIG_SWAP /* Copied from generic_swapfile_activate() to check any holes */ static int check_swap_activate(struct file *swap_file, unsigned int max) { struct address_space *mapping = swap_file->f_mapping; struct inode *inode = mapping->host; unsigned blocks_per_page; unsigned long page_no; unsigned blkbits; sector_t probe_block; sector_t last_block; sector_t lowest_block = -1; sector_t highest_block = 0; blkbits = inode->i_blkbits; blocks_per_page = PAGE_SIZE >> blkbits; /* * Map all the blocks into the extent list. This code doesn't try * to be very smart. */ probe_block = 0; page_no = 0; last_block = i_size_read(inode) >> blkbits; while ((probe_block + blocks_per_page) <= last_block && page_no < max) { unsigned block_in_page; sector_t first_block; cond_resched(); first_block = bmap(inode, probe_block); if (first_block == 0) goto bad_bmap; /* * It must be PAGE_SIZE aligned on-disk */ if (first_block & (blocks_per_page - 1)) { probe_block++; goto reprobe; } for (block_in_page = 1; block_in_page < blocks_per_page; block_in_page++) { sector_t block; block = bmap(inode, probe_block + block_in_page); if (block == 0) goto bad_bmap; if (block != first_block + block_in_page) { /* Discontiguity */ probe_block++; goto reprobe; } } first_block >>= (PAGE_SHIFT - blkbits); if (page_no) { /* exclude the header page */ if (first_block < lowest_block) lowest_block = first_block; if (first_block > highest_block) highest_block = first_block; } page_no++; probe_block += blocks_per_page; reprobe: continue; } return 0; bad_bmap: pr_err("swapon: swapfile has holes "); return -EINVAL; } static int f2fs_swap_activate(struct swap_info_struct *sis, struct file *file, sector_t *span) { struct inode *inode = file_inode(file); int ret; if (!S_ISREG(inode->i_mode)) return -EINVAL; if (f2fs_readonly(F2FS_I_SB(inode)->sb)) return -EROFS; ret = f2fs_convert_inline_inode(inode); if (ret) return ret; ret = check_swap_activate(file, sis->max); if (ret) return ret; set_inode_flag(inode, FI_PIN_FILE); f2fs_precache_extents(inode); f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); return 0; } static void f2fs_swap_deactivate(struct file *file) { struct inode *inode = file_inode(file); clear_inode_flag(inode, FI_PIN_FILE); } #else static int f2fs_swap_activate(struct swap_info_struct *sis, struct file *file, sector_t *span) { return -EOPNOTSUPP; } static void f2fs_swap_deactivate(struct file *file) { } #endif |
eb47b8009 f2fs: add address... |
3076 3077 3078 3079 3080 3081 |
const struct address_space_operations f2fs_dblock_aops = { .readpage = f2fs_read_data_page, .readpages = f2fs_read_data_pages, .writepage = f2fs_write_data_page, .writepages = f2fs_write_data_pages, .write_begin = f2fs_write_begin, |
a1dd3c13c f2fs: fix to reco... |
3082 |
.write_end = f2fs_write_end, |
eb47b8009 f2fs: add address... |
3083 |
.set_page_dirty = f2fs_set_data_page_dirty, |
487261f39 f2fs: merge {inva... |
3084 3085 |
.invalidatepage = f2fs_invalidate_page, .releasepage = f2fs_release_page, |
eb47b8009 f2fs: add address... |
3086 |
.direct_IO = f2fs_direct_IO, |
c01e54b77 f2fs: support swa... |
3087 |
.bmap = f2fs_bmap, |
4969c06a0 f2fs: support swa... |
3088 3089 |
.swap_activate = f2fs_swap_activate, .swap_deactivate = f2fs_swap_deactivate, |
5b7a487cf f2fs: add customi... |
3090 3091 3092 |
#ifdef CONFIG_MIGRATION .migratepage = f2fs_migrate_page, #endif |
eb47b8009 f2fs: add address... |
3093 |
}; |
6dbb17961 f2fs: refactor re... |
3094 |
|
5ec2d99de f2fs: Convert to ... |
3095 |
void f2fs_clear_page_cache_dirty_tag(struct page *page) |
aec2f729f f2fs: clean up wi... |
3096 3097 3098 3099 3100 |
{ struct address_space *mapping = page_mapping(page); unsigned long flags; xa_lock_irqsave(&mapping->i_pages, flags); |
5ec2d99de f2fs: Convert to ... |
3101 |
__xa_clear_mark(&mapping->i_pages, page_index(page), |
aec2f729f f2fs: clean up wi... |
3102 3103 3104 |
PAGECACHE_TAG_DIRTY); xa_unlock_irqrestore(&mapping->i_pages, flags); } |
6dbb17961 f2fs: refactor re... |
3105 3106 |
int __init f2fs_init_post_read_processing(void) { |
95ae251fe f2fs: add fs-veri... |
3107 3108 3109 |
bio_post_read_ctx_cache = kmem_cache_create("f2fs_bio_post_read_ctx", sizeof(struct bio_post_read_ctx), 0, 0, NULL); |
6dbb17961 f2fs: refactor re... |
3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 |
if (!bio_post_read_ctx_cache) goto fail; bio_post_read_ctx_pool = mempool_create_slab_pool(NUM_PREALLOC_POST_READ_CTXS, bio_post_read_ctx_cache); if (!bio_post_read_ctx_pool) goto fail_free_cache; return 0; fail_free_cache: kmem_cache_destroy(bio_post_read_ctx_cache); fail: return -ENOMEM; } |
0b20fcec8 f2fs: cache globa... |
3124 |
void f2fs_destroy_post_read_processing(void) |
6dbb17961 f2fs: refactor re... |
3125 3126 3127 3128 |
{ mempool_destroy(bio_post_read_ctx_pool); kmem_cache_destroy(bio_post_read_ctx_cache); } |
0b20fcec8 f2fs: cache globa... |
3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 |
int __init f2fs_init_bio_entry_cache(void) { bio_entry_slab = f2fs_kmem_cache_create("bio_entry_slab", sizeof(struct bio_entry)); if (!bio_entry_slab) return -ENOMEM; return 0; } void __exit f2fs_destroy_bio_entry_cache(void) { kmem_cache_destroy(bio_entry_slab); } |