Blame view

fs/f2fs/data.c 79.3 KB
7c1a000d4   Chao Yu   f2fs: add SPDX li...
1
  // SPDX-License-Identifier: GPL-2.0
0a8165d7c   Jaegeuk Kim   f2fs: adjust kern...
2
  /*
eb47b8009   Jaegeuk Kim   f2fs: add address...
3
4
5
6
   * fs/f2fs/data.c
   *
   * Copyright (c) 2012 Samsung Electronics Co., Ltd.
   *             http://www.samsung.com/
eb47b8009   Jaegeuk Kim   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   Chao Yu   f2fs: expose f2fs...
14
  #include <linux/pagevec.h>
eb47b8009   Jaegeuk Kim   f2fs: add address...
15
16
  #include <linux/blkdev.h>
  #include <linux/bio.h>
4969c06a0   Jaegeuk Kim   f2fs: support swa...
17
  #include <linux/swap.h>
690e4a3ea   Geert Uytterhoeven   f2fs: add missing...
18
  #include <linux/prefetch.h>
e2e40f2c1   Christoph Hellwig   fs: move struct k...
19
  #include <linux/uio.h>
f1e886601   Jaegeuk Kim   f2fs: expose f2fs...
20
  #include <linux/cleancache.h>
174cd4b1e   Ingo Molnar   sched/headers: Pr...
21
  #include <linux/sched/signal.h>
eb47b8009   Jaegeuk Kim   f2fs: add address...
22
23
24
25
  
  #include "f2fs.h"
  #include "node.h"
  #include "segment.h"
db9f7c1a9   Jaegeuk Kim   f2fs: activate f2...
26
  #include "trace.h"
848753aa3   Namjae Jeon   f2fs: add tracepo...
27
  #include <trace/events/f2fs.h>
eb47b8009   Jaegeuk Kim   f2fs: add address...
28

6dbb17961   Eric Biggers   f2fs: refactor re...
29
30
31
  #define NUM_PREALLOC_POST_READ_CTXS	128
  
  static struct kmem_cache *bio_post_read_ctx_cache;
0b20fcec8   Chao Yu   f2fs: cache globa...
32
  static struct kmem_cache *bio_entry_slab;
6dbb17961   Eric Biggers   f2fs: refactor re...
33
  static mempool_t *bio_post_read_ctx_pool;
36951b38d   Chao Yu   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   Chao Yu   f2fs: fix to let ...
49
  			(S_ISREG(inode->i_mode) &&
af033b2aa   Chao Yu   f2fs: guarantee j...
50
  			(f2fs_is_atomic_file(inode) || IS_NOQUOTA(inode))) ||
36951b38d   Chao Yu   f2fs: don't wait ...
51
52
53
54
  			is_cold_data(page))
  		return true;
  	return false;
  }
5f9abab42   Jaegeuk Kim   f2fs: account rea...
55
56
  static enum count_type __read_io_type(struct page *page)
  {
4969c06a0   Jaegeuk Kim   f2fs: support swa...
57
  	struct address_space *mapping = page_file_mapping(page);
5f9abab42   Jaegeuk Kim   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   Eric Biggers   f2fs: refactor re...
71
72
73
74
  /* postprocessing steps for read bios */
  enum bio_post_read_step {
  	STEP_INITIAL = 0,
  	STEP_DECRYPT,
95ae251fe   Eric Biggers   f2fs: add fs-veri...
75
  	STEP_VERITY,
6dbb17961   Eric Biggers   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   Jaegeuk Kim   f2fs: refactor bi...
86
  {
6dbb17961   Eric Biggers   f2fs: refactor re...
87
88
  	struct page *page;
  	struct bio_vec *bv;
6dc4f100c   Ming Lei   block: allow bio_...
89
  	struct bvec_iter_all iter_all;
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
90

2b070cfe5   Christoph Hellwig   block: remove the...
91
  	bio_for_each_segment_all(bv, bio, iter_all) {
6dbb17961   Eric Biggers   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   Jaegeuk Kim   f2fs: clear PageE...
97
98
  			/* will re-read again later */
  			ClearPageError(page);
6dbb17961   Eric Biggers   f2fs: refactor re...
99
100
101
  		} else {
  			SetPageUptodate(page);
  		}
5f9abab42   Jaegeuk Kim   f2fs: account rea...
102
  		dec_page_count(F2FS_P_SB(page), __read_io_type(page));
6dbb17961   Eric Biggers   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   Eric Biggers   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   Eric Biggers   f2fs: refactor re...
130
131
  static void bio_post_read_processing(struct bio_post_read_ctx *ctx)
  {
95ae251fe   Eric Biggers   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   Eric Biggers   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   Eric Biggers   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   Eric Biggers   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   Chao Yu   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   Christoph Hellwig   block: switch bio...
170
  		bio->bi_status = BLK_STS_IOERR;
55523519b   Chao Yu   f2fs: show simple...
171
  	}
8b038c70d   Chao Yu   f2fs: support IO ...
172

6dbb17961   Eric Biggers   f2fs: refactor re...
173
174
  	if (f2fs_bio_post_read_required(bio)) {
  		struct bio_post_read_ctx *ctx = bio->bi_private;
f1e886601   Jaegeuk Kim   f2fs: expose f2fs...
175

6dbb17961   Eric Biggers   f2fs: refactor re...
176
177
178
  		ctx->cur_step = STEP_INITIAL;
  		bio_post_read_processing(ctx);
  		return;
f1e886601   Jaegeuk Kim   f2fs: expose f2fs...
179
  	}
6dbb17961   Eric Biggers   f2fs: refactor re...
180
181
  
  	__read_end_io(bio);
f1e886601   Jaegeuk Kim   f2fs: expose f2fs...
182
  }
4246a0b63   Christoph Hellwig   block: add a bi_e...
183
  static void f2fs_write_end_io(struct bio *bio)
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
184
  {
1b1f559fc   Jaegeuk Kim   f2fs: remove the ...
185
  	struct f2fs_sb_info *sbi = bio->bi_private;
f568849ed   Linus Torvalds   Merge branch 'for...
186
  	struct bio_vec *bvec;
6dc4f100c   Ming Lei   block: allow bio_...
187
  	struct bvec_iter_all iter_all;
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
188

6f5c2ed0a   Chao Yu   f2fs: split IO er...
189
  	if (time_to_inject(sbi, FAULT_WRITE_IO)) {
c45d6002f   Chao Yu   f2fs: show f2fs i...
190
  		f2fs_show_injection_info(sbi, FAULT_WRITE_IO);
6f5c2ed0a   Chao Yu   f2fs: split IO er...
191
192
  		bio->bi_status = BLK_STS_IOERR;
  	}
2b070cfe5   Christoph Hellwig   block: remove the...
193
  	bio_for_each_segment_all(bvec, bio, iter_all) {
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
194
  		struct page *page = bvec->bv_page;
36951b38d   Chao Yu   f2fs: don't wait ...
195
  		enum count_type type = WB_DATA_TYPE(page);
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
196

0a595ebaa   Jaegeuk Kim   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   Christoph Hellwig   block: switch bio...
202
  			if (unlikely(bio->bi_status))
0a595ebaa   Jaegeuk Kim   f2fs: support IO ...
203
204
205
  				f2fs_stop_checkpoint(sbi, true);
  			continue;
  		}
d2d0727b1   Eric Biggers   fscrypt: simplify...
206
  		fscrypt_finalize_bounce_page(&page);
4375a3366   Jaegeuk Kim   f2fs crypto: add ...
207

4e4cbee93   Christoph Hellwig   block: switch bio...
208
  		if (unlikely(bio->bi_status)) {
5114a97a8   Michal Hocko   fs: use mapping_s...
209
  			mapping_set_error(page->mapping, -EIO);
b1ca321d1   Jaegeuk Kim   f2fs: skip stop_c...
210
211
  			if (type == F2FS_WB_CP_DATA)
  				f2fs_stop_checkpoint(sbi, true);
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
212
  		}
7dff55d27   Yunlei He   f2fs: check node ...
213
214
215
  
  		f2fs_bug_on(sbi, page->mapping == NODE_MAPPING(sbi) &&
  					page->index != nid_of_node(page));
36951b38d   Chao Yu   f2fs: don't wait ...
216
  		dec_page_count(sbi, type);
50fa53ecc   Chao Yu   f2fs: fix to avoi...
217
218
  		if (f2fs_in_warm_node_list(sbi, page))
  			f2fs_del_fsync_node_entry(sbi, page);
36951b38d   Chao Yu   f2fs: don't wait ...
219
  		clear_cold_data(page);
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
220
  		end_page_writeback(page);
f568849ed   Linus Torvalds   Merge branch 'for...
221
  	}
36951b38d   Chao Yu   f2fs: don't wait ...
222
  	if (!get_pages(sbi, F2FS_WB_CP_DATA) &&
f57301849   Jaegeuk Kim   f2fs: use bio cou...
223
  				wq_has_sleeper(&sbi->cp_wait))
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
224
225
226
227
  		wake_up(&sbi->cp_wait);
  
  	bio_put(bio);
  }
940a6d34b   Gu Zheng   f2fs: move all th...
228
  /*
3c62be17d   Jaegeuk Kim   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   Damien Le Moal   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   Jaegeuk Kim   f2fs: support mul...
244
245
246
  		}
  	}
  	if (bio) {
74d46992e   Christoph Hellwig   block: replace bi...
247
  		bio_set_dev(bio, bdev);
3c62be17d   Jaegeuk Kim   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   Damien Le Moal   f2fs: Fix use of ...
256
257
  	if (!f2fs_is_multi_device(sbi))
  		return 0;
3c62be17d   Jaegeuk Kim   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   Christoph Hellwig   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   Jaegeuk Kim   f2fs: support mul...
269
270
271
  }
  
  /*
940a6d34b   Gu Zheng   f2fs: move all th...
272
273
   * Low-level block read/write IO operations.
   */
b757f6edb   Chao Yu   f2fs: clean up __...
274
  static struct bio *__bio_alloc(struct f2fs_io_info *fio, int npages)
940a6d34b   Gu Zheng   f2fs: move all th...
275
  {
b757f6edb   Chao Yu   f2fs: clean up __...
276
  	struct f2fs_sb_info *sbi = fio->sbi;
940a6d34b   Gu Zheng   f2fs: move all th...
277
  	struct bio *bio;
d62fe9714   Chao Yu   f2fs: support bio...
278
  	bio = f2fs_bio_alloc(sbi, npages, true);
940a6d34b   Gu Zheng   f2fs: move all th...
279

b757f6edb   Chao Yu   f2fs: clean up __...
280
281
  	f2fs_target_device(sbi, fio->new_blkaddr, bio);
  	if (is_read_io(fio->op)) {
0cdd31953   Hyunchul Lee   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   Chao Yu   f2fs: clean up __...
287
288
  		bio->bi_write_hint = f2fs_io_type_to_rw_hint(sbi,
  						fio->type, fio->temp);
0cdd31953   Hyunchul Lee   f2fs: support pas...
289
  	}
b757f6edb   Chao Yu   f2fs: clean up __...
290
291
  	if (fio->io_wbc)
  		wbc_init_bio(fio->io_wbc, bio);
940a6d34b   Gu Zheng   f2fs: move all th...
292
293
294
  
  	return bio;
  }
4fc29c1aa   Linus Torvalds   Merge tag 'for-f2...
295
296
  static inline void __submit_bio(struct f2fs_sb_info *sbi,
  				struct bio *bio, enum page_type type)
f57301849   Jaegeuk Kim   f2fs: use bio cou...
297
  {
4fc29c1aa   Linus Torvalds   Merge tag 'for-f2...
298
  	if (!is_read_io(bio_op(bio))) {
0a595ebaa   Jaegeuk Kim   f2fs: support IO ...
299
  		unsigned int start;
0a595ebaa   Jaegeuk Kim   f2fs: support IO ...
300
301
  		if (type != DATA && type != NODE)
  			goto submit_io;
66415cee3   Yunlong Song   f2fs: blk_finish_...
302
  		if (test_opt(sbi, LFS) && current->plug)
3bb09a0e7   Tiezhu Yang   f2fs: remove redu...
303
  			blk_finish_plug(current->plug);
8223ecc45   Chao Yu   f2fs: fix to add ...
304
305
  		if (F2FS_IO_ALIGNED(sbi))
  			goto submit_io;
0a595ebaa   Jaegeuk Kim   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   Gao Xiang   f2fs: silence VM_...
316
  					      GFP_NOIO | __GFP_NOFAIL);
0a595ebaa   Jaegeuk Kim   f2fs: support IO ...
317
  			f2fs_bug_on(sbi, !page);
bc73a4b24   Gao Xiang   f2fs: silence VM_...
318
  			zero_user_segment(page, 0, PAGE_SIZE);
0a595ebaa   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: drop any bl...
331
  	}
0a595ebaa   Jaegeuk Kim   f2fs: support IO ...
332
  submit_io:
554b5125f   Jaegeuk Kim   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   Mike Christie   block/fs/drivers:...
337
  	submit_bio(bio);
f57301849   Jaegeuk Kim   f2fs: use bio cou...
338
  }
458e6197c   Jaegeuk Kim   f2fs: refactor bi...
339
  static void __submit_merged_bio(struct f2fs_bio_info *io)
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
340
  {
458e6197c   Jaegeuk Kim   f2fs: refactor bi...
341
  	struct f2fs_io_info *fio = &io->fio;
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
342
343
344
  
  	if (!io->bio)
  		return;
554b5125f   Jaegeuk Kim   f2fs: add submit_...
345
  	bio_set_op_attrs(io->bio, fio->op, fio->op_flags);
04d328def   Mike Christie   f2fs: use bio op ...
346
  	if (is_read_io(fio->op))
554b5125f   Jaegeuk Kim   f2fs: add submit_...
347
  		trace_f2fs_prepare_read_bio(io->sbi->sb, fio->type, io->bio);
6a8f8ca58   Jaegeuk Kim   f2fs: avoid race ...
348
  	else
554b5125f   Jaegeuk Kim   f2fs: add submit_...
349
  		trace_f2fs_prepare_write_bio(io->sbi->sb, fio->type, io->bio);
04d328def   Mike Christie   f2fs: use bio op ...
350

4fc29c1aa   Linus Torvalds   Merge tag 'for-f2...
351
  	__submit_bio(io->sbi, io->bio, fio->type);
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
352
353
  	io->bio = NULL;
  }
8648de2c5   Chao Yu   f2fs: add bio cac...
354
  static bool __has_merged_page(struct bio *bio, struct inode *inode,
bab475c54   Chao Yu   Revert: "f2fs: ch...
355
  						struct page *page, nid_t ino)
0fd785eb9   Chao Yu   f2fs: relocate is...
356
  {
0fd785eb9   Chao Yu   f2fs: relocate is...
357
358
  	struct bio_vec *bvec;
  	struct page *target;
6dc4f100c   Ming Lei   block: allow bio_...
359
  	struct bvec_iter_all iter_all;
0fd785eb9   Chao Yu   f2fs: relocate is...
360

8648de2c5   Chao Yu   f2fs: add bio cac...
361
  	if (!bio)
0fd785eb9   Chao Yu   f2fs: relocate is...
362
  		return false;
0c3a57975   Chao Yu   f2fs: introduce f...
363

bab475c54   Chao Yu   Revert: "f2fs: ch...
364
  	if (!inode && !page && !ino)
0c3a57975   Chao Yu   f2fs: introduce f...
365
  		return true;
0fd785eb9   Chao Yu   f2fs: relocate is...
366

8648de2c5   Chao Yu   f2fs: add bio cac...
367
  	bio_for_each_segment_all(bvec, bio, iter_all) {
0fd785eb9   Chao Yu   f2fs: relocate is...
368

d2d0727b1   Eric Biggers   fscrypt: simplify...
369
370
371
  		target = bvec->bv_page;
  		if (fscrypt_is_bounce_page(target))
  			target = fscrypt_pagecache_page(target);
0fd785eb9   Chao Yu   f2fs: relocate is...
372

0c3a57975   Chao Yu   f2fs: introduce f...
373
374
  		if (inode && inode == target->mapping->host)
  			return true;
bab475c54   Chao Yu   Revert: "f2fs: ch...
375
376
  		if (page && page == target)
  			return true;
0c3a57975   Chao Yu   f2fs: introduce f...
377
  		if (ino && ino == ino_of_node(target))
0fd785eb9   Chao Yu   f2fs: relocate is...
378
  			return true;
0fd785eb9   Chao Yu   f2fs: relocate is...
379
  	}
0fd785eb9   Chao Yu   f2fs: relocate is...
380
381
  	return false;
  }
b9109b0e4   Jaegeuk Kim   f2fs: remove unne...
382
  static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi,
a912b54d3   Jaegeuk Kim   f2fs: split bio c...
383
  				enum page_type type, enum temp_type temp)
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
384
385
  {
  	enum page_type btype = PAGE_TYPE_OF_BIO(type);
a912b54d3   Jaegeuk Kim   f2fs: split bio c...
386
  	struct f2fs_bio_info *io = sbi->write_io[btype] + temp;
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
387

df0f8dc0e   Chao Yu   f2fs: avoid unnec...
388
  	down_write(&io->io_rwsem);
458e6197c   Jaegeuk Kim   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   Mike Christie   f2fs: use bio op ...
393
  		io->fio.op = REQ_OP_WRITE;
3adc5fcb7   Jan Kara   f2fs: Make flush ...
394
  		io->fio.op_flags = REQ_META | REQ_PRIO | REQ_SYNC;
70fd76140   Christoph Hellwig   block,fs: use REQ...
395
  		if (!test_opt(sbi, NOBARRIER))
7f54f51f4   Jaegeuk Kim   f2fs: remove pref...
396
  			io->fio.op_flags |= REQ_PREFLUSH | REQ_FUA;
458e6197c   Jaegeuk Kim   f2fs: refactor bi...
397
398
  	}
  	__submit_merged_bio(io);
df0f8dc0e   Chao Yu   f2fs: avoid unnec...
399
  	up_write(&io->io_rwsem);
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
400
  }
a912b54d3   Jaegeuk Kim   f2fs: split bio c...
401
  static void __submit_merged_write_cond(struct f2fs_sb_info *sbi,
bab475c54   Chao Yu   Revert: "f2fs: ch...
402
403
  				struct inode *inode, struct page *page,
  				nid_t ino, enum page_type type, bool force)
0c3a57975   Chao Yu   f2fs: introduce f...
404
  {
a912b54d3   Jaegeuk Kim   f2fs: split bio c...
405
  	enum temp_type temp;
1e771e83c   Yunlong Song   f2fs: only flush ...
406
  	bool ret = true;
a912b54d3   Jaegeuk Kim   f2fs: split bio c...
407
408
  
  	for (temp = HOT; temp < NR_TEMP_TYPE; temp++) {
1e771e83c   Yunlong Song   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   Jaegeuk Kim   f2fs: split bio c...
412

1e771e83c   Yunlong Song   f2fs: only flush ...
413
  			down_read(&io->io_rwsem);
8648de2c5   Chao Yu   f2fs: add bio cac...
414
  			ret = __has_merged_page(io->bio, inode, page, ino);
1e771e83c   Yunlong Song   f2fs: only flush ...
415
416
417
418
  			up_read(&io->io_rwsem);
  		}
  		if (ret)
  			__f2fs_submit_merged_write(sbi, type, temp);
a912b54d3   Jaegeuk Kim   f2fs: split bio c...
419
420
421
422
423
  
  		/* TODO: use HOT temp only for meta pages now. */
  		if (type >= META)
  			break;
  	}
