diff options
Diffstat (limited to 'fs/nilfs2/dat.c')
-rw-r--r-- | fs/nilfs2/dat.c | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c index 013146755683..7091c4e0f042 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) |
@@ -327,6 +328,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); | 328 | ret = nilfs_palloc_get_entry_block(dat, vblocknr, 0, &entry_bh); |
328 | if (ret < 0) | 329 | if (ret < 0) |
329 | return ret; | 330 | return ret; |
331 | |||
332 | /* | ||
333 | * The given disk block number (blocknr) is not yet written to | ||
334 | * the device at this point. | ||
335 | * | ||
336 | * To prevent nilfs_dat_translate() from returning the | ||
337 | * uncommited block number, this makes a copy of the entry | ||
338 | * buffer and redirects nilfs_dat_translate() to the copy. | ||
339 | */ | ||
340 | if (!buffer_nilfs_redirected(entry_bh)) { | ||
341 | ret = nilfs_mdt_freeze_buffer(dat, entry_bh); | ||
342 | if (ret) { | ||
343 | brelse(entry_bh); | ||
344 | return ret; | ||
345 | } | ||
346 | } | ||
347 | |||
330 | kaddr = kmap_atomic(entry_bh->b_page, KM_USER0); | 348 | kaddr = kmap_atomic(entry_bh->b_page, KM_USER0); |
331 | entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr); | 349 | entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr); |
332 | if (unlikely(entry->de_blocknr == cpu_to_le64(0))) { | 350 | if (unlikely(entry->de_blocknr == cpu_to_le64(0))) { |
@@ -371,7 +389,7 @@ int nilfs_dat_move(struct inode *dat, __u64 vblocknr, sector_t blocknr) | |||
371 | */ | 389 | */ |
372 | int nilfs_dat_translate(struct inode *dat, __u64 vblocknr, sector_t *blocknrp) | 390 | int nilfs_dat_translate(struct inode *dat, __u64 vblocknr, sector_t *blocknrp) |
373 | { | 391 | { |
374 | struct buffer_head *entry_bh; | 392 | struct buffer_head *entry_bh, *bh; |
375 | struct nilfs_dat_entry *entry; | 393 | struct nilfs_dat_entry *entry; |
376 | sector_t blocknr; | 394 | sector_t blocknr; |
377 | void *kaddr; | 395 | void *kaddr; |
@@ -381,6 +399,15 @@ int nilfs_dat_translate(struct inode *dat, __u64 vblocknr, sector_t *blocknrp) | |||
381 | if (ret < 0) | 399 | if (ret < 0) |
382 | return ret; | 400 | return ret; |
383 | 401 | ||
402 | if (!nilfs_doing_gc() && buffer_nilfs_redirected(entry_bh)) { | ||
403 | bh = nilfs_mdt_get_frozen_buffer(dat, entry_bh); | ||
404 | if (bh) { | ||
405 | WARN_ON(!buffer_uptodate(bh)); | ||
406 | brelse(entry_bh); | ||
407 | entry_bh = bh; | ||
408 | } | ||
409 | } | ||
410 | |||
384 | kaddr = kmap_atomic(entry_bh->b_page, KM_USER0); | 411 | kaddr = kmap_atomic(entry_bh->b_page, KM_USER0); |
385 | entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr); | 412 | entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr); |
386 | blocknr = le64_to_cpu(entry->de_blocknr); | 413 | blocknr = le64_to_cpu(entry->de_blocknr); |
@@ -468,6 +495,7 @@ struct inode *nilfs_dat_new(struct the_nilfs *nilfs, size_t entry_size) | |||
468 | di = NILFS_DAT_I(dat); | 495 | di = NILFS_DAT_I(dat); |
469 | lockdep_set_class(&di->mi.mi_sem, &dat_lock_key); | 496 | lockdep_set_class(&di->mi.mi_sem, &dat_lock_key); |
470 | nilfs_palloc_setup_cache(dat, &di->palloc_cache); | 497 | nilfs_palloc_setup_cache(dat, &di->palloc_cache); |
498 | nilfs_mdt_setup_shadow_map(dat, &di->shadow); | ||
471 | } | 499 | } |
472 | return dat; | 500 | return dat; |
473 | } | 501 | } |