Commit | Line | Data |
---|---|---|
e18c65b2 HL |
1 | /* |
2 | * fs/f2fs/inline.c | |
3 | * Copyright (c) 2013, Intel Corporation | |
4 | * Authors: Huajun Li <huajun.li@intel.com> | |
5 | * Haicheng Li <haicheng.li@intel.com> | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2 as | |
8 | * published by the Free Software Foundation. | |
9 | */ | |
10 | ||
11 | #include <linux/fs.h> | |
12 | #include <linux/f2fs_fs.h> | |
13 | ||
14 | #include "f2fs.h" | |
15 | ||
e18c65b2 HL |
16 | bool f2fs_may_inline(struct inode *inode) |
17 | { | |
e18c65b2 HL |
18 | block_t nr_blocks; |
19 | loff_t i_size; | |
20 | ||
4081363f | 21 | if (!test_opt(F2FS_I_SB(inode), INLINE_DATA)) |
e18c65b2 HL |
22 | return false; |
23 | ||
88b88a66 JK |
24 | if (f2fs_is_atomic_file(inode)) |
25 | return false; | |
26 | ||
e18c65b2 HL |
27 | nr_blocks = F2FS_I(inode)->i_xattr_nid ? 3 : 2; |
28 | if (inode->i_blocks > nr_blocks) | |
29 | return false; | |
30 | ||
31 | i_size = i_size_read(inode); | |
32 | if (i_size > MAX_INLINE_DATA) | |
33 | return false; | |
34 | ||
35 | return true; | |
36 | } | |
37 | ||
38 | int f2fs_read_inline_data(struct inode *inode, struct page *page) | |
39 | { | |
e18c65b2 HL |
40 | struct page *ipage; |
41 | void *src_addr, *dst_addr; | |
42 | ||
04a17fb1 CY |
43 | if (page->index) { |
44 | zero_user_segment(page, 0, PAGE_CACHE_SIZE); | |
45 | goto out; | |
46 | } | |
47 | ||
4081363f | 48 | ipage = get_node_page(F2FS_I_SB(inode), inode->i_ino); |
d54c795b CY |
49 | if (IS_ERR(ipage)) { |
50 | unlock_page(page); | |
e18c65b2 | 51 | return PTR_ERR(ipage); |
d54c795b | 52 | } |
e18c65b2 | 53 | |
18309aaa | 54 | zero_user_segment(page, MAX_INLINE_DATA, PAGE_CACHE_SIZE); |
e18c65b2 HL |
55 | |
56 | /* Copy the whole inline data block */ | |
57 | src_addr = inline_data_addr(ipage); | |
f1e33a04 | 58 | dst_addr = kmap_atomic(page); |
e18c65b2 | 59 | memcpy(dst_addr, src_addr, MAX_INLINE_DATA); |
f1e33a04 | 60 | kunmap_atomic(dst_addr); |
e18c65b2 | 61 | f2fs_put_page(ipage, 1); |
04a17fb1 | 62 | out: |
e18c65b2 HL |
63 | SetPageUptodate(page); |
64 | unlock_page(page); | |
65 | ||
66 | return 0; | |
67 | } | |
68 | ||
69 | static int __f2fs_convert_inline_data(struct inode *inode, struct page *page) | |
70 | { | |
ec4e7af4 | 71 | int err = 0; |
e18c65b2 HL |
72 | struct page *ipage; |
73 | struct dnode_of_data dn; | |
74 | void *src_addr, *dst_addr; | |
75 | block_t new_blk_addr; | |
4081363f | 76 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); |
e18c65b2 HL |
77 | struct f2fs_io_info fio = { |
78 | .type = DATA, | |
79 | .rw = WRITE_SYNC | REQ_PRIO, | |
80 | }; | |
81 | ||
82 | f2fs_lock_op(sbi); | |
83 | ipage = get_node_page(sbi, inode->i_ino); | |
15c6e3aa JK |
84 | if (IS_ERR(ipage)) { |
85 | err = PTR_ERR(ipage); | |
86 | goto out; | |
87 | } | |
e18c65b2 | 88 | |
ec4e7af4 JK |
89 | /* someone else converted inline_data already */ |
90 | if (!f2fs_has_inline_data(inode)) | |
91 | goto out; | |
92 | ||
e18c65b2 HL |
93 | /* |
94 | * i_addr[0] is not used for inline data, | |
95 | * so reserving new block will not destroy inline data | |
96 | */ | |
a8865372 | 97 | set_new_dnode(&dn, inode, ipage, NULL, 0); |
e18c65b2 | 98 | err = f2fs_reserve_block(&dn, 0); |
15c6e3aa JK |
99 | if (err) |
100 | goto out; | |
e18c65b2 | 101 | |
9ac1349a | 102 | f2fs_wait_on_page_writeback(page, DATA); |
18309aaa | 103 | zero_user_segment(page, MAX_INLINE_DATA, PAGE_CACHE_SIZE); |
e18c65b2 HL |
104 | |
105 | /* Copy the whole inline data block */ | |
106 | src_addr = inline_data_addr(ipage); | |
f1e33a04 | 107 | dst_addr = kmap_atomic(page); |
e18c65b2 | 108 | memcpy(dst_addr, src_addr, MAX_INLINE_DATA); |
f1e33a04 | 109 | kunmap_atomic(dst_addr); |
9e09fc85 | 110 | SetPageUptodate(page); |
e18c65b2 HL |
111 | |
112 | /* write data page to try to make data consistent */ | |
113 | set_page_writeback(page); | |
114 | write_data_page(page, &dn, &new_blk_addr, &fio); | |
115 | update_extent_cache(new_blk_addr, &dn); | |
5514f0aa | 116 | f2fs_wait_on_page_writeback(page, DATA); |
e18c65b2 HL |
117 | |
118 | /* clear inline data and flag after data writeback */ | |
119 | zero_user_segment(ipage, INLINE_DATA_OFFSET, | |
120 | INLINE_DATA_OFFSET + MAX_INLINE_DATA); | |
121 | clear_inode_flag(F2FS_I(inode), FI_INLINE_DATA); | |
0dbdc2ae | 122 | stat_dec_inline_inode(inode); |
e18c65b2 HL |
123 | |
124 | sync_inode_page(&dn); | |
a8865372 | 125 | f2fs_put_dnode(&dn); |
15c6e3aa | 126 | out: |
e18c65b2 | 127 | f2fs_unlock_op(sbi); |
e18c65b2 HL |
128 | return err; |
129 | } | |
130 | ||
b067ba1f JK |
131 | int f2fs_convert_inline_data(struct inode *inode, pgoff_t to_size, |
132 | struct page *page) | |
e18c65b2 | 133 | { |
b067ba1f | 134 | struct page *new_page = page; |
9e09fc85 | 135 | int err; |
e18c65b2 | 136 | |
9e09fc85 JK |
137 | if (!f2fs_has_inline_data(inode)) |
138 | return 0; | |
139 | else if (to_size <= MAX_INLINE_DATA) | |
140 | return 0; | |
e18c65b2 | 141 | |
b067ba1f JK |
142 | if (!page || page->index != 0) { |
143 | new_page = grab_cache_page(inode->i_mapping, 0); | |
144 | if (!new_page) | |
145 | return -ENOMEM; | |
146 | } | |
e18c65b2 | 147 | |
b067ba1f JK |
148 | err = __f2fs_convert_inline_data(inode, new_page); |
149 | if (!page || page->index != 0) | |
150 | f2fs_put_page(new_page, 1); | |
e18c65b2 HL |
151 | return err; |
152 | } | |
153 | ||
154 | int f2fs_write_inline_data(struct inode *inode, | |
b067ba1f | 155 | struct page *page, unsigned size) |
e18c65b2 HL |
156 | { |
157 | void *src_addr, *dst_addr; | |
158 | struct page *ipage; | |
159 | struct dnode_of_data dn; | |
160 | int err; | |
161 | ||
162 | set_new_dnode(&dn, inode, NULL, NULL, 0); | |
163 | err = get_dnode_of_data(&dn, 0, LOOKUP_NODE); | |
164 | if (err) | |
165 | return err; | |
166 | ipage = dn.inode_page; | |
167 | ||
c08a690b JK |
168 | /* Release any data block if it is allocated */ |
169 | if (!f2fs_has_inline_data(inode)) { | |
170 | int count = ADDRS_PER_PAGE(dn.node_page, F2FS_I(inode)); | |
171 | truncate_data_blocks_range(&dn, count); | |
172 | set_inode_flag(F2FS_I(inode), FI_INLINE_DATA); | |
173 | stat_inc_inline_inode(inode); | |
174 | } | |
175 | ||
54b591df | 176 | f2fs_wait_on_page_writeback(ipage, NODE); |
e18c65b2 HL |
177 | zero_user_segment(ipage, INLINE_DATA_OFFSET, |
178 | INLINE_DATA_OFFSET + MAX_INLINE_DATA); | |
f1e33a04 | 179 | src_addr = kmap_atomic(page); |
e18c65b2 HL |
180 | dst_addr = inline_data_addr(ipage); |
181 | memcpy(dst_addr, src_addr, size); | |
f1e33a04 | 182 | kunmap_atomic(src_addr); |
e18c65b2 | 183 | |
fff04f90 | 184 | set_inode_flag(F2FS_I(inode), FI_APPEND_WRITE); |
e18c65b2 HL |
185 | sync_inode_page(&dn); |
186 | f2fs_put_dnode(&dn); | |
187 | ||
188 | return 0; | |
189 | } | |
1e1bb4ba | 190 | |
8aa6f1c5 CY |
191 | void truncate_inline_data(struct inode *inode, u64 from) |
192 | { | |
8aa6f1c5 CY |
193 | struct page *ipage; |
194 | ||
195 | if (from >= MAX_INLINE_DATA) | |
196 | return; | |
197 | ||
4081363f | 198 | ipage = get_node_page(F2FS_I_SB(inode), inode->i_ino); |
8aa6f1c5 CY |
199 | if (IS_ERR(ipage)) |
200 | return; | |
201 | ||
54b591df JK |
202 | f2fs_wait_on_page_writeback(ipage, NODE); |
203 | ||
8aa6f1c5 CY |
204 | zero_user_segment(ipage, INLINE_DATA_OFFSET + from, |
205 | INLINE_DATA_OFFSET + MAX_INLINE_DATA); | |
206 | set_page_dirty(ipage); | |
207 | f2fs_put_page(ipage, 1); | |
208 | } | |
209 | ||
0342fd30 | 210 | bool recover_inline_data(struct inode *inode, struct page *npage) |
1e1bb4ba | 211 | { |
4081363f | 212 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); |
1e1bb4ba JK |
213 | struct f2fs_inode *ri = NULL; |
214 | void *src_addr, *dst_addr; | |
215 | struct page *ipage; | |
216 | ||
217 | /* | |
218 | * The inline_data recovery policy is as follows. | |
219 | * [prev.] [next] of inline_data flag | |
220 | * o o -> recover inline_data | |
221 | * o x -> remove inline_data, and then recover data blocks | |
222 | * x o -> remove inline_data, and then recover inline_data | |
223 | * x x -> recover data blocks | |
224 | */ | |
225 | if (IS_INODE(npage)) | |
226 | ri = F2FS_INODE(npage); | |
227 | ||
228 | if (f2fs_has_inline_data(inode) && | |
0342fd30 | 229 | ri && (ri->i_inline & F2FS_INLINE_DATA)) { |
1e1bb4ba JK |
230 | process_inline: |
231 | ipage = get_node_page(sbi, inode->i_ino); | |
9850cf4a | 232 | f2fs_bug_on(sbi, IS_ERR(ipage)); |
1e1bb4ba | 233 | |
54b591df JK |
234 | f2fs_wait_on_page_writeback(ipage, NODE); |
235 | ||
1e1bb4ba JK |
236 | src_addr = inline_data_addr(npage); |
237 | dst_addr = inline_data_addr(ipage); | |
238 | memcpy(dst_addr, src_addr, MAX_INLINE_DATA); | |
239 | update_inode(inode, ipage); | |
240 | f2fs_put_page(ipage, 1); | |
0342fd30 | 241 | return true; |
1e1bb4ba JK |
242 | } |
243 | ||
244 | if (f2fs_has_inline_data(inode)) { | |
245 | ipage = get_node_page(sbi, inode->i_ino); | |
9850cf4a | 246 | f2fs_bug_on(sbi, IS_ERR(ipage)); |
54b591df | 247 | f2fs_wait_on_page_writeback(ipage, NODE); |
1e1bb4ba JK |
248 | zero_user_segment(ipage, INLINE_DATA_OFFSET, |
249 | INLINE_DATA_OFFSET + MAX_INLINE_DATA); | |
250 | clear_inode_flag(F2FS_I(inode), FI_INLINE_DATA); | |
251 | update_inode(inode, ipage); | |
252 | f2fs_put_page(ipage, 1); | |
0342fd30 | 253 | } else if (ri && (ri->i_inline & F2FS_INLINE_DATA)) { |
764aa3e9 | 254 | truncate_blocks(inode, 0, false); |
1e1bb4ba JK |
255 | set_inode_flag(F2FS_I(inode), FI_INLINE_DATA); |
256 | goto process_inline; | |
257 | } | |
0342fd30 | 258 | return false; |
1e1bb4ba | 259 | } |
201a05be CY |
260 | |
261 | struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir, | |
262 | struct qstr *name, struct page **res_page) | |
263 | { | |
264 | struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); | |
4e6ebf6d | 265 | struct f2fs_inline_dentry *inline_dentry; |
201a05be | 266 | struct f2fs_dir_entry *de; |
7b3cd7d6 | 267 | struct f2fs_dentry_ptr d; |
4e6ebf6d | 268 | struct page *ipage; |
201a05be CY |
269 | |
270 | ipage = get_node_page(sbi, dir->i_ino); | |
271 | if (IS_ERR(ipage)) | |
272 | return NULL; | |
273 | ||
4e6ebf6d | 274 | inline_dentry = inline_data_addr(ipage); |
201a05be | 275 | |
7b3cd7d6 JK |
276 | make_dentry_ptr(&d, (void *)inline_dentry, 2); |
277 | de = find_target_dentry(name, NULL, &d); | |
278 | ||
201a05be | 279 | unlock_page(ipage); |
4e6ebf6d JK |
280 | if (de) |
281 | *res_page = ipage; | |
282 | else | |
283 | f2fs_put_page(ipage, 0); | |
284 | ||
285 | /* | |
286 | * For the most part, it should be a bug when name_len is zero. | |
287 | * We stop here for figuring out where the bugs has occurred. | |
288 | */ | |
7b3cd7d6 | 289 | f2fs_bug_on(sbi, d.max < 0); |
201a05be CY |
290 | return de; |
291 | } | |
292 | ||
293 | struct f2fs_dir_entry *f2fs_parent_inline_dir(struct inode *dir, | |
294 | struct page **p) | |
295 | { | |
296 | struct f2fs_sb_info *sbi = F2FS_I_SB(dir); | |
297 | struct page *ipage; | |
298 | struct f2fs_dir_entry *de; | |
299 | struct f2fs_inline_dentry *dentry_blk; | |
300 | ||
301 | ipage = get_node_page(sbi, dir->i_ino); | |
302 | if (IS_ERR(ipage)) | |
303 | return NULL; | |
304 | ||
305 | dentry_blk = inline_data_addr(ipage); | |
306 | de = &dentry_blk->dentry[1]; | |
307 | *p = ipage; | |
308 | unlock_page(ipage); | |
309 | return de; | |
310 | } | |
311 | ||
312 | int make_empty_inline_dir(struct inode *inode, struct inode *parent, | |
313 | struct page *ipage) | |
314 | { | |
315 | struct f2fs_inline_dentry *dentry_blk; | |
062a3e7b | 316 | struct f2fs_dentry_ptr d; |
201a05be CY |
317 | |
318 | dentry_blk = inline_data_addr(ipage); | |
319 | ||
062a3e7b JK |
320 | make_dentry_ptr(&d, (void *)dentry_blk, 2); |
321 | do_make_empty_dir(inode, parent, &d); | |
201a05be CY |
322 | |
323 | set_page_dirty(ipage); | |
324 | ||
325 | /* update i_size to MAX_INLINE_DATA */ | |
326 | if (i_size_read(inode) < MAX_INLINE_DATA) { | |
327 | i_size_write(inode, MAX_INLINE_DATA); | |
328 | set_inode_flag(F2FS_I(inode), FI_UPDATE_DIR); | |
329 | } | |
330 | return 0; | |
331 | } | |
332 | ||
d64948a4 | 333 | static int f2fs_convert_inline_dir(struct inode *dir, struct page *ipage, |
201a05be CY |
334 | struct f2fs_inline_dentry *inline_dentry) |
335 | { | |
336 | struct page *page; | |
337 | struct dnode_of_data dn; | |
338 | struct f2fs_dentry_block *dentry_blk; | |
339 | int err; | |
340 | ||
341 | page = grab_cache_page(dir->i_mapping, 0); | |
342 | if (!page) | |
343 | return -ENOMEM; | |
344 | ||
345 | set_new_dnode(&dn, dir, ipage, NULL, 0); | |
346 | err = f2fs_reserve_block(&dn, 0); | |
347 | if (err) | |
348 | goto out; | |
349 | ||
350 | f2fs_wait_on_page_writeback(page, DATA); | |
351 | zero_user_segment(page, 0, PAGE_CACHE_SIZE); | |
352 | ||
f1e33a04 | 353 | dentry_blk = kmap_atomic(page); |
201a05be CY |
354 | |
355 | /* copy data from inline dentry block to new dentry block */ | |
356 | memcpy(dentry_blk->dentry_bitmap, inline_dentry->dentry_bitmap, | |
357 | INLINE_DENTRY_BITMAP_SIZE); | |
358 | memcpy(dentry_blk->dentry, inline_dentry->dentry, | |
359 | sizeof(struct f2fs_dir_entry) * NR_INLINE_DENTRY); | |
360 | memcpy(dentry_blk->filename, inline_dentry->filename, | |
361 | NR_INLINE_DENTRY * F2FS_SLOT_LEN); | |
362 | ||
f1e33a04 | 363 | kunmap_atomic(dentry_blk); |
201a05be CY |
364 | SetPageUptodate(page); |
365 | set_page_dirty(page); | |
366 | ||
367 | /* clear inline dir and flag after data writeback */ | |
368 | zero_user_segment(ipage, INLINE_DATA_OFFSET, | |
369 | INLINE_DATA_OFFSET + MAX_INLINE_DATA); | |
3289c061 | 370 | stat_dec_inline_dir(dir); |
622f28ae | 371 | clear_inode_flag(F2FS_I(dir), FI_INLINE_DENTRY); |
201a05be CY |
372 | |
373 | if (i_size_read(dir) < PAGE_CACHE_SIZE) { | |
374 | i_size_write(dir, PAGE_CACHE_SIZE); | |
375 | set_inode_flag(F2FS_I(dir), FI_UPDATE_DIR); | |
376 | } | |
377 | ||
378 | sync_inode_page(&dn); | |
379 | out: | |
380 | f2fs_put_page(page, 1); | |
381 | return err; | |
382 | } | |
383 | ||
384 | int f2fs_add_inline_entry(struct inode *dir, const struct qstr *name, | |
385 | struct inode *inode) | |
386 | { | |
387 | struct f2fs_sb_info *sbi = F2FS_I_SB(dir); | |
388 | struct page *ipage; | |
389 | unsigned int bit_pos; | |
390 | f2fs_hash_t name_hash; | |
391 | struct f2fs_dir_entry *de; | |
392 | size_t namelen = name->len; | |
393 | struct f2fs_inline_dentry *dentry_blk = NULL; | |
394 | int slots = GET_DENTRY_SLOTS(namelen); | |
395 | struct page *page; | |
396 | int err = 0; | |
397 | int i; | |
398 | ||
399 | name_hash = f2fs_dentry_hash(name); | |
400 | ||
401 | ipage = get_node_page(sbi, dir->i_ino); | |
402 | if (IS_ERR(ipage)) | |
403 | return PTR_ERR(ipage); | |
404 | ||
405 | dentry_blk = inline_data_addr(ipage); | |
a82afa20 JK |
406 | bit_pos = room_for_filename(&dentry_blk->dentry_bitmap, |
407 | slots, NR_INLINE_DENTRY); | |
201a05be CY |
408 | if (bit_pos >= NR_INLINE_DENTRY) { |
409 | err = f2fs_convert_inline_dir(dir, ipage, dentry_blk); | |
410 | if (!err) | |
411 | err = -EAGAIN; | |
412 | goto out; | |
413 | } | |
414 | ||
201a05be | 415 | down_write(&F2FS_I(inode)->i_sem); |
bce8d112 | 416 | page = init_inode_metadata(inode, dir, name, ipage); |
201a05be CY |
417 | if (IS_ERR(page)) { |
418 | err = PTR_ERR(page); | |
419 | goto fail; | |
420 | } | |
bce8d112 JK |
421 | |
422 | f2fs_wait_on_page_writeback(ipage, NODE); | |
201a05be CY |
423 | de = &dentry_blk->dentry[bit_pos]; |
424 | de->hash_code = name_hash; | |
425 | de->name_len = cpu_to_le16(namelen); | |
426 | memcpy(dentry_blk->filename[bit_pos], name->name, name->len); | |
427 | de->ino = cpu_to_le32(inode->i_ino); | |
428 | set_de_type(de, inode); | |
429 | for (i = 0; i < slots; i++) | |
430 | test_and_set_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap); | |
431 | set_page_dirty(ipage); | |
432 | ||
433 | /* we don't need to mark_inode_dirty now */ | |
434 | F2FS_I(inode)->i_pino = dir->i_ino; | |
435 | update_inode(inode, page); | |
436 | f2fs_put_page(page, 1); | |
437 | ||
438 | update_parent_metadata(dir, inode, 0); | |
439 | fail: | |
440 | up_write(&F2FS_I(inode)->i_sem); | |
441 | ||
442 | if (is_inode_flag_set(F2FS_I(dir), FI_UPDATE_DIR)) { | |
443 | update_inode(dir, ipage); | |
444 | clear_inode_flag(F2FS_I(dir), FI_UPDATE_DIR); | |
445 | } | |
446 | out: | |
447 | f2fs_put_page(ipage, 1); | |
448 | return err; | |
449 | } | |
450 | ||
451 | void f2fs_delete_inline_entry(struct f2fs_dir_entry *dentry, struct page *page, | |
452 | struct inode *dir, struct inode *inode) | |
453 | { | |
454 | struct f2fs_inline_dentry *inline_dentry; | |
455 | int slots = GET_DENTRY_SLOTS(le16_to_cpu(dentry->name_len)); | |
456 | unsigned int bit_pos; | |
457 | int i; | |
458 | ||
459 | lock_page(page); | |
59a06155 | 460 | f2fs_wait_on_page_writeback(page, NODE); |
201a05be CY |
461 | |
462 | inline_dentry = inline_data_addr(page); | |
463 | bit_pos = dentry - inline_dentry->dentry; | |
464 | for (i = 0; i < slots; i++) | |
465 | test_and_clear_bit_le(bit_pos + i, | |
466 | &inline_dentry->dentry_bitmap); | |
467 | ||
468 | set_page_dirty(page); | |
469 | ||
470 | dir->i_ctime = dir->i_mtime = CURRENT_TIME; | |
471 | ||
472 | if (inode) | |
473 | f2fs_drop_nlink(dir, inode, page); | |
474 | ||
475 | f2fs_put_page(page, 1); | |
476 | } | |
477 | ||
478 | bool f2fs_empty_inline_dir(struct inode *dir) | |
479 | { | |
480 | struct f2fs_sb_info *sbi = F2FS_I_SB(dir); | |
481 | struct page *ipage; | |
482 | unsigned int bit_pos = 2; | |
483 | struct f2fs_inline_dentry *dentry_blk; | |
484 | ||
485 | ipage = get_node_page(sbi, dir->i_ino); | |
486 | if (IS_ERR(ipage)) | |
487 | return false; | |
488 | ||
489 | dentry_blk = inline_data_addr(ipage); | |
490 | bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap, | |
491 | NR_INLINE_DENTRY, | |
492 | bit_pos); | |
493 | ||
494 | f2fs_put_page(ipage, 1); | |
495 | ||
496 | if (bit_pos < NR_INLINE_DENTRY) | |
497 | return false; | |
498 | ||
499 | return true; | |
500 | } | |
501 | ||
502 | int f2fs_read_inline_dir(struct file *file, struct dir_context *ctx) | |
503 | { | |
504 | struct inode *inode = file_inode(file); | |
201a05be | 505 | struct f2fs_inline_dentry *inline_dentry = NULL; |
201a05be | 506 | struct page *ipage = NULL; |
7b3cd7d6 | 507 | struct f2fs_dentry_ptr d; |
201a05be CY |
508 | |
509 | if (ctx->pos == NR_INLINE_DENTRY) | |
510 | return 0; | |
511 | ||
38594de7 | 512 | ipage = get_node_page(F2FS_I_SB(inode), inode->i_ino); |
201a05be CY |
513 | if (IS_ERR(ipage)) |
514 | return PTR_ERR(ipage); | |
515 | ||
201a05be | 516 | inline_dentry = inline_data_addr(ipage); |
201a05be | 517 | |
7b3cd7d6 JK |
518 | make_dentry_ptr(&d, (void *)inline_dentry, 2); |
519 | ||
520 | if (!f2fs_fill_dentries(ctx, &d, 0)) | |
38594de7 | 521 | ctx->pos = NR_INLINE_DENTRY; |
201a05be | 522 | |
38594de7 | 523 | f2fs_put_page(ipage, 1); |
201a05be CY |
524 | return 0; |
525 | } |