diff options
Diffstat (limited to 'fs/nilfs2/dat.c')
-rw-r--r-- | fs/nilfs2/dat.c | 92 |
1 files changed, 65 insertions, 27 deletions
diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c index 013146755683..49c844dab33a 100644 --- a/fs/nilfs2/dat.c +++ b/fs/nilfs2/dat.c | |||
@@ -36,6 +36,7 @@ | |||
36 | struct nilfs_dat_info { | 36 | struct nilfs_dat_info { |
37 | struct nilfs_mdt_info mi; | 37 | struct nilfs_mdt_info mi; |
38 | struct nilfs_palloc_cache palloc_cache; | 38 | struct nilfs_palloc_cache palloc_cache; |
39 | struct nilfs_shadow_map shadow; | ||
39 | }; | 40 | }; |
40 | 41 | ||
41 | static inline struct nilfs_dat_info *NILFS_DAT_I(struct inode *dat) | 42 | static inline struct nilfs_dat_info *NILFS_DAT_I(struct inode *dat) |
@@ -102,7 +103,8 @@ void nilfs_dat_abort_alloc(struct inode *dat, struct nilfs_palloc_req *req) | |||
102 | nilfs_palloc_abort_alloc_entry(dat, req); | 103 | nilfs_palloc_abort_alloc_entry(dat, req); |
103 | } | 104 | } |
104 | 105 | ||
105 | void nilfs_dat_commit_free(struct inode *dat, struct nilfs_palloc_req *req) | 106 | static void nilfs_dat_commit_free(struct inode *dat, |
107 | struct nilfs_palloc_req *req) | ||
106 | { | 108 | { |
107 | struct nilfs_dat_entry *entry; | 109 | struct nilfs_dat_entry *entry; |
108 | void *kaddr; | 110 | void *kaddr; |
@@ -327,6 +329,23 @@ int nilfs_dat_move(struct inode *dat, __u64 vblocknr, sector_t blocknr) | |||
327 | ret = nilfs_palloc_get_entry_block(dat, vblocknr, 0, &entry_bh); | 329 | ret = nilfs_palloc_get_entry_block(dat, vblocknr, 0, &entry_bh); |
328 | if (ret < 0) | 330 | if (ret < 0) |
329 | return ret; | 331 | return ret; |
332 | |||
333 | /* | ||
334 | * The given disk block number (blocknr) is not yet written to | ||
335 | * the device at this point. | ||
336 | * | ||
337 | * To prevent nilfs_dat_translate() from returning the | ||
338 | * uncommited block number, this makes a copy of the entry | ||
339 | * buffer and redirects nilfs_dat_translate() to the copy. | ||
340 | */ | ||
341 | if (!buffer_nilfs_redirected(entry_bh)) { | ||
342 | ret = nilfs_mdt_freeze_buffer(dat, entry_bh); | ||
343 | if (ret) { | ||
344 | brelse(entry_bh); | ||
345 | return ret; | ||
346 | } | ||
347 | } | ||
348 | |||
330 | kaddr = kmap_atomic(entry_bh->b_page, KM_USER0); | 349 | kaddr = kmap_atomic(entry_bh->b_page, KM_USER0); |
331 | entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr); | 350 | entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr); |
332 | if (unlikely(entry->de_blocknr == cpu_to_le64(0))) { | 351 | if (unlikely(entry->de_blocknr == cpu_to_le64(0))) { |
@@ -371,7 +390,7 @@ int nilfs_dat_move(struct inode *dat, __u64 vblocknr, sector_t blocknr) | |||
371 | */ | 390 | */ |
372 | int nilfs_dat_translate(struct inode *dat, __u64 vblocknr, sector_t *blocknrp) | 391 | int nilfs_dat_translate(struct inode *dat, __u64 vblocknr, sector_t *blocknrp) |
373 | { | 392 | { |
374 | struct buffer_head *entry_bh; | 393 | struct buffer_head *entry_bh, *bh; |
375 | struct nilfs_dat_entry *entry; | 394 | struct nilfs_dat_entry *entry; |
376 | sector_t blocknr; | 395 | sector_t blocknr; |
377 | void *kaddr; | 396 | void *kaddr; |
@@ -381,6 +400,15 @@ int nilfs_dat_translate(struct inode *dat, __u64 vblocknr, sector_t *blocknrp) | |||
381 | if (ret < 0) | 400 | if (ret < 0) |
382 | return ret; | 401 | return ret; |
383 | 402 | ||
403 | if (!nilfs_doing_gc() && buffer_nilfs_redirected(entry_bh)) { | ||
404 | bh = nilfs_mdt_get_frozen_buffer(dat, entry_bh); | ||
405 | if (bh) { | ||
406 | WARN_ON(!buffer_uptodate(bh)); | ||
407 | brelse(entry_bh); | ||
408 | entry_bh = bh; | ||
409 | } | ||
410 | } | ||
411 | |||
384 | kaddr = kmap_atomic(entry_bh->b_page, KM_USER0); | 412 | kaddr = kmap_atomic(entry_bh->b_page, KM_USER0); |
385 | entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr); | 413 | entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr); |
386 | blocknr = le64_to_cpu(entry->de_blocknr); | 414 | blocknr = le64_to_cpu(entry->de_blocknr); |
@@ -436,38 +464,48 @@ ssize_t nilfs_dat_get_vinfo(struct inode *dat, void *buf, unsigned visz, | |||
436 | } | 464 | } |
437 | 465 | ||
438 | /** | 466 | /** |
439 | * nilfs_dat_read - read dat inode | 467 | * nilfs_dat_read - read or get dat inode |
440 | * @dat: dat inode | 468 | * @sb: super block instance |
441 | * @raw_inode: on-disk dat inode | ||
442 | */ | ||
443 | int nilfs_dat_read(struct inode *dat, struct nilfs_inode *raw_inode) | ||
444 | { | ||
445 | return nilfs_read_inode_common(dat, raw_inode); | ||
446 | } | ||
447 | |||
448 | /** | ||
449 | * nilfs_dat_new - create dat file | ||
450 | * @nilfs: nilfs object | ||
451 | * @entry_size: size of a dat entry | 469 | * @entry_size: size of a dat entry |
470 | * @raw_inode: on-disk dat inode | ||
471 | * @inodep: buffer to store the inode | ||
452 | */ | 472 | */ |
453 | struct inode *nilfs_dat_new(struct the_nilfs *nilfs, size_t entry_size) | 473 | int nilfs_dat_read(struct super_block *sb, size_t entry_size, |
474 | struct nilfs_inode *raw_inode, struct inode **inodep) | ||
454 | { | 475 | { |
455 | static struct lock_class_key dat_lock_key; | 476 | static struct lock_class_key dat_lock_key; |
456 | struct inode *dat; | 477 | struct inode *dat; |
457 | struct nilfs_dat_info *di; | 478 | struct nilfs_dat_info *di; |
458 | int err; | 479 | int err; |
459 | 480 | ||
460 | dat = nilfs_mdt_new(nilfs, NULL, NILFS_DAT_INO, sizeof(*di)); | 481 | dat = nilfs_iget_locked(sb, NULL, NILFS_DAT_INO); |
461 | if (dat) { | 482 | if (unlikely(!dat)) |
462 | err = nilfs_palloc_init_blockgroup(dat, entry_size); | 483 | return -ENOMEM; |
463 | if (unlikely(err)) { | 484 | if (!(dat->i_state & I_NEW)) |
464 | nilfs_mdt_destroy(dat); | 485 | goto out; |
465 | return NULL; | ||
466 | } | ||
467 | 486 | ||
468 | di = NILFS_DAT_I(dat); | 487 | err = nilfs_mdt_init(dat, NILFS_MDT_GFP, sizeof(*di)); |
469 | lockdep_set_class(&di->mi.mi_sem, &dat_lock_key); | 488 | if (err) |
470 | nilfs_palloc_setup_cache(dat, &di->palloc_cache); | 489 | goto failed; |
471 | } | 490 | |
472 | return dat; | 491 | err = nilfs_palloc_init_blockgroup(dat, entry_size); |
492 | if (err) | ||
493 | goto failed; | ||
494 | |||
495 | di = NILFS_DAT_I(dat); | ||
496 | lockdep_set_class(&di->mi.mi_sem, &dat_lock_key); | ||
497 | nilfs_palloc_setup_cache(dat, &di->palloc_cache); | ||
498 | nilfs_mdt_setup_shadow_map(dat, &di->shadow); | ||
499 | |||
500 | err = nilfs_read_inode_common(dat, raw_inode); | ||
501 | if (err) | ||
502 | goto failed; | ||
503 | |||
504 | unlock_new_inode(dat); | ||
505 | out: | ||
506 | *inodep = dat; | ||
507 | return 0; | ||
508 | failed: | ||
509 | iget_failed(dat); | ||
510 | return err; | ||
473 | } | 511 | } |