diff options
Diffstat (limited to 'fs/f2fs/dir.c')
-rw-r--r-- | fs/f2fs/dir.c | 109 |
1 files changed, 62 insertions, 47 deletions
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 600bb5efe603..9d1cd423450d 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include "f2fs.h" | 13 | #include "f2fs.h" |
14 | #include "node.h" | 14 | #include "node.h" |
15 | #include "acl.h" | 15 | #include "acl.h" |
16 | #include "xattr.h" | ||
16 | 17 | ||
17 | static unsigned long dir_blocks(struct inode *inode) | 18 | static unsigned long dir_blocks(struct inode *inode) |
18 | { | 19 | { |
@@ -215,9 +216,9 @@ struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir, | |||
215 | 216 | ||
216 | struct f2fs_dir_entry *f2fs_parent_dir(struct inode *dir, struct page **p) | 217 | struct f2fs_dir_entry *f2fs_parent_dir(struct inode *dir, struct page **p) |
217 | { | 218 | { |
218 | struct page *page = NULL; | 219 | struct page *page; |
219 | struct f2fs_dir_entry *de = NULL; | 220 | struct f2fs_dir_entry *de; |
220 | struct f2fs_dentry_block *dentry_blk = NULL; | 221 | struct f2fs_dentry_block *dentry_blk; |
221 | 222 | ||
222 | page = get_lock_data_page(dir, 0); | 223 | page = get_lock_data_page(dir, 0); |
223 | if (IS_ERR(page)) | 224 | if (IS_ERR(page)) |
@@ -264,15 +265,10 @@ void f2fs_set_link(struct inode *dir, struct f2fs_dir_entry *de, | |||
264 | f2fs_put_page(page, 1); | 265 | f2fs_put_page(page, 1); |
265 | } | 266 | } |
266 | 267 | ||
267 | void init_dent_inode(const struct qstr *name, struct page *ipage) | 268 | static void init_dent_inode(const struct qstr *name, struct page *ipage) |
268 | { | 269 | { |
269 | struct f2fs_node *rn; | 270 | struct f2fs_node *rn; |
270 | 271 | ||
271 | if (IS_ERR(ipage)) | ||
272 | return; | ||
273 | |||
274 | wait_on_page_writeback(ipage); | ||
275 | |||
276 | /* copy name info. to this inode page */ | 272 | /* copy name info. to this inode page */ |
277 | rn = (struct f2fs_node *)page_address(ipage); | 273 | rn = (struct f2fs_node *)page_address(ipage); |
278 | rn->i.i_namelen = cpu_to_le32(name->len); | 274 | rn->i.i_namelen = cpu_to_le32(name->len); |
@@ -280,14 +276,15 @@ void init_dent_inode(const struct qstr *name, struct page *ipage) | |||
280 | set_page_dirty(ipage); | 276 | set_page_dirty(ipage); |
281 | } | 277 | } |
282 | 278 | ||
283 | static int make_empty_dir(struct inode *inode, struct inode *parent) | 279 | static int make_empty_dir(struct inode *inode, |
280 | struct inode *parent, struct page *page) | ||
284 | { | 281 | { |
285 | struct page *dentry_page; | 282 | struct page *dentry_page; |
286 | struct f2fs_dentry_block *dentry_blk; | 283 | struct f2fs_dentry_block *dentry_blk; |
287 | struct f2fs_dir_entry *de; | 284 | struct f2fs_dir_entry *de; |
288 | void *kaddr; | 285 | void *kaddr; |
289 | 286 | ||
290 | dentry_page = get_new_data_page(inode, 0, true); | 287 | dentry_page = get_new_data_page(inode, page, 0, true); |
291 | if (IS_ERR(dentry_page)) | 288 | if (IS_ERR(dentry_page)) |
292 | return PTR_ERR(dentry_page); | 289 | return PTR_ERR(dentry_page); |
293 | 290 | ||
@@ -317,63 +314,76 @@ static int make_empty_dir(struct inode *inode, struct inode *parent) | |||
317 | return 0; | 314 | return 0; |
318 | } | 315 | } |
319 | 316 | ||
320 | static int init_inode_metadata(struct inode *inode, | 317 | static struct page *init_inode_metadata(struct inode *inode, |
321 | struct inode *dir, const struct qstr *name) | 318 | struct inode *dir, const struct qstr *name) |
322 | { | 319 | { |
320 | struct page *page; | ||
321 | int err; | ||
322 | |||
323 | if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE)) { | 323 | if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE)) { |
324 | int err; | 324 | page = new_inode_page(inode, name); |
325 | err = new_inode_page(inode, name); | 325 | if (IS_ERR(page)) |
326 | if (err) | 326 | return page; |
327 | return err; | ||
328 | 327 | ||
329 | if (S_ISDIR(inode->i_mode)) { | 328 | if (S_ISDIR(inode->i_mode)) { |
330 | err = make_empty_dir(inode, dir); | 329 | err = make_empty_dir(inode, dir, page); |
331 | if (err) { | 330 | if (err) |
332 | remove_inode_page(inode); | 331 | goto error; |
333 | return err; | ||
334 | } | ||
335 | } | 332 | } |
336 | 333 | ||
337 | err = f2fs_init_acl(inode, dir); | 334 | err = f2fs_init_acl(inode, dir); |
338 | if (err) { | 335 | if (err) |
339 | remove_inode_page(inode); | 336 | goto error; |
340 | return err; | 337 | |
341 | } | 338 | err = f2fs_init_security(inode, dir, name, page); |
339 | if (err) | ||
340 | goto error; | ||
341 | |||
342 | wait_on_page_writeback(page); | ||
342 | } else { | 343 | } else { |
343 | struct page *ipage; | 344 | page = get_node_page(F2FS_SB(dir->i_sb), inode->i_ino); |
344 | ipage = get_node_page(F2FS_SB(dir->i_sb), inode->i_ino); | 345 | if (IS_ERR(page)) |
345 | if (IS_ERR(ipage)) | 346 | return page; |
346 | return PTR_ERR(ipage); | 347 | |
347 | set_cold_node(inode, ipage); | 348 | wait_on_page_writeback(page); |
348 | init_dent_inode(name, ipage); | 349 | set_cold_node(inode, page); |
349 | f2fs_put_page(ipage, 1); | ||
350 | } | 350 | } |
351 | |||
352 | init_dent_inode(name, page); | ||
353 | |||
354 | /* | ||
355 | * This file should be checkpointed during fsync. | ||
356 | * We lost i_pino from now on. | ||
357 | */ | ||
351 | if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK)) { | 358 | if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK)) { |
359 | file_lost_pino(inode); | ||
352 | inc_nlink(inode); | 360 | inc_nlink(inode); |
353 | update_inode_page(inode); | ||
354 | } | 361 | } |
355 | return 0; | 362 | return page; |
363 | |||
364 | error: | ||
365 | f2fs_put_page(page, 1); | ||
366 | remove_inode_page(inode); | ||
367 | return ERR_PTR(err); | ||
356 | } | 368 | } |
357 | 369 | ||
358 | static void update_parent_metadata(struct inode *dir, struct inode *inode, | 370 | static void update_parent_metadata(struct inode *dir, struct inode *inode, |
359 | unsigned int current_depth) | 371 | unsigned int current_depth) |
360 | { | 372 | { |
361 | bool need_dir_update = false; | ||
362 | |||
363 | if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE)) { | 373 | if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE)) { |
364 | if (S_ISDIR(inode->i_mode)) { | 374 | if (S_ISDIR(inode->i_mode)) { |
365 | inc_nlink(dir); | 375 | inc_nlink(dir); |
366 | need_dir_update = true; | 376 | set_inode_flag(F2FS_I(dir), FI_UPDATE_DIR); |
367 | } | 377 | } |
368 | clear_inode_flag(F2FS_I(inode), FI_NEW_INODE); | 378 | clear_inode_flag(F2FS_I(inode), FI_NEW_INODE); |
369 | } | 379 | } |
370 | dir->i_mtime = dir->i_ctime = CURRENT_TIME; | 380 | dir->i_mtime = dir->i_ctime = CURRENT_TIME; |
371 | if (F2FS_I(dir)->i_current_depth != current_depth) { | 381 | if (F2FS_I(dir)->i_current_depth != current_depth) { |
372 | F2FS_I(dir)->i_current_depth = current_depth; | 382 | F2FS_I(dir)->i_current_depth = current_depth; |
373 | need_dir_update = true; | 383 | set_inode_flag(F2FS_I(dir), FI_UPDATE_DIR); |
374 | } | 384 | } |
375 | 385 | ||
376 | if (need_dir_update) | 386 | if (is_inode_flag_set(F2FS_I(dir), FI_UPDATE_DIR)) |
377 | update_inode_page(dir); | 387 | update_inode_page(dir); |
378 | else | 388 | else |
379 | mark_inode_dirty(dir); | 389 | mark_inode_dirty(dir); |
@@ -423,6 +433,7 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name, struct inode *in | |||
423 | struct page *dentry_page = NULL; | 433 | struct page *dentry_page = NULL; |
424 | struct f2fs_dentry_block *dentry_blk = NULL; | 434 | struct f2fs_dentry_block *dentry_blk = NULL; |
425 | int slots = GET_DENTRY_SLOTS(namelen); | 435 | int slots = GET_DENTRY_SLOTS(namelen); |
436 | struct page *page; | ||
426 | int err = 0; | 437 | int err = 0; |
427 | int i; | 438 | int i; |
428 | 439 | ||
@@ -448,7 +459,7 @@ start: | |||
448 | bidx = dir_block_index(level, (le32_to_cpu(dentry_hash) % nbucket)); | 459 | bidx = dir_block_index(level, (le32_to_cpu(dentry_hash) % nbucket)); |
449 | 460 | ||
450 | for (block = bidx; block <= (bidx + nblock - 1); block++) { | 461 | for (block = bidx; block <= (bidx + nblock - 1); block++) { |
451 | dentry_page = get_new_data_page(dir, block, true); | 462 | dentry_page = get_new_data_page(dir, NULL, block, true); |
452 | if (IS_ERR(dentry_page)) | 463 | if (IS_ERR(dentry_page)) |
453 | return PTR_ERR(dentry_page); | 464 | return PTR_ERR(dentry_page); |
454 | 465 | ||
@@ -465,12 +476,13 @@ start: | |||
465 | ++level; | 476 | ++level; |
466 | goto start; | 477 | goto start; |
467 | add_dentry: | 478 | add_dentry: |
468 | err = init_inode_metadata(inode, dir, name); | ||
469 | if (err) | ||
470 | goto fail; | ||
471 | |||
472 | wait_on_page_writeback(dentry_page); | 479 | wait_on_page_writeback(dentry_page); |
473 | 480 | ||
481 | page = init_inode_metadata(inode, dir, name); | ||
482 | if (IS_ERR(page)) { | ||
483 | err = PTR_ERR(page); | ||
484 | goto fail; | ||
485 | } | ||
474 | de = &dentry_blk->dentry[bit_pos]; | 486 | de = &dentry_blk->dentry[bit_pos]; |
475 | de->hash_code = dentry_hash; | 487 | de->hash_code = dentry_hash; |
476 | de->name_len = cpu_to_le16(namelen); | 488 | de->name_len = cpu_to_le16(namelen); |
@@ -481,11 +493,14 @@ add_dentry: | |||
481 | test_and_set_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap); | 493 | test_and_set_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap); |
482 | set_page_dirty(dentry_page); | 494 | set_page_dirty(dentry_page); |
483 | 495 | ||
484 | update_parent_metadata(dir, inode, current_depth); | 496 | /* we don't need to mark_inode_dirty now */ |
485 | |||
486 | /* update parent inode number before releasing dentry page */ | ||
487 | F2FS_I(inode)->i_pino = dir->i_ino; | 497 | F2FS_I(inode)->i_pino = dir->i_ino; |
498 | update_inode(inode, page); | ||
499 | f2fs_put_page(page, 1); | ||
500 | |||
501 | update_parent_metadata(dir, inode, current_depth); | ||
488 | fail: | 502 | fail: |
503 | clear_inode_flag(F2FS_I(dir), FI_UPDATE_DIR); | ||
489 | kunmap(dentry_page); | 504 | kunmap(dentry_page); |
490 | f2fs_put_page(dentry_page, 1); | 505 | f2fs_put_page(dentry_page, 1); |
491 | return err; | 506 | return err; |