0c3a57975   Chao Yu   f2fs: introduce f...
424
  }
b9109b0e4   Jaegeuk Kim   f2fs: remove unne...
425
  void f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type)
0c3a57975   Chao Yu   f2fs: introduce f...
426
  {
adcc00f7d   Hariprasad Kelam   f2fs: data: fix w...
427
  	__submit_merged_write_cond(sbi, NULL, NULL, 0, type, true);
0c3a57975   Chao Yu   f2fs: introduce f...
428
  }
b9109b0e4   Jaegeuk Kim   f2fs: remove unne...
429
  void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi,
bab475c54   Chao Yu   Revert: "f2fs: ch...
430
431
  				struct inode *inode, struct page *page,
  				nid_t ino, enum page_type type)
0c3a57975   Chao Yu   f2fs: introduce f...
432
  {
bab475c54   Chao Yu   Revert: "f2fs: ch...
433
  	__submit_merged_write_cond(sbi, inode, page, ino, type, false);
0c3a57975   Chao Yu   f2fs: introduce f...
434
  }
b9109b0e4   Jaegeuk Kim   f2fs: remove unne...
435
  void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi)
406657dd1   Chao Yu   f2fs: introduce f...
436
  {
b9109b0e4   Jaegeuk Kim   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   Chao Yu   f2fs: introduce f...
440
  }
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
441
442
  /*
   * Fill the locked page with data located in the block address.
771a9a717   Tomohiro Kusumi   f2fs: fix comment...
443
   * A caller needs to unlock the page on failure.
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
444
   */
05ca3632e   Jaegeuk Kim   f2fs: add sbi and...
445
  int f2fs_submit_page_bio(struct f2fs_io_info *fio)
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
446
  {
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
447
  	struct bio *bio;
0b81d0779   Jaegeuk Kim   fs crypto: move p...
448
449
  	struct page *page = fio->encrypted_page ?
  			fio->encrypted_page : fio->page;
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
450

c9b60788f   Chao Yu   f2fs: fix to do s...
451
  	if (!f2fs_is_valid_blkaddr(fio->sbi, fio->new_blkaddr,
93770ab7a   Chao Yu   f2fs: introduce D...
452
453
  			fio->is_por ? META_POR : (__is_meta_io(fio) ?
  			META_GENERIC : DATA_GENERIC_ENHANCE)))
10f966bbf   Chao Yu   f2fs: use generic...
454
  		return -EFSCORRUPTED;
c9b60788f   Chao Yu   f2fs: fix to do s...
455

2ace38e00   Chao Yu   f2fs: cleanup par...
456
  	trace_f2fs_submit_page_bio(page, fio);
05ca3632e   Jaegeuk Kim   f2fs: add sbi and...
457
  	f2fs_trace_ios(fio, 0);
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
458
459
  
  	/* Allocate a new bio */
b757f6edb   Chao Yu   f2fs: clean up __...
460
  	bio = __bio_alloc(fio, 1);
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
461

09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
462
  	if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
463
  		bio_put(bio);
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
464
465
  		return -EFAULT;
  	}
78efac537   Chao Yu   f2fs: fix to acco...
466
467
  
  	if (fio->io_wbc && !is_read_io(fio->op))
34e51a5e1   Tejun Heo   blkcg, writeback:...
468
  		wbc_account_cgroup_owner(fio->io_wbc, page, PAGE_SIZE);
78efac537   Chao Yu   f2fs: fix to acco...
469

04d328def   Mike Christie   f2fs: use bio op ...
470
  	bio_set_op_attrs(bio, fio->op, fio->op_flags);
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
471

5f9abab42   Jaegeuk Kim   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   Chao Yu   f2fs: fix to acco...
474
475
  
  	__submit_bio(fio->sbi, bio, fio->type);
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
476
477
  	return 0;
  }
8896cbdfe   Chao Yu   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   Chao Yu   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   Chao Yu   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   Chao Yu   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   Chao Yu   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   Chao Yu   f2fs: use generic...
641
  		return -EFSCORRUPTED;
8648de2c5   Chao Yu   f2fs: add bio cac...
642
643
644
  
  	trace_f2fs_submit_page_bio(page, fio);
  	f2fs_trace_ios(fio, 0);
8896cbdfe   Chao Yu   f2fs: introduce {...
645
  	if (bio && !page_is_mergeable(fio->sbi, bio, *fio->last_block,
0b20fcec8   Chao Yu   f2fs: cache globa...
646
647
  						fio->new_blkaddr))
  		f2fs_submit_merged_ipu_write(fio->sbi, &bio, NULL);
8648de2c5   Chao Yu   f2fs: add bio cac...
648
649
  alloc_new:
  	if (!bio) {
b757f6edb   Chao Yu   f2fs: clean up __...
650
  		bio = __bio_alloc(fio, BIO_MAX_PAGES);
8648de2c5   Chao Yu   f2fs: add bio cac...
651
  		bio_set_op_attrs(bio, fio->op, fio->op_flags);
8648de2c5   Chao Yu   f2fs: add bio cac...
652

0b20fcec8   Chao Yu   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   Chao Yu   f2fs: add bio cac...
657
658
659
  	}
  
  	if (fio->io_wbc)
9637d5173   Linus Torvalds   Merge tag 'for-li...
660
  		wbc_account_cgroup_owner(fio->io_wbc, page, PAGE_SIZE);
8648de2c5   Chao Yu   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   Chao Yu   f2fs: fix to let ...
669
  void f2fs_submit_page_write(struct f2fs_io_info *fio)
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
670
  {
05ca3632e   Jaegeuk Kim   f2fs: add sbi and...
671
  	struct f2fs_sb_info *sbi = fio->sbi;
458e6197c   Jaegeuk Kim   f2fs: refactor bi...
672
  	enum page_type btype = PAGE_TYPE_OF_BIO(fio->type);
a912b54d3   Jaegeuk Kim   f2fs: split bio c...
673
  	struct f2fs_bio_info *io = sbi->write_io[btype] + fio->temp;
4375a3366   Jaegeuk Kim   f2fs crypto: add ...
674
  	struct page *bio_page;
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
675

b9109b0e4   Jaegeuk Kim   f2fs: remove unne...
676
  	f2fs_bug_on(sbi, is_read_io(fio->op));
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
677

fb830fc5c   Chao Yu   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   Chao Yu   f2fs: fix to let ...
684
  			goto out;
fb830fc5c   Chao Yu   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   Jaegeuk Kim   f2fs: refactor bi...
691

93770ab7a   Chao Yu   f2fs: introduce D...
692
  	verify_fio_blkaddr(fio);
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
693

36951b38d   Chao Yu   f2fs: don't wait ...
694
  	bio_page = fio->encrypted_page ? fio->encrypted_page : fio->page;
ebf7c522f   Thomas Meyer   f2fs: Fix bool in...
695
696
  	/* set submitted = true as a return value */
  	fio->submitted = true;
d68f735b3   Jaegeuk Kim   f2fs: check io su...
697

b9109b0e4   Jaegeuk Kim   f2fs: remove unne...
698
  	inc_page_count(sbi, WB_DATA_TYPE(bio_page));
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
699

8896cbdfe   Chao Yu   f2fs: introduce {...
700
701
  	if (io->bio && !io_is_mergeable(sbi, io->bio, io, fio,
  			io->last_block_in_bio, fio->new_blkaddr))
458e6197c   Jaegeuk Kim   f2fs: refactor bi...
702
  		__submit_merged_bio(io);
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
703
704
  alloc_new:
  	if (io->bio == NULL) {
8223ecc45   Chao Yu   f2fs: fix to add ...
705
706
  		if (F2FS_IO_ALIGNED(sbi) &&
  				(fio->type == DATA || fio->type == NODE) &&
0a595ebaa   Jaegeuk Kim   f2fs: support IO ...
707
  				fio->new_blkaddr & F2FS_IO_SIZE_MASK(sbi)) {
b9109b0e4   Jaegeuk Kim   f2fs: remove unne...
708
  			dec_page_count(sbi, WB_DATA_TYPE(bio_page));
fe16efe6a   Chao Yu   f2fs: fix to let ...
709
710
  			fio->retry = true;
  			goto skip;
0a595ebaa   Jaegeuk Kim   f2fs: support IO ...
711
  		}
b757f6edb   Chao Yu   f2fs: clean up __...
712
  		io->bio = __bio_alloc(fio, BIO_MAX_PAGES);
458e6197c   Jaegeuk Kim   f2fs: refactor bi...
713
  		io->fio = *fio;
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
714
  	}
a912b54d3   Jaegeuk Kim   f2fs: split bio c...
715
  	if (bio_add_page(io->bio, bio_page, PAGE_SIZE, 0) < PAGE_SIZE) {
458e6197c   Jaegeuk Kim   f2fs: refactor bi...
716
  		__submit_merged_bio(io);
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
717
718
  		goto alloc_new;
  	}
578c64787   Yufen Yu   f2fs: implement c...
719
  	if (fio->io_wbc)
34e51a5e1   Tejun Heo   blkcg, writeback:...
720
  		wbc_account_cgroup_owner(fio->io_wbc, bio_page, PAGE_SIZE);
578c64787   Yufen Yu   f2fs: implement c...
721

7a9d75481   Chao Yu   f2fs: trace old b...
722
  	io->last_block_in_bio = fio->new_blkaddr;
05ca3632e   Jaegeuk Kim   f2fs: add sbi and...
723
  	f2fs_trace_ios(fio, 0);
fb830fc5c   Chao Yu   f2fs: introduce i...
724
725
  
  	trace_f2fs_submit_page_write(fio->page, fio);
fe16efe6a   Chao Yu   f2fs: fix to let ...
726
  skip:
fb830fc5c   Chao Yu   f2fs: introduce i...
727
728
  	if (fio->in_list)
  		goto next;
fe16efe6a   Chao Yu   f2fs: fix to let ...
729
  out:
4354994f0   Daniel Rosenberg   f2fs: checkpoint ...
730
  	if (is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN) ||
00e09c0bc   Chao Yu   f2fs: enhance f2f...
731
  				!f2fs_is_checkpoint_ready(sbi))
5ce805869   Jaegeuk Kim   f2fs: submit bio ...
732
  		__submit_merged_bio(io);
df0f8dc0e   Chao Yu   f2fs: avoid unnec...
733
  	up_write(&io->io_rwsem);
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
734
  }
95ae251fe   Eric Biggers   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   Jaegeuk Kim   f2fs: make get_lo...
740
  static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr,
95ae251fe   Eric Biggers   f2fs: add fs-veri...
741
742
  				      unsigned nr_pages, unsigned op_flag,
  				      pgoff_t first_idx)
13ba41e34   Jaegeuk Kim   f2fs: make get_lo...
743
744
  {
  	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
13ba41e34   Jaegeuk Kim   f2fs: make get_lo...
745
  	struct bio *bio;
6dbb17961   Eric Biggers   f2fs: refactor re...
746
747
  	struct bio_post_read_ctx *ctx;
  	unsigned int post_read_steps = 0;
13ba41e34   Jaegeuk Kim   f2fs: make get_lo...
748

d62fe9714   Chao Yu   f2fs: support bio...
749
  	bio = f2fs_bio_alloc(sbi, min_t(int, nr_pages, BIO_MAX_PAGES), false);
6dbb17961   Eric Biggers   f2fs: refactor re...
750
  	if (!bio)
13ba41e34   Jaegeuk Kim   f2fs: make get_lo...
751
  		return ERR_PTR(-ENOMEM);
13ba41e34   Jaegeuk Kim   f2fs: make get_lo...
752
753
  	f2fs_target_device(sbi, blkaddr, bio);
  	bio->bi_end_io = f2fs_read_end_io;
e2e59414a   Jaegeuk Kim   f2fs: assign REQ_...
754
  	bio_set_op_attrs(bio, REQ_OP_READ, op_flag);
13ba41e34   Jaegeuk Kim   f2fs: make get_lo...
755

6dbb17961   Eric Biggers   f2fs: refactor re...
756
757
  	if (f2fs_encrypted_file(inode))
  		post_read_steps |= 1 << STEP_DECRYPT;
95ae251fe   Eric Biggers   f2fs: add fs-veri...
758
759
760
  
  	if (f2fs_need_verity(inode, first_idx))
  		post_read_steps |= 1 << STEP_VERITY;
6dbb17961   Eric Biggers   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   Eric Biggers   f2fs: refactor re...
770
  	}
13ba41e34   Jaegeuk Kim   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   Chao Yu   f2fs: introduce D...
778
779
  	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
  	struct bio *bio;
13ba41e34   Jaegeuk Kim   f2fs: make get_lo...
780

95ae251fe   Eric Biggers   f2fs: add fs-veri...
781
  	bio = f2fs_grab_read_bio(inode, blkaddr, 1, 0, page->index);
13ba41e34   Jaegeuk Kim   f2fs: make get_lo...
782
783
  	if (IS_ERR(bio))
  		return PTR_ERR(bio);
0ded69f63   Jaegeuk Kim   f2fs: avoid wrong...
784
785
  	/* wait for GCed page writeback via META_MAPPING */
  	f2fs_wait_on_block_writeback(inode, blkaddr);
13ba41e34   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: clear PageE...
790
  	ClearPageError(page);
93770ab7a   Chao Yu   f2fs: introduce D...
791
792
  	inc_page_count(sbi, F2FS_RD_DATA);
  	__submit_bio(sbi, bio, DATA);
13ba41e34   Jaegeuk Kim   f2fs: make get_lo...
793
794
  	return 0;
  }
46008c6d4   Chao Yu   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   Chao Yu   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   Chao Yu   f2fs: support in ...
803
804
805
  
  	/* Get physical address of data block */
  	addr_array = blkaddr_in_node(rn);
7a2af766a   Chao Yu   f2fs: enhance on-...
806
  	addr_array[base + dn->ofs_in_node] = cpu_to_le32(dn->data_blkaddr);
46008c6d4   Chao Yu   f2fs: support in ...
807
  }
93dfe2ac5   Jaegeuk Kim   f2fs: refactor bi...
808
  /*
eb47b8009   Jaegeuk Kim   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   Chao Yu   f2fs: clean up sy...
814
  void f2fs_set_data_blkaddr(struct dnode_of_data *dn)
eb47b8009   Jaegeuk Kim   f2fs: add address...
815
  {
bae0ee7a7   Chao Yu   f2fs: check PageW...
816
  	f2fs_wait_on_page_writeback(dn->node_page, NODE, true, true);
46008c6d4   Chao Yu   f2fs: support in ...
817
818
  	__set_data_blkaddr(dn);
  	if (set_page_dirty(dn->node_page))
12719ae14   Jaegeuk Kim   f2fs: avoid unnec...
819
  		dn->node_changed = true;
eb47b8009   Jaegeuk Kim   f2fs: add address...
820
  }
f28b3434a   Chao Yu   f2fs: introduce f...
821
822
823
  void f2fs_update_data_blkaddr(struct dnode_of_data *dn, block_t blkaddr)
  {
  	dn->data_blkaddr = blkaddr;
4d57b86dd   Chao Yu   f2fs: clean up sy...
824
  	f2fs_set_data_blkaddr(dn);
f28b3434a   Chao Yu   f2fs: introduce f...
825
826
  	f2fs_update_extent_cache(dn);
  }
46008c6d4   Chao Yu   f2fs: support in ...
827
  /* dn->ofs_in_node will be returned with up-to-date last block pointer */
4d57b86dd   Chao Yu   f2fs: clean up sy...
828
  int f2fs_reserve_new_blocks(struct dnode_of_data *dn, blkcnt_t count)
eb47b8009   Jaegeuk Kim   f2fs: add address...
829
  {
4081363fb   Jaegeuk Kim   f2fs: introduce F...
830
  	struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
0abd675e9   Chao Yu   f2fs: support pla...
831
  	int err;
eb47b8009   Jaegeuk Kim   f2fs: add address...
832

46008c6d4   Chao Yu   f2fs: support in ...
833
834
  	if (!count)
  		return 0;
91942321e   Jaegeuk Kim   f2fs: use inode p...
835
  	if (unlikely(is_inode_flag_set(dn->inode, FI_NO_ALLOC)))
eb47b8009   Jaegeuk Kim   f2fs: add address...
836
  		return -EPERM;
0abd675e9   Chao Yu   f2fs: support pla...
837
838
  	if (unlikely((err = inc_valid_block_count(sbi, dn->inode, &count))))
  		return err;
eb47b8009   Jaegeuk Kim   f2fs: add address...
839

46008c6d4   Chao Yu   f2fs: support in ...
840
841
  	trace_f2fs_reserve_new_blocks(dn->inode, dn->nid,
  						dn->ofs_in_node, count);
bae0ee7a7   Chao Yu   f2fs: check PageW...
842
  	f2fs_wait_on_page_writeback(dn->node_page, NODE, true, true);
46008c6d4   Chao Yu   f2fs: support in ...
843
844
  
  	for (; count > 0; dn->ofs_in_node++) {
7a2af766a   Chao Yu   f2fs: enhance on-...
845
846
  		block_t blkaddr = datablock_addr(dn->inode,
  					dn->node_page, dn->ofs_in_node);
46008c6d4   Chao Yu   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   Jaegeuk Kim   f2fs: add address...
856
857
  	return 0;
  }
46008c6d4   Chao Yu   f2fs: support in ...
858
  /* Should keep dn->ofs_in_node unchanged */
4d57b86dd   Chao Yu   f2fs: clean up sy...
859
  int f2fs_reserve_new_block(struct dnode_of_data *dn)
46008c6d4   Chao Yu   f2fs: support in ...
860
861
862
  {
  	unsigned int ofs_in_node = dn->ofs_in_node;
  	int ret;
4d57b86dd   Chao Yu   f2fs: clean up sy...
863
  	ret = f2fs_reserve_new_blocks(dn, 1);
46008c6d4   Chao Yu   f2fs: support in ...
864
865
866
  	dn->ofs_in_node = ofs_in_node;
  	return ret;
  }
b600965c4   Huajun Li   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   Chao Yu   f2fs: clean up sy...
871
  	err = f2fs_get_dnode_of_data(dn, index, ALLOC_NODE);
b600965c4   Huajun Li   f2fs: add a new f...
872
873
  	if (err)
  		return err;
a8865372a   Jaegeuk Kim   f2fs: handle erro...
874

b600965c4   Huajun Li   f2fs: add a new f...
875
  	if (dn->data_blkaddr == NULL_ADDR)
4d57b86dd   Chao Yu   f2fs: clean up sy...
876
  		err = f2fs_reserve_new_block(dn);
a8865372a   Jaegeuk Kim   f2fs: handle erro...
877
  	if (err || need_put)
b600965c4   Huajun Li   f2fs: add a new f...
878
879
880
  		f2fs_put_dnode(dn);
  	return err;
  }
759af1c9c   Fan Li   f2fs: use extent ...
881
  int f2fs_get_block(struct dnode_of_data *dn, pgoff_t index)
eb47b8009   Jaegeuk Kim   f2fs: add address...
882
  {
e15882b6c   Hou Pengyang   f2fs: init local ...
883
  	struct extent_info ei  = {0,0,0};
759af1c9c   Fan Li   f2fs: use extent ...
884
  	struct inode *inode = dn->inode;
028a41e89   Chao Yu   f2fs: initialize ...
885

759af1c9c   Fan Li   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   Chao Yu   f2fs: add core fu...
889
  	}
028a41e89   Chao Yu   f2fs: initialize ...
890

759af1c9c   Fan Li   f2fs: use extent ...
891
  	return f2fs_reserve_block(dn, index);
eb47b8009   Jaegeuk Kim   f2fs: add address...
892
  }
4d57b86dd   Chao Yu   f2fs: clean up sy...
893
  struct page *f2fs_get_read_data_page(struct inode *inode, pgoff_t index,
04d328def   Mike Christie   f2fs: use bio op ...
894
  						int op_flags, bool for_write)
eb47b8009   Jaegeuk Kim   f2fs: add address...
895
  {
eb47b8009   Jaegeuk Kim   f2fs: add address...
896
897
898
  	struct address_space *mapping = inode->i_mapping;
  	struct dnode_of_data dn;
  	struct page *page;
e15882b6c   Hou Pengyang   f2fs: init local ...
899
  	struct extent_info ei = {0,0,0};
eb47b8009   Jaegeuk Kim   f2fs: add address...
900
  	int err;
4375a3366   Jaegeuk Kim   f2fs crypto: add ...
901

a56c7c6fb   Jaegeuk Kim   f2fs: set GFP_NOF...
902
  	page = f2fs_grab_cache_page(mapping, index, for_write);
650495ded   Jaegeuk Kim   f2fs: fix the inc...
903
904
  	if (!page)
  		return ERR_PTR(-ENOMEM);
cb3bc9ee0   Chao Yu   f2fs: use extent ...
905
906
  	if (f2fs_lookup_extent_cache(inode, index, &ei)) {
  		dn.data_blkaddr = ei.blk + index - ei.fofs;
93770ab7a   Chao Yu   f2fs: introduce D...
907
908
  		if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), dn.data_blkaddr,
  						DATA_GENERIC_ENHANCE_READ)) {
10f966bbf   Chao Yu   f2fs: use generic...
909
  			err = -EFSCORRUPTED;
93770ab7a   Chao Yu   f2fs: introduce D...
910
911
  			goto put_err;
  		}
cb3bc9ee0   Chao Yu   f2fs: use extent ...
912
913
  		goto got_it;
  	}
eb47b8009   Jaegeuk Kim   f2fs: add address...
914
  	set_new_dnode(&dn, inode, NULL, NULL, 0);
4d57b86dd   Chao Yu   f2fs: clean up sy...
915
  	err = f2fs_get_dnode_of_data(&dn, index, LOOKUP_NODE);
86531d6b8   Jaegeuk Kim   f2fs: callers tak...
916
917
  	if (err)
  		goto put_err;
eb47b8009   Jaegeuk Kim   f2fs: add address...
918
  	f2fs_put_dnode(&dn);
6bacf52fb   Jaegeuk Kim   f2fs: add unlikel...
919
  	if (unlikely(dn.data_blkaddr == NULL_ADDR)) {
86531d6b8   Jaegeuk Kim   f2fs: callers tak...
920
921
  		err = -ENOENT;
  		goto put_err;
650495ded   Jaegeuk Kim   f2fs: fix the inc...
922
  	}
93770ab7a   Chao Yu   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   Chao Yu   f2fs: use generic...
927
  		err = -EFSCORRUPTED;
93770ab7a   Chao Yu   f2fs: introduce D...
928
929
  		goto put_err;
  	}
cb3bc9ee0   Chao Yu   f2fs: use extent ...
930
  got_it:
43f3eae1d   Jaegeuk Kim   f2fs: split find_...
931
932
  	if (PageUptodate(page)) {
  		unlock_page(page);
eb47b8009   Jaegeuk Kim   f2fs: add address...
933
  		return page;
43f3eae1d   Jaegeuk Kim   f2fs: split find_...
934
  	}
eb47b8009   Jaegeuk Kim   f2fs: add address...
935

d59ff4df7   Jaegeuk Kim   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   Chao Yu   f2fs: clean up sy...
940
941
  	 * see, f2fs_add_link -> f2fs_get_new_data_page ->
  	 * f2fs_init_inode_metadata.
d59ff4df7   Jaegeuk Kim   f2fs: fix wrong B...
942
943
  	 */
  	if (dn.data_blkaddr == NEW_ADDR) {
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
944
  		zero_user_segment(page, 0, PAGE_SIZE);
237c0790e   Jaegeuk Kim   f2fs: call SetPag...
945
946
  		if (!PageUptodate(page))
  			SetPageUptodate(page);
43f3eae1d   Jaegeuk Kim   f2fs: split find_...
947
  		unlock_page(page);
d59ff4df7   Jaegeuk Kim   f2fs: fix wrong B...
948
949
  		return page;
  	}
eb47b8009   Jaegeuk Kim   f2fs: add address...
950

13ba41e34   Jaegeuk Kim   f2fs: make get_lo...
951
  	err = f2fs_submit_page_read(inode, page, dn.data_blkaddr);
393ff91f5   Jaegeuk Kim   f2fs: reduce unnc...
952
  	if (err)
86531d6b8   Jaegeuk Kim   f2fs: callers tak...
953
  		goto put_err;
43f3eae1d   Jaegeuk Kim   f2fs: split find_...
954
  	return page;
86531d6b8   Jaegeuk Kim   f2fs: callers tak...
955
956
957
958
  
  put_err:
  	f2fs_put_page(page, 1);
  	return ERR_PTR(err);
43f3eae1d   Jaegeuk Kim   f2fs: split find_...
959
  }
4d57b86dd   Chao Yu   f2fs: clean up sy...
960
  struct page *f2fs_find_data_page(struct inode *inode, pgoff_t index)
43f3eae1d   Jaegeuk Kim   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   Chao Yu   f2fs: clean up sy...
969
  	page = f2fs_get_read_data_page(inode, index, 0, false);
43f3eae1d   Jaegeuk Kim   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   Chao Yu   f2fs: clean up sy...
989
  struct page *f2fs_get_lock_data_page(struct inode *inode, pgoff_t index,
a56c7c6fb   Jaegeuk Kim   f2fs: set GFP_NOF...
990
  							bool for_write)
43f3eae1d   Jaegeuk Kim   f2fs: split find_...
991
992
993
994
  {
  	struct address_space *mapping = inode->i_mapping;
  	struct page *page;
  repeat:
4d57b86dd   Chao Yu   f2fs: clean up sy...
995
  	page = f2fs_get_read_data_page(inode, index, 0, for_write);
43f3eae1d   Jaegeuk Kim   f2fs: split find_...
996
997
  	if (IS_ERR(page))
  		return page;
393ff91f5   Jaegeuk Kim   f2fs: reduce unnc...
998

43f3eae1d   Jaegeuk Kim   f2fs: split find_...
999
  	/* wait for read completion */
393ff91f5   Jaegeuk Kim   f2fs: reduce unnc...
1000
  	lock_page(page);
6bacf52fb   Jaegeuk Kim   f2fs: add unlikel...
1001
  	if (unlikely(page->mapping != mapping)) {
afcb7ca01   Jaegeuk Kim   f2fs: check trunc...
1002
1003
  		f2fs_put_page(page, 1);
  		goto repeat;
eb47b8009   Jaegeuk Kim   f2fs: add address...
1004
  	}
1563ac75e   Chao Yu   f2fs: fix to dete...
1005
1006
1007
1008
  	if (unlikely(!PageUptodate(page))) {
  		f2fs_put_page(page, 1);
  		return ERR_PTR(-EIO);
  	}
eb47b8009   Jaegeuk Kim   f2fs: add address...
1009
1010
  	return page;
  }
0a8165d7c   Jaegeuk Kim   f2fs: adjust kern...
1011
  /*
eb47b8009   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: introduce a...
1014
   *
4f4124d0b   Chao Yu   f2fs: update seve...
1015
1016
   * Also, caller should grab and release a rwsem by calling f2fs_lock_op() and
   * f2fs_unlock_op().
470f00e96   Chao Yu   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   Jaegeuk Kim   f2fs: add address...
1019
   */
4d57b86dd   Chao Yu   f2fs: clean up sy...
1020
  struct page *f2fs_get_new_data_page(struct inode *inode,
a8865372a   Jaegeuk Kim   f2fs: handle erro...
1021
  		struct page *ipage, pgoff_t index, bool new_i_size)
eb47b8009   Jaegeuk Kim   f2fs: add address...
1022
  {
eb47b8009   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: check the p...
1027

a56c7c6fb   Jaegeuk Kim   f2fs: set GFP_NOF...
1028
  	page = f2fs_grab_cache_page(mapping, index, true);
470f00e96   Chao Yu   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   Jaegeuk Kim   f2fs: fix race on...
1035
  		return ERR_PTR(-ENOMEM);
470f00e96   Chao Yu   f2fs: fix to rele...
1036
  	}
eb47b8009   Jaegeuk Kim   f2fs: add address...
1037

a8865372a   Jaegeuk Kim   f2fs: handle erro...
1038
  	set_new_dnode(&dn, inode, ipage, NULL, 0);
b600965c4   Huajun Li   f2fs: add a new f...
1039
  	err = f2fs_reserve_block(&dn, index);
01f28610a   Jaegeuk Kim   f2fs: fix race on...
1040
1041
  	if (err) {
  		f2fs_put_page(page, 1);
eb47b8009   Jaegeuk Kim   f2fs: add address...
1042
  		return ERR_PTR(err);
a8865372a   Jaegeuk Kim   f2fs: handle erro...
1043
  	}
01f28610a   Jaegeuk Kim   f2fs: fix race on...
1044
1045
  	if (!ipage)
  		f2fs_put_dnode(&dn);
eb47b8009   Jaegeuk Kim   f2fs: add address...
1046
1047
  
  	if (PageUptodate(page))
01f28610a   Jaegeuk Kim   f2fs: fix race on...
1048
  		goto got_it;
eb47b8009   Jaegeuk Kim   f2fs: add address...
1049
1050
  
  	if (dn.data_blkaddr == NEW_ADDR) {
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1051
  		zero_user_segment(page, 0, PAGE_SIZE);
237c0790e   Jaegeuk Kim   f2fs: call SetPag...
1052
1053
  		if (!PageUptodate(page))
  			SetPageUptodate(page);
eb47b8009   Jaegeuk Kim   f2fs: add address...
1054
  	} else {
4375a3366   Jaegeuk Kim   f2fs crypto: add ...
1055
  		f2fs_put_page(page, 1);
a8865372a   Jaegeuk Kim   f2fs: handle erro...
1056

7612118ae   Jaegeuk Kim   f2fs: check the p...
1057
1058
  		/* if ipage exists, blkaddr should be NEW_ADDR */
  		f2fs_bug_on(F2FS_I_SB(inode), ipage);
4d57b86dd   Chao Yu   f2fs: clean up sy...
1059
  		page = f2fs_get_lock_data_page(inode, index, true);
4375a3366   Jaegeuk Kim   f2fs crypto: add ...
1060
  		if (IS_ERR(page))
7612118ae   Jaegeuk Kim   f2fs: check the p...
1061
  			return page;
eb47b8009   Jaegeuk Kim   f2fs: add address...
1062
  	}
01f28610a   Jaegeuk Kim   f2fs: fix race on...
1063
  got_it:
9edcdabf3   Chao Yu   f2fs: fix overflo...
1064
  	if (new_i_size && i_size_read(inode) <
ee6d182f2   Jaegeuk Kim   f2fs: remove sync...
1065
  				((loff_t)(index + 1) << PAGE_SHIFT))
fc9581c80   Jaegeuk Kim   f2fs: introduce f...
1066
  		f2fs_i_size_write(inode, ((loff_t)(index + 1) << PAGE_SHIFT));
eb47b8009   Jaegeuk Kim   f2fs: add address...
1067
1068
  	return page;
  }
d5097be55   Hyunchul Lee   f2fs: apply write...
1069
  static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
bfad7c2d4   Jaegeuk Kim   f2fs: introduce a...
1070
  {
4081363fb   Jaegeuk Kim   f2fs: introduce F...
1071
  	struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
bfad7c2d4   Jaegeuk Kim   f2fs: introduce a...
1072
  	struct f2fs_summary sum;
bfad7c2d4   Jaegeuk Kim   f2fs: introduce a...
1073
  	struct node_info ni;
6aa58d8ad   Chao Yu   f2fs: readahead e...
1074
  	block_t old_blkaddr;
46008c6d4   Chao Yu   f2fs: support in ...
1075
  	blkcnt_t count = 1;
0abd675e9   Chao Yu   f2fs: support pla...
1076
  	int err;
bfad7c2d4   Jaegeuk Kim   f2fs: introduce a...
1077

91942321e   Jaegeuk Kim   f2fs: use inode p...
1078
  	if (unlikely(is_inode_flag_set(dn->inode, FI_NO_ALLOC)))
bfad7c2d4   Jaegeuk Kim   f2fs: introduce a...
1079
  		return -EPERM;
df6136ef5   Chao Yu   f2fs: preallocate...
1080

7735730d3   Chao Yu   f2fs: fix to prop...
1081
1082
1083
  	err = f2fs_get_node_info(sbi, dn->nid, &ni);
  	if (err)
  		return err;
7a2af766a   Chao Yu   f2fs: enhance on-...
1084
1085
  	dn->data_blkaddr = datablock_addr(dn->inode,
  				dn->node_page, dn->ofs_in_node);
f847c699c   Chao Yu   f2fs: allow out-p...
1086
  	if (dn->data_blkaddr != NULL_ADDR)
df6136ef5   Chao Yu   f2fs: preallocate...
1087
  		goto alloc;
0abd675e9   Chao Yu   f2fs: support pla...
1088
1089
  	if (unlikely((err = inc_valid_block_count(sbi, dn->inode, &count))))
  		return err;
bfad7c2d4   Jaegeuk Kim   f2fs: introduce a...
1090

df6136ef5   Chao Yu   f2fs: preallocate...
1091
  alloc:
bfad7c2d4   Jaegeuk Kim   f2fs: introduce a...
1092
  	set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
6aa58d8ad   Chao Yu   f2fs: readahead e...
1093
1094
  	old_blkaddr = dn->data_blkaddr;
  	f2fs_allocate_data_block(sbi, NULL, old_blkaddr, &dn->data_blkaddr,
d5097be55   Hyunchul Lee   f2fs: apply write...
1095
  					&sum, seg_type, NULL, false);
6aa58d8ad   Chao Yu   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   Chao Yu   f2fs: fix extent ...
1099
  	f2fs_update_data_blkaddr(dn, dn->data_blkaddr);
bfad7c2d4   Jaegeuk Kim   f2fs: introduce a...
1100

0a4daae5f   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: introduce a...
1105
1106
  	return 0;
  }
a7de60869   Jaegeuk Kim   f2fs: use err for...
1107
  int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *from)
59b802e5a   Jaegeuk Kim   f2fs: allocate da...
1108
  {
b439b103a   Jaegeuk Kim   f2fs: move dio pr...
1109
  	struct inode *inode = file_inode(iocb->ki_filp);
5b8db7fad   Chao Yu   f2fs: simplify __...
1110
  	struct f2fs_map_blocks map;
d6d478a14   Chao Yu   f2fs: continue to...
1111
  	int flag;
a7de60869   Jaegeuk Kim   f2fs: use err for...
1112
  	int err = 0;
d6d478a14   Chao Yu   f2fs: continue to...
1113
  	bool direct_io = iocb->ki_flags & IOCB_DIRECT;
59b802e5a   Jaegeuk Kim   f2fs: allocate da...
1114

71ad682c1   Weichao Guo   f2fs: convert inl...
1115
  	/* convert inline data for Direct I/O*/
d6d478a14   Chao Yu   f2fs: continue to...
1116
  	if (direct_io) {
71ad682c1   Weichao Guo   f2fs: convert inl...
1117
1118
1119
1120
  		err = f2fs_convert_inline_inode(inode);
  		if (err)
  			return err;
  	}
f9d6d0597   Chao Yu   f2fs: fix out-pla...
1121
1122
  	if (direct_io && allow_outplace_dio(inode, iocb, from))
  		return 0;
dc91de78e   Jaegeuk Kim   f2fs: do not prea...
1123
1124
  	if (is_inode_flag_set(inode, FI_NO_PREALLOC))
  		return 0;
0080c5076   Jaegeuk Kim   f2fs: do not prea...
1125
  	map.m_lblk = F2FS_BLK_ALIGN(iocb->ki_pos);
dfd02e4de   Chao Yu   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   Chao Yu   f2fs: speed up ha...
1131
  	map.m_next_pgofs = NULL;
c4020b2da   Chao Yu   f2fs: support F2F...
1132
  	map.m_next_extent = NULL;
d5097be55   Hyunchul Lee   f2fs: apply write...
1133
  	map.m_seg_type = NO_CHECK_TYPE;
f9d6d0597   Chao Yu   f2fs: fix out-pla...
1134
  	map.m_may_create = true;
2a3407607   Jaegeuk Kim   f2fs: call f2fs_b...
1135

d6d478a14   Chao Yu   f2fs: continue to...
1136
  	if (direct_io) {
4d57b86dd   Chao Yu   f2fs: clean up sy...
1137
  		map.m_seg_type = f2fs_rw_hint_to_seg_type(iocb->ki_hint);
f847c699c   Chao Yu   f2fs: allow out-p...
1138
  		flag = f2fs_force_buffered_io(inode, iocb, from) ?
d6d478a14   Chao Yu   f2fs: continue to...
1139
1140
1141
  					F2FS_GET_BLOCK_PRE_AIO :
  					F2FS_GET_BLOCK_PRE_DIO;
  		goto map_blocks;
d5097be55   Hyunchul Lee   f2fs: apply write...
1142
  	}
f24703712   Chao Yu   f2fs: make max in...
1143
  	if (iocb->ki_pos + iov_iter_count(from) > MAX_INLINE_DATA(inode)) {
a7de60869   Jaegeuk Kim   f2fs: use err for...
1144
1145
1146
  		err = f2fs_convert_inline_inode(inode);
  		if (err)
  			return err;
b439b103a   Jaegeuk Kim   f2fs: move dio pr...
1147
  	}
d6d478a14   Chao Yu   f2fs: continue to...
1148
  	if (f2fs_has_inline_data(inode))
25006645d   Sheng Yong   f2fs: still write...
1149
  		return err;
d6d478a14   Chao Yu   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   Sheng Yong   f2fs: still write...
1159
  	}
a7de60869   Jaegeuk Kim   f2fs: use err for...
1160
  	return err;
59b802e5a   Jaegeuk Kim   f2fs: allocate da...
1161
  }
39a869582   Chao Yu   f2fs: refactor ->...
1162
  void __do_map_lock(struct f2fs_sb_info *sbi, int flag, bool lock)
59c9081bc   Yunlei He   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   Jaegeuk Kim   f2fs: adjust kern...
1176
  /*
003a3e1d6   Jaegeuk Kim   f2fs: add f2fs_ma...
1177
1178
   * f2fs_map_blocks() now supported readahead/bmap/rw direct_IO with
   * f2fs_map_blocks structure.
4f4124d0b   Chao Yu   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   Jaegeuk Kim   f2fs: add address...
1184
   */
d323d005a   Chao Yu   f2fs: support fil...
1185
  int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map,
e2b4e2bc8   Chao Yu   f2fs: fix incorre...
1186
  						int create, int flag)
eb47b8009   Jaegeuk Kim   f2fs: add address...
1187
  {
003a3e1d6   Jaegeuk Kim   f2fs: add f2fs_ma...
1188
  	unsigned int maxblocks = map->m_len;
eb47b8009   Jaegeuk Kim   f2fs: add address...
1189
  	struct dnode_of_data dn;
f9811703f   Chao Yu   f2fs: fix to hand...
1190
  	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
f9d6d0597   Chao Yu   f2fs: fix out-pla...
1191
  	int mode = map->m_may_create ? ALLOC_NODE : LOOKUP_NODE;
46008c6d4   Chao Yu   f2fs: support in ...
1192
  	pgoff_t pgofs, end_offset, end;
bfad7c2d4   Jaegeuk Kim   f2fs: introduce a...
1193
  	int err = 0, ofs = 1;
46008c6d4   Chao Yu   f2fs: support in ...
1194
1195
  	unsigned int ofs_in_node, last_ofs_in_node;
  	blkcnt_t prealloc;
e15882b6c   Hou Pengyang   f2fs: init local ...
1196
  	struct extent_info ei = {0,0,0};
7df3a4318   Fan Li   f2fs: optimize th...
1197
  	block_t blkaddr;
c4020b2da   Chao Yu   f2fs: support F2F...
1198
  	unsigned int start_pgofs;
eb47b8009   Jaegeuk Kim   f2fs: add address...
1199

dfd02e4de   Chao Yu   f2fs: fix to prea...
1200
1201
  	if (!maxblocks)
  		return 0;
003a3e1d6   Jaegeuk Kim   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   Chao Yu   f2fs: support in ...
1207
  	end = pgofs + maxblocks;
eb47b8009   Jaegeuk Kim   f2fs: add address...
1208

24b849125   Jaegeuk Kim   f2fs: preallocate...
1209
  	if (!create && f2fs_lookup_extent_cache(inode, pgofs, &ei)) {
f4f0b6777   Jia Zhu   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   Jaegeuk Kim   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   Chao Yu   f2fs: support F2F...
1216
1217
  		if (map->m_next_extent)
  			*map->m_next_extent = pgofs + map->m_len;
1e78e8bd9   Sahitya Tummala   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   Jaegeuk Kim   f2fs: introduce a...
1223
  		goto out;
a2e7d1bfe   Chao Yu   f2fs: introduce f...
1224
  	}
bfad7c2d4   Jaegeuk Kim   f2fs: introduce a...
1225

4fe71e88b   Chao Yu   f2fs: simplify f2...
1226
  next_dnode:
f9d6d0597   Chao Yu   f2fs: fix out-pla...
1227
  	if (map->m_may_create)
59c9081bc   Yunlei He   f2fs: allow write...
1228
  		__do_map_lock(sbi, flag, true);
eb47b8009   Jaegeuk Kim   f2fs: add address...
1229
1230
1231
  
  	/* When reading holes, we need its node page */
  	set_new_dnode(&dn, inode, NULL, NULL, 0);
4d57b86dd   Chao Yu   f2fs: clean up sy...
1232
  	err = f2fs_get_dnode_of_data(&dn, pgofs, mode);
1ec79083b   Jaegeuk Kim   f2fs: should put ...
1233
  	if (err) {
43473f964   Chao Yu   f2fs: fix incorre...
1234
1235
  		if (flag == F2FS_GET_BLOCK_BMAP)
  			map->m_pblk = 0;
da85985c6   Chao Yu   f2fs: speed up ha...
1236
  		if (err == -ENOENT) {
bfad7c2d4   Jaegeuk Kim   f2fs: introduce a...
1237
  			err = 0;
da85985c6   Chao Yu   f2fs: speed up ha...
1238
1239
  			if (map->m_next_pgofs)
  				*map->m_next_pgofs =
4d57b86dd   Chao Yu   f2fs: clean up sy...
1240
  					f2fs_get_next_page_offset(&dn, pgofs);
c4020b2da   Chao Yu   f2fs: support F2F...
1241
1242
  			if (map->m_next_extent)
  				*map->m_next_extent =
4d57b86dd   Chao Yu   f2fs: clean up sy...
1243
  					f2fs_get_next_page_offset(&dn, pgofs);
da85985c6   Chao Yu   f2fs: speed up ha...
1244
  		}
bfad7c2d4   Jaegeuk Kim   f2fs: introduce a...
1245
  		goto unlock_out;
848753aa3   Namjae Jeon   f2fs: add tracepo...
1246
  	}
973163fc0   Chao Yu   f2fs: reorganize ...
1247

c4020b2da   Chao Yu   f2fs: support F2F...
1248
  	start_pgofs = pgofs;
46008c6d4   Chao Yu   f2fs: support in ...
1249
  	prealloc = 0;
230436b3e   Arnd Bergmann   f2fs: hide a mayb...
1250
  	last_ofs_in_node = ofs_in_node = dn.ofs_in_node;
81ca7350c   Chao Yu   f2fs: remove unne...
1251
  	end_offset = ADDRS_PER_PAGE(dn.node_page, inode);
4fe71e88b   Chao Yu   f2fs: simplify f2...
1252
1253
  
  next_block:
7a2af766a   Chao Yu   f2fs: enhance on-...
1254
  	blkaddr = datablock_addr(dn.inode, dn.node_page, dn.ofs_in_node);
4fe71e88b   Chao Yu   f2fs: simplify f2...
1255

c9b60788f   Chao Yu   f2fs: fix to do s...
1256
  	if (__is_valid_data_blkaddr(blkaddr) &&
93770ab7a   Chao Yu   f2fs: introduce D...
1257
  		!f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC_ENHANCE)) {
10f966bbf   Chao Yu   f2fs: use generic...
1258
  		err = -EFSCORRUPTED;
c9b60788f   Chao Yu   f2fs: fix to do s...
1259
1260
  		goto sync_out;
  	}
93770ab7a   Chao Yu   f2fs: introduce D...
1261
  	if (__is_valid_data_blkaddr(blkaddr)) {
f847c699c   Chao Yu   f2fs: allow out-p...
1262
  		/* use out-place-update for driect IO under LFS mode */
f9d6d0597   Chao Yu   f2fs: fix out-pla...
1263
1264
  		if (test_opt(sbi, LFS) && flag == F2FS_GET_BLOCK_DIO &&
  							map->m_may_create) {
f847c699c   Chao Yu   f2fs: allow out-p...
1265
  			err = __allocate_data_block(&dn, map->m_seg_type);
05e360061   Chao Yu   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   Chao Yu   f2fs: allow out-p...
1270
1271
  		}
  	} else {
973163fc0   Chao Yu   f2fs: reorganize ...
1272
  		if (create) {
f9811703f   Chao Yu   f2fs: fix to hand...
1273
1274
  			if (unlikely(f2fs_cp_error(sbi))) {
  				err = -EIO;
4fe71e88b   Chao Yu   f2fs: simplify f2...
1275
  				goto sync_out;
f9811703f   Chao Yu   f2fs: fix to hand...
1276
  			}
24b849125   Jaegeuk Kim   f2fs: preallocate...
1277
  			if (flag == F2FS_GET_BLOCK_PRE_AIO) {
46008c6d4   Chao Yu   f2fs: support in ...
1278
1279
1280
1281
  				if (blkaddr == NULL_ADDR) {
  					prealloc++;
  					last_ofs_in_node = dn.ofs_in_node;
  				}
24b849125   Jaegeuk Kim   f2fs: preallocate...
1282
  			} else {
0a4daae5f   Jaegeuk Kim   f2fs: update i_si...
1283
1284
  				WARN_ON(flag != F2FS_GET_BLOCK_PRE_DIO &&
  					flag != F2FS_GET_BLOCK_DIO);
d5097be55   Hyunchul Lee   f2fs: apply write...
1285
1286
  				err = __allocate_data_block(&dn,
  							map->m_seg_type);
6f2d8ed65   Chao Yu   f2fs: don't miss ...
1287
  				if (!err)
91942321e   Jaegeuk Kim   f2fs: use inode p...
1288
  					set_inode_flag(inode, FI_APPEND_WRITE);
24b849125   Jaegeuk Kim   f2fs: preallocate...
1289
  			}
973163fc0   Chao Yu   f2fs: reorganize ...
1290
  			if (err)
4fe71e88b   Chao Yu   f2fs: simplify f2...
1291
  				goto sync_out;
3f2be0430   Kinglong Mee   f2fs: avoid m_fla...
1292
  			map->m_flags |= F2FS_MAP_NEW;
4fe71e88b   Chao Yu   f2fs: simplify f2...
1293
  			blkaddr = dn.data_blkaddr;
973163fc0   Chao Yu   f2fs: reorganize ...
1294
  		} else {
43473f964   Chao Yu   f2fs: fix incorre...
1295
1296
1297
1298
  			if (flag == F2FS_GET_BLOCK_BMAP) {
  				map->m_pblk = 0;
  				goto sync_out;
  			}
c4020b2da   Chao Yu   f2fs: support F2F...
1299
1300
  			if (flag == F2FS_GET_BLOCK_PRECACHE)
  				goto sync_out;
da85985c6   Chao Yu   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   Chao Yu   f2fs: clean up f2...
1305
  				goto sync_out;
da85985c6   Chao Yu   f2fs: speed up ha...
1306
  			}
f3d98e74f   Chao Yu   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   Chao Yu   f2fs: simplify f2...
1311
  				goto sync_out;
f3d98e74f   Chao Yu   f2fs: speed up de...
1312
  			}
e2b4e2bc8   Chao Yu   f2fs: fix incorre...
1313
  		}
e2b4e2bc8   Chao Yu   f2fs: fix incorre...
1314
  	}
eb47b8009   Jaegeuk Kim   f2fs: add address...
1315

46008c6d4   Chao Yu   f2fs: support in ...
1316
1317
  	if (flag == F2FS_GET_BLOCK_PRE_AIO)
  		goto skip;
4fe71e88b   Chao Yu   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   Jaegeuk Kim   f2fs: move dio pr...
1328
  			(map->m_pblk == NEW_ADDR && blkaddr == NEW_ADDR) ||
46008c6d4   Chao Yu   f2fs: support in ...
1329
  			flag == F2FS_GET_BLOCK_PRE_DIO) {
4fe71e88b   Chao Yu   f2fs: simplify f2...
1330
1331
1332
1333
1334
  		ofs++;
  		map->m_len++;
  	} else {
  		goto sync_out;
  	}
bfad7c2d4   Jaegeuk Kim   f2fs: introduce a...
1335

46008c6d4   Chao Yu   f2fs: support in ...
1336
  skip:
bfad7c2d4   Jaegeuk Kim   f2fs: introduce a...
1337
1338
  	dn.ofs_in_node++;
  	pgofs++;
46008c6d4   Chao Yu   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   Fan Li   f2fs: optimize th...
1342

46008c6d4   Chao Yu   f2fs: support in ...
1343
  		dn.ofs_in_node = ofs_in_node;
4d57b86dd   Chao Yu   f2fs: clean up sy...
1344
  		err = f2fs_reserve_new_blocks(&dn, prealloc);
46008c6d4   Chao Yu   f2fs: support in ...
1345
1346
  		if (err)
  			goto sync_out;
bfad7c2d4   Jaegeuk Kim   f2fs: introduce a...
1347

46008c6d4   Chao Yu   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   Chao Yu   f2fs: reduce cove...
1352
  		}
46008c6d4   Chao Yu   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   Chao Yu   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   Chao Yu   f2fs: support in ...
1369
  	f2fs_put_dnode(&dn);
f9d6d0597   Chao Yu   f2fs: fix out-pla...
1370
  	if (map->m_may_create) {
59c9081bc   Yunlei He   f2fs: allow write...
1371
  		__do_map_lock(sbi, flag, false);
6f2d8ed65   Chao Yu   f2fs: don't miss ...
1372
  		f2fs_balance_fs(sbi, dn.node_changed);
eb47b8009   Jaegeuk Kim   f2fs: add address...
1373
  	}
46008c6d4   Chao Yu   f2fs: support in ...
1374
  	goto next_dnode;
7df3a4318   Fan Li   f2fs: optimize th...
1375

bfad7c2d4   Jaegeuk Kim   f2fs: introduce a...
1376
  sync_out:
1e78e8bd9   Sahitya Tummala   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   Chao Yu   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   Jaegeuk Kim   f2fs: add address...
1393
  	f2fs_put_dnode(&dn);
bfad7c2d4   Jaegeuk Kim   f2fs: introduce a...
1394
  unlock_out:
f9d6d0597   Chao Yu   f2fs: fix out-pla...
1395
  	if (map->m_may_create) {
59c9081bc   Yunlei He   f2fs: allow write...
1396
  		__do_map_lock(sbi, flag, false);
6f2d8ed65   Chao Yu   f2fs: don't miss ...
1397
  		f2fs_balance_fs(sbi, dn.node_changed);
2a3407607   Jaegeuk Kim   f2fs: call f2fs_b...
1398
  	}
bfad7c2d4   Jaegeuk Kim   f2fs: introduce a...
1399
  out:
003a3e1d6   Jaegeuk Kim   f2fs: add f2fs_ma...
1400
  	trace_f2fs_map_blocks(inode, map, err);
bfad7c2d4   Jaegeuk Kim   f2fs: introduce a...
1401
  	return err;
eb47b8009   Jaegeuk Kim   f2fs: add address...
1402
  }
b91050a80   Hyunchul Lee   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   Jia Zhu   f2fs: fix m_may_c...
1416
  	map.m_may_create = false;
b91050a80   Hyunchul Lee   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   Jaegeuk Kim   f2fs: add f2fs_ma...
1428
  static int __get_data_block(struct inode *inode, sector_t iblock,
da85985c6   Chao Yu   f2fs: speed up ha...
1429
  			struct buffer_head *bh, int create, int flag,
f9d6d0597   Chao Yu   f2fs: fix out-pla...
1430
  			pgoff_t *next_pgofs, int seg_type, bool may_write)
003a3e1d6   Jaegeuk Kim   f2fs: add f2fs_ma...
1431
1432
  {
  	struct f2fs_map_blocks map;
a7de60869   Jaegeuk Kim   f2fs: use err for...
1433
  	int err;
003a3e1d6   Jaegeuk Kim   f2fs: add f2fs_ma...
1434
1435
1436
  
  	map.m_lblk = iblock;
  	map.m_len = bh->b_size >> inode->i_blkbits;
da85985c6   Chao Yu   f2fs: speed up ha...
1437
  	map.m_next_pgofs = next_pgofs;
c4020b2da   Chao Yu   f2fs: support F2F...
1438
  	map.m_next_extent = NULL;
d5097be55   Hyunchul Lee   f2fs: apply write...
1439
  	map.m_seg_type = seg_type;
f9d6d0597   Chao Yu   f2fs: fix out-pla...
1440
  	map.m_may_create = may_write;
003a3e1d6   Jaegeuk Kim   f2fs: add f2fs_ma...
1441

a7de60869   Jaegeuk Kim   f2fs: use err for...
1442
1443
  	err = f2fs_map_blocks(inode, &map, create, flag);
  	if (!err) {
003a3e1d6   Jaegeuk Kim   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   Wei Fang   f2fs: fix a dead ...
1446
  		bh->b_size = (u64)map.m_len << inode->i_blkbits;
003a3e1d6   Jaegeuk Kim   f2fs: add f2fs_ma...
1447
  	}
a7de60869   Jaegeuk Kim   f2fs: use err for...
1448
  	return err;
003a3e1d6   Jaegeuk Kim   f2fs: add f2fs_ma...
1449
  }
ccfb30001   Jaegeuk Kim   f2fs: fix to repo...
1450
  static int get_data_block(struct inode *inode, sector_t iblock,
da85985c6   Chao Yu   f2fs: speed up ha...
1451
1452
  			struct buffer_head *bh_result, int create, int flag,
  			pgoff_t *next_pgofs)
e2b4e2bc8   Chao Yu   f2fs: fix incorre...
1453
  {
da85985c6   Chao Yu   f2fs: speed up ha...
1454
  	return __get_data_block(inode, iblock, bh_result, create,
d5097be55   Hyunchul Lee   f2fs: apply write...
1455
  							flag, next_pgofs,
f9d6d0597   Chao Yu   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   Jaegeuk Kim   f2fs: fix liveloc...
1465
  				IS_SWAPFILE(inode) ? false : true);
e2b4e2bc8   Chao Yu   f2fs: fix incorre...
1466
1467
1468
  }
  
  static int get_data_block_dio(struct inode *inode, sector_t iblock,
ccfb30001   Jaegeuk Kim   f2fs: fix to repo...
1469
1470
  			struct buffer_head *bh_result, int create)
  {
e2b4e2bc8   Chao Yu   f2fs: fix incorre...
1471
  	return __get_data_block(inode, iblock, bh_result, create,
f9d6d0597   Chao Yu   f2fs: fix out-pla...
1472
1473
1474
  				F2FS_GET_BLOCK_DIO, NULL,
  				f2fs_rw_hint_to_seg_type(inode->i_write_hint),
  				false);
ccfb30001   Jaegeuk Kim   f2fs: fix to repo...
1475
  }
e2b4e2bc8   Chao Yu   f2fs: fix incorre...
1476
  static int get_data_block_bmap(struct inode *inode, sector_t iblock,
ccfb30001   Jaegeuk Kim   f2fs: fix to repo...
1477
1478
  			struct buffer_head *bh_result, int create)
  {
179448bfe   Yunlei He   f2fs: add a max b...
1479
  	/* Block number less than F2FS MAX BLOCKS */
e0afc4d6d   Chao Yu   f2fs: introduce m...
1480
  	if (unlikely(iblock >= F2FS_I_SB(inode)->max_file_blocks))
179448bfe   Yunlei He   f2fs: add a max b...
1481
  		return -EFBIG;
e2b4e2bc8   Chao Yu   f2fs: fix incorre...
1482
  	return __get_data_block(inode, iblock, bh_result, create,
d5097be55   Hyunchul Lee   f2fs: apply write...
1483
  						F2FS_GET_BLOCK_BMAP, NULL,
f9d6d0597   Chao Yu   f2fs: fix out-pla...
1484
  						NO_CHECK_TYPE, create);
ccfb30001   Jaegeuk Kim   f2fs: fix to repo...
1485
  }
7f63eb77a   Jaegeuk Kim   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   Chao Yu   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   Chao Yu   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   Chao Yu   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   Chao Yu   f2fs: kill F2FS_I...
1522
  					get_inline_xattr_addrs(inode));
442a9dbd5   Chao Yu   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   Chao Yu   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   Chao Yu   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   Jaegeuk Kim   f2fs: support f2f...
1562
1563
1564
  int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
  		u64 start, u64 len)
  {
7f63eb77a   Jaegeuk Kim   f2fs: report unwr...
1565
1566
  	struct buffer_head map_bh;
  	sector_t start_blk, last_blk;
da85985c6   Chao Yu   f2fs: speed up ha...
1567
  	pgoff_t next_pgofs;
7f63eb77a   Jaegeuk Kim   f2fs: report unwr...
1568
1569
  	u64 logical = 0, phys = 0, size = 0;
  	u32 flags = 0;
7f63eb77a   Jaegeuk Kim   f2fs: report unwr...
1570
  	int ret = 0;
c4020b2da   Chao Yu   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   Chao Yu   f2fs: support FIE...
1576
  	ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC | FIEMAP_FLAG_XATTR);
7f63eb77a   Jaegeuk Kim   f2fs: report unwr...
1577
1578
  	if (ret)
  		return ret;
f1b43d4cd   Chao Yu   f2fs: fix to cove...
1579
  	inode_lock(inode);
442a9dbd5   Chao Yu   f2fs: support FIE...
1580
1581
1582
1583
  	if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) {
  		ret = f2fs_xattr_fiemap(inode, fieinfo);
  		goto out;
  	}
7975f3498   Chao Yu   f2fs: support fie...
1584
  	if (f2fs_has_inline_data(inode) || f2fs_has_inline_dentry(inode)) {
67f8cf3ce   Jaegeuk Kim   f2fs: support fie...
1585
1586
  		ret = f2fs_inline_data_fiemap(inode, fieinfo, start, len);
  		if (ret != -EAGAIN)
f1b43d4cd   Chao Yu   f2fs: fix to cove...
1587
  			goto out;
67f8cf3ce   Jaegeuk Kim   f2fs: support fie...
1588
  	}
7f63eb77a   Jaegeuk Kim   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   Fan Li   f2fs: fix bugs an...
1594

7f63eb77a   Jaegeuk Kim   f2fs: report unwr...
1595
1596
1597
  next:
  	memset(&map_bh, 0, sizeof(struct buffer_head));
  	map_bh.b_size = len;
e2b4e2bc8   Chao Yu   f2fs: fix incorre...
1598
  	ret = get_data_block(inode, start_blk, &map_bh, 0,
da85985c6   Chao Yu   f2fs: speed up ha...
1599
  					F2FS_GET_BLOCK_FIEMAP, &next_pgofs);
7f63eb77a   Jaegeuk Kim   f2fs: report unwr...
1600
1601
1602
1603
1604
  	if (ret)
  		goto out;
  
  	/* HOLE */
  	if (!buffer_mapped(&map_bh)) {
da85985c6   Chao Yu   f2fs: speed up ha...
1605
  		start_blk = next_pgofs;
58736fa60   Chao Yu   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   Fan Li   f2fs: fix bugs an...
1609
  			goto prep_next;
58736fa60   Chao Yu   f2fs: be aware of...
1610

9a950d52b   Fan Li   f2fs: fix bugs an...
1611
1612
  		flags |= FIEMAP_EXTENT_LAST;
  	}
7f63eb77a   Jaegeuk Kim   f2fs: report unwr...
1613

da5af127a   Chao Yu   f2fs: recognize e...
1614
  	if (size) {
62230e0d7   Chandan Rajendra   f2fs: use IS_ENCR...
1615
  		if (IS_ENCRYPTED(inode))
da5af127a   Chao Yu   f2fs: recognize e...
1616
  			flags |= FIEMAP_EXTENT_DATA_ENCRYPTED;
9a950d52b   Fan Li   f2fs: fix bugs an...
1617
1618
  		ret = fiemap_fill_next_extent(fieinfo, logical,
  				phys, size, flags);
da5af127a   Chao Yu   f2fs: recognize e...
1619
  	}
7f63eb77a   Jaegeuk Kim   f2fs: report unwr...
1620

9a950d52b   Fan Li   f2fs: fix bugs an...
1621
1622
  	if (start_blk > last_blk || ret)
  		goto out;
7f63eb77a   Jaegeuk Kim   f2fs: report unwr...
1623

9a950d52b   Fan Li   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   Jaegeuk Kim   f2fs: report unwr...
1630

9a950d52b   Fan Li   f2fs: fix bugs an...
1631
  	start_blk += logical_to_blk(inode, size);
7f63eb77a   Jaegeuk Kim   f2fs: report unwr...
1632

9a950d52b   Fan Li   f2fs: fix bugs an...
1633
  prep_next:
7f63eb77a   Jaegeuk Kim   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   Al Viro   wrappers for ->i_...
1642
  	inode_unlock(inode);
7f63eb77a   Jaegeuk Kim   f2fs: report unwr...
1643
  	return ret;
9ab701349   Jaegeuk Kim   f2fs: support f2f...
1644
  }
95ae251fe   Eric Biggers   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   Chao Yu   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   Jaegeuk Kim   f2fs: support swa...
1668
  	block_in_file = (sector_t)page_index(page);
2df0ab045   Chao Yu   f2fs: introduce f...
1669
  	last_block = block_in_file + nr_pages;
95ae251fe   Eric Biggers   f2fs: add fs-veri...
1670
  	last_block_in_file = (f2fs_readpage_limit(inode) + blocksize - 1) >>
2df0ab045   Chao Yu   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   Jaegeuk Kim   f2fs: support swa...
1700
1701
  		if (!PageUptodate(page) && (!PageSwapCache(page) &&
  					!cleancache_get_page(page))) {
2df0ab045   Chao Yu   f2fs: introduce f...
1702
1703
1704
1705
1706
  			SetPageUptodate(page);
  			goto confused;
  		}
  
  		if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), block_nr,
93770ab7a   Chao Yu   f2fs: introduce D...
1707
  						DATA_GENERIC_ENHANCE_READ)) {
10f966bbf   Chao Yu   f2fs: use generic...
1708
  			ret = -EFSCORRUPTED;
2df0ab045   Chao Yu   f2fs: introduce f...
1709
1710
1711
1712
1713
  			goto out;
  		}
  	} else {
  zero_out:
  		zero_user_segment(page, 0, PAGE_SIZE);
95ae251fe   Eric Biggers   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   Chao Yu   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   Chao Yu   f2fs: introduce {...
1729
1730
  	if (bio && !page_is_mergeable(F2FS_I_SB(inode), bio,
  				*last_block_in_bio, block_nr)) {
2df0ab045   Chao Yu   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   Eric Biggers   f2fs: add fs-veri...
1737
  				is_readahead ? REQ_RAHEAD : 0, page->index);
2df0ab045   Chao Yu   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   Jaegeuk Kim   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   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: expose f2fs...
1776
1777
1778
   */
  static int f2fs_mpage_readpages(struct address_space *mapping,
  			struct list_head *pages, struct page *page,
e2e59414a   Jaegeuk Kim   f2fs: assign REQ_...
1779
  			unsigned nr_pages, bool is_readahead)
f1e886601   Jaegeuk Kim   f2fs: expose f2fs...
1780
1781
  {
  	struct bio *bio = NULL;
f1e886601   Jaegeuk Kim   f2fs: expose f2fs...
1782
1783
  	sector_t last_block_in_bio = 0;
  	struct inode *inode = mapping->host;
f1e886601   Jaegeuk Kim   f2fs: expose f2fs...
1784
  	struct f2fs_map_blocks map;
2df0ab045   Chao Yu   f2fs: introduce f...
1785
  	int ret = 0;
f1e886601   Jaegeuk Kim   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   Chao Yu   f2fs: speed up ha...
1791
  	map.m_next_pgofs = NULL;
c4020b2da   Chao Yu   f2fs: support F2F...
1792
  	map.m_next_extent = NULL;
d5097be55   Hyunchul Lee   f2fs: apply write...
1793
  	map.m_seg_type = NO_CHECK_TYPE;
f9d6d0597   Chao Yu   f2fs: fix out-pla...
1794
  	map.m_may_create = false;
f1e886601   Jaegeuk Kim   f2fs: expose f2fs...
1795

736c0a748   LiFan   f2fs: remove an e...
1796
  	for (; nr_pages; nr_pages--) {
f1e886601   Jaegeuk Kim   f2fs: expose f2fs...
1797
  		if (pages) {
939afa943   Chao Yu   f2fs: clean up wi...
1798
  			page = list_last_entry(pages, struct page, lru);
a83d50bc1   Kinglong Mee   f2fs: fix bad pre...
1799
1800
  
  			prefetchw(&page->flags);
f1e886601   Jaegeuk Kim   f2fs: expose f2fs...
1801
1802
  			list_del(&page->lru);
  			if (add_to_page_cache_lru(page, mapping,
4969c06a0   Jaegeuk Kim   f2fs: support swa...
1803
  						  page_index(page),
8a5c743e3   Michal Hocko   mm, memcg: use co...
1804
  						  readahead_gfp_mask(mapping)))
f1e886601   Jaegeuk Kim   f2fs: expose f2fs...
1805
1806
  				goto next_page;
  		}
2df0ab045   Chao Yu   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   Kirill A. Shutemov   mm, fs: get rid o...
1811
  			zero_user_segment(page, 0, PAGE_SIZE);
f1e886601   Jaegeuk Kim   f2fs: expose f2fs...
1812
  			unlock_page(page);
f1e886601   Jaegeuk Kim   f2fs: expose f2fs...
1813
  		}
f1e886601   Jaegeuk Kim   f2fs: expose f2fs...
1814
1815
  next_page:
  		if (pages)
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1816
  			put_page(page);
f1e886601   Jaegeuk Kim   f2fs: expose f2fs...
1817
1818
1819
  	}
  	BUG_ON(pages && !list_empty(pages));
  	if (bio)
4fc29c1aa   Linus Torvalds   Merge tag 'for-f2...
1820
  		__submit_bio(F2FS_I_SB(inode), bio, DATA);
2df0ab045   Chao Yu   f2fs: introduce f...
1821
  	return pages ? 0 : ret;
f1e886601   Jaegeuk Kim   f2fs: expose f2fs...
1822
  }
eb47b8009   Jaegeuk Kim   f2fs: add address...
1823
1824
  static int f2fs_read_data_page(struct file *file, struct page *page)
  {
4969c06a0   Jaegeuk Kim   f2fs: support swa...
1825
  	struct inode *inode = page_file_mapping(page)->host;
b3d208f96   Jaegeuk Kim   f2fs: revisit inl...
1826
  	int ret = -EAGAIN;
9ffe0fb5f   Huajun Li   f2fs: handle inli...
1827

c20e89cde   Chao Yu   f2fs: add a trace...
1828
  	trace_f2fs_readpage(page, DATA);
e1c420452   arter97   f2fs: fix typo
1829
  	/* If the file has inline data, try to read it directly */
9ffe0fb5f   Huajun Li   f2fs: handle inli...
1830
1831
  	if (f2fs_has_inline_data(inode))
  		ret = f2fs_read_inline_data(inode, page);
b3d208f96   Jaegeuk Kim   f2fs: revisit inl...
1832
  	if (ret == -EAGAIN)
4969c06a0   Jaegeuk Kim   f2fs: support swa...
1833
1834
  		ret = f2fs_mpage_readpages(page_file_mapping(page),
  						NULL, page, 1, false);
9ffe0fb5f   Huajun Li   f2fs: handle inli...
1835
  	return ret;
eb47b8009   Jaegeuk Kim   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   Hsiang Kao   f2fs: allow readp...
1842
  	struct inode *inode = mapping->host;
939afa943   Chao Yu   f2fs: clean up wi...
1843
  	struct page *page = list_last_entry(pages, struct page, lru);
b8c294004   Chao Yu   f2fs: add a trace...
1844
1845
  
  	trace_f2fs_readpages(inode, page, nr_pages);
9ffe0fb5f   Huajun Li   f2fs: handle inli...
1846
1847
1848
1849
  
  	/* If the file has inline data, skip readpages */
  	if (f2fs_has_inline_data(inode))
  		return 0;
e2e59414a   Jaegeuk Kim   f2fs: assign REQ_...
1850
  	return f2fs_mpage_readpages(mapping, pages, NULL, nr_pages, true);
eb47b8009   Jaegeuk Kim   f2fs: add address...
1851
  }
7eab0c0df   Hou Pengyang   f2fs: reconstruct...
1852
1853
1854
  static int encrypt_one_page(struct f2fs_io_info *fio)
  {
  	struct inode *inode = fio->page->mapping->host;
6aa58d8ad   Chao Yu   f2fs: readahead e...
1855
  	struct page *mpage;
7eab0c0df   Hou Pengyang   f2fs: reconstruct...
1856
  	gfp_t gfp_flags = GFP_NOFS;
1958593e4   Jaegeuk Kim   f2fs: introduce f...
1857
  	if (!f2fs_encrypted_file(inode))
7eab0c0df   Hou Pengyang   f2fs: reconstruct...
1858
  		return 0;
6dbb17961   Eric Biggers   f2fs: refactor re...
1859
  	/* wait for GCed page writeback via META_MAPPING */
0ded69f63   Jaegeuk Kim   f2fs: avoid wrong...
1860
  	f2fs_wait_on_block_writeback(inode, fio->old_blkaddr);
7eab0c0df   Hou Pengyang   f2fs: reconstruct...
1861
1862
  
  retry_encrypt:
53bc1d854   Eric Biggers   fscrypt: support ...
1863
1864
1865
  	fio->encrypted_page = fscrypt_encrypt_pagecache_blocks(fio->page,
  							       PAGE_SIZE, 0,
  							       gfp_flags);
6aa58d8ad   Chao Yu   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   Hou Pengyang   f2fs: reconstruct...
1876

6aa58d8ad   Chao Yu   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   Hou Pengyang   f2fs: reconstruct...
1883
  	}
6aa58d8ad   Chao Yu   f2fs: readahead e...
1884
  	return 0;
7eab0c0df   Hou Pengyang   f2fs: reconstruct...
1885
  }
bb9e3bb8d   Chao Yu   f2fs: split need_...
1886
1887
  static inline bool check_inplace_update_policy(struct inode *inode,
  				struct f2fs_io_info *fio)
7eab0c0df   Hou Pengyang   f2fs: reconstruct...
1888
  {
bb9e3bb8d   Chao Yu   f2fs: split need_...
1889
1890
  	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
  	unsigned int policy = SM_I(sbi)->ipu_policy;
7eab0c0df   Hou Pengyang   f2fs: reconstruct...
1891

bb9e3bb8d   Chao Yu   f2fs: split need_...
1892
1893
  	if (policy & (0x1 << F2FS_IPU_FORCE))
  		return true;
4d57b86dd   Chao Yu   f2fs: clean up sy...
1894
  	if (policy & (0x1 << F2FS_IPU_SSR) && f2fs_need_SSR(sbi))
bb9e3bb8d   Chao Yu   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   Chao Yu   f2fs: clean up sy...
1899
  	if (policy & (0x1 << F2FS_IPU_SSR_UTIL) && f2fs_need_SSR(sbi) &&
bb9e3bb8d   Chao Yu   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   Chandan Rajendra   f2fs: use IS_ENCR...
1909
  			!IS_ENCRYPTED(inode))
bb9e3bb8d   Chao Yu   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   Daniel Rosenberg   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   Chao Yu   f2fs: split need_...
1919
1920
  	return false;
  }
4d57b86dd   Chao Yu   f2fs: clean up sy...
1921
  bool f2fs_should_update_inplace(struct inode *inode, struct f2fs_io_info *fio)
bb9e3bb8d   Chao Yu   f2fs: split need_...
1922
  {
1ad71a271   Jaegeuk Kim   f2fs: add an ioct...
1923
1924
  	if (f2fs_is_pinned_file(inode))
  		return true;
bb9e3bb8d   Chao Yu   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   Chao Yu   f2fs: clean up sy...
1932
  bool f2fs_should_update_outplace(struct inode *inode, struct f2fs_io_info *fio)
bb9e3bb8d   Chao Yu   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   Chao Yu   f2fs: guarantee j...
1940
1941
  	if (IS_NOQUOTA(inode))
  		return true;
bb9e3bb8d   Chao Yu   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   Daniel Rosenberg   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   Chao Yu   f2fs: split need_...
1952
1953
1954
  	}
  	return false;
  }
7eab0c0df   Hou Pengyang   f2fs: reconstruct...
1955
1956
1957
  static inline bool need_inplace_update(struct f2fs_io_info *fio)
  {
  	struct inode *inode = fio->page->mapping->host;
4d57b86dd   Chao Yu   f2fs: clean up sy...
1958
  	if (f2fs_should_update_outplace(inode, fio))
7eab0c0df   Hou Pengyang   f2fs: reconstruct...
1959
  		return false;
4d57b86dd   Chao Yu   f2fs: clean up sy...
1960
  	return f2fs_should_update_inplace(inode, fio);
7eab0c0df   Hou Pengyang   f2fs: reconstruct...
1961
  }
4d57b86dd   Chao Yu   f2fs: clean up sy...
1962
  int f2fs_do_write_data_page(struct f2fs_io_info *fio)
eb47b8009   Jaegeuk Kim   f2fs: add address...
1963
  {
05ca3632e   Jaegeuk Kim   f2fs: add sbi and...
1964
  	struct page *page = fio->page;
eb47b8009   Jaegeuk Kim   f2fs: add address...
1965
  	struct inode *inode = page->mapping->host;
eb47b8009   Jaegeuk Kim   f2fs: add address...
1966
  	struct dnode_of_data dn;
e959c8f54   Hou Pengyang   f2fs: lookup exte...
1967
  	struct extent_info ei = {0,0,0};
7735730d3   Chao Yu   f2fs: fix to prop...
1968
  	struct node_info ni;
e959c8f54   Hou Pengyang   f2fs: lookup exte...
1969
  	bool ipu_force = false;
eb47b8009   Jaegeuk Kim   f2fs: add address...
1970
1971
1972
  	int err = 0;
  
  	set_new_dnode(&dn, inode, NULL, NULL, 0);
e959c8f54   Hou Pengyang   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   Jaegeuk Kim   f2fs: introduce v...
1976

c9b60788f   Chao Yu   f2fs: fix to do s...
1977
  		if (!f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr,
93770ab7a   Chao Yu   f2fs: introduce D...
1978
  						DATA_GENERIC_ENHANCE))
10f966bbf   Chao Yu   f2fs: use generic...
1979
  			return -EFSCORRUPTED;
c9b60788f   Chao Yu   f2fs: fix to do s...
1980
1981
1982
1983
  
  		ipu_force = true;
  		fio->need_lock = LOCK_DONE;
  		goto got_it;
e959c8f54   Hou Pengyang   f2fs: lookup exte...
1984
  	}
279d6df20   Hou Pengyang   f2fs: release cp ...
1985

d29460e5c   Jaegeuk Kim   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   Hou Pengyang   f2fs: release cp ...
1989

4d57b86dd   Chao Yu   f2fs: clean up sy...
1990
  	err = f2fs_get_dnode_of_data(&dn, page->index, LOOKUP_NODE);
eb47b8009   Jaegeuk Kim   f2fs: add address...
1991
  	if (err)
279d6df20   Hou Pengyang   f2fs: release cp ...
1992
  		goto out;
eb47b8009   Jaegeuk Kim   f2fs: add address...
1993

28bc106b2   Chao Yu   f2fs: support rev...
1994
  	fio->old_blkaddr = dn.data_blkaddr;
eb47b8009   Jaegeuk Kim   f2fs: add address...
1995
1996
  
  	/* This page is already truncated */
7a9d75481   Chao Yu   f2fs: trace old b...
1997
  	if (fio->old_blkaddr == NULL_ADDR) {
2bca1e238   Jaegeuk Kim   f2fs: clear page'...
1998
  		ClearPageUptodate(page);
2baf07818   Chao Yu   f2fs: fix to spre...
1999
  		clear_cold_data(page);
eb47b8009   Jaegeuk Kim   f2fs: add address...
2000
  		goto out_writepage;
2bca1e238   Jaegeuk Kim   f2fs: clear page'...
2001
  	}
e959c8f54   Hou Pengyang   f2fs: lookup exte...
2002
  got_it:
c9b60788f   Chao Yu   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   Chao Yu   f2fs: introduce D...
2005
  						DATA_GENERIC_ENHANCE)) {
10f966bbf   Chao Yu   f2fs: use generic...
2006
  		err = -EFSCORRUPTED;
c9b60788f   Chao Yu   f2fs: fix to do s...
2007
2008
  		goto out_writepage;
  	}
eb47b8009   Jaegeuk Kim   f2fs: add address...
2009
2010
2011
2012
  	/*
  	 * If current allocation needs SSR,
  	 * it had better in-place writes for updated data.
  	 */
93770ab7a   Chao Yu   f2fs: introduce D...
2013
2014
  	if (ipu_force ||
  		(__is_valid_data_blkaddr(fio->old_blkaddr) &&
7b525dd01   Chao Yu   f2fs: clean up wi...
2015
  					need_inplace_update(fio))) {
cc15620bc   Jaegeuk Kim   f2fs: avoid f2fs_...
2016
2017
2018
2019
2020
  		err = encrypt_one_page(fio);
  		if (err)
  			goto out_writepage;
  
  		set_page_writeback(page);
17c500350   Jaegeuk Kim   f2fs: clear PageE...
2021
  		ClearPageError(page);
279d6df20   Hou Pengyang   f2fs: release cp ...
2022
  		f2fs_put_dnode(&dn);
cc15620bc   Jaegeuk Kim   f2fs: avoid f2fs_...
2023
  		if (fio->need_lock == LOCK_REQ)
279d6df20   Hou Pengyang   f2fs: release cp ...
2024
  			f2fs_unlock_op(fio->sbi);
4d57b86dd   Chao Yu   f2fs: clean up sy...
2025
  		err = f2fs_inplace_write_data(fio);
6492a335f   Chao Yu   f2fs: fix encrypt...
2026
2027
  		if (err) {
  			if (f2fs_encrypted_file(inode))
d2d0727b1   Eric Biggers   fscrypt: simplify...
2028
  				fscrypt_finalize_bounce_page(&fio->encrypted_page);
6492a335f   Chao Yu   f2fs: fix encrypt...
2029
2030
  			if (PageWriteback(page))
  				end_page_writeback(page);
cd23ffa9f   Chao Yu   f2fs: fix to set ...
2031
2032
  		} else {
  			set_inode_flag(inode, FI_UPDATE_WRITE);
6492a335f   Chao Yu   f2fs: fix encrypt...
2033
  		}
7eab0c0df   Hou Pengyang   f2fs: reconstruct...
2034
  		trace_f2fs_do_write_data_page(fio->page, IPU);
279d6df20   Hou Pengyang   f2fs: release cp ...
2035
  		return err;
eb47b8009   Jaegeuk Kim   f2fs: add address...
2036
  	}
279d6df20   Hou Pengyang   f2fs: release cp ...
2037

cc15620bc   Jaegeuk Kim   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   Chao Yu   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   Jaegeuk Kim   f2fs: avoid f2fs_...
2050
2051
2052
2053
2054
  	err = encrypt_one_page(fio);
  	if (err)
  		goto out_writepage;
  
  	set_page_writeback(page);
17c500350   Jaegeuk Kim   f2fs: clear PageE...
2055
  	ClearPageError(page);
cc15620bc   Jaegeuk Kim   f2fs: avoid f2fs_...
2056

279d6df20   Hou Pengyang   f2fs: release cp ...
2057
  	/* LFS mode write path */
4d57b86dd   Chao Yu   f2fs: clean up sy...
2058
  	f2fs_outplace_write_data(&dn, fio);
279d6df20   Hou Pengyang   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   Jaegeuk Kim   f2fs: add address...
2063
2064
  out_writepage:
  	f2fs_put_dnode(&dn);
279d6df20   Hou Pengyang   f2fs: release cp ...
2065
  out:
cc15620bc   Jaegeuk Kim   f2fs: avoid f2fs_...
2066
  	if (fio->need_lock == LOCK_REQ)
279d6df20   Hou Pengyang   f2fs: release cp ...
2067
  		f2fs_unlock_op(fio->sbi);
eb47b8009   Jaegeuk Kim   f2fs: add address...
2068
2069
  	return err;
  }
d68f735b3   Jaegeuk Kim   f2fs: check io su...
2070
  static int __write_data_page(struct page *page, bool *submitted,
8648de2c5   Chao Yu   f2fs: add bio cac...
2071
2072
  				struct bio **bio,
  				sector_t *last_block,
b0af6d491   Chao Yu   f2fs: add app/fs ...
2073
2074
  				struct writeback_control *wbc,
  				enum iostat_type io_type)
eb47b8009   Jaegeuk Kim   f2fs: add address...
2075
2076
  {
  	struct inode *inode = page->mapping->host;
4081363fb   Jaegeuk Kim   f2fs: introduce F...
2077
  	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
eb47b8009   Jaegeuk Kim   f2fs: add address...
2078
2079
  	loff_t i_size = i_size_read(inode);
  	const pgoff_t end_index = ((unsigned long long) i_size)
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
2080
  							>> PAGE_SHIFT;
1f0d5c911   Chao Yu   f2fs: fix potenti...
2081
  	loff_t psize = (loff_t)(page->index + 1) << PAGE_SHIFT;
9ffe0fb5f   Huajun Li   f2fs: handle inli...
2082
  	unsigned offset = 0;
399368372   Jaegeuk Kim   f2fs: introduce a...
2083
  	bool need_balance_fs = false;
eb47b8009   Jaegeuk Kim   f2fs: add address...
2084
  	int err = 0;
458e6197c   Jaegeuk Kim   f2fs: refactor bi...
2085
  	struct f2fs_io_info fio = {
05ca3632e   Jaegeuk Kim   f2fs: add sbi and...
2086
  		.sbi = sbi,
39d787bec   Chao Yu   f2fs: enhance mul...
2087
  		.ino = inode->i_ino,
458e6197c   Jaegeuk Kim   f2fs: refactor bi...
2088
  		.type = DATA,
04d328def   Mike Christie   f2fs: use bio op ...
2089
  		.op = REQ_OP_WRITE,
7637241e6   Jens Axboe   writeback: add wb...
2090
  		.op_flags = wbc_to_write_flags(wbc),
e959c8f54   Hou Pengyang   f2fs: lookup exte...
2091
  		.old_blkaddr = NULL_ADDR,
05ca3632e   Jaegeuk Kim   f2fs: add sbi and...
2092
  		.page = page,
4375a3366   Jaegeuk Kim   f2fs crypto: add ...
2093
  		.encrypted_page = NULL,
d68f735b3   Jaegeuk Kim   f2fs: check io su...
2094
  		.submitted = false,
cc15620bc   Jaegeuk Kim   f2fs: avoid f2fs_...
2095
  		.need_lock = LOCK_RETRY,
b0af6d491   Chao Yu   f2fs: add app/fs ...
2096
  		.io_type = io_type,
578c64787   Yufen Yu   f2fs: implement c...
2097
  		.io_wbc = wbc,
8648de2c5   Chao Yu   f2fs: add bio cac...
2098
2099
  		.bio = bio,
  		.last_block = last_block,
458e6197c   Jaegeuk Kim   f2fs: refactor bi...
2100
  	};
eb47b8009   Jaegeuk Kim   f2fs: add address...
2101

ecda0de34   Chao Yu   f2fs: add a trace...
2102
  	trace_f2fs_writepage(page, DATA);
db198ae0f   Chao Yu   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   Chao Yu   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   Chao Yu   f2fs: drop page c...
2112
2113
  		goto out;
  	}
0771fcc71   Chao Yu   f2fs: skip ->writ...
2114
2115
  	if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
  		goto redirty_out;
95ae251fe   Eric Biggers   f2fs: add fs-veri...
2116
  	if (page->index < end_index || f2fs_verity_in_progress(inode))
399368372   Jaegeuk Kim   f2fs: introduce a...
2117
  		goto write;
eb47b8009   Jaegeuk Kim   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   Kirill A. Shutemov   mm, fs: get rid o...
2123
  	offset = i_size & (PAGE_SIZE - 1);
76f60268e   Jaegeuk Kim   f2fs: call redirt...
2124
  	if ((page->index >= end_index + 1) || !offset)
399368372   Jaegeuk Kim   f2fs: introduce a...
2125
  		goto out;
eb47b8009   Jaegeuk Kim   f2fs: add address...
2126

09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
2127
  	zero_user_segment(page, offset, PAGE_SIZE);
399368372   Jaegeuk Kim   f2fs: introduce a...
2128
  write:
1e84371ff   Jaegeuk Kim   f2fs: change atom...
2129
2130
  	if (f2fs_is_drop_cache(inode))
  		goto out;
e6e5f5610   Jaegeuk Kim   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   Chao Yu   f2fs: clean up sy...
2134
  			f2fs_available_free_memory(sbi, BASE_CHECK))))
1e84371ff   Jaegeuk Kim   f2fs: change atom...
2135
  		goto redirty_out;
eb47b8009   Jaegeuk Kim   f2fs: add address...
2136

399368372   Jaegeuk Kim   f2fs: introduce a...
2137
  	/* Dentry blocks are controlled by checkpoint */
eb47b8009   Jaegeuk Kim   f2fs: add address...
2138
  	if (S_ISDIR(inode->i_mode)) {
cc15620bc   Jaegeuk Kim   f2fs: avoid f2fs_...
2139
  		fio.need_lock = LOCK_DONE;
4d57b86dd   Chao Yu   f2fs: clean up sy...
2140
  		err = f2fs_do_write_data_page(&fio);
8618b881e   Jaegeuk Kim   f2fs: fix not to ...
2141
2142
  		goto done;
  	}
9ffe0fb5f   Huajun Li   f2fs: handle inli...
2143

8618b881e   Jaegeuk Kim   f2fs: fix not to ...
2144
  	if (!wbc->for_reclaim)
399368372   Jaegeuk Kim   f2fs: introduce a...
2145
  		need_balance_fs = true;
7f3037a5e   Jaegeuk Kim   f2fs: check free_...
2146
  	else if (has_not_enough_free_secs(sbi, 0, 0))
399368372   Jaegeuk Kim   f2fs: introduce a...
2147
  		goto redirty_out;
ef095d19e   Jaegeuk Kim   f2fs: write small...
2148
2149
  	else
  		set_inode_flag(inode, FI_HOT_DATA);
eb47b8009   Jaegeuk Kim   f2fs: add address...
2150

b3d208f96   Jaegeuk Kim   f2fs: revisit inl...
2151
  	err = -EAGAIN;
dd7b2333e   Yunlei He   f2fs: no need loc...
2152
  	if (f2fs_has_inline_data(inode)) {
b3d208f96   Jaegeuk Kim   f2fs: revisit inl...
2153
  		err = f2fs_write_inline_data(inode, page);
dd7b2333e   Yunlei He   f2fs: no need loc...
2154
2155
2156
  		if (!err)
  			goto out;
  	}
279d6df20   Hou Pengyang   f2fs: release cp ...
2157

cc15620bc   Jaegeuk Kim   f2fs: avoid f2fs_...
2158
  	if (err == -EAGAIN) {
4d57b86dd   Chao Yu   f2fs: clean up sy...
2159
  		err = f2fs_do_write_data_page(&fio);
cc15620bc   Jaegeuk Kim   f2fs: avoid f2fs_...
2160
2161
  		if (err == -EAGAIN) {
  			fio.need_lock = LOCK_REQ;
4d57b86dd   Chao Yu   f2fs: clean up sy...
2162
  			err = f2fs_do_write_data_page(&fio);
cc15620bc   Jaegeuk Kim   f2fs: avoid f2fs_...
2163
2164
  		}
  	}
a0d00fad3   Chao Yu   f2fs: fix to avoi...
2165

eb4497975   Chao Yu   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   Hou Pengyang   f2fs: release cp ...
2174

8618b881e   Jaegeuk Kim   f2fs: fix not to ...
2175
2176
2177
  done:
  	if (err && err != -ENOENT)
  		goto redirty_out;
eb47b8009   Jaegeuk Kim   f2fs: add address...
2178

399368372   Jaegeuk Kim   f2fs: introduce a...
2179
  out:
a7ffdbe22   Jaegeuk Kim   f2fs: expand coun...
2180
  	inode_dec_dirty_pages(inode);
2baf07818   Chao Yu   f2fs: fix to spre...
2181
  	if (err) {
2bca1e238   Jaegeuk Kim   f2fs: clear page'...
2182
  		ClearPageUptodate(page);
2baf07818   Chao Yu   f2fs: fix to spre...
2183
2184
  		clear_cold_data(page);
  	}
0c3a57975   Chao Yu   f2fs: introduce f...
2185
2186
  
  	if (wbc->for_reclaim) {
bab475c54   Chao Yu   Revert: "f2fs: ch...
2187
  		f2fs_submit_merged_write_cond(sbi, NULL, page, 0, DATA);
ef095d19e   Jaegeuk Kim   f2fs: write small...
2188
  		clear_inode_flag(inode, FI_HOT_DATA);
4d57b86dd   Chao Yu   f2fs: clean up sy...
2189
  		f2fs_remove_dirty_inode(inode);
d68f735b3   Jaegeuk Kim   f2fs: check io su...
2190
  		submitted = NULL;
0c3a57975   Chao Yu   f2fs: introduce f...
2191
  	}
eb47b8009   Jaegeuk Kim   f2fs: add address...
2192
  	unlock_page(page);
186857c5a   Chao Yu   f2fs: fix potenti...
2193
  	if (!S_ISDIR(inode->i_mode) && !IS_NOQUOTA(inode) &&
0b20fcec8   Chao Yu   f2fs: cache globa...
2194
  					!F2FS_I(inode)->cp_task)
a78818930   Jaegeuk Kim   f2fs: fix out-of ...
2195
  		f2fs_balance_fs(sbi, need_balance_fs);
0c3a57975   Chao Yu   f2fs: introduce f...
2196

d68f735b3   Jaegeuk Kim   f2fs: check io su...
2197
  	if (unlikely(f2fs_cp_error(sbi))) {
b9109b0e4   Jaegeuk Kim   f2fs: remove unne...
2198
  		f2fs_submit_merged_write(sbi, DATA);
0b20fcec8   Chao Yu   f2fs: cache globa...
2199
  		f2fs_submit_merged_ipu_write(sbi, bio, NULL);
d68f735b3   Jaegeuk Kim   f2fs: check io su...
2200
2201
2202
2203
2204
  		submitted = NULL;
  	}
  
  	if (submitted)
  		*submitted = fio.submitted;
0c3a57975   Chao Yu   f2fs: introduce f...
2205

eb47b8009   Jaegeuk Kim   f2fs: add address...
2206
  	return 0;
eb47b8009   Jaegeuk Kim   f2fs: add address...
2207
  redirty_out:
76f60268e   Jaegeuk Kim   f2fs: call redirt...
2208
  	redirty_page_for_writepage(wbc, page);
5b19d284f   Jaegeuk Kim   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   Chao Yu   f2fs: return AOP_...
2216
  		return AOP_WRITEPAGE_ACTIVATE;
b230e6cab   Jaegeuk Kim   f2fs: handle writ...
2217
2218
  	unlock_page(page);
  	return err;
fa9150a84   Namjae Jeon   f2fs: remove the ...
2219
  }
f566bae84   Jaegeuk Kim   f2fs: call intern...
2220
2221
2222
  static int f2fs_write_data_page(struct page *page,
  					struct writeback_control *wbc)
  {
8648de2c5   Chao Yu   f2fs: add bio cac...
2223
  	return __write_data_page(page, NULL, NULL, NULL, wbc, FS_DATA_IO);
f566bae84   Jaegeuk Kim   f2fs: call intern...
2224
  }
8f46dcaea   Chao Yu   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   Chao Yu   f2fs: add app/fs ...
2231
2232
  					struct writeback_control *wbc,
  					enum iostat_type io_type)
8f46dcaea   Chao Yu   f2fs: expose f2fs...
2233
2234
2235
2236
  {
  	int ret = 0;
  	int done = 0;
  	struct pagevec pvec;
c29fd0c0e   Chao Yu   f2fs: let sync no...
2237
  	struct f2fs_sb_info *sbi = F2FS_M_SB(mapping);
8648de2c5   Chao Yu   f2fs: add bio cac...
2238
2239
  	struct bio *bio = NULL;
  	sector_t last_block;
8f46dcaea   Chao Yu   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   Matthew Wilcox   pagevec: Use xa_m...
2247
  	xa_mark_t tag;
bab475c54   Chao Yu   Revert: "f2fs: ch...
2248
  	int nwritten = 0;
8f46dcaea   Chao Yu   f2fs: expose f2fs...
2249

866798201   Mel Gorman   mm, pagevec: remo...
2250
  	pagevec_init(&pvec);
46ae957f9   Jaegeuk Kim   f2fs: remove two ...
2251

ef095d19e   Jaegeuk Kim   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   Chao Yu   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   Kirill A. Shutemov   mm, fs: get rid o...
2266
2267
  		index = wbc->range_start >> PAGE_SHIFT;
  		end = wbc->range_end >> PAGE_SHIFT;
8f46dcaea   Chao Yu   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   Jan Kara   f2fs: use pagevec...
2282
  		nr_pages = pagevec_lookup_range_tag(&pvec, mapping, &index, end,
67fd707f4   Jan Kara   mm: remove nr_pag...
2283
  				tag);
8f46dcaea   Chao Yu   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   Jaegeuk Kim   f2fs: check io su...
2289
  			bool submitted = false;
8f46dcaea   Chao Yu   f2fs: expose f2fs...
2290

f8de43312   Chao Yu   f2fs: detect sync...
2291
  			/* give a priority to WB_SYNC threads */
c29fd0c0e   Chao Yu   f2fs: let sync no...
2292
  			if (atomic_read(&sbi->wb_sync_req[DATA]) &&
f8de43312   Chao Yu   f2fs: detect sync...
2293
2294
2295
2296
  					wbc->sync_mode == WB_SYNC_NONE) {
  				done = 1;
  				break;
  			}
8f46dcaea   Chao Yu   f2fs: expose f2fs...
2297
  			done_index = page->index;
d29460e5c   Jaegeuk Kim   f2fs: avoid deadl...
2298
  retry_write:
8f46dcaea   Chao Yu   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   Chao Yu   f2fs: expose f2fs...
2311
  			if (PageWriteback(page)) {
0b20fcec8   Chao Yu   f2fs: cache globa...
2312
  				if (wbc->sync_mode != WB_SYNC_NONE)
fec1d6576   Jaegeuk Kim   f2fs: use wait_fo...
2313
  					f2fs_wait_on_page_writeback(page,
bae0ee7a7   Chao Yu   f2fs: check PageW...
2314
  							DATA, true, true);
0b20fcec8   Chao Yu   f2fs: cache globa...
2315
  				else
8f46dcaea   Chao Yu   f2fs: expose f2fs...
2316
2317
  					goto continue_unlock;
  			}
8f46dcaea   Chao Yu   f2fs: expose f2fs...
2318
2319
  			if (!clear_page_dirty_for_io(page))
  				goto continue_unlock;
8648de2c5   Chao Yu   f2fs: add bio cac...
2320
2321
  			ret = __write_data_page(page, &submitted, &bio,
  					&last_block, wbc, io_type);
8f46dcaea   Chao Yu   f2fs: expose f2fs...
2322
  			if (unlikely(ret)) {
0002b61bd   Chao Yu   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   Jaegeuk Kim   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   Chao Yu   f2fs: return AOP_...
2340
  				}
b230e6cab   Jaegeuk Kim   f2fs: handle writ...
2341
2342
2343
  				done_index = page->index + 1;
  				done = 1;
  				break;
d68f735b3   Jaegeuk Kim   f2fs: check io su...
2344
  			} else if (submitted) {
bab475c54   Chao Yu   Revert: "f2fs: ch...
2345
  				nwritten++;
8f46dcaea   Chao Yu   f2fs: expose f2fs...
2346
  			}
f8de43312   Chao Yu   f2fs: detect sync...
2347
  			if (--wbc->nr_to_write <= 0 &&
687de7f10   Jaegeuk Kim   f2fs: avoid IO sp...
2348
  					wbc->sync_mode == WB_SYNC_NONE) {
8f46dcaea   Chao Yu   f2fs: expose f2fs...
2349
2350
2351
2352
2353
2354
2355
  				done = 1;
  				break;
  			}
  		}
  		pagevec_release(&pvec);
  		cond_resched();
  	}
8f46dcaea   Chao Yu   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   Chao Yu   Revert: "f2fs: ch...
2364
  	if (nwritten)
b9109b0e4   Jaegeuk Kim   f2fs: remove unne...
2365
  		f2fs_submit_merged_write_cond(F2FS_M_SB(mapping), mapping->host,
bab475c54   Chao Yu   Revert: "f2fs: ch...
2366
  								NULL, 0, DATA);
8648de2c5   Chao Yu   f2fs: add bio cac...
2367
2368
  	/* submit cached bio of IPU write */
  	if (bio)
0b20fcec8   Chao Yu   f2fs: cache globa...
2369
  		f2fs_submit_merged_ipu_write(sbi, &bio, NULL);
6ca56ca42   Chao Yu   f2fs: don't submi...
2370

8f46dcaea   Chao Yu   f2fs: expose f2fs...
2371
2372
  	return ret;
  }
853137cef   Jaegeuk Kim   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   Chao Yu   f2fs: guarantee j...
2378
2379
  	if (IS_NOQUOTA(inode))
  		return false;
040d2bb31   Chao Yu   f2fs: fix to avoi...
2380
2381
2382
  	/* to avoid deadlock in path of data flush */
  	if (F2FS_I(inode)->cp_task)
  		return false;
853137cef   Jaegeuk Kim   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   Chao Yu   f2fs: make __f2fs...
2389
  static int __f2fs_write_data_pages(struct address_space *mapping,
b0af6d491   Chao Yu   f2fs: add app/fs ...
2390
2391
  						struct writeback_control *wbc,
  						enum iostat_type io_type)
eb47b8009   Jaegeuk Kim   f2fs: add address...
2392
2393
  {
  	struct inode *inode = mapping->host;
4081363fb   Jaegeuk Kim   f2fs: introduce F...
2394
  	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
9dfa1baff   Jaegeuk Kim   f2fs: use blk_plu...
2395
  	struct blk_plug plug;
eb47b8009   Jaegeuk Kim   f2fs: add address...
2396
  	int ret;
853137cef   Jaegeuk Kim   f2fs: fix perform...
2397
  	bool locked = false;
eb47b8009   Jaegeuk Kim   f2fs: add address...
2398

cfb185a14   P J P   f2fs: add NULL po...
2399
2400
2401
  	/* deal with chardevs and other special file */
  	if (!mapping->a_ops->writepage)
  		return 0;
6a2905443   Chao Yu   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   Chao Yu   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   Chao Yu   f2fs: guarantee j...
2408
2409
  	if ((S_ISDIR(inode->i_mode) || IS_NOQUOTA(inode)) &&
  			wbc->sync_mode == WB_SYNC_NONE &&
a12570232   Jaegeuk Kim   Revert "f2fs: do ...
2410
  			get_dirty_pages(inode) < nr_pages_to_skip(sbi, DATA) &&
4d57b86dd   Chao Yu   f2fs: clean up sy...
2411
  			f2fs_available_free_memory(sbi, DIRTY_DENTS))
a12570232   Jaegeuk Kim   Revert "f2fs: do ...
2412
  		goto skip_write;
d323d005a   Chao Yu   f2fs: support fil...
2413
  	/* skip writing during file defragment */
91942321e   Jaegeuk Kim   f2fs: use inode p...
2414
  	if (is_inode_flag_set(inode, FI_DO_DEFRAG))
d323d005a   Chao Yu   f2fs: support fil...
2415
  		goto skip_write;
d31c7c3f0   Yunlei He   f2fs: fix missing...
2416
  	trace_f2fs_writepages(mapping->host, wbc, DATA);
687de7f10   Jaegeuk Kim   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   Chao Yu   f2fs: let sync no...
2419
2420
  		atomic_inc(&sbi->wb_sync_req[DATA]);
  	else if (atomic_read(&sbi->wb_sync_req[DATA]))
687de7f10   Jaegeuk Kim   f2fs: avoid IO sp...
2421
  		goto skip_write;
853137cef   Jaegeuk Kim   f2fs: fix perform...
2422
2423
2424
2425
  	if (__should_serialize_io(inode, wbc)) {
  		mutex_lock(&sbi->writepages);
  		locked = true;
  	}
9dfa1baff   Jaegeuk Kim   f2fs: use blk_plu...
2426
  	blk_start_plug(&plug);
b0af6d491   Chao Yu   f2fs: add app/fs ...
2427
  	ret = f2fs_write_cache_pages(mapping, wbc, io_type);
9dfa1baff   Jaegeuk Kim   f2fs: use blk_plu...
2428
  	blk_finish_plug(&plug);
687de7f10   Jaegeuk Kim   f2fs: avoid IO sp...
2429

853137cef   Jaegeuk Kim   f2fs: fix perform...
2430
2431
  	if (locked)
  		mutex_unlock(&sbi->writepages);
687de7f10   Jaegeuk Kim   f2fs: avoid IO sp...
2432
  	if (wbc->sync_mode == WB_SYNC_ALL)
c29fd0c0e   Chao Yu   f2fs: let sync no...
2433
  		atomic_dec(&sbi->wb_sync_req[DATA]);
28ea6162e   Jaegeuk Kim   f2fs: do not skip...
2434
2435
2436
2437
  	/*
  	 * if some pages were truncated, we cannot guarantee its mapping->host
  	 * to detect pending bios.
  	 */
458e6197c   Jaegeuk Kim   f2fs: refactor bi...
2438

4d57b86dd   Chao Yu   f2fs: clean up sy...
2439
  	f2fs_remove_dirty_inode(inode);
eb47b8009   Jaegeuk Kim   f2fs: add address...
2440
  	return ret;
d3baf95da   Jaegeuk Kim   f2fs: increase pa...
2441
2442
  
  skip_write:
a7ffdbe22   Jaegeuk Kim   f2fs: expand coun...
2443
  	wbc->pages_skipped += get_dirty_pages(inode);
d31c7c3f0   Yunlei He   f2fs: fix missing...
2444
  	trace_f2fs_writepages(mapping->host, wbc, DATA);
d3baf95da   Jaegeuk Kim   f2fs: increase pa...
2445
  	return 0;
eb47b8009   Jaegeuk Kim   f2fs: add address...
2446
  }
b0af6d491   Chao Yu   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   Chao Yu   f2fs: introduce f...
2456
2457
2458
  static void f2fs_write_failed(struct address_space *mapping, loff_t to)
  {
  	struct inode *inode = mapping->host;
819d9153d   Jaegeuk Kim   f2fs: use i_size_...
2459
  	loff_t i_size = i_size_read(inode);
3aab8f828   Chao Yu   f2fs: introduce f...
2460

95ae251fe   Eric Biggers   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   Chao Yu   f2fs: fix avoid r...
2463
  		down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
6f8d44550   Jaegeuk Kim   f2fs: avoid fi->i...
2464
  		down_write(&F2FS_I(inode)->i_mmap_sem);
a33c15023   Chao Yu   f2fs: fix avoid r...
2465

819d9153d   Jaegeuk Kim   f2fs: use i_size_...
2466
  		truncate_pagecache(inode, i_size);
c42d28ce3   Chao Yu   f2fs: fix potenti...
2467
2468
  		if (!IS_NOQUOTA(inode))
  			f2fs_truncate_blocks(inode, i_size, true);
a33c15023   Chao Yu   f2fs: fix avoid r...
2469

5a3a2d83c   Qiuyang Sun   f2fs: dax: fix ra...
2470
  		up_write(&F2FS_I(inode)->i_mmap_sem);
6f8d44550   Jaegeuk Kim   f2fs: avoid fi->i...
2471
  		up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
3aab8f828   Chao Yu   f2fs: introduce f...
2472
2473
  	}
  }
2aadac085   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: avoid f2fs_...
2482
  	bool locked = false;
e15882b6c   Hou Pengyang   f2fs: init local ...
2483
  	struct extent_info ei = {0,0,0};
2aadac085   Jaegeuk Kim   f2fs: introduce p...
2484
  	int err = 0;
2866fb16d   Sheng Yong   f2fs: fix race be...
2485
  	int flag;
2aadac085   Jaegeuk Kim   f2fs: introduce p...
2486

24b849125   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: do not prea...
2491
  	if (!f2fs_has_inline_data(inode) && len == PAGE_SIZE &&
95ae251fe   Eric Biggers   f2fs: add fs-veri...
2492
2493
  	    !is_inode_flag_set(inode, FI_NO_PREALLOC) &&
  	    !f2fs_verity_in_progress(inode))
24b849125   Jaegeuk Kim   f2fs: preallocate...
2494
  		return 0;
2866fb16d   Sheng Yong   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   Jaegeuk Kim   f2fs: avoid f2fs_...
2500
  	if (f2fs_has_inline_data(inode) ||
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
2501
  			(pos & PAGE_MASK) >= i_size_read(inode)) {
2866fb16d   Sheng Yong   f2fs: fix race be...
2502
  		__do_map_lock(sbi, flag, true);
b4d07a3e1   Jaegeuk Kim   f2fs: avoid f2fs_...
2503
2504
2505
  		locked = true;
  	}
  restart:
2aadac085   Jaegeuk Kim   f2fs: introduce p...
2506
  	/* check inline_data */
4d57b86dd   Chao Yu   f2fs: clean up sy...
2507
  	ipage = f2fs_get_node_page(sbi, inode->i_ino);
2aadac085   Jaegeuk Kim   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   Chao Yu   f2fs: make max in...
2516
  		if (pos + len <= MAX_INLINE_DATA(inode)) {
4d57b86dd   Chao Yu   f2fs: clean up sy...
2517
  			f2fs_do_read_inline_data(page, ipage);
91942321e   Jaegeuk Kim   f2fs: use inode p...
2518
  			set_inode_flag(inode, FI_DATA_EXIST);
ab47036d8   Chao Yu   f2fs: fix deadloc...
2519
2520
  			if (inode->i_nlink)
  				set_inline_node(ipage);
2aadac085   Jaegeuk Kim   f2fs: introduce p...
2521
2522
2523
  		} else {
  			err = f2fs_convert_inline_page(&dn, page);
  			if (err)
b4d07a3e1   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: avoid f2fs_...
2534
  			/* hole case */
4d57b86dd   Chao Yu   f2fs: clean up sy...
2535
  			err = f2fs_get_dnode_of_data(&dn, index, LOOKUP_NODE);
4da7bf5a4   Jaegeuk Kim   f2fs: remove redu...
2536
  			if (err || dn.data_blkaddr == NULL_ADDR) {
b4d07a3e1   Jaegeuk Kim   f2fs: avoid f2fs_...
2537
  				f2fs_put_dnode(&dn);
59c9081bc   Yunlei He   f2fs: allow write...
2538
2539
  				__do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO,
  								true);
2866fb16d   Sheng Yong   f2fs: fix race be...
2540
  				WARN_ON(flag != F2FS_GET_BLOCK_PRE_AIO);
b4d07a3e1   Jaegeuk Kim   f2fs: avoid f2fs_...
2541
2542
2543
  				locked = true;
  				goto restart;
  			}
2aadac085   Jaegeuk Kim   f2fs: introduce p...
2544
2545
  		}
  	}
b4d07a3e1   Jaegeuk Kim   f2fs: avoid f2fs_...
2546

2aadac085   Jaegeuk Kim   f2fs: introduce p...
2547
2548
2549
  	/* convert_inline_page can make node_changed */
  	*blk_addr = dn.data_blkaddr;
  	*node_changed = dn.node_changed;
b4d07a3e1   Jaegeuk Kim   f2fs: avoid f2fs_...
2550
  out:
2aadac085   Jaegeuk Kim   f2fs: introduce p...
2551
2552
  	f2fs_put_dnode(&dn);
  unlock_out:
b4d07a3e1   Jaegeuk Kim   f2fs: avoid f2fs_...
2553
  	if (locked)
2866fb16d   Sheng Yong   f2fs: fix race be...
2554
  		__do_map_lock(sbi, flag, false);
2aadac085   Jaegeuk Kim   f2fs: introduce p...
2555
2556
  	return err;
  }
eb47b8009   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: introduce F...
2562
  	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
86531d6b8   Jaegeuk Kim   f2fs: callers tak...
2563
  	struct page *page = NULL;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
2564
  	pgoff_t index = ((unsigned long long) pos) >> PAGE_SHIFT;
a2e2e76b2   Chao Yu   f2fs: fix to drop...
2565
  	bool need_balance = false, drop_atomic = false;
2aadac085   Jaegeuk Kim   f2fs: introduce p...
2566
  	block_t blkaddr = NULL_ADDR;
eb47b8009   Jaegeuk Kim   f2fs: add address...
2567
  	int err = 0;
62aed044e   Chao Yu   f2fs: add a trace...
2568
  	trace_f2fs_write_begin(inode, pos, len, flags);
00e09c0bc   Chao Yu   f2fs: enhance f2f...
2569
2570
  	if (!f2fs_is_checkpoint_ready(sbi)) {
  		err = -ENOSPC;
4354994f0   Daniel Rosenberg   f2fs: checkpoint ...
2571
  		goto fail;
00e09c0bc   Chao Yu   f2fs: enhance f2f...
2572
  	}
4354994f0   Daniel Rosenberg   f2fs: checkpoint ...
2573

455e3a588   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: limit # of ...
2577
  		err = -ENOMEM;
a2e2e76b2   Chao Yu   f2fs: fix to drop...
2578
  		drop_atomic = true;
57864ae5c   Jaegeuk Kim   f2fs: limit # of ...
2579
2580
  		goto fail;
  	}
5f7273958   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: check trunc...
2591
  repeat:
86d54795c   Jaegeuk Kim   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   Chao Yu   f2fs: support get...
2596
  	page = f2fs_pagecache_get_page(mapping, index,
86d54795c   Jaegeuk Kim   f2fs: do not wait...
2597
  				FGP_LOCK | FGP_WRITE | FGP_CREAT, GFP_NOFS);
3aab8f828   Chao Yu   f2fs: introduce f...
2598
2599
2600
2601
  	if (!page) {
  		err = -ENOMEM;
  		goto fail;
  	}
d5f66990b   Jaegeuk Kim   f2fs: decrease th...
2602

eb47b8009   Jaegeuk Kim   f2fs: add address...
2603
  	*pagep = page;
2aadac085   Jaegeuk Kim   f2fs: introduce p...
2604
2605
  	err = prepare_write_begin(sbi, page, pos, len,
  					&blkaddr, &need_balance);
9ba69cf98   Jaegeuk Kim   f2fs: avoid to al...
2606
  	if (err)
2aadac085   Jaegeuk Kim   f2fs: introduce p...
2607
  		goto fail;
9ba69cf98   Jaegeuk Kim   f2fs: avoid to al...
2608

af033b2aa   Chao Yu   f2fs: guarantee j...
2609
2610
  	if (need_balance && !IS_NOQUOTA(inode) &&
  			has_not_enough_free_secs(sbi, 0, 0)) {
2a3407607   Jaegeuk Kim   f2fs: call f2fs_b...
2611
  		unlock_page(page);
2c4db1a6f   Jaegeuk Kim   f2fs: clean up f2...
2612
  		f2fs_balance_fs(sbi, true);
2a3407607   Jaegeuk Kim   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   Chao Yu   f2fs: check PageW...
2620
  	f2fs_wait_on_page_writeback(page, DATA, false, true);
b3d208f96   Jaegeuk Kim   f2fs: revisit inl...
2621

649d7df29   Jaegeuk Kim   f2fs: fix to set ...
2622
2623
  	if (len == PAGE_SIZE || PageUptodate(page))
  		return 0;
eb47b8009   Jaegeuk Kim   f2fs: add address...
2624

95ae251fe   Eric Biggers   f2fs: add fs-veri...
2625
2626
  	if (!(pos & (PAGE_SIZE - 1)) && (pos + len) >= i_size_read(inode) &&
  	    !f2fs_verity_in_progress(inode)) {
746e24039   Yunlei He   f2fs: add a case ...
2627
2628
2629
  		zero_user_segment(page, len, PAGE_SIZE);
  		return 0;
  	}
2aadac085   Jaegeuk Kim   f2fs: introduce p...
2630
  	if (blkaddr == NEW_ADDR) {
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
2631
  		zero_user_segment(page, 0, PAGE_SIZE);
649d7df29   Jaegeuk Kim   f2fs: fix to set ...
2632
  		SetPageUptodate(page);
eb47b8009   Jaegeuk Kim   f2fs: add address...
2633
  	} else {
93770ab7a   Chao Yu   f2fs: introduce D...
2634
2635
  		if (!f2fs_is_valid_blkaddr(sbi, blkaddr,
  				DATA_GENERIC_ENHANCE_READ)) {
10f966bbf   Chao Yu   f2fs: use generic...
2636
  			err = -EFSCORRUPTED;
93770ab7a   Chao Yu   f2fs: introduce D...
2637
2638
  			goto fail;
  		}
13ba41e34   Jaegeuk Kim   f2fs: make get_lo...
2639
2640
  		err = f2fs_submit_page_read(inode, page, blkaddr);
  		if (err)
78682f794   Chao Yu   f2fs: fix to avoi...
2641
  			goto fail;
d54c795b4   Chao Yu   f2fs: fix error p...
2642

393ff91f5   Jaegeuk Kim   f2fs: reduce unnc...
2643
  		lock_page(page);
6bacf52fb   Jaegeuk Kim   f2fs: add unlikel...
2644
  		if (unlikely(page->mapping != mapping)) {
afcb7ca01   Jaegeuk Kim   f2fs: check trunc...
2645
2646
  			f2fs_put_page(page, 1);
  			goto repeat;
eb47b8009   Jaegeuk Kim   f2fs: add address...
2647
  		}
1563ac75e   Chao Yu   f2fs: fix to dete...
2648
2649
2650
  		if (unlikely(!PageUptodate(page))) {
  			err = -EIO;
  			goto fail;
4375a3366   Jaegeuk Kim   f2fs crypto: add ...
2651
  		}
eb47b8009   Jaegeuk Kim   f2fs: add address...
2652
  	}
eb47b8009   Jaegeuk Kim   f2fs: add address...
2653
  	return 0;
9ba69cf98   Jaegeuk Kim   f2fs: avoid to al...
2654

3aab8f828   Chao Yu   f2fs: introduce f...
2655
  fail:
86531d6b8   Jaegeuk Kim   f2fs: callers tak...
2656
  	f2fs_put_page(page, 1);
3aab8f828   Chao Yu   f2fs: introduce f...
2657
  	f2fs_write_failed(mapping, pos + len);
a2e2e76b2   Chao Yu   f2fs: fix to drop...
2658
  	if (drop_atomic)
4d57b86dd   Chao Yu   f2fs: clean up sy...
2659
  		f2fs_drop_inmem_pages_all(sbi, false);
3aab8f828   Chao Yu   f2fs: introduce f...
2660
  	return err;
eb47b8009   Jaegeuk Kim   f2fs: add address...
2661
  }
a1dd3c13c   Jaegeuk Kim   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   Chao Yu   f2fs: add a trace...
2668
  	trace_f2fs_write_end(inode, pos, len, copied);
649d7df29   Jaegeuk Kim   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   Yunlei He   f2fs: add a case ...
2675
  		if (unlikely(copied != len))
649d7df29   Jaegeuk Kim   f2fs: fix to set ...
2676
2677
2678
2679
2680
2681
  			copied = 0;
  		else
  			SetPageUptodate(page);
  	}
  	if (!copied)
  		goto unlock_out;
34ba94bac   Jaegeuk Kim   f2fs: do not make...
2682
  	set_page_dirty(page);
a1dd3c13c   Jaegeuk Kim   f2fs: fix to reco...
2683

95ae251fe   Eric Biggers   f2fs: add fs-veri...
2684
2685
  	if (pos + copied > i_size_read(inode) &&
  	    !f2fs_verity_in_progress(inode))
fc9581c80   Jaegeuk Kim   f2fs: introduce f...
2686
  		f2fs_i_size_write(inode, pos + copied);
649d7df29   Jaegeuk Kim   f2fs: fix to set ...
2687
  unlock_out:
3024c9a1f   Chao Yu   Revert "f2fs: mov...
2688
  	f2fs_put_page(page, 1);
d0239e1bf   Jaegeuk Kim   f2fs: detect idle...
2689
  	f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
a1dd3c13c   Jaegeuk Kim   f2fs: fix to reco...
2690
2691
  	return copied;
  }
6f6737631   Omar Sandoval   direct_IO: use io...
2692
2693
  static int check_direct_IO(struct inode *inode, struct iov_iter *iter,
  			   loff_t offset)
944fcfc18   Jaegeuk Kim   f2fs: check the b...
2694
  {
8a56dd968   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: check the b...
2709
2710
  	return 0;
  }
02b16d0a3   Chao Yu   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   Jaegeuk Kim   f2fs: use kvmallo...
2720
  	kvfree(dio);
02b16d0a3   Chao Yu   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   Chao Yu   f2fs: add to acco...
2730
2731
2732
  
  	dio = f2fs_kzalloc(F2FS_I_SB(inode),
  			sizeof(struct f2fs_private_dio), GFP_NOFS);
8e1140387   YueHaibing   f2fs: remove set ...
2733
  	if (!dio)
02b16d0a3   Chao Yu   f2fs: add to acco...
2734
  		goto out;
02b16d0a3   Chao Yu   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   Christoph Hellwig   direct-io: elimin...
2753
  static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
eb47b8009   Jaegeuk Kim   f2fs: add address...
2754
  {
b439b103a   Jaegeuk Kim   f2fs: move dio pr...
2755
  	struct address_space *mapping = iocb->ki_filp->f_mapping;
3aab8f828   Chao Yu   f2fs: introduce f...
2756
  	struct inode *inode = mapping->host;
0cdd31953   Hyunchul Lee   f2fs: support pas...
2757
  	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
f847c699c   Chao Yu   f2fs: allow out-p...
2758
  	struct f2fs_inode_info *fi = F2FS_I(inode);
3aab8f828   Chao Yu   f2fs: introduce f...
2759
  	size_t count = iov_iter_count(iter);
c8b8e32d7   Christoph Hellwig   direct-io: elimin...
2760
  	loff_t offset = iocb->ki_pos;
82e0a5aa5   Chao Yu   f2fs: fix to avoi...
2761
  	int rw = iov_iter_rw(iter);
3aab8f828   Chao Yu   f2fs: introduce f...
2762
  	int err;
0cdd31953   Hyunchul Lee   f2fs: support pas...
2763
  	enum rw_hint hint = iocb->ki_hint;
63189b785   Chao Yu   f2fs: wrap all op...
2764
  	int whint_mode = F2FS_OPTION(sbi).whint_mode;
f847c699c   Chao Yu   f2fs: allow out-p...
2765
  	bool do_opu;
944fcfc18   Jaegeuk Kim   f2fs: check the b...
2766

b439b103a   Jaegeuk Kim   f2fs: move dio pr...
2767
  	err = check_direct_IO(inode, iter, offset);
b9d777b85   Jaegeuk Kim   f2fs: check inlin...
2768
  	if (err)
8a56dd968   Jaegeuk Kim   f2fs: allow wrong...
2769
  		return err < 0 ? err : 0;
9ffe0fb5f   Huajun Li   f2fs: handle inli...
2770

f847c699c   Chao Yu   f2fs: allow out-p...
2771
  	if (f2fs_force_buffered_io(inode, iocb, iter))
36abef4e7   Jaegeuk Kim   f2fs: introduce m...
2772
  		return 0;
fcc85a4d8   Jaegeuk Kim   f2fs crypto: acti...
2773

f847c699c   Chao Yu   f2fs: allow out-p...
2774
  	do_opu = allow_outplace_dio(inode, iocb, iter);
5302fb000   Jaegeuk Kim   f2fs: clean up co...
2775
  	trace_f2fs_direct_IO_enter(inode, offset, count, rw);
70407fad8   Chao Yu   f2fs: add tracepo...
2776

0cdd31953   Hyunchul Lee   f2fs: support pas...
2777
2778
  	if (rw == WRITE && whint_mode == WHINT_MODE_OFF)
  		iocb->ki_hint = WRITE_LIFE_NOT_SET;
f847c699c   Chao Yu   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   Hyunchul Lee   f2fs: add nowait ...
2787
2788
2789
2790
  			iocb->ki_hint = hint;
  			err = -EAGAIN;
  			goto out;
  		}
f847c699c   Chao Yu   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   Hyunchul Lee   f2fs: add nowait ...
2795
  	}
02b16d0a3   Chao Yu   f2fs: add to acco...
2796
  	err = __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev,
f9d6d0597   Chao Yu   f2fs: fix out-pla...
2797
2798
  			iter, rw == WRITE ? get_data_block_dio_write :
  			get_data_block_dio, NULL, f2fs_dio_submit_bio,
02b16d0a3   Chao Yu   f2fs: add to acco...
2799
  			DIO_LOCKING | DIO_SKIP_HOLES);
f847c699c   Chao Yu   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   Chao Yu   f2fs: fix to avoi...
2805
2806
  
  	if (rw == WRITE) {
0cdd31953   Hyunchul Lee   f2fs: support pas...
2807
2808
  		if (whint_mode == WHINT_MODE_OFF)
  			iocb->ki_hint = hint;
b0af6d491   Chao Yu   f2fs: add app/fs ...
2809
2810
2811
  		if (err > 0) {
  			f2fs_update_iostat(F2FS_I_SB(inode), APP_DIRECT_IO,
  									err);
f847c699c   Chao Yu   f2fs: allow out-p...
2812
2813
  			if (!do_opu)
  				set_inode_flag(inode, FI_UPDATE_WRITE);
b0af6d491   Chao Yu   f2fs: add app/fs ...
2814
  		} else if (err < 0) {
6bfc49197   Jaegeuk Kim   f2fs: issue cache...
2815
  			f2fs_write_failed(mapping, offset + count);
b0af6d491   Chao Yu   f2fs: add app/fs ...
2816
  		}
6bfc49197   Jaegeuk Kim   f2fs: issue cache...
2817
  	}
70407fad8   Chao Yu   f2fs: add tracepo...
2818

b91050a80   Hyunchul Lee   f2fs: add nowait ...
2819
  out:
5302fb000   Jaegeuk Kim   f2fs: clean up co...
2820
  	trace_f2fs_direct_IO_exit(inode, offset, count, rw, err);
70407fad8   Chao Yu   f2fs: add tracepo...
2821

3aab8f828   Chao Yu   f2fs: introduce f...
2822
  	return err;
eb47b8009   Jaegeuk Kim   f2fs: add address...
2823
  }
487261f39   Chao Yu   f2fs: merge {inva...
2824
2825
  void f2fs_invalidate_page(struct page *page, unsigned int offset,
  							unsigned int length)
eb47b8009   Jaegeuk Kim   f2fs: add address...
2826
2827
  {
  	struct inode *inode = page->mapping->host;
487261f39   Chao Yu   f2fs: merge {inva...
2828
  	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
a7ffdbe22   Jaegeuk Kim   f2fs: expand coun...
2829

487261f39   Chao Yu   f2fs: merge {inva...
2830
  	if (inode->i_ino >= F2FS_ROOT_INO(sbi) &&
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
2831
  		(offset % PAGE_SIZE || length != PAGE_SIZE))
a7ffdbe22   Jaegeuk Kim   f2fs: expand coun...
2832
  		return;
487261f39   Chao Yu   f2fs: merge {inva...
2833
  	if (PageDirty(page)) {
933439c8f   Chao Yu   f2fs: give a chan...
2834
  		if (inode->i_ino == F2FS_META_INO(sbi)) {
487261f39   Chao Yu   f2fs: merge {inva...
2835
  			dec_page_count(sbi, F2FS_DIRTY_META);
933439c8f   Chao Yu   f2fs: give a chan...
2836
  		} else if (inode->i_ino == F2FS_NODE_INO(sbi)) {
487261f39   Chao Yu   f2fs: merge {inva...
2837
  			dec_page_count(sbi, F2FS_DIRTY_NODES);
933439c8f   Chao Yu   f2fs: give a chan...
2838
  		} else {
487261f39   Chao Yu   f2fs: merge {inva...
2839
  			inode_dec_dirty_pages(inode);
4d57b86dd   Chao Yu   f2fs: clean up sy...
2840
  			f2fs_remove_dirty_inode(inode);
933439c8f   Chao Yu   f2fs: give a chan...
2841
  		}
487261f39   Chao Yu   f2fs: merge {inva...
2842
  	}
decd36b6c   Chao Yu   f2fs: remove inme...
2843

2baf07818   Chao Yu   f2fs: fix to spre...
2844
  	clear_cold_data(page);
decd36b6c   Chao Yu   f2fs: remove inme...
2845
  	if (IS_ATOMIC_WRITTEN_PAGE(page))
4d57b86dd   Chao Yu   f2fs: clean up sy...
2846
  		return f2fs_drop_inmem_page(inode, page);
decd36b6c   Chao Yu   f2fs: remove inme...
2847

240a59156   Chao Yu   f2fs: fix to add ...
2848
  	f2fs_clear_page_private(page);
eb47b8009   Jaegeuk Kim   f2fs: add address...
2849
  }
487261f39   Chao Yu   f2fs: merge {inva...
2850
  int f2fs_release_page(struct page *page, gfp_t wait)
eb47b8009   Jaegeuk Kim   f2fs: add address...
2851
  {
f68daeebb   Jaegeuk Kim   f2fs: keep PagePr...
2852
2853
2854
  	/* If this is dirty page, keep PagePrivate */
  	if (PageDirty(page))
  		return 0;
decd36b6c   Chao Yu   f2fs: remove inme...
2855
2856
2857
  	/* This is atomic written page, keep Private */
  	if (IS_ATOMIC_WRITTEN_PAGE(page))
  		return 0;
2baf07818   Chao Yu   f2fs: fix to spre...
2858
  	clear_cold_data(page);
240a59156   Chao Yu   f2fs: fix to add ...
2859
  	f2fs_clear_page_private(page);
c3850aa1c   Jaegeuk Kim   f2fs: fix return ...
2860
  	return 1;
eb47b8009   Jaegeuk Kim   f2fs: add address...
2861
2862
2863
2864
  }
  
  static int f2fs_set_data_page_dirty(struct page *page)
  {
4969c06a0   Jaegeuk Kim   f2fs: support swa...
2865
  	struct inode *inode = page_file_mapping(page)->host;
eb47b8009   Jaegeuk Kim   f2fs: add address...
2866

26c6b8879   Jaegeuk Kim   f2fs: add tracepo...
2867
  	trace_f2fs_set_page_dirty(page, DATA);
237c0790e   Jaegeuk Kim   f2fs: call SetPag...
2868
2869
  	if (!PageUptodate(page))
  		SetPageUptodate(page);
4969c06a0   Jaegeuk Kim   f2fs: support swa...
2870
2871
  	if (PageSwapCache(page))
  		return __set_page_dirty_nobuffers(page);
34ba94bac   Jaegeuk Kim   f2fs: do not make...
2872

5fe457430   Chao Yu   f2fs: introduce F...
2873
  	if (f2fs_is_atomic_file(inode) && !f2fs_is_commit_atomic_write(inode)) {
decd36b6c   Chao Yu   f2fs: remove inme...
2874
  		if (!IS_ATOMIC_WRITTEN_PAGE(page)) {
4d57b86dd   Chao Yu   f2fs: clean up sy...
2875
  			f2fs_register_inmem_page(inode, page);
decd36b6c   Chao Yu   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   Jaegeuk Kim   f2fs: do not make...
2883
  	}
eb47b8009   Jaegeuk Kim   f2fs: add address...
2884
  	if (!PageDirty(page)) {
b87078ad3   Jaegeuk Kim   Revert "f2fs: int...
2885
  		__set_page_dirty_nobuffers(page);
4d57b86dd   Chao Yu   f2fs: clean up sy...
2886
  		f2fs_update_dirty_page(inode, page);
eb47b8009   Jaegeuk Kim   f2fs: add address...
2887
2888
2889
2890
  		return 1;
  	}
  	return 0;
  }
c01e54b77   Jaegeuk Kim   f2fs: support swa...
2891
2892
  static sector_t f2fs_bmap(struct address_space *mapping, sector_t block)
  {
454ae7e51   Chao Yu   f2fs: handle inli...
2893
  	struct inode *inode = mapping->host;
1d373a0ef   Jaegeuk Kim   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   Chao Yu   f2fs: fix incorre...
2900
  	return generic_block_bmap(mapping, block, get_data_block_bmap);
429511cdf   Chao Yu   f2fs: add core fu...
2901
  }
5b7a487cf   Weichao Guo   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   Jaegeuk Kim   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   Weichao Guo   f2fs: add customi...
2921

240a59156   Chao Yu   f2fs: fix to add ...
2922
2923
  	/* one extra reference was held for atomic_write page */
  	extra_count = atomic_written ? 1 : 0;
5b7a487cf   Weichao Guo   f2fs: add customi...
2924
  	rc = migrate_page_move_mapping(mapping, newpage,
371096949   Keith Busch   mm: migrate: remo...
2925
  				page, extra_count);
5b7a487cf   Weichao Guo   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   Chao Yu   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   Weichao Guo   f2fs: add customi...
2947

2916ecc0f   Jérôme Glisse   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   Weichao Guo   f2fs: add customi...
2952
2953
2954
2955
  
  	return MIGRATEPAGE_SUCCESS;
  }
  #endif
4969c06a0   Jaegeuk Kim   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   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: fix to reco...
3082
  	.write_end	= f2fs_write_end,
eb47b8009   Jaegeuk Kim   f2fs: add address...
3083
  	.set_page_dirty	= f2fs_set_data_page_dirty,
487261f39   Chao Yu   f2fs: merge {inva...
3084
3085
  	.invalidatepage	= f2fs_invalidate_page,
  	.releasepage	= f2fs_release_page,
eb47b8009   Jaegeuk Kim   f2fs: add address...
3086
  	.direct_IO	= f2fs_direct_IO,
c01e54b77   Jaegeuk Kim   f2fs: support swa...
3087
  	.bmap		= f2fs_bmap,
4969c06a0   Jaegeuk Kim   f2fs: support swa...
3088
3089
  	.swap_activate  = f2fs_swap_activate,
  	.swap_deactivate = f2fs_swap_deactivate,
5b7a487cf   Weichao Guo   f2fs: add customi...
3090
3091
3092
  #ifdef CONFIG_MIGRATION
  	.migratepage    = f2fs_migrate_page,
  #endif
eb47b8009   Jaegeuk Kim   f2fs: add address...
3093
  };
6dbb17961   Eric Biggers   f2fs: refactor re...
3094

5ec2d99de   Matthew Wilcox   f2fs: Convert to ...
3095
  void f2fs_clear_page_cache_dirty_tag(struct page *page)
aec2f729f   Chao Yu   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   Matthew Wilcox   f2fs: Convert to ...
3101
  	__xa_clear_mark(&mapping->i_pages, page_index(page),
aec2f729f   Chao Yu   f2fs: clean up wi...
3102
3103
3104
  						PAGECACHE_TAG_DIRTY);
  	xa_unlock_irqrestore(&mapping->i_pages, flags);
  }
6dbb17961   Eric Biggers   f2fs: refactor re...
3105
3106
  int __init f2fs_init_post_read_processing(void)
  {
95ae251fe   Eric Biggers   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   Eric Biggers   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   Chao Yu   f2fs: cache globa...
3124
  void f2fs_destroy_post_read_processing(void)
6dbb17961   Eric Biggers   f2fs: refactor re...
3125
3126
3127
3128
  {
  	mempool_destroy(bio_post_read_ctx_pool);
  	kmem_cache_destroy(bio_post_read_ctx_cache);
  }
0b20fcec8   Chao Yu   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);
  }