diff options
33 files changed, 1339 insertions, 1257 deletions
diff --git a/fs/nilfs2/Makefile b/fs/nilfs2/Makefile index df3e62c1ddc5..85c98737a146 100644 --- a/fs/nilfs2/Makefile +++ b/fs/nilfs2/Makefile | |||
| @@ -2,4 +2,4 @@ obj-$(CONFIG_NILFS2_FS) += nilfs2.o | |||
| 2 | nilfs2-y := inode.o file.o dir.o super.o namei.o page.o mdt.o \ | 2 | nilfs2-y := inode.o file.o dir.o super.o namei.o page.o mdt.o \ |
| 3 | btnode.o bmap.o btree.o direct.o dat.o recovery.o \ | 3 | btnode.o bmap.o btree.o direct.o dat.o recovery.o \ |
| 4 | the_nilfs.o segbuf.o segment.o cpfile.o sufile.o \ | 4 | the_nilfs.o segbuf.o segment.o cpfile.o sufile.o \ |
| 5 | ifile.o alloc.o gcinode.o ioctl.o gcdat.o | 5 | ifile.o alloc.o gcinode.o ioctl.o |
diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c index 3dbdc1d356bf..8b782b062baa 100644 --- a/fs/nilfs2/bmap.c +++ b/fs/nilfs2/bmap.c | |||
| @@ -533,18 +533,20 @@ void nilfs_bmap_init_gc(struct nilfs_bmap *bmap) | |||
| 533 | nilfs_btree_init_gc(bmap); | 533 | nilfs_btree_init_gc(bmap); |
| 534 | } | 534 | } |
| 535 | 535 | ||
| 536 | void nilfs_bmap_init_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap) | 536 | void nilfs_bmap_save(const struct nilfs_bmap *bmap, |
| 537 | struct nilfs_bmap_store *store) | ||
| 537 | { | 538 | { |
| 538 | memcpy(gcbmap, bmap, sizeof(*bmap)); | 539 | memcpy(store->data, bmap->b_u.u_data, sizeof(store->data)); |
| 539 | init_rwsem(&gcbmap->b_sem); | 540 | store->last_allocated_key = bmap->b_last_allocated_key; |
| 540 | lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key); | 541 | store->last_allocated_ptr = bmap->b_last_allocated_ptr; |
| 541 | gcbmap->b_inode = &NILFS_BMAP_I(gcbmap)->vfs_inode; | 542 | store->state = bmap->b_state; |
| 542 | } | 543 | } |
| 543 | 544 | ||
| 544 | void nilfs_bmap_commit_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap) | 545 | void nilfs_bmap_restore(struct nilfs_bmap *bmap, |
| 546 | const struct nilfs_bmap_store *store) | ||
| 545 | { | 547 | { |
| 546 | memcpy(bmap, gcbmap, sizeof(*bmap)); | 548 | memcpy(bmap->b_u.u_data, store->data, sizeof(store->data)); |
| 547 | init_rwsem(&bmap->b_sem); | 549 | bmap->b_last_allocated_key = store->last_allocated_key; |
| 548 | lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key); | 550 | bmap->b_last_allocated_ptr = store->last_allocated_ptr; |
| 549 | bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode; | 551 | bmap->b_state = store->state; |
| 550 | } | 552 | } |
diff --git a/fs/nilfs2/bmap.h b/fs/nilfs2/bmap.h index a20569b19929..bde1c0aa2e15 100644 --- a/fs/nilfs2/bmap.h +++ b/fs/nilfs2/bmap.h | |||
| @@ -135,6 +135,12 @@ struct nilfs_bmap { | |||
| 135 | /* state */ | 135 | /* state */ |
| 136 | #define NILFS_BMAP_DIRTY 0x00000001 | 136 | #define NILFS_BMAP_DIRTY 0x00000001 |
| 137 | 137 | ||
| 138 | struct nilfs_bmap_store { | ||
| 139 | __le64 data[NILFS_BMAP_SIZE / sizeof(__le64)]; | ||
| 140 | __u64 last_allocated_key; | ||
| 141 | __u64 last_allocated_ptr; | ||
| 142 | int state; | ||
| 143 | }; | ||
| 138 | 144 | ||
| 139 | int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *); | 145 | int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *); |
| 140 | int nilfs_bmap_read(struct nilfs_bmap *, struct nilfs_inode *); | 146 | int nilfs_bmap_read(struct nilfs_bmap *, struct nilfs_inode *); |
| @@ -153,9 +159,9 @@ int nilfs_bmap_lookup_at_level(struct nilfs_bmap *, __u64, int, __u64 *); | |||
| 153 | int nilfs_bmap_mark(struct nilfs_bmap *, __u64, int); | 159 | int nilfs_bmap_mark(struct nilfs_bmap *, __u64, int); |
| 154 | 160 | ||
| 155 | void nilfs_bmap_init_gc(struct nilfs_bmap *); | 161 | void nilfs_bmap_init_gc(struct nilfs_bmap *); |
| 156 | void nilfs_bmap_init_gcdat(struct nilfs_bmap *, struct nilfs_bmap *); | ||
| 157 | void nilfs_bmap_commit_gcdat(struct nilfs_bmap *, struct nilfs_bmap *); | ||
| 158 | 162 | ||
| 163 | void nilfs_bmap_save(const struct nilfs_bmap *, struct nilfs_bmap_store *); | ||
| 164 | void nilfs_bmap_restore(struct nilfs_bmap *, const struct nilfs_bmap_store *); | ||
| 159 | 165 | ||
| 160 | static inline int nilfs_bmap_lookup(struct nilfs_bmap *bmap, __u64 key, | 166 | static inline int nilfs_bmap_lookup(struct nilfs_bmap *bmap, __u64 key, |
| 161 | __u64 *ptr) | 167 | __u64 *ptr) |
diff --git a/fs/nilfs2/btnode.c b/fs/nilfs2/btnode.c index f78ab1044d1d..5115814cb745 100644 --- a/fs/nilfs2/btnode.c +++ b/fs/nilfs2/btnode.c | |||
| @@ -37,15 +37,7 @@ | |||
| 37 | 37 | ||
| 38 | void nilfs_btnode_cache_init_once(struct address_space *btnc) | 38 | void nilfs_btnode_cache_init_once(struct address_space *btnc) |
| 39 | { | 39 | { |
| 40 | memset(btnc, 0, sizeof(*btnc)); | 40 | nilfs_mapping_init_once(btnc); |
| 41 | INIT_RADIX_TREE(&btnc->page_tree, GFP_ATOMIC); | ||
| 42 | spin_lock_init(&btnc->tree_lock); | ||
| 43 | INIT_LIST_HEAD(&btnc->private_list); | ||
| 44 | spin_lock_init(&btnc->private_lock); | ||
| 45 | |||
| 46 | spin_lock_init(&btnc->i_mmap_lock); | ||
| 47 | INIT_RAW_PRIO_TREE_ROOT(&btnc->i_mmap); | ||
| 48 | INIT_LIST_HEAD(&btnc->i_mmap_nonlinear); | ||
| 49 | } | 41 | } |
| 50 | 42 | ||
| 51 | static const struct address_space_operations def_btnode_aops = { | 43 | static const struct address_space_operations def_btnode_aops = { |
| @@ -55,12 +47,7 @@ static const struct address_space_operations def_btnode_aops = { | |||
| 55 | void nilfs_btnode_cache_init(struct address_space *btnc, | 47 | void nilfs_btnode_cache_init(struct address_space *btnc, |
| 56 | struct backing_dev_info *bdi) | 48 | struct backing_dev_info *bdi) |
| 57 | { | 49 | { |
| 58 | btnc->host = NULL; /* can safely set to host inode ? */ | 50 | nilfs_mapping_init(btnc, bdi, &def_btnode_aops); |
| 59 | btnc->flags = 0; | ||
| 60 | mapping_set_gfp_mask(btnc, GFP_NOFS); | ||
| 61 | btnc->assoc_mapping = NULL; | ||
| 62 | btnc->backing_dev_info = bdi; | ||
| 63 | btnc->a_ops = &def_btnode_aops; | ||
| 64 | } | 51 | } |
| 65 | 52 | ||
| 66 | void nilfs_btnode_cache_clear(struct address_space *btnc) | 53 | void nilfs_btnode_cache_clear(struct address_space *btnc) |
diff --git a/fs/nilfs2/cpfile.c b/fs/nilfs2/cpfile.c index 18737818db63..5ff15a8a1024 100644 --- a/fs/nilfs2/cpfile.c +++ b/fs/nilfs2/cpfile.c | |||
| @@ -863,26 +863,19 @@ int nilfs_cpfile_is_snapshot(struct inode *cpfile, __u64 cno) | |||
| 863 | */ | 863 | */ |
| 864 | int nilfs_cpfile_change_cpmode(struct inode *cpfile, __u64 cno, int mode) | 864 | int nilfs_cpfile_change_cpmode(struct inode *cpfile, __u64 cno, int mode) |
| 865 | { | 865 | { |
| 866 | struct the_nilfs *nilfs; | ||
| 867 | int ret; | 866 | int ret; |
| 868 | 867 | ||
| 869 | nilfs = NILFS_MDT(cpfile)->mi_nilfs; | ||
| 870 | |||
| 871 | switch (mode) { | 868 | switch (mode) { |
| 872 | case NILFS_CHECKPOINT: | 869 | case NILFS_CHECKPOINT: |
| 873 | /* | 870 | if (nilfs_checkpoint_is_mounted(cpfile->i_sb, cno)) |
| 874 | * Check for protecting existing snapshot mounts: | 871 | /* |
| 875 | * ns_mount_mutex is used to make this operation atomic and | 872 | * Current implementation does not have to protect |
| 876 | * exclusive with a new mount job. Though it doesn't cover | 873 | * plain read-only mounts since they are exclusive |
| 877 | * umount, it's enough for the purpose. | 874 | * with a read/write mount and are protected from the |
| 878 | */ | 875 | * cleaner. |
| 879 | if (nilfs_checkpoint_is_mounted(nilfs, cno, 1)) { | 876 | */ |
| 880 | /* Current implementation does not have to protect | ||
| 881 | plain read-only mounts since they are exclusive | ||
| 882 | with a read/write mount and are protected from the | ||
| 883 | cleaner. */ | ||
| 884 | ret = -EBUSY; | 877 | ret = -EBUSY; |
| 885 | } else | 878 | else |
| 886 | ret = nilfs_cpfile_clear_snapshot(cpfile, cno); | 879 | ret = nilfs_cpfile_clear_snapshot(cpfile, cno); |
| 887 | return ret; | 880 | return ret; |
| 888 | case NILFS_SNAPSHOT: | 881 | case NILFS_SNAPSHOT: |
| @@ -933,27 +926,40 @@ int nilfs_cpfile_get_stat(struct inode *cpfile, struct nilfs_cpstat *cpstat) | |||
| 933 | } | 926 | } |
| 934 | 927 | ||
| 935 | /** | 928 | /** |
| 936 | * nilfs_cpfile_read - read cpfile inode | 929 | * nilfs_cpfile_read - read or get cpfile inode |
| 937 | * @cpfile: cpfile inode | 930 | * @sb: super block instance |
| 938 | * @raw_inode: on-disk cpfile inode | ||
| 939 | */ | ||
| 940 | int nilfs_cpfile_read(struct inode *cpfile, struct nilfs_inode *raw_inode) | ||
| 941 | { | ||
| 942 | return nilfs_read_inode_common(cpfile, raw_inode); | ||
| 943 | } | ||
| 944 | |||
| 945 | /** | ||
| 946 | * nilfs_cpfile_new - create cpfile | ||
| 947 | * @nilfs: nilfs object | ||
| 948 | * @cpsize: size of a checkpoint entry | 931 | * @cpsize: size of a checkpoint entry |
| 932 | * @raw_inode: on-disk cpfile inode | ||
| 933 | * @inodep: buffer to store the inode | ||
| 949 | */ | 934 | */ |
| 950 | struct inode *nilfs_cpfile_new(struct the_nilfs *nilfs, size_t cpsize) | 935 | int nilfs_cpfile_read(struct super_block *sb, size_t cpsize, |
| 936 | struct nilfs_inode *raw_inode, struct inode **inodep) | ||
| 951 | { | 937 | { |
| 952 | struct inode *cpfile; | 938 | struct inode *cpfile; |
| 939 | int err; | ||
| 940 | |||
| 941 | cpfile = nilfs_iget_locked(sb, NULL, NILFS_CPFILE_INO); | ||
| 942 | if (unlikely(!cpfile)) | ||
| 943 | return -ENOMEM; | ||
| 944 | if (!(cpfile->i_state & I_NEW)) | ||
| 945 | goto out; | ||
| 946 | |||
| 947 | err = nilfs_mdt_init(cpfile, NILFS_MDT_GFP, 0); | ||
| 948 | if (err) | ||
| 949 | goto failed; | ||
| 953 | 950 | ||
| 954 | cpfile = nilfs_mdt_new(nilfs, NULL, NILFS_CPFILE_INO, 0); | 951 | nilfs_mdt_set_entry_size(cpfile, cpsize, |
| 955 | if (cpfile) | 952 | sizeof(struct nilfs_cpfile_header)); |
| 956 | nilfs_mdt_set_entry_size(cpfile, cpsize, | 953 | |
| 957 | sizeof(struct nilfs_cpfile_header)); | 954 | err = nilfs_read_inode_common(cpfile, raw_inode); |
| 958 | return cpfile; | 955 | if (err) |
| 956 | goto failed; | ||
| 957 | |||
| 958 | unlock_new_inode(cpfile); | ||
| 959 | out: | ||
| 960 | *inodep = cpfile; | ||
| 961 | return 0; | ||
| 962 | failed: | ||
| 963 | iget_failed(cpfile); | ||
| 964 | return err; | ||
| 959 | } | 965 | } |
diff --git a/fs/nilfs2/cpfile.h b/fs/nilfs2/cpfile.h index bc0809e0ab43..a242b9a314f9 100644 --- a/fs/nilfs2/cpfile.h +++ b/fs/nilfs2/cpfile.h | |||
| @@ -40,7 +40,7 @@ int nilfs_cpfile_get_stat(struct inode *, struct nilfs_cpstat *); | |||
| 40 | ssize_t nilfs_cpfile_get_cpinfo(struct inode *, __u64 *, int, void *, unsigned, | 40 | ssize_t nilfs_cpfile_get_cpinfo(struct inode *, __u64 *, int, void *, unsigned, |
| 41 | size_t); | 41 | size_t); |
| 42 | 42 | ||
| 43 | int nilfs_cpfile_read(struct inode *cpfile, struct nilfs_inode *raw_inode); | 43 | int nilfs_cpfile_read(struct super_block *sb, size_t cpsize, |
| 44 | struct inode *nilfs_cpfile_new(struct the_nilfs *nilfs, size_t cpsize); | 44 | struct nilfs_inode *raw_inode, struct inode **inodep); |
| 45 | 45 | ||
| 46 | #endif /* _NILFS_CPFILE_H */ | 46 | #endif /* _NILFS_CPFILE_H */ |
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 | } |
diff --git a/fs/nilfs2/dat.h b/fs/nilfs2/dat.h index d31c3aab0efe..cbd8e9732503 100644 --- a/fs/nilfs2/dat.h +++ b/fs/nilfs2/dat.h | |||
| @@ -53,7 +53,7 @@ int nilfs_dat_freev(struct inode *, __u64 *, size_t); | |||
| 53 | int nilfs_dat_move(struct inode *, __u64, sector_t); | 53 | int nilfs_dat_move(struct inode *, __u64, sector_t); |
| 54 | ssize_t nilfs_dat_get_vinfo(struct inode *, void *, unsigned, size_t); | 54 | ssize_t nilfs_dat_get_vinfo(struct inode *, void *, unsigned, size_t); |
| 55 | 55 | ||
| 56 | int nilfs_dat_read(struct inode *dat, struct nilfs_inode *raw_inode); | 56 | int nilfs_dat_read(struct super_block *sb, size_t entry_size, |
| 57 | struct inode *nilfs_dat_new(struct the_nilfs *nilfs, size_t entry_size); | 57 | struct nilfs_inode *raw_inode, struct inode **inodep); |
| 58 | 58 | ||
| 59 | #endif /* _NILFS_DAT_H */ | 59 | #endif /* _NILFS_DAT_H */ |
diff --git a/fs/nilfs2/export.h b/fs/nilfs2/export.h new file mode 100644 index 000000000000..a71cc412b651 --- /dev/null +++ b/fs/nilfs2/export.h | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | #ifndef NILFS_EXPORT_H | ||
| 2 | #define NILFS_EXPORT_H | ||
| 3 | |||
| 4 | #include <linux/exportfs.h> | ||
| 5 | |||
| 6 | extern const struct export_operations nilfs_export_ops; | ||
| 7 | |||
| 8 | struct nilfs_fid { | ||
| 9 | u64 cno; | ||
| 10 | u64 ino; | ||
| 11 | u32 gen; | ||
| 12 | |||
| 13 | u32 parent_gen; | ||
| 14 | u64 parent_ino; | ||
| 15 | } __attribute__ ((packed)); | ||
| 16 | |||
| 17 | #endif | ||
diff --git a/fs/nilfs2/gcdat.c b/fs/nilfs2/gcdat.c deleted file mode 100644 index 84a45d1d5464..000000000000 --- a/fs/nilfs2/gcdat.c +++ /dev/null | |||
| @@ -1,87 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * gcdat.c - NILFS shadow DAT inode for GC | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 19 | * | ||
| 20 | * Written by Seiji Kihara <kihara@osrg.net>, Amagai Yoshiji <amagai@osrg.net>, | ||
| 21 | * and Ryusuke Konishi <ryusuke@osrg.net>. | ||
| 22 | * | ||
| 23 | */ | ||
| 24 | |||
| 25 | #include <linux/buffer_head.h> | ||
| 26 | #include "nilfs.h" | ||
| 27 | #include "page.h" | ||
| 28 | #include "mdt.h" | ||
| 29 | |||
| 30 | int nilfs_init_gcdat_inode(struct the_nilfs *nilfs) | ||
| 31 | { | ||
| 32 | struct inode *dat = nilfs->ns_dat, *gcdat = nilfs->ns_gc_dat; | ||
| 33 | struct nilfs_inode_info *dii = NILFS_I(dat), *gii = NILFS_I(gcdat); | ||
| 34 | int err; | ||
| 35 | |||
| 36 | gcdat->i_state = 0; | ||
| 37 | gcdat->i_blocks = dat->i_blocks; | ||
| 38 | gii->i_flags = dii->i_flags; | ||
| 39 | gii->i_state = dii->i_state | (1 << NILFS_I_GCDAT); | ||
| 40 | gii->i_cno = 0; | ||
| 41 | nilfs_bmap_init_gcdat(gii->i_bmap, dii->i_bmap); | ||
| 42 | err = nilfs_copy_dirty_pages(gcdat->i_mapping, dat->i_mapping); | ||
| 43 | if (unlikely(err)) | ||
| 44 | return err; | ||
| 45 | |||
| 46 | return nilfs_copy_dirty_pages(&gii->i_btnode_cache, | ||
| 47 | &dii->i_btnode_cache); | ||
| 48 | } | ||
| 49 | |||
| 50 | void nilfs_commit_gcdat_inode(struct the_nilfs *nilfs) | ||
| 51 | { | ||
| 52 | struct inode *dat = nilfs->ns_dat, *gcdat = nilfs->ns_gc_dat; | ||
| 53 | struct nilfs_inode_info *dii = NILFS_I(dat), *gii = NILFS_I(gcdat); | ||
| 54 | struct address_space *mapping = dat->i_mapping; | ||
| 55 | struct address_space *gmapping = gcdat->i_mapping; | ||
| 56 | |||
| 57 | down_write(&NILFS_MDT(dat)->mi_sem); | ||
| 58 | dat->i_blocks = gcdat->i_blocks; | ||
| 59 | dii->i_flags = gii->i_flags; | ||
| 60 | dii->i_state = gii->i_state & ~(1 << NILFS_I_GCDAT); | ||
| 61 | |||
| 62 | nilfs_bmap_commit_gcdat(gii->i_bmap, dii->i_bmap); | ||
| 63 | |||
| 64 | nilfs_palloc_clear_cache(dat); | ||
| 65 | nilfs_palloc_clear_cache(gcdat); | ||
| 66 | nilfs_clear_dirty_pages(mapping); | ||
| 67 | nilfs_copy_back_pages(mapping, gmapping); | ||
| 68 | /* note: mdt dirty flags should be cleared by segctor. */ | ||
| 69 | |||
| 70 | nilfs_clear_dirty_pages(&dii->i_btnode_cache); | ||
| 71 | nilfs_copy_back_pages(&dii->i_btnode_cache, &gii->i_btnode_cache); | ||
| 72 | |||
| 73 | up_write(&NILFS_MDT(dat)->mi_sem); | ||
| 74 | } | ||
| 75 | |||
| 76 | void nilfs_clear_gcdat_inode(struct the_nilfs *nilfs) | ||
| 77 | { | ||
| 78 | struct inode *gcdat = nilfs->ns_gc_dat; | ||
| 79 | struct nilfs_inode_info *gii = NILFS_I(gcdat); | ||
| 80 | |||
| 81 | gcdat->i_state = I_FREEING | I_CLEAR; | ||
| 82 | gii->i_flags = 0; | ||
| 83 | |||
| 84 | nilfs_palloc_clear_cache(gcdat); | ||
| 85 | truncate_inode_pages(gcdat->i_mapping, 0); | ||
| 86 | truncate_inode_pages(&gii->i_btnode_cache, 0); | ||
| 87 | } | ||
diff --git a/fs/nilfs2/gcinode.c b/fs/nilfs2/gcinode.c index bed3a783129b..33ad25ddd5c4 100644 --- a/fs/nilfs2/gcinode.c +++ b/fs/nilfs2/gcinode.c | |||
| @@ -28,13 +28,6 @@ | |||
| 28 | * gcinodes), and this file provides lookup function of the dummy | 28 | * gcinodes), and this file provides lookup function of the dummy |
| 29 | * inodes and their buffer read function. | 29 | * inodes and their buffer read function. |
| 30 | * | 30 | * |
| 31 | * Since NILFS2 keeps up multiple checkpoints/snapshots across GC, it | ||
| 32 | * has to treat blocks that belong to a same file but have different | ||
| 33 | * checkpoint numbers. To avoid interference among generations, dummy | ||
| 34 | * inodes are managed separately from actual inodes, and their lookup | ||
| 35 | * function (nilfs_gc_iget) is designed to be specified with a | ||
| 36 | * checkpoint number argument as well as an inode number. | ||
| 37 | * | ||
| 38 | * Buffers and pages held by the dummy inodes will be released each | 31 | * Buffers and pages held by the dummy inodes will be released each |
| 39 | * time after they are copied to a new log. Dirty blocks made on the | 32 | * time after they are copied to a new log. Dirty blocks made on the |
| 40 | * current generation and the blocks to be moved by GC never overlap | 33 | * current generation and the blocks to be moved by GC never overlap |
| @@ -175,125 +168,46 @@ int nilfs_gccache_wait_and_mark_dirty(struct buffer_head *bh) | |||
| 175 | } | 168 | } |
| 176 | nilfs_btnode_mark_dirty(bh); | 169 | nilfs_btnode_mark_dirty(bh); |
| 177 | } else { | 170 | } else { |
| 178 | nilfs_mdt_mark_buffer_dirty(bh); | 171 | nilfs_mark_buffer_dirty(bh); |
| 179 | } | 172 | } |
| 180 | return 0; | 173 | return 0; |
| 181 | } | 174 | } |
| 182 | 175 | ||
| 183 | /* | 176 | int nilfs_init_gcinode(struct inode *inode) |
| 184 | * nilfs_init_gccache() - allocate and initialize gc_inode hash table | ||
| 185 | * @nilfs - the_nilfs | ||
| 186 | * | ||
| 187 | * Return Value: On success, 0. | ||
| 188 | * On error, a negative error code is returned. | ||
| 189 | */ | ||
| 190 | int nilfs_init_gccache(struct the_nilfs *nilfs) | ||
| 191 | { | 177 | { |
| 192 | int loop; | 178 | struct nilfs_inode_info *ii = NILFS_I(inode); |
| 193 | 179 | struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; | |
| 194 | BUG_ON(nilfs->ns_gc_inodes_h); | ||
| 195 | |||
| 196 | INIT_LIST_HEAD(&nilfs->ns_gc_inodes); | ||
| 197 | |||
| 198 | nilfs->ns_gc_inodes_h = | ||
| 199 | kmalloc(sizeof(struct hlist_head) * NILFS_GCINODE_HASH_SIZE, | ||
| 200 | GFP_NOFS); | ||
| 201 | if (nilfs->ns_gc_inodes_h == NULL) | ||
| 202 | return -ENOMEM; | ||
| 203 | |||
| 204 | for (loop = 0; loop < NILFS_GCINODE_HASH_SIZE; loop++) | ||
| 205 | INIT_HLIST_HEAD(&nilfs->ns_gc_inodes_h[loop]); | ||
| 206 | return 0; | ||
| 207 | } | ||
| 208 | |||
| 209 | /* | ||
| 210 | * nilfs_destroy_gccache() - free gc_inode hash table | ||
| 211 | * @nilfs - the nilfs | ||
| 212 | */ | ||
| 213 | void nilfs_destroy_gccache(struct the_nilfs *nilfs) | ||
| 214 | { | ||
| 215 | if (nilfs->ns_gc_inodes_h) { | ||
| 216 | nilfs_remove_all_gcinode(nilfs); | ||
| 217 | kfree(nilfs->ns_gc_inodes_h); | ||
| 218 | nilfs->ns_gc_inodes_h = NULL; | ||
| 219 | } | ||
| 220 | } | ||
| 221 | |||
| 222 | static struct inode *alloc_gcinode(struct the_nilfs *nilfs, ino_t ino, | ||
| 223 | __u64 cno) | ||
| 224 | { | ||
| 225 | struct inode *inode; | ||
| 226 | struct nilfs_inode_info *ii; | ||
| 227 | |||
| 228 | inode = nilfs_mdt_new_common(nilfs, NULL, ino, GFP_NOFS, 0); | ||
| 229 | if (!inode) | ||
| 230 | return NULL; | ||
| 231 | 180 | ||
| 232 | inode->i_op = NULL; | 181 | inode->i_mode = S_IFREG; |
| 233 | inode->i_fop = NULL; | 182 | mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS); |
| 234 | inode->i_mapping->a_ops = &def_gcinode_aops; | 183 | inode->i_mapping->a_ops = &def_gcinode_aops; |
| 184 | inode->i_mapping->backing_dev_info = inode->i_sb->s_bdi; | ||
| 235 | 185 | ||
| 236 | ii = NILFS_I(inode); | ||
| 237 | ii->i_cno = cno; | ||
| 238 | ii->i_flags = 0; | 186 | ii->i_flags = 0; |
| 239 | ii->i_state = 1 << NILFS_I_GCINODE; | ||
| 240 | ii->i_bh = NULL; | ||
| 241 | nilfs_bmap_init_gc(ii->i_bmap); | 187 | nilfs_bmap_init_gc(ii->i_bmap); |
| 242 | 188 | ||
| 243 | return inode; | 189 | /* |
| 244 | } | 190 | * Add the inode to GC inode list. Garbage Collection |
| 245 | 191 | * is serialized and no two processes manipulate the | |
| 246 | static unsigned long ihash(ino_t ino, __u64 cno) | 192 | * list simultaneously. |
| 247 | { | 193 | */ |
| 248 | return hash_long((unsigned long)((ino << 2) + cno), | 194 | igrab(inode); |
| 249 | NILFS_GCINODE_HASH_BITS); | 195 | list_add(&NILFS_I(inode)->i_dirty, &nilfs->ns_gc_inodes); |
| 250 | } | ||
| 251 | |||
| 252 | /* | ||
| 253 | * nilfs_gc_iget() - find or create gc inode with specified (ino,cno) | ||
| 254 | */ | ||
| 255 | struct inode *nilfs_gc_iget(struct the_nilfs *nilfs, ino_t ino, __u64 cno) | ||
| 256 | { | ||
| 257 | struct hlist_head *head = nilfs->ns_gc_inodes_h + ihash(ino, cno); | ||
| 258 | struct hlist_node *node; | ||
| 259 | struct inode *inode; | ||
| 260 | |||
| 261 | hlist_for_each_entry(inode, node, head, i_hash) { | ||
| 262 | if (inode->i_ino == ino && NILFS_I(inode)->i_cno == cno) | ||
| 263 | return inode; | ||
| 264 | } | ||
| 265 | 196 | ||
| 266 | inode = alloc_gcinode(nilfs, ino, cno); | 197 | return 0; |
| 267 | if (likely(inode)) { | ||
| 268 | hlist_add_head(&inode->i_hash, head); | ||
| 269 | list_add(&NILFS_I(inode)->i_dirty, &nilfs->ns_gc_inodes); | ||
| 270 | } | ||
| 271 | return inode; | ||
| 272 | } | ||
| 273 | |||
| 274 | /* | ||
| 275 | * nilfs_clear_gcinode() - clear and free a gc inode | ||
| 276 | */ | ||
| 277 | void nilfs_clear_gcinode(struct inode *inode) | ||
| 278 | { | ||
| 279 | nilfs_mdt_destroy(inode); | ||
| 280 | } | 198 | } |
| 281 | 199 | ||
| 282 | /* | 200 | /** |
| 283 | * nilfs_remove_all_gcinode() - remove all inodes from the_nilfs | 201 | * nilfs_remove_all_gcinodes() - remove all unprocessed gc inodes |
| 284 | */ | 202 | */ |
| 285 | void nilfs_remove_all_gcinode(struct the_nilfs *nilfs) | 203 | void nilfs_remove_all_gcinodes(struct the_nilfs *nilfs) |
| 286 | { | 204 | { |
| 287 | struct hlist_head *head = nilfs->ns_gc_inodes_h; | 205 | struct list_head *head = &nilfs->ns_gc_inodes; |
| 288 | struct hlist_node *node, *n; | 206 | struct nilfs_inode_info *ii; |
| 289 | struct inode *inode; | ||
| 290 | int loop; | ||
| 291 | 207 | ||
| 292 | for (loop = 0; loop < NILFS_GCINODE_HASH_SIZE; loop++, head++) { | 208 | while (!list_empty(head)) { |
| 293 | hlist_for_each_entry_safe(inode, node, n, head, i_hash) { | 209 | ii = list_first_entry(head, struct nilfs_inode_info, i_dirty); |
| 294 | hlist_del_init(&inode->i_hash); | 210 | list_del_init(&ii->i_dirty); |
| 295 | list_del_init(&NILFS_I(inode)->i_dirty); | 211 | iput(&ii->vfs_inode); |
| 296 | nilfs_clear_gcinode(inode); /* might sleep */ | ||
| 297 | } | ||
| 298 | } | 212 | } |
| 299 | } | 213 | } |
diff --git a/fs/nilfs2/ifile.c b/fs/nilfs2/ifile.c index 922d9dd42c8f..9f8a2da67f90 100644 --- a/fs/nilfs2/ifile.c +++ b/fs/nilfs2/ifile.c | |||
| @@ -161,25 +161,46 @@ int nilfs_ifile_get_inode_block(struct inode *ifile, ino_t ino, | |||
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | /** | 163 | /** |
| 164 | * nilfs_ifile_new - create inode file | 164 | * nilfs_ifile_read - read or get ifile inode |
| 165 | * @sbi: nilfs_sb_info struct | 165 | * @sb: super block instance |
| 166 | * @root: root object | ||
| 166 | * @inode_size: size of an inode | 167 | * @inode_size: size of an inode |
| 168 | * @raw_inode: on-disk ifile inode | ||
| 169 | * @inodep: buffer to store the inode | ||
| 167 | */ | 170 | */ |
| 168 | struct inode *nilfs_ifile_new(struct nilfs_sb_info *sbi, size_t inode_size) | 171 | int nilfs_ifile_read(struct super_block *sb, struct nilfs_root *root, |
| 172 | size_t inode_size, struct nilfs_inode *raw_inode, | ||
| 173 | struct inode **inodep) | ||
| 169 | { | 174 | { |
| 170 | struct inode *ifile; | 175 | struct inode *ifile; |
| 171 | int err; | 176 | int err; |
| 172 | 177 | ||
| 173 | ifile = nilfs_mdt_new(sbi->s_nilfs, sbi->s_super, NILFS_IFILE_INO, | 178 | ifile = nilfs_iget_locked(sb, root, NILFS_IFILE_INO); |
| 174 | sizeof(struct nilfs_ifile_info)); | 179 | if (unlikely(!ifile)) |
| 175 | if (ifile) { | 180 | return -ENOMEM; |
| 176 | err = nilfs_palloc_init_blockgroup(ifile, inode_size); | 181 | if (!(ifile->i_state & I_NEW)) |
| 177 | if (unlikely(err)) { | 182 | goto out; |
| 178 | nilfs_mdt_destroy(ifile); | 183 | |
| 179 | return NULL; | 184 | err = nilfs_mdt_init(ifile, NILFS_MDT_GFP, |
| 180 | } | 185 | sizeof(struct nilfs_ifile_info)); |
| 181 | nilfs_palloc_setup_cache(ifile, | 186 | if (err) |
| 182 | &NILFS_IFILE_I(ifile)->palloc_cache); | 187 | goto failed; |
| 183 | } | 188 | |
| 184 | return ifile; | 189 | err = nilfs_palloc_init_blockgroup(ifile, inode_size); |
| 190 | if (err) | ||
| 191 | goto failed; | ||
| 192 | |||
| 193 | nilfs_palloc_setup_cache(ifile, &NILFS_IFILE_I(ifile)->palloc_cache); | ||
| 194 | |||
| 195 | err = nilfs_read_inode_common(ifile, raw_inode); | ||
| 196 | if (err) | ||
| 197 | goto failed; | ||
| 198 | |||
| 199 | unlock_new_inode(ifile); | ||
| 200 | out: | ||
| 201 | *inodep = ifile; | ||
| 202 | return 0; | ||
| 203 | failed: | ||
| 204 | iget_failed(ifile); | ||
| 205 | return err; | ||
| 185 | } | 206 | } |
diff --git a/fs/nilfs2/ifile.h b/fs/nilfs2/ifile.h index cbca32e498f2..59b6f2b51df6 100644 --- a/fs/nilfs2/ifile.h +++ b/fs/nilfs2/ifile.h | |||
| @@ -49,6 +49,8 @@ int nilfs_ifile_create_inode(struct inode *, ino_t *, struct buffer_head **); | |||
| 49 | int nilfs_ifile_delete_inode(struct inode *, ino_t); | 49 | int nilfs_ifile_delete_inode(struct inode *, ino_t); |
| 50 | int nilfs_ifile_get_inode_block(struct inode *, ino_t, struct buffer_head **); | 50 | int nilfs_ifile_get_inode_block(struct inode *, ino_t, struct buffer_head **); |
| 51 | 51 | ||
| 52 | struct inode *nilfs_ifile_new(struct nilfs_sb_info *sbi, size_t inode_size); | 52 | int nilfs_ifile_read(struct super_block *sb, struct nilfs_root *root, |
| 53 | size_t inode_size, struct nilfs_inode *raw_inode, | ||
| 54 | struct inode **inodep); | ||
| 53 | 55 | ||
| 54 | #endif /* _NILFS_IFILE_H */ | 56 | #endif /* _NILFS_IFILE_H */ |
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index eccb2f2e2315..71d4bc8464e0 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c | |||
| @@ -34,6 +34,12 @@ | |||
| 34 | #include "cpfile.h" | 34 | #include "cpfile.h" |
| 35 | #include "ifile.h" | 35 | #include "ifile.h" |
| 36 | 36 | ||
| 37 | struct nilfs_iget_args { | ||
| 38 | u64 ino; | ||
| 39 | __u64 cno; | ||
| 40 | struct nilfs_root *root; | ||
| 41 | int for_gc; | ||
| 42 | }; | ||
| 37 | 43 | ||
| 38 | /** | 44 | /** |
| 39 | * nilfs_get_block() - get a file block on the filesystem (callback function) | 45 | * nilfs_get_block() - get a file block on the filesystem (callback function) |
| @@ -279,6 +285,7 @@ struct inode *nilfs_new_inode(struct inode *dir, int mode) | |||
| 279 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 285 | struct nilfs_sb_info *sbi = NILFS_SB(sb); |
| 280 | struct inode *inode; | 286 | struct inode *inode; |
| 281 | struct nilfs_inode_info *ii; | 287 | struct nilfs_inode_info *ii; |
| 288 | struct nilfs_root *root; | ||
| 282 | int err = -ENOMEM; | 289 | int err = -ENOMEM; |
| 283 | ino_t ino; | 290 | ino_t ino; |
| 284 | 291 | ||
| @@ -289,15 +296,17 @@ struct inode *nilfs_new_inode(struct inode *dir, int mode) | |||
| 289 | mapping_set_gfp_mask(inode->i_mapping, | 296 | mapping_set_gfp_mask(inode->i_mapping, |
| 290 | mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); | 297 | mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); |
| 291 | 298 | ||
| 299 | root = NILFS_I(dir)->i_root; | ||
| 292 | ii = NILFS_I(inode); | 300 | ii = NILFS_I(inode); |
| 293 | ii->i_state = 1 << NILFS_I_NEW; | 301 | ii->i_state = 1 << NILFS_I_NEW; |
| 302 | ii->i_root = root; | ||
| 294 | 303 | ||
| 295 | err = nilfs_ifile_create_inode(sbi->s_ifile, &ino, &ii->i_bh); | 304 | err = nilfs_ifile_create_inode(root->ifile, &ino, &ii->i_bh); |
| 296 | if (unlikely(err)) | 305 | if (unlikely(err)) |
| 297 | goto failed_ifile_create_inode; | 306 | goto failed_ifile_create_inode; |
| 298 | /* reference count of i_bh inherits from nilfs_mdt_read_block() */ | 307 | /* reference count of i_bh inherits from nilfs_mdt_read_block() */ |
| 299 | 308 | ||
| 300 | atomic_inc(&sbi->s_inodes_count); | 309 | atomic_inc(&root->inodes_count); |
| 301 | inode_init_owner(inode, dir, mode); | 310 | inode_init_owner(inode, dir, mode); |
| 302 | inode->i_ino = ino; | 311 | inode->i_ino = ino; |
| 303 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | 312 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; |
| @@ -320,7 +329,6 @@ struct inode *nilfs_new_inode(struct inode *dir, int mode) | |||
| 320 | /* ii->i_file_acl = 0; */ | 329 | /* ii->i_file_acl = 0; */ |
| 321 | /* ii->i_dir_acl = 0; */ | 330 | /* ii->i_dir_acl = 0; */ |
| 322 | ii->i_dir_start_lookup = 0; | 331 | ii->i_dir_start_lookup = 0; |
| 323 | ii->i_cno = 0; | ||
| 324 | nilfs_set_inode_flags(inode); | 332 | nilfs_set_inode_flags(inode); |
| 325 | spin_lock(&sbi->s_next_gen_lock); | 333 | spin_lock(&sbi->s_next_gen_lock); |
| 326 | inode->i_generation = sbi->s_next_generation++; | 334 | inode->i_generation = sbi->s_next_generation++; |
| @@ -350,16 +358,6 @@ struct inode *nilfs_new_inode(struct inode *dir, int mode) | |||
| 350 | return ERR_PTR(err); | 358 | return ERR_PTR(err); |
| 351 | } | 359 | } |
| 352 | 360 | ||
| 353 | void nilfs_free_inode(struct inode *inode) | ||
| 354 | { | ||
| 355 | struct super_block *sb = inode->i_sb; | ||
| 356 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | ||
| 357 | |||
| 358 | /* XXX: check error code? Is there any thing I can do? */ | ||
| 359 | (void) nilfs_ifile_delete_inode(sbi->s_ifile, inode->i_ino); | ||
| 360 | atomic_dec(&sbi->s_inodes_count); | ||
| 361 | } | ||
| 362 | |||
| 363 | void nilfs_set_inode_flags(struct inode *inode) | 361 | void nilfs_set_inode_flags(struct inode *inode) |
| 364 | { | 362 | { |
| 365 | unsigned int flags = NILFS_I(inode)->i_flags; | 363 | unsigned int flags = NILFS_I(inode)->i_flags; |
| @@ -410,7 +408,6 @@ int nilfs_read_inode_common(struct inode *inode, | |||
| 410 | 0 : le32_to_cpu(raw_inode->i_dir_acl); | 408 | 0 : le32_to_cpu(raw_inode->i_dir_acl); |
| 411 | #endif | 409 | #endif |
| 412 | ii->i_dir_start_lookup = 0; | 410 | ii->i_dir_start_lookup = 0; |
| 413 | ii->i_cno = 0; | ||
| 414 | inode->i_generation = le32_to_cpu(raw_inode->i_generation); | 411 | inode->i_generation = le32_to_cpu(raw_inode->i_generation); |
| 415 | 412 | ||
| 416 | if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || | 413 | if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || |
| @@ -424,7 +421,8 @@ int nilfs_read_inode_common(struct inode *inode, | |||
| 424 | return 0; | 421 | return 0; |
| 425 | } | 422 | } |
| 426 | 423 | ||
| 427 | static int __nilfs_read_inode(struct super_block *sb, unsigned long ino, | 424 | static int __nilfs_read_inode(struct super_block *sb, |
| 425 | struct nilfs_root *root, unsigned long ino, | ||
| 428 | struct inode *inode) | 426 | struct inode *inode) |
| 429 | { | 427 | { |
| 430 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 428 | struct nilfs_sb_info *sbi = NILFS_SB(sb); |
| @@ -434,11 +432,11 @@ static int __nilfs_read_inode(struct super_block *sb, unsigned long ino, | |||
| 434 | int err; | 432 | int err; |
| 435 | 433 | ||
| 436 | down_read(&NILFS_MDT(dat)->mi_sem); /* XXX */ | 434 | down_read(&NILFS_MDT(dat)->mi_sem); /* XXX */ |
| 437 | err = nilfs_ifile_get_inode_block(sbi->s_ifile, ino, &bh); | 435 | err = nilfs_ifile_get_inode_block(root->ifile, ino, &bh); |
| 438 | if (unlikely(err)) | 436 | if (unlikely(err)) |
| 439 | goto bad_inode; | 437 | goto bad_inode; |
| 440 | 438 | ||
| 441 | raw_inode = nilfs_ifile_map_inode(sbi->s_ifile, ino, bh); | 439 | raw_inode = nilfs_ifile_map_inode(root->ifile, ino, bh); |
| 442 | 440 | ||
| 443 | err = nilfs_read_inode_common(inode, raw_inode); | 441 | err = nilfs_read_inode_common(inode, raw_inode); |
| 444 | if (err) | 442 | if (err) |
| @@ -461,14 +459,14 @@ static int __nilfs_read_inode(struct super_block *sb, unsigned long ino, | |||
| 461 | inode, inode->i_mode, | 459 | inode, inode->i_mode, |
| 462 | huge_decode_dev(le64_to_cpu(raw_inode->i_device_code))); | 460 | huge_decode_dev(le64_to_cpu(raw_inode->i_device_code))); |
| 463 | } | 461 | } |
| 464 | nilfs_ifile_unmap_inode(sbi->s_ifile, ino, bh); | 462 | nilfs_ifile_unmap_inode(root->ifile, ino, bh); |
| 465 | brelse(bh); | 463 | brelse(bh); |
| 466 | up_read(&NILFS_MDT(dat)->mi_sem); /* XXX */ | 464 | up_read(&NILFS_MDT(dat)->mi_sem); /* XXX */ |
| 467 | nilfs_set_inode_flags(inode); | 465 | nilfs_set_inode_flags(inode); |
| 468 | return 0; | 466 | return 0; |
| 469 | 467 | ||
| 470 | failed_unmap: | 468 | failed_unmap: |
| 471 | nilfs_ifile_unmap_inode(sbi->s_ifile, ino, bh); | 469 | nilfs_ifile_unmap_inode(root->ifile, ino, bh); |
| 472 | brelse(bh); | 470 | brelse(bh); |
| 473 | 471 | ||
| 474 | bad_inode: | 472 | bad_inode: |
| @@ -476,18 +474,95 @@ static int __nilfs_read_inode(struct super_block *sb, unsigned long ino, | |||
| 476 | return err; | 474 | return err; |
| 477 | } | 475 | } |
| 478 | 476 | ||
| 479 | struct inode *nilfs_iget(struct super_block *sb, unsigned long ino) | 477 | static int nilfs_iget_test(struct inode *inode, void *opaque) |
| 478 | { | ||
| 479 | struct nilfs_iget_args *args = opaque; | ||
| 480 | struct nilfs_inode_info *ii; | ||
| 481 | |||
| 482 | if (args->ino != inode->i_ino || args->root != NILFS_I(inode)->i_root) | ||
| 483 | return 0; | ||
| 484 | |||
| 485 | ii = NILFS_I(inode); | ||
| 486 | if (!test_bit(NILFS_I_GCINODE, &ii->i_state)) | ||
| 487 | return !args->for_gc; | ||
| 488 | |||
| 489 | return args->for_gc && args->cno == ii->i_cno; | ||
| 490 | } | ||
| 491 | |||
| 492 | static int nilfs_iget_set(struct inode *inode, void *opaque) | ||
| 493 | { | ||
| 494 | struct nilfs_iget_args *args = opaque; | ||
| 495 | |||
| 496 | inode->i_ino = args->ino; | ||
| 497 | if (args->for_gc) { | ||
| 498 | NILFS_I(inode)->i_state = 1 << NILFS_I_GCINODE; | ||
| 499 | NILFS_I(inode)->i_cno = args->cno; | ||
| 500 | NILFS_I(inode)->i_root = NULL; | ||
| 501 | } else { | ||
| 502 | if (args->root && args->ino == NILFS_ROOT_INO) | ||
| 503 | nilfs_get_root(args->root); | ||
| 504 | NILFS_I(inode)->i_root = args->root; | ||
| 505 | } | ||
| 506 | return 0; | ||
| 507 | } | ||
| 508 | |||
| 509 | struct inode *nilfs_ilookup(struct super_block *sb, struct nilfs_root *root, | ||
| 510 | unsigned long ino) | ||
| 511 | { | ||
| 512 | struct nilfs_iget_args args = { | ||
| 513 | .ino = ino, .root = root, .cno = 0, .for_gc = 0 | ||
| 514 | }; | ||
| 515 | |||
| 516 | return ilookup5(sb, ino, nilfs_iget_test, &args); | ||
| 517 | } | ||
| 518 | |||
| 519 | struct inode *nilfs_iget_locked(struct super_block *sb, struct nilfs_root *root, | ||
| 520 | unsigned long ino) | ||
| 521 | { | ||
| 522 | struct nilfs_iget_args args = { | ||
| 523 | .ino = ino, .root = root, .cno = 0, .for_gc = 0 | ||
| 524 | }; | ||
| 525 | |||
| 526 | return iget5_locked(sb, ino, nilfs_iget_test, nilfs_iget_set, &args); | ||
| 527 | } | ||
| 528 | |||
| 529 | struct inode *nilfs_iget(struct super_block *sb, struct nilfs_root *root, | ||
| 530 | unsigned long ino) | ||
| 480 | { | 531 | { |
| 481 | struct inode *inode; | 532 | struct inode *inode; |
| 482 | int err; | 533 | int err; |
| 483 | 534 | ||
| 484 | inode = iget_locked(sb, ino); | 535 | inode = nilfs_iget_locked(sb, root, ino); |
| 485 | if (unlikely(!inode)) | 536 | if (unlikely(!inode)) |
| 486 | return ERR_PTR(-ENOMEM); | 537 | return ERR_PTR(-ENOMEM); |
| 487 | if (!(inode->i_state & I_NEW)) | 538 | if (!(inode->i_state & I_NEW)) |
| 488 | return inode; | 539 | return inode; |
| 489 | 540 | ||
| 490 | err = __nilfs_read_inode(sb, ino, inode); | 541 | err = __nilfs_read_inode(sb, root, ino, inode); |
| 542 | if (unlikely(err)) { | ||
| 543 | iget_failed(inode); | ||
| 544 | return ERR_PTR(err); | ||
| 545 | } | ||
| 546 | unlock_new_inode(inode); | ||
| 547 | return inode; | ||
| 548 | } | ||
| 549 | |||
| 550 | struct inode *nilfs_iget_for_gc(struct super_block *sb, unsigned long ino, | ||
| 551 | __u64 cno) | ||
| 552 | { | ||
| 553 | struct nilfs_iget_args args = { | ||
| 554 | .ino = ino, .root = NULL, .cno = cno, .for_gc = 1 | ||
| 555 | }; | ||
| 556 | struct inode *inode; | ||
| 557 | int err; | ||
| 558 | |||
| 559 | inode = iget5_locked(sb, ino, nilfs_iget_test, nilfs_iget_set, &args); | ||
| 560 | if (unlikely(!inode)) | ||
| 561 | return ERR_PTR(-ENOMEM); | ||
| 562 | if (!(inode->i_state & I_NEW)) | ||
| 563 | return inode; | ||
| 564 | |||
| 565 | err = nilfs_init_gcinode(inode); | ||
| 491 | if (unlikely(err)) { | 566 | if (unlikely(err)) { |
| 492 | iget_failed(inode); | 567 | iget_failed(inode); |
| 493 | return ERR_PTR(err); | 568 | return ERR_PTR(err); |
| @@ -528,21 +603,20 @@ void nilfs_update_inode(struct inode *inode, struct buffer_head *ibh) | |||
| 528 | { | 603 | { |
| 529 | ino_t ino = inode->i_ino; | 604 | ino_t ino = inode->i_ino; |
| 530 | struct nilfs_inode_info *ii = NILFS_I(inode); | 605 | struct nilfs_inode_info *ii = NILFS_I(inode); |
| 531 | struct super_block *sb = inode->i_sb; | 606 | struct inode *ifile = ii->i_root->ifile; |
| 532 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | ||
| 533 | struct nilfs_inode *raw_inode; | 607 | struct nilfs_inode *raw_inode; |
| 534 | 608 | ||
| 535 | raw_inode = nilfs_ifile_map_inode(sbi->s_ifile, ino, ibh); | 609 | raw_inode = nilfs_ifile_map_inode(ifile, ino, ibh); |
| 536 | 610 | ||
| 537 | if (test_and_clear_bit(NILFS_I_NEW, &ii->i_state)) | 611 | if (test_and_clear_bit(NILFS_I_NEW, &ii->i_state)) |
| 538 | memset(raw_inode, 0, NILFS_MDT(sbi->s_ifile)->mi_entry_size); | 612 | memset(raw_inode, 0, NILFS_MDT(ifile)->mi_entry_size); |
| 539 | set_bit(NILFS_I_INODE_DIRTY, &ii->i_state); | 613 | set_bit(NILFS_I_INODE_DIRTY, &ii->i_state); |
| 540 | 614 | ||
| 541 | nilfs_write_inode_common(inode, raw_inode, 0); | 615 | nilfs_write_inode_common(inode, raw_inode, 0); |
| 542 | /* XXX: call with has_bmap = 0 is a workaround to avoid | 616 | /* XXX: call with has_bmap = 0 is a workaround to avoid |
| 543 | deadlock of bmap. This delays update of i_bmap to just | 617 | deadlock of bmap. This delays update of i_bmap to just |
| 544 | before writing */ | 618 | before writing */ |
| 545 | nilfs_ifile_unmap_inode(sbi->s_ifile, ino, ibh); | 619 | nilfs_ifile_unmap_inode(ifile, ino, ibh); |
| 546 | } | 620 | } |
| 547 | 621 | ||
| 548 | #define NILFS_MAX_TRUNCATE_BLOCKS 16384 /* 64MB for 4KB block */ | 622 | #define NILFS_MAX_TRUNCATE_BLOCKS 16384 /* 64MB for 4KB block */ |
| @@ -617,6 +691,7 @@ void nilfs_truncate(struct inode *inode) | |||
| 617 | static void nilfs_clear_inode(struct inode *inode) | 691 | static void nilfs_clear_inode(struct inode *inode) |
| 618 | { | 692 | { |
| 619 | struct nilfs_inode_info *ii = NILFS_I(inode); | 693 | struct nilfs_inode_info *ii = NILFS_I(inode); |
| 694 | struct nilfs_mdt_info *mdi = NILFS_MDT(inode); | ||
| 620 | 695 | ||
| 621 | /* | 696 | /* |
| 622 | * Free resources allocated in nilfs_read_inode(), here. | 697 | * Free resources allocated in nilfs_read_inode(), here. |
| @@ -625,10 +700,16 @@ static void nilfs_clear_inode(struct inode *inode) | |||
| 625 | brelse(ii->i_bh); | 700 | brelse(ii->i_bh); |
| 626 | ii->i_bh = NULL; | 701 | ii->i_bh = NULL; |
| 627 | 702 | ||
| 703 | if (mdi && mdi->mi_palloc_cache) | ||
| 704 | nilfs_palloc_destroy_cache(inode); | ||
| 705 | |||
| 628 | if (test_bit(NILFS_I_BMAP, &ii->i_state)) | 706 | if (test_bit(NILFS_I_BMAP, &ii->i_state)) |
| 629 | nilfs_bmap_clear(ii->i_bmap); | 707 | nilfs_bmap_clear(ii->i_bmap); |
| 630 | 708 | ||
| 631 | nilfs_btnode_cache_clear(&ii->i_btnode_cache); | 709 | nilfs_btnode_cache_clear(&ii->i_btnode_cache); |
| 710 | |||
| 711 | if (ii->i_root && inode->i_ino == NILFS_ROOT_INO) | ||
| 712 | nilfs_put_root(ii->i_root); | ||
| 632 | } | 713 | } |
| 633 | 714 | ||
| 634 | void nilfs_evict_inode(struct inode *inode) | 715 | void nilfs_evict_inode(struct inode *inode) |
| @@ -637,7 +718,7 @@ void nilfs_evict_inode(struct inode *inode) | |||
| 637 | struct super_block *sb = inode->i_sb; | 718 | struct super_block *sb = inode->i_sb; |
| 638 | struct nilfs_inode_info *ii = NILFS_I(inode); | 719 | struct nilfs_inode_info *ii = NILFS_I(inode); |
| 639 | 720 | ||
| 640 | if (inode->i_nlink || unlikely(is_bad_inode(inode))) { | 721 | if (inode->i_nlink || !ii->i_root || unlikely(is_bad_inode(inode))) { |
| 641 | if (inode->i_data.nrpages) | 722 | if (inode->i_data.nrpages) |
| 642 | truncate_inode_pages(&inode->i_data, 0); | 723 | truncate_inode_pages(&inode->i_data, 0); |
| 643 | end_writeback(inode); | 724 | end_writeback(inode); |
| @@ -649,12 +730,16 @@ void nilfs_evict_inode(struct inode *inode) | |||
| 649 | if (inode->i_data.nrpages) | 730 | if (inode->i_data.nrpages) |
| 650 | truncate_inode_pages(&inode->i_data, 0); | 731 | truncate_inode_pages(&inode->i_data, 0); |
| 651 | 732 | ||
| 733 | /* TODO: some of the following operations may fail. */ | ||
| 652 | nilfs_truncate_bmap(ii, 0); | 734 | nilfs_truncate_bmap(ii, 0); |
| 653 | nilfs_mark_inode_dirty(inode); | 735 | nilfs_mark_inode_dirty(inode); |
| 654 | end_writeback(inode); | 736 | end_writeback(inode); |
| 737 | |||
| 738 | nilfs_ifile_delete_inode(ii->i_root->ifile, inode->i_ino); | ||
| 739 | atomic_dec(&ii->i_root->inodes_count); | ||
| 740 | |||
| 655 | nilfs_clear_inode(inode); | 741 | nilfs_clear_inode(inode); |
| 656 | nilfs_free_inode(inode); | 742 | |
| 657 | /* nilfs_free_inode() marks inode buffer dirty */ | ||
| 658 | if (IS_SYNC(inode)) | 743 | if (IS_SYNC(inode)) |
| 659 | nilfs_set_transaction_flag(NILFS_TI_SYNC); | 744 | nilfs_set_transaction_flag(NILFS_TI_SYNC); |
| 660 | nilfs_transaction_commit(sb); | 745 | nilfs_transaction_commit(sb); |
| @@ -700,6 +785,17 @@ out_err: | |||
| 700 | return err; | 785 | return err; |
| 701 | } | 786 | } |
| 702 | 787 | ||
| 788 | int nilfs_permission(struct inode *inode, int mask) | ||
| 789 | { | ||
| 790 | struct nilfs_root *root = NILFS_I(inode)->i_root; | ||
| 791 | |||
| 792 | if ((mask & MAY_WRITE) && root && | ||
| 793 | root->cno != NILFS_CPTREE_CURRENT_CNO) | ||
| 794 | return -EROFS; /* snapshot is not writable */ | ||
| 795 | |||
| 796 | return generic_permission(inode, mask, NULL); | ||
| 797 | } | ||
| 798 | |||
| 703 | int nilfs_load_inode_block(struct nilfs_sb_info *sbi, struct inode *inode, | 799 | int nilfs_load_inode_block(struct nilfs_sb_info *sbi, struct inode *inode, |
| 704 | struct buffer_head **pbh) | 800 | struct buffer_head **pbh) |
| 705 | { | 801 | { |
| @@ -709,8 +805,8 @@ int nilfs_load_inode_block(struct nilfs_sb_info *sbi, struct inode *inode, | |||
| 709 | spin_lock(&sbi->s_inode_lock); | 805 | spin_lock(&sbi->s_inode_lock); |
| 710 | if (ii->i_bh == NULL) { | 806 | if (ii->i_bh == NULL) { |
| 711 | spin_unlock(&sbi->s_inode_lock); | 807 | spin_unlock(&sbi->s_inode_lock); |
| 712 | err = nilfs_ifile_get_inode_block(sbi->s_ifile, inode->i_ino, | 808 | err = nilfs_ifile_get_inode_block(ii->i_root->ifile, |
| 713 | pbh); | 809 | inode->i_ino, pbh); |
| 714 | if (unlikely(err)) | 810 | if (unlikely(err)) |
| 715 | return err; | 811 | return err; |
| 716 | spin_lock(&sbi->s_inode_lock); | 812 | spin_lock(&sbi->s_inode_lock); |
| @@ -790,7 +886,7 @@ int nilfs_mark_inode_dirty(struct inode *inode) | |||
| 790 | } | 886 | } |
| 791 | nilfs_update_inode(inode, ibh); | 887 | nilfs_update_inode(inode, ibh); |
| 792 | nilfs_mdt_mark_buffer_dirty(ibh); | 888 | nilfs_mdt_mark_buffer_dirty(ibh); |
| 793 | nilfs_mdt_mark_dirty(sbi->s_ifile); | 889 | nilfs_mdt_mark_dirty(NILFS_I(inode)->i_root->ifile); |
| 794 | brelse(ibh); | 890 | brelse(ibh); |
| 795 | return 0; | 891 | return 0; |
| 796 | } | 892 | } |
| @@ -808,6 +904,7 @@ int nilfs_mark_inode_dirty(struct inode *inode) | |||
| 808 | void nilfs_dirty_inode(struct inode *inode) | 904 | void nilfs_dirty_inode(struct inode *inode) |
| 809 | { | 905 | { |
| 810 | struct nilfs_transaction_info ti; | 906 | struct nilfs_transaction_info ti; |
| 907 | struct nilfs_mdt_info *mdi = NILFS_MDT(inode); | ||
| 811 | 908 | ||
| 812 | if (is_bad_inode(inode)) { | 909 | if (is_bad_inode(inode)) { |
| 813 | nilfs_warning(inode->i_sb, __func__, | 910 | nilfs_warning(inode->i_sb, __func__, |
| @@ -815,6 +912,10 @@ void nilfs_dirty_inode(struct inode *inode) | |||
| 815 | dump_stack(); | 912 | dump_stack(); |
| 816 | return; | 913 | return; |
| 817 | } | 914 | } |
| 915 | if (mdi) { | ||
| 916 | nilfs_mdt_mark_dirty(inode); | ||
| 917 | return; | ||
| 918 | } | ||
| 818 | nilfs_transaction_begin(inode->i_sb, &ti, 0); | 919 | nilfs_transaction_begin(inode->i_sb, &ti, 0); |
| 819 | nilfs_mark_inode_dirty(inode); | 920 | nilfs_mark_inode_dirty(inode); |
| 820 | nilfs_transaction_commit(inode->i_sb); /* never fails */ | 921 | nilfs_transaction_commit(inode->i_sb); /* never fails */ |
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 0442ee3b394f..3e90f86d5bfe 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c | |||
| @@ -117,7 +117,7 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, | |||
| 117 | if (copy_from_user(&cpmode, argp, sizeof(cpmode))) | 117 | if (copy_from_user(&cpmode, argp, sizeof(cpmode))) |
| 118 | goto out; | 118 | goto out; |
| 119 | 119 | ||
| 120 | mutex_lock(&nilfs->ns_mount_mutex); | 120 | down_read(&inode->i_sb->s_umount); |
| 121 | 121 | ||
| 122 | nilfs_transaction_begin(inode->i_sb, &ti, 0); | 122 | nilfs_transaction_begin(inode->i_sb, &ti, 0); |
| 123 | ret = nilfs_cpfile_change_cpmode( | 123 | ret = nilfs_cpfile_change_cpmode( |
| @@ -127,7 +127,7 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, | |||
| 127 | else | 127 | else |
| 128 | nilfs_transaction_commit(inode->i_sb); /* never fails */ | 128 | nilfs_transaction_commit(inode->i_sb); /* never fails */ |
| 129 | 129 | ||
| 130 | mutex_unlock(&nilfs->ns_mount_mutex); | 130 | up_read(&inode->i_sb->s_umount); |
| 131 | out: | 131 | out: |
| 132 | mnt_drop_write(filp->f_path.mnt); | 132 | mnt_drop_write(filp->f_path.mnt); |
| 133 | return ret; | 133 | return ret; |
| @@ -333,7 +333,7 @@ static int nilfs_ioctl_move_inode_block(struct inode *inode, | |||
| 333 | return 0; | 333 | return 0; |
| 334 | } | 334 | } |
| 335 | 335 | ||
| 336 | static int nilfs_ioctl_move_blocks(struct the_nilfs *nilfs, | 336 | static int nilfs_ioctl_move_blocks(struct super_block *sb, |
| 337 | struct nilfs_argv *argv, void *buf) | 337 | struct nilfs_argv *argv, void *buf) |
| 338 | { | 338 | { |
| 339 | size_t nmembs = argv->v_nmembs; | 339 | size_t nmembs = argv->v_nmembs; |
| @@ -348,7 +348,7 @@ static int nilfs_ioctl_move_blocks(struct the_nilfs *nilfs, | |||
| 348 | for (i = 0, vdesc = buf; i < nmembs; ) { | 348 | for (i = 0, vdesc = buf; i < nmembs; ) { |
| 349 | ino = vdesc->vd_ino; | 349 | ino = vdesc->vd_ino; |
| 350 | cno = vdesc->vd_cno; | 350 | cno = vdesc->vd_cno; |
| 351 | inode = nilfs_gc_iget(nilfs, ino, cno); | 351 | inode = nilfs_iget_for_gc(sb, ino, cno); |
| 352 | if (unlikely(inode == NULL)) { | 352 | if (unlikely(inode == NULL)) { |
| 353 | ret = -ENOMEM; | 353 | ret = -ENOMEM; |
| 354 | goto failed; | 354 | goto failed; |
| @@ -356,11 +356,15 @@ static int nilfs_ioctl_move_blocks(struct the_nilfs *nilfs, | |||
| 356 | do { | 356 | do { |
| 357 | ret = nilfs_ioctl_move_inode_block(inode, vdesc, | 357 | ret = nilfs_ioctl_move_inode_block(inode, vdesc, |
| 358 | &buffers); | 358 | &buffers); |
| 359 | if (unlikely(ret < 0)) | 359 | if (unlikely(ret < 0)) { |
| 360 | iput(inode); | ||
| 360 | goto failed; | 361 | goto failed; |
| 362 | } | ||
| 361 | vdesc++; | 363 | vdesc++; |
| 362 | } while (++i < nmembs && | 364 | } while (++i < nmembs && |
| 363 | vdesc->vd_ino == ino && vdesc->vd_cno == cno); | 365 | vdesc->vd_ino == ino && vdesc->vd_cno == cno); |
| 366 | |||
| 367 | iput(inode); /* The inode still remains in GC inode list */ | ||
| 364 | } | 368 | } |
| 365 | 369 | ||
| 366 | list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) { | 370 | list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) { |
| @@ -566,7 +570,7 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, | |||
| 566 | } | 570 | } |
| 567 | 571 | ||
| 568 | /* | 572 | /* |
| 569 | * nilfs_ioctl_move_blocks() will call nilfs_gc_iget(), | 573 | * nilfs_ioctl_move_blocks() will call nilfs_iget_for_gc(), |
| 570 | * which will operates an inode list without blocking. | 574 | * which will operates an inode list without blocking. |
| 571 | * To protect the list from concurrent operations, | 575 | * To protect the list from concurrent operations, |
| 572 | * nilfs_ioctl_move_blocks should be atomic operation. | 576 | * nilfs_ioctl_move_blocks should be atomic operation. |
| @@ -576,15 +580,16 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, | |||
| 576 | goto out_free; | 580 | goto out_free; |
| 577 | } | 581 | } |
| 578 | 582 | ||
| 579 | ret = nilfs_ioctl_move_blocks(nilfs, &argv[0], kbufs[0]); | 583 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); |
| 584 | |||
| 585 | ret = nilfs_ioctl_move_blocks(inode->i_sb, &argv[0], kbufs[0]); | ||
| 580 | if (ret < 0) | 586 | if (ret < 0) |
| 581 | printk(KERN_ERR "NILFS: GC failed during preparation: " | 587 | printk(KERN_ERR "NILFS: GC failed during preparation: " |
| 582 | "cannot read source blocks: err=%d\n", ret); | 588 | "cannot read source blocks: err=%d\n", ret); |
| 583 | else | 589 | else |
| 584 | ret = nilfs_clean_segments(inode->i_sb, argv, kbufs); | 590 | ret = nilfs_clean_segments(inode->i_sb, argv, kbufs); |
| 585 | 591 | ||
| 586 | if (ret < 0) | 592 | nilfs_remove_all_gcinodes(nilfs); |
| 587 | nilfs_remove_all_gcinode(nilfs); | ||
| 588 | clear_nilfs_gc_running(nilfs); | 593 | clear_nilfs_gc_running(nilfs); |
| 589 | 594 | ||
| 590 | out_free: | 595 | out_free: |
diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c index d01aff4957d9..39a5b84e2c9f 100644 --- a/fs/nilfs2/mdt.c +++ b/fs/nilfs2/mdt.c | |||
| @@ -36,7 +36,6 @@ | |||
| 36 | 36 | ||
| 37 | #define NILFS_MDT_MAX_RA_BLOCKS (16 - 1) | 37 | #define NILFS_MDT_MAX_RA_BLOCKS (16 - 1) |
| 38 | 38 | ||
| 39 | #define INIT_UNUSED_INODE_FIELDS | ||
| 40 | 39 | ||
| 41 | static int | 40 | static int |
| 42 | nilfs_mdt_insert_new_block(struct inode *inode, unsigned long block, | 41 | nilfs_mdt_insert_new_block(struct inode *inode, unsigned long block, |
| @@ -78,25 +77,11 @@ static int nilfs_mdt_create_block(struct inode *inode, unsigned long block, | |||
| 78 | struct buffer_head *, | 77 | struct buffer_head *, |
| 79 | void *)) | 78 | void *)) |
| 80 | { | 79 | { |
| 81 | struct the_nilfs *nilfs = NILFS_MDT(inode)->mi_nilfs; | ||
| 82 | struct super_block *sb = inode->i_sb; | 80 | struct super_block *sb = inode->i_sb; |
| 83 | struct nilfs_transaction_info ti; | 81 | struct nilfs_transaction_info ti; |
| 84 | struct buffer_head *bh; | 82 | struct buffer_head *bh; |
| 85 | int err; | 83 | int err; |
| 86 | 84 | ||
| 87 | if (!sb) { | ||
| 88 | /* | ||
| 89 | * Make sure this function is not called from any | ||
| 90 | * read-only context. | ||
| 91 | */ | ||
| 92 | if (!nilfs->ns_writer) { | ||
| 93 | WARN_ON(1); | ||
| 94 | err = -EROFS; | ||
| 95 | goto out; | ||
| 96 | } | ||
| 97 | sb = nilfs->ns_writer->s_super; | ||
| 98 | } | ||
| 99 | |||
| 100 | nilfs_transaction_begin(sb, &ti, 0); | 85 | nilfs_transaction_begin(sb, &ti, 0); |
| 101 | 86 | ||
| 102 | err = -ENOMEM; | 87 | err = -ENOMEM; |
| @@ -112,7 +97,7 @@ static int nilfs_mdt_create_block(struct inode *inode, unsigned long block, | |||
| 112 | if (buffer_uptodate(bh)) | 97 | if (buffer_uptodate(bh)) |
| 113 | goto failed_bh; | 98 | goto failed_bh; |
| 114 | 99 | ||
| 115 | bh->b_bdev = nilfs->ns_bdev; | 100 | bh->b_bdev = sb->s_bdev; |
| 116 | err = nilfs_mdt_insert_new_block(inode, block, bh, init_block); | 101 | err = nilfs_mdt_insert_new_block(inode, block, bh, init_block); |
| 117 | if (likely(!err)) { | 102 | if (likely(!err)) { |
| 118 | get_bh(bh); | 103 | get_bh(bh); |
| @@ -129,7 +114,7 @@ static int nilfs_mdt_create_block(struct inode *inode, unsigned long block, | |||
| 129 | err = nilfs_transaction_commit(sb); | 114 | err = nilfs_transaction_commit(sb); |
| 130 | else | 115 | else |
| 131 | nilfs_transaction_abort(sb); | 116 | nilfs_transaction_abort(sb); |
| 132 | out: | 117 | |
| 133 | return err; | 118 | return err; |
| 134 | } | 119 | } |
| 135 | 120 | ||
| @@ -167,9 +152,7 @@ nilfs_mdt_submit_block(struct inode *inode, unsigned long blkoff, | |||
| 167 | unlock_buffer(bh); | 152 | unlock_buffer(bh); |
| 168 | goto failed_bh; | 153 | goto failed_bh; |
| 169 | } | 154 | } |
| 170 | bh->b_bdev = NILFS_MDT(inode)->mi_nilfs->ns_bdev; | 155 | map_bh(bh, inode->i_sb, (sector_t)blknum); |
| 171 | bh->b_blocknr = (sector_t)blknum; | ||
| 172 | set_buffer_mapped(bh); | ||
| 173 | 156 | ||
| 174 | bh->b_end_io = end_buffer_read_sync; | 157 | bh->b_end_io = end_buffer_read_sync; |
| 175 | get_bh(bh); | 158 | get_bh(bh); |
| @@ -398,35 +381,24 @@ int nilfs_mdt_fetch_dirty(struct inode *inode) | |||
| 398 | static int | 381 | static int |
| 399 | nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc) | 382 | nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc) |
| 400 | { | 383 | { |
| 401 | struct inode *inode = container_of(page->mapping, | 384 | struct inode *inode; |
| 402 | struct inode, i_data); | 385 | struct super_block *sb; |
| 403 | struct super_block *sb = inode->i_sb; | ||
| 404 | struct the_nilfs *nilfs = NILFS_MDT(inode)->mi_nilfs; | ||
| 405 | struct nilfs_sb_info *writer = NULL; | ||
| 406 | int err = 0; | 386 | int err = 0; |
| 407 | 387 | ||
| 408 | redirty_page_for_writepage(wbc, page); | 388 | redirty_page_for_writepage(wbc, page); |
| 409 | unlock_page(page); | 389 | unlock_page(page); |
| 410 | 390 | ||
| 411 | if (page->mapping->assoc_mapping) | 391 | inode = page->mapping->host; |
| 412 | return 0; /* Do not request flush for shadow page cache */ | 392 | if (!inode) |
| 413 | if (!sb) { | 393 | return 0; |
| 414 | down_read(&nilfs->ns_writer_sem); | 394 | |
| 415 | writer = nilfs->ns_writer; | 395 | sb = inode->i_sb; |
| 416 | if (!writer) { | ||
| 417 | up_read(&nilfs->ns_writer_sem); | ||
| 418 | return -EROFS; | ||
| 419 | } | ||
| 420 | sb = writer->s_super; | ||
| 421 | } | ||
| 422 | 396 | ||
| 423 | if (wbc->sync_mode == WB_SYNC_ALL) | 397 | if (wbc->sync_mode == WB_SYNC_ALL) |
| 424 | err = nilfs_construct_segment(sb); | 398 | err = nilfs_construct_segment(sb); |
| 425 | else if (wbc->for_reclaim) | 399 | else if (wbc->for_reclaim) |
| 426 | nilfs_flush_segment(sb, inode->i_ino); | 400 | nilfs_flush_segment(sb, inode->i_ino); |
| 427 | 401 | ||
| 428 | if (writer) | ||
| 429 | up_read(&nilfs->ns_writer_sem); | ||
| 430 | return err; | 402 | return err; |
| 431 | } | 403 | } |
| 432 | 404 | ||
| @@ -439,105 +411,27 @@ static const struct address_space_operations def_mdt_aops = { | |||
| 439 | static const struct inode_operations def_mdt_iops; | 411 | static const struct inode_operations def_mdt_iops; |
| 440 | static const struct file_operations def_mdt_fops; | 412 | static const struct file_operations def_mdt_fops; |
| 441 | 413 | ||
| 442 | /* | 414 | |
| 443 | * NILFS2 uses pseudo inodes for meta data files such as DAT, cpfile, sufile, | 415 | int nilfs_mdt_init(struct inode *inode, gfp_t gfp_mask, size_t objsz) |
| 444 | * ifile, or gcinodes. This allows the B-tree code and segment constructor | ||
| 445 | * to treat them like regular files, and this helps to simplify the | ||
| 446 | * implementation. | ||
| 447 | * On the other hand, some of the pseudo inodes have an irregular point: | ||
| 448 | * They don't have valid inode->i_sb pointer because their lifetimes are | ||
| 449 | * longer than those of the super block structs; they may continue for | ||
| 450 | * several consecutive mounts/umounts. This would need discussions. | ||
| 451 | */ | ||
| 452 | /** | ||
| 453 | * nilfs_mdt_new_common - allocate a pseudo inode for metadata file | ||
| 454 | * @nilfs: nilfs object | ||
| 455 | * @sb: super block instance the metadata file belongs to | ||
| 456 | * @ino: inode number | ||
| 457 | * @gfp_mask: gfp mask for data pages | ||
| 458 | * @objsz: size of the private object attached to inode->i_private | ||
| 459 | */ | ||
| 460 | struct inode * | ||
| 461 | nilfs_mdt_new_common(struct the_nilfs *nilfs, struct super_block *sb, | ||
| 462 | ino_t ino, gfp_t gfp_mask, size_t objsz) | ||
| 463 | { | 416 | { |
| 464 | struct inode *inode = nilfs_alloc_inode_common(nilfs); | 417 | struct nilfs_mdt_info *mi; |
| 465 | 418 | ||
| 466 | if (!inode) | 419 | mi = kzalloc(max(sizeof(*mi), objsz), GFP_NOFS); |
| 467 | return NULL; | 420 | if (!mi) |
| 468 | else { | 421 | return -ENOMEM; |
| 469 | struct address_space * const mapping = &inode->i_data; | ||
| 470 | struct nilfs_mdt_info *mi; | ||
| 471 | |||
| 472 | mi = kzalloc(max(sizeof(*mi), objsz), GFP_NOFS); | ||
| 473 | if (!mi) { | ||
| 474 | nilfs_destroy_inode(inode); | ||
| 475 | return NULL; | ||
| 476 | } | ||
| 477 | mi->mi_nilfs = nilfs; | ||
| 478 | init_rwsem(&mi->mi_sem); | ||
| 479 | |||
| 480 | inode->i_sb = sb; /* sb may be NULL for some meta data files */ | ||
| 481 | inode->i_blkbits = nilfs->ns_blocksize_bits; | ||
| 482 | inode->i_flags = 0; | ||
| 483 | atomic_set(&inode->i_count, 1); | ||
| 484 | inode->i_nlink = 1; | ||
| 485 | inode->i_ino = ino; | ||
| 486 | inode->i_mode = S_IFREG; | ||
| 487 | inode->i_private = mi; | ||
| 488 | |||
| 489 | #ifdef INIT_UNUSED_INODE_FIELDS | ||
| 490 | atomic_set(&inode->i_writecount, 0); | ||
| 491 | inode->i_size = 0; | ||
| 492 | inode->i_blocks = 0; | ||
| 493 | inode->i_bytes = 0; | ||
| 494 | inode->i_generation = 0; | ||
| 495 | #ifdef CONFIG_QUOTA | ||
| 496 | memset(&inode->i_dquot, 0, sizeof(inode->i_dquot)); | ||
| 497 | #endif | ||
| 498 | inode->i_pipe = NULL; | ||
| 499 | inode->i_bdev = NULL; | ||
| 500 | inode->i_cdev = NULL; | ||
| 501 | inode->i_rdev = 0; | ||
| 502 | #ifdef CONFIG_SECURITY | ||
| 503 | inode->i_security = NULL; | ||
| 504 | #endif | ||
| 505 | inode->dirtied_when = 0; | ||
| 506 | |||
| 507 | INIT_LIST_HEAD(&inode->i_list); | ||
| 508 | INIT_LIST_HEAD(&inode->i_sb_list); | ||
| 509 | inode->i_state = 0; | ||
| 510 | #endif | ||
| 511 | |||
| 512 | spin_lock_init(&inode->i_lock); | ||
| 513 | mutex_init(&inode->i_mutex); | ||
| 514 | init_rwsem(&inode->i_alloc_sem); | ||
| 515 | |||
| 516 | mapping->host = NULL; /* instead of inode */ | ||
| 517 | mapping->flags = 0; | ||
| 518 | mapping_set_gfp_mask(mapping, gfp_mask); | ||
| 519 | mapping->assoc_mapping = NULL; | ||
| 520 | mapping->backing_dev_info = nilfs->ns_bdi; | ||
| 521 | |||
| 522 | inode->i_mapping = mapping; | ||
| 523 | } | ||
| 524 | 422 | ||
| 525 | return inode; | 423 | init_rwsem(&mi->mi_sem); |
| 526 | } | 424 | inode->i_private = mi; |
| 527 | 425 | ||
| 528 | struct inode *nilfs_mdt_new(struct the_nilfs *nilfs, struct super_block *sb, | 426 | inode->i_mode = S_IFREG; |
| 529 | ino_t ino, size_t objsz) | 427 | mapping_set_gfp_mask(inode->i_mapping, gfp_mask); |
| 530 | { | 428 | inode->i_mapping->backing_dev_info = inode->i_sb->s_bdi; |
| 531 | struct inode *inode; | ||
| 532 | |||
| 533 | inode = nilfs_mdt_new_common(nilfs, sb, ino, NILFS_MDT_GFP, objsz); | ||
| 534 | if (!inode) | ||
| 535 | return NULL; | ||
| 536 | 429 | ||
| 537 | inode->i_op = &def_mdt_iops; | 430 | inode->i_op = &def_mdt_iops; |
| 538 | inode->i_fop = &def_mdt_fops; | 431 | inode->i_fop = &def_mdt_fops; |
| 539 | inode->i_mapping->a_ops = &def_mdt_aops; | 432 | inode->i_mapping->a_ops = &def_mdt_aops; |
| 540 | return inode; | 433 | |
| 434 | return 0; | ||
| 541 | } | 435 | } |
| 542 | 436 | ||
| 543 | void nilfs_mdt_set_entry_size(struct inode *inode, unsigned entry_size, | 437 | void nilfs_mdt_set_entry_size(struct inode *inode, unsigned entry_size, |
| @@ -550,34 +444,159 @@ void nilfs_mdt_set_entry_size(struct inode *inode, unsigned entry_size, | |||
| 550 | mi->mi_first_entry_offset = DIV_ROUND_UP(header_size, entry_size); | 444 | mi->mi_first_entry_offset = DIV_ROUND_UP(header_size, entry_size); |
| 551 | } | 445 | } |
| 552 | 446 | ||
| 553 | void nilfs_mdt_set_shadow(struct inode *orig, struct inode *shadow) | 447 | static const struct address_space_operations shadow_map_aops = { |
| 448 | .sync_page = block_sync_page, | ||
| 449 | }; | ||
| 450 | |||
| 451 | /** | ||
| 452 | * nilfs_mdt_setup_shadow_map - setup shadow map and bind it to metadata file | ||
| 453 | * @inode: inode of the metadata file | ||
| 454 | * @shadow: shadow mapping | ||
| 455 | */ | ||
| 456 | int nilfs_mdt_setup_shadow_map(struct inode *inode, | ||
| 457 | struct nilfs_shadow_map *shadow) | ||
| 554 | { | 458 | { |
| 555 | shadow->i_mapping->assoc_mapping = orig->i_mapping; | 459 | struct nilfs_mdt_info *mi = NILFS_MDT(inode); |
| 556 | NILFS_I(shadow)->i_btnode_cache.assoc_mapping = | 460 | struct backing_dev_info *bdi = inode->i_sb->s_bdi; |
| 557 | &NILFS_I(orig)->i_btnode_cache; | 461 | |
| 462 | INIT_LIST_HEAD(&shadow->frozen_buffers); | ||
| 463 | nilfs_mapping_init_once(&shadow->frozen_data); | ||
| 464 | nilfs_mapping_init(&shadow->frozen_data, bdi, &shadow_map_aops); | ||
| 465 | nilfs_mapping_init_once(&shadow->frozen_btnodes); | ||
| 466 | nilfs_mapping_init(&shadow->frozen_btnodes, bdi, &shadow_map_aops); | ||
| 467 | mi->mi_shadow = shadow; | ||
| 468 | return 0; | ||
| 558 | } | 469 | } |
| 559 | 470 | ||
| 560 | static void nilfs_mdt_clear(struct inode *inode) | 471 | /** |
| 472 | * nilfs_mdt_save_to_shadow_map - copy bmap and dirty pages to shadow map | ||
| 473 | * @inode: inode of the metadata file | ||
| 474 | */ | ||
| 475 | int nilfs_mdt_save_to_shadow_map(struct inode *inode) | ||
| 561 | { | 476 | { |
| 477 | struct nilfs_mdt_info *mi = NILFS_MDT(inode); | ||
| 562 | struct nilfs_inode_info *ii = NILFS_I(inode); | 478 | struct nilfs_inode_info *ii = NILFS_I(inode); |
| 479 | struct nilfs_shadow_map *shadow = mi->mi_shadow; | ||
| 480 | int ret; | ||
| 563 | 481 | ||
| 564 | invalidate_mapping_pages(inode->i_mapping, 0, -1); | 482 | ret = nilfs_copy_dirty_pages(&shadow->frozen_data, inode->i_mapping); |
| 565 | truncate_inode_pages(inode->i_mapping, 0); | 483 | if (ret) |
| 484 | goto out; | ||
| 485 | |||
| 486 | ret = nilfs_copy_dirty_pages(&shadow->frozen_btnodes, | ||
| 487 | &ii->i_btnode_cache); | ||
| 488 | if (ret) | ||
| 489 | goto out; | ||
| 566 | 490 | ||
| 567 | if (test_bit(NILFS_I_BMAP, &ii->i_state)) | 491 | nilfs_bmap_save(ii->i_bmap, &shadow->bmap_store); |
| 568 | nilfs_bmap_clear(ii->i_bmap); | 492 | out: |
| 569 | nilfs_btnode_cache_clear(&ii->i_btnode_cache); | 493 | return ret; |
| 570 | } | 494 | } |
| 571 | 495 | ||
| 572 | void nilfs_mdt_destroy(struct inode *inode) | 496 | int nilfs_mdt_freeze_buffer(struct inode *inode, struct buffer_head *bh) |
| 573 | { | 497 | { |
| 574 | struct nilfs_mdt_info *mdi = NILFS_MDT(inode); | 498 | struct nilfs_shadow_map *shadow = NILFS_MDT(inode)->mi_shadow; |
| 499 | struct buffer_head *bh_frozen; | ||
| 500 | struct page *page; | ||
| 501 | int blkbits = inode->i_blkbits; | ||
| 502 | int ret = -ENOMEM; | ||
| 503 | |||
| 504 | page = grab_cache_page(&shadow->frozen_data, bh->b_page->index); | ||
| 505 | if (!page) | ||
| 506 | return ret; | ||
| 507 | |||
| 508 | if (!page_has_buffers(page)) | ||
| 509 | create_empty_buffers(page, 1 << blkbits, 0); | ||
| 510 | |||
| 511 | bh_frozen = nilfs_page_get_nth_block(page, bh_offset(bh) >> blkbits); | ||
| 512 | if (bh_frozen) { | ||
| 513 | if (!buffer_uptodate(bh_frozen)) | ||
| 514 | nilfs_copy_buffer(bh_frozen, bh); | ||
| 515 | if (list_empty(&bh_frozen->b_assoc_buffers)) { | ||
| 516 | list_add_tail(&bh_frozen->b_assoc_buffers, | ||
| 517 | &shadow->frozen_buffers); | ||
| 518 | set_buffer_nilfs_redirected(bh); | ||
| 519 | } else { | ||
| 520 | brelse(bh_frozen); /* already frozen */ | ||
| 521 | } | ||
| 522 | ret = 0; | ||
| 523 | } | ||
| 524 | unlock_page(page); | ||
| 525 | page_cache_release(page); | ||
| 526 | return ret; | ||
| 527 | } | ||
| 528 | |||
| 529 | struct buffer_head * | ||
| 530 | nilfs_mdt_get_frozen_buffer(struct inode *inode, struct buffer_head *bh) | ||
| 531 | { | ||
| 532 | struct nilfs_shadow_map *shadow = NILFS_MDT(inode)->mi_shadow; | ||
| 533 | struct buffer_head *bh_frozen = NULL; | ||
| 534 | struct page *page; | ||
| 535 | int n; | ||
| 536 | |||
| 537 | page = find_lock_page(&shadow->frozen_data, bh->b_page->index); | ||
| 538 | if (page) { | ||
| 539 | if (page_has_buffers(page)) { | ||
| 540 | n = bh_offset(bh) >> inode->i_blkbits; | ||
| 541 | bh_frozen = nilfs_page_get_nth_block(page, n); | ||
| 542 | } | ||
| 543 | unlock_page(page); | ||
| 544 | page_cache_release(page); | ||
| 545 | } | ||
| 546 | return bh_frozen; | ||
| 547 | } | ||
| 548 | |||
| 549 | static void nilfs_release_frozen_buffers(struct nilfs_shadow_map *shadow) | ||
| 550 | { | ||
| 551 | struct list_head *head = &shadow->frozen_buffers; | ||
| 552 | struct buffer_head *bh; | ||
| 553 | |||
| 554 | while (!list_empty(head)) { | ||
| 555 | bh = list_first_entry(head, struct buffer_head, | ||
| 556 | b_assoc_buffers); | ||
| 557 | list_del_init(&bh->b_assoc_buffers); | ||
| 558 | brelse(bh); /* drop ref-count to make it releasable */ | ||
| 559 | } | ||
| 560 | } | ||
| 561 | |||
| 562 | /** | ||
| 563 | * nilfs_mdt_restore_from_shadow_map - restore dirty pages and bmap state | ||
| 564 | * @inode: inode of the metadata file | ||
| 565 | */ | ||
| 566 | void nilfs_mdt_restore_from_shadow_map(struct inode *inode) | ||
| 567 | { | ||
| 568 | struct nilfs_mdt_info *mi = NILFS_MDT(inode); | ||
| 569 | struct nilfs_inode_info *ii = NILFS_I(inode); | ||
| 570 | struct nilfs_shadow_map *shadow = mi->mi_shadow; | ||
| 571 | |||
| 572 | down_write(&mi->mi_sem); | ||
| 575 | 573 | ||
| 576 | if (mdi->mi_palloc_cache) | 574 | if (mi->mi_palloc_cache) |
| 577 | nilfs_palloc_destroy_cache(inode); | 575 | nilfs_palloc_clear_cache(inode); |
| 578 | nilfs_mdt_clear(inode); | 576 | |
| 577 | nilfs_clear_dirty_pages(inode->i_mapping); | ||
| 578 | nilfs_copy_back_pages(inode->i_mapping, &shadow->frozen_data); | ||
| 579 | |||
| 580 | nilfs_clear_dirty_pages(&ii->i_btnode_cache); | ||
| 581 | nilfs_copy_back_pages(&ii->i_btnode_cache, &shadow->frozen_btnodes); | ||
| 582 | |||
| 583 | nilfs_bmap_restore(ii->i_bmap, &shadow->bmap_store); | ||
| 584 | |||
| 585 | up_write(&mi->mi_sem); | ||
| 586 | } | ||
| 587 | |||
| 588 | /** | ||
| 589 | * nilfs_mdt_clear_shadow_map - truncate pages in shadow map caches | ||
| 590 | * @inode: inode of the metadata file | ||
| 591 | */ | ||
| 592 | void nilfs_mdt_clear_shadow_map(struct inode *inode) | ||
| 593 | { | ||
| 594 | struct nilfs_mdt_info *mi = NILFS_MDT(inode); | ||
| 595 | struct nilfs_shadow_map *shadow = mi->mi_shadow; | ||
| 579 | 596 | ||
| 580 | kfree(mdi->mi_bgl); /* kfree(NULL) is safe */ | 597 | down_write(&mi->mi_sem); |
| 581 | kfree(mdi); | 598 | nilfs_release_frozen_buffers(shadow); |
| 582 | nilfs_destroy_inode(inode); | 599 | truncate_inode_pages(&shadow->frozen_data, 0); |
| 600 | truncate_inode_pages(&shadow->frozen_btnodes, 0); | ||
| 601 | up_write(&mi->mi_sem); | ||
| 583 | } | 602 | } |
diff --git a/fs/nilfs2/mdt.h b/fs/nilfs2/mdt.h index 6c4bbb0470fc..b13734bf3521 100644 --- a/fs/nilfs2/mdt.h +++ b/fs/nilfs2/mdt.h | |||
| @@ -28,26 +28,33 @@ | |||
| 28 | #include "nilfs.h" | 28 | #include "nilfs.h" |
| 29 | #include "page.h" | 29 | #include "page.h" |
| 30 | 30 | ||
| 31 | struct nilfs_shadow_map { | ||
| 32 | struct nilfs_bmap_store bmap_store; | ||
| 33 | struct address_space frozen_data; | ||
| 34 | struct address_space frozen_btnodes; | ||
| 35 | struct list_head frozen_buffers; | ||
| 36 | }; | ||
| 37 | |||
| 31 | /** | 38 | /** |
| 32 | * struct nilfs_mdt_info - on-memory private data of meta data files | 39 | * struct nilfs_mdt_info - on-memory private data of meta data files |
| 33 | * @mi_nilfs: back pointer to the_nilfs struct | ||
| 34 | * @mi_sem: reader/writer semaphore for meta data operations | 40 | * @mi_sem: reader/writer semaphore for meta data operations |
| 35 | * @mi_bgl: per-blockgroup locking | 41 | * @mi_bgl: per-blockgroup locking |
| 36 | * @mi_entry_size: size of an entry | 42 | * @mi_entry_size: size of an entry |
| 37 | * @mi_first_entry_offset: offset to the first entry | 43 | * @mi_first_entry_offset: offset to the first entry |
| 38 | * @mi_entries_per_block: number of entries in a block | 44 | * @mi_entries_per_block: number of entries in a block |
| 39 | * @mi_palloc_cache: persistent object allocator cache | 45 | * @mi_palloc_cache: persistent object allocator cache |
| 46 | * @mi_shadow: shadow of bmap and page caches | ||
| 40 | * @mi_blocks_per_group: number of blocks in a group | 47 | * @mi_blocks_per_group: number of blocks in a group |
| 41 | * @mi_blocks_per_desc_block: number of blocks per descriptor block | 48 | * @mi_blocks_per_desc_block: number of blocks per descriptor block |
| 42 | */ | 49 | */ |
| 43 | struct nilfs_mdt_info { | 50 | struct nilfs_mdt_info { |
| 44 | struct the_nilfs *mi_nilfs; | ||
| 45 | struct rw_semaphore mi_sem; | 51 | struct rw_semaphore mi_sem; |
| 46 | struct blockgroup_lock *mi_bgl; | 52 | struct blockgroup_lock *mi_bgl; |
| 47 | unsigned mi_entry_size; | 53 | unsigned mi_entry_size; |
| 48 | unsigned mi_first_entry_offset; | 54 | unsigned mi_first_entry_offset; |
| 49 | unsigned long mi_entries_per_block; | 55 | unsigned long mi_entries_per_block; |
| 50 | struct nilfs_palloc_cache *mi_palloc_cache; | 56 | struct nilfs_palloc_cache *mi_palloc_cache; |
| 57 | struct nilfs_shadow_map *mi_shadow; | ||
| 51 | unsigned long mi_blocks_per_group; | 58 | unsigned long mi_blocks_per_group; |
| 52 | unsigned long mi_blocks_per_desc_block; | 59 | unsigned long mi_blocks_per_desc_block; |
| 53 | }; | 60 | }; |
| @@ -59,9 +66,7 @@ static inline struct nilfs_mdt_info *NILFS_MDT(const struct inode *inode) | |||
| 59 | 66 | ||
| 60 | static inline struct the_nilfs *NILFS_I_NILFS(struct inode *inode) | 67 | static inline struct the_nilfs *NILFS_I_NILFS(struct inode *inode) |
| 61 | { | 68 | { |
| 62 | struct super_block *sb = inode->i_sb; | 69 | return NILFS_SB(inode->i_sb)->s_nilfs; |
| 63 | |||
| 64 | return sb ? NILFS_SB(sb)->s_nilfs : NILFS_MDT(inode)->mi_nilfs; | ||
| 65 | } | 70 | } |
| 66 | 71 | ||
| 67 | /* Default GFP flags using highmem */ | 72 | /* Default GFP flags using highmem */ |
| @@ -76,14 +81,17 @@ int nilfs_mdt_forget_block(struct inode *, unsigned long); | |||
| 76 | int nilfs_mdt_mark_block_dirty(struct inode *, unsigned long); | 81 | int nilfs_mdt_mark_block_dirty(struct inode *, unsigned long); |
| 77 | int nilfs_mdt_fetch_dirty(struct inode *); | 82 | int nilfs_mdt_fetch_dirty(struct inode *); |
| 78 | 83 | ||
| 79 | struct inode *nilfs_mdt_new(struct the_nilfs *, struct super_block *, ino_t, | 84 | int nilfs_mdt_init(struct inode *inode, gfp_t gfp_mask, size_t objsz); |
| 80 | size_t); | ||
| 81 | struct inode *nilfs_mdt_new_common(struct the_nilfs *, struct super_block *, | ||
| 82 | ino_t, gfp_t, size_t); | ||
| 83 | void nilfs_mdt_destroy(struct inode *); | ||
| 84 | void nilfs_mdt_set_entry_size(struct inode *, unsigned, unsigned); | 85 | void nilfs_mdt_set_entry_size(struct inode *, unsigned, unsigned); |
| 85 | void nilfs_mdt_set_shadow(struct inode *, struct inode *); | ||
| 86 | 86 | ||
| 87 | int nilfs_mdt_setup_shadow_map(struct inode *inode, | ||
| 88 | struct nilfs_shadow_map *shadow); | ||
| 89 | int nilfs_mdt_save_to_shadow_map(struct inode *inode); | ||
| 90 | void nilfs_mdt_restore_from_shadow_map(struct inode *inode); | ||
| 91 | void nilfs_mdt_clear_shadow_map(struct inode *inode); | ||
| 92 | int nilfs_mdt_freeze_buffer(struct inode *inode, struct buffer_head *bh); | ||
| 93 | struct buffer_head *nilfs_mdt_get_frozen_buffer(struct inode *inode, | ||
| 94 | struct buffer_head *bh); | ||
| 87 | 95 | ||
| 88 | #define nilfs_mdt_mark_buffer_dirty(bh) nilfs_mark_buffer_dirty(bh) | 96 | #define nilfs_mdt_mark_buffer_dirty(bh) nilfs_mark_buffer_dirty(bh) |
| 89 | 97 | ||
| @@ -100,7 +108,7 @@ static inline void nilfs_mdt_clear_dirty(struct inode *inode) | |||
| 100 | 108 | ||
| 101 | static inline __u64 nilfs_mdt_cno(struct inode *inode) | 109 | static inline __u64 nilfs_mdt_cno(struct inode *inode) |
| 102 | { | 110 | { |
| 103 | return NILFS_MDT(inode)->mi_nilfs->ns_cno; | 111 | return NILFS_I_NILFS(inode)->ns_cno; |
| 104 | } | 112 | } |
| 105 | 113 | ||
| 106 | #define nilfs_mdt_bgl_lock(inode, bg) \ | 114 | #define nilfs_mdt_bgl_lock(inode, bg) \ |
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c index ad6ed2cf19b4..185d1607cb00 100644 --- a/fs/nilfs2/namei.c +++ b/fs/nilfs2/namei.c | |||
| @@ -40,7 +40,11 @@ | |||
| 40 | 40 | ||
| 41 | #include <linux/pagemap.h> | 41 | #include <linux/pagemap.h> |
| 42 | #include "nilfs.h" | 42 | #include "nilfs.h" |
| 43 | #include "export.h" | ||
| 43 | 44 | ||
| 45 | #define NILFS_FID_SIZE_NON_CONNECTABLE \ | ||
| 46 | (offsetof(struct nilfs_fid, parent_gen) / 4) | ||
| 47 | #define NILFS_FID_SIZE_CONNECTABLE (sizeof(struct nilfs_fid) / 4) | ||
| 44 | 48 | ||
| 45 | static inline int nilfs_add_nondir(struct dentry *dentry, struct inode *inode) | 49 | static inline int nilfs_add_nondir(struct dentry *dentry, struct inode *inode) |
| 46 | { | 50 | { |
| @@ -70,29 +74,13 @@ nilfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | |||
| 70 | ino = nilfs_inode_by_name(dir, &dentry->d_name); | 74 | ino = nilfs_inode_by_name(dir, &dentry->d_name); |
| 71 | inode = NULL; | 75 | inode = NULL; |
| 72 | if (ino) { | 76 | if (ino) { |
| 73 | inode = nilfs_iget(dir->i_sb, ino); | 77 | inode = nilfs_iget(dir->i_sb, NILFS_I(dir)->i_root, ino); |
| 74 | if (IS_ERR(inode)) | 78 | if (IS_ERR(inode)) |
| 75 | return ERR_CAST(inode); | 79 | return ERR_CAST(inode); |
| 76 | } | 80 | } |
| 77 | return d_splice_alias(inode, dentry); | 81 | return d_splice_alias(inode, dentry); |
| 78 | } | 82 | } |
| 79 | 83 | ||
| 80 | struct dentry *nilfs_get_parent(struct dentry *child) | ||
| 81 | { | ||
| 82 | unsigned long ino; | ||
| 83 | struct inode *inode; | ||
| 84 | struct qstr dotdot = {.name = "..", .len = 2}; | ||
| 85 | |||
| 86 | ino = nilfs_inode_by_name(child->d_inode, &dotdot); | ||
| 87 | if (!ino) | ||
| 88 | return ERR_PTR(-ENOENT); | ||
| 89 | |||
| 90 | inode = nilfs_iget(child->d_inode->i_sb, ino); | ||
| 91 | if (IS_ERR(inode)) | ||
| 92 | return ERR_CAST(inode); | ||
| 93 | return d_obtain_alias(inode); | ||
| 94 | } | ||
| 95 | |||
| 96 | /* | 84 | /* |
| 97 | * By the time this is called, we already have created | 85 | * By the time this is called, we already have created |
| 98 | * the directory cache entry for the new file, but it | 86 | * the directory cache entry for the new file, but it |
| @@ -468,6 +456,115 @@ out: | |||
| 468 | return err; | 456 | return err; |
| 469 | } | 457 | } |
| 470 | 458 | ||
| 459 | /* | ||
| 460 | * Export operations | ||
| 461 | */ | ||
| 462 | static struct dentry *nilfs_get_parent(struct dentry *child) | ||
| 463 | { | ||
| 464 | unsigned long ino; | ||
| 465 | struct inode *inode; | ||
| 466 | struct qstr dotdot = {.name = "..", .len = 2}; | ||
| 467 | struct nilfs_root *root; | ||
| 468 | |||
| 469 | ino = nilfs_inode_by_name(child->d_inode, &dotdot); | ||
| 470 | if (!ino) | ||
| 471 | return ERR_PTR(-ENOENT); | ||
| 472 | |||
| 473 | root = NILFS_I(child->d_inode)->i_root; | ||
| 474 | |||
| 475 | inode = nilfs_iget(child->d_inode->i_sb, root, ino); | ||
| 476 | if (IS_ERR(inode)) | ||
| 477 | return ERR_CAST(inode); | ||
| 478 | |||
| 479 | return d_obtain_alias(inode); | ||
| 480 | } | ||
| 481 | |||
| 482 | static struct dentry *nilfs_get_dentry(struct super_block *sb, u64 cno, | ||
| 483 | u64 ino, u32 gen) | ||
| 484 | { | ||
| 485 | struct nilfs_root *root; | ||
| 486 | struct inode *inode; | ||
| 487 | |||
| 488 | if (ino < NILFS_FIRST_INO(sb) && ino != NILFS_ROOT_INO) | ||
| 489 | return ERR_PTR(-ESTALE); | ||
| 490 | |||
| 491 | root = nilfs_lookup_root(NILFS_SB(sb)->s_nilfs, cno); | ||
| 492 | if (!root) | ||
| 493 | return ERR_PTR(-ESTALE); | ||
| 494 | |||
| 495 | inode = nilfs_iget(sb, root, ino); | ||
| 496 | nilfs_put_root(root); | ||
| 497 | |||
| 498 | if (IS_ERR(inode)) | ||
| 499 | return ERR_CAST(inode); | ||
| 500 | if (gen && inode->i_generation != gen) { | ||
| 501 | iput(inode); | ||
| 502 | return ERR_PTR(-ESTALE); | ||
| 503 | } | ||
| 504 | return d_obtain_alias(inode); | ||
| 505 | } | ||
| 506 | |||
| 507 | static struct dentry *nilfs_fh_to_dentry(struct super_block *sb, struct fid *fh, | ||
| 508 | int fh_len, int fh_type) | ||
| 509 | { | ||
| 510 | struct nilfs_fid *fid = (struct nilfs_fid *)fh; | ||
| 511 | |||
| 512 | if ((fh_len != NILFS_FID_SIZE_NON_CONNECTABLE && | ||
| 513 | fh_len != NILFS_FID_SIZE_CONNECTABLE) || | ||
| 514 | (fh_type != FILEID_NILFS_WITH_PARENT && | ||
| 515 | fh_type != FILEID_NILFS_WITHOUT_PARENT)) | ||
| 516 | return NULL; | ||
| 517 | |||
| 518 | return nilfs_get_dentry(sb, fid->cno, fid->ino, fid->gen); | ||
| 519 | } | ||
| 520 | |||
| 521 | static struct dentry *nilfs_fh_to_parent(struct super_block *sb, struct fid *fh, | ||
| 522 | int fh_len, int fh_type) | ||
| 523 | { | ||
| 524 | struct nilfs_fid *fid = (struct nilfs_fid *)fh; | ||
| 525 | |||
| 526 | if (fh_len != NILFS_FID_SIZE_CONNECTABLE || | ||
| 527 | fh_type != FILEID_NILFS_WITH_PARENT) | ||
| 528 | return NULL; | ||
| 529 | |||
| 530 | return nilfs_get_dentry(sb, fid->cno, fid->parent_ino, fid->parent_gen); | ||
| 531 | } | ||
| 532 | |||
| 533 | static int nilfs_encode_fh(struct dentry *dentry, __u32 *fh, int *lenp, | ||
| 534 | int connectable) | ||
| 535 | { | ||
| 536 | struct nilfs_fid *fid = (struct nilfs_fid *)fh; | ||
| 537 | struct inode *inode = dentry->d_inode; | ||
| 538 | struct nilfs_root *root = NILFS_I(inode)->i_root; | ||
| 539 | int type; | ||
| 540 | |||
| 541 | if (*lenp < NILFS_FID_SIZE_NON_CONNECTABLE || | ||
| 542 | (connectable && *lenp < NILFS_FID_SIZE_CONNECTABLE)) | ||
| 543 | return 255; | ||
| 544 | |||
| 545 | fid->cno = root->cno; | ||
| 546 | fid->ino = inode->i_ino; | ||
| 547 | fid->gen = inode->i_generation; | ||
| 548 | |||
| 549 | if (connectable && !S_ISDIR(inode->i_mode)) { | ||
| 550 | struct inode *parent; | ||
| 551 | |||
| 552 | spin_lock(&dentry->d_lock); | ||
| 553 | parent = dentry->d_parent->d_inode; | ||
| 554 | fid->parent_ino = parent->i_ino; | ||
| 555 | fid->parent_gen = parent->i_generation; | ||
| 556 | spin_unlock(&dentry->d_lock); | ||
| 557 | |||
| 558 | type = FILEID_NILFS_WITH_PARENT; | ||
| 559 | *lenp = NILFS_FID_SIZE_CONNECTABLE; | ||
| 560 | } else { | ||
| 561 | type = FILEID_NILFS_WITHOUT_PARENT; | ||
| 562 | *lenp = NILFS_FID_SIZE_NON_CONNECTABLE; | ||
| 563 | } | ||
| 564 | |||
| 565 | return type; | ||
| 566 | } | ||
| 567 | |||
| 471 | const struct inode_operations nilfs_dir_inode_operations = { | 568 | const struct inode_operations nilfs_dir_inode_operations = { |
| 472 | .create = nilfs_create, | 569 | .create = nilfs_create, |
| 473 | .lookup = nilfs_lookup, | 570 | .lookup = nilfs_lookup, |
| @@ -491,4 +588,12 @@ const struct inode_operations nilfs_symlink_inode_operations = { | |||
| 491 | .readlink = generic_readlink, | 588 | .readlink = generic_readlink, |
| 492 | .follow_link = page_follow_link_light, | 589 | .follow_link = page_follow_link_light, |
| 493 | .put_link = page_put_link, | 590 | .put_link = page_put_link, |
| 591 | .permission = nilfs_permission, | ||
| 592 | }; | ||
| 593 | |||
| 594 | const struct export_operations nilfs_export_ops = { | ||
| 595 | .encode_fh = nilfs_encode_fh, | ||
| 596 | .fh_to_dentry = nilfs_fh_to_dentry, | ||
| 597 | .fh_to_parent = nilfs_fh_to_parent, | ||
| 598 | .get_parent = nilfs_get_parent, | ||
| 494 | }; | 599 | }; |
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index d3d54046e5f8..f7560da5a567 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h | |||
| @@ -59,6 +59,7 @@ struct nilfs_inode_info { | |||
| 59 | #endif | 59 | #endif |
| 60 | struct buffer_head *i_bh; /* i_bh contains a new or dirty | 60 | struct buffer_head *i_bh; /* i_bh contains a new or dirty |
| 61 | disk inode */ | 61 | disk inode */ |
| 62 | struct nilfs_root *i_root; | ||
| 62 | struct inode vfs_inode; | 63 | struct inode vfs_inode; |
| 63 | }; | 64 | }; |
| 64 | 65 | ||
| @@ -100,7 +101,6 @@ enum { | |||
| 100 | NILFS_I_INODE_DIRTY, /* write_inode is requested */ | 101 | NILFS_I_INODE_DIRTY, /* write_inode is requested */ |
| 101 | NILFS_I_BMAP, /* has bmap and btnode_cache */ | 102 | NILFS_I_BMAP, /* has bmap and btnode_cache */ |
| 102 | NILFS_I_GCINODE, /* inode for GC, on memory only */ | 103 | NILFS_I_GCINODE, /* inode for GC, on memory only */ |
| 103 | NILFS_I_GCDAT, /* shadow DAT, on memory only */ | ||
| 104 | }; | 104 | }; |
| 105 | 105 | ||
| 106 | /* | 106 | /* |
| @@ -192,7 +192,7 @@ static inline int nilfs_doing_construction(void) | |||
| 192 | 192 | ||
| 193 | static inline struct inode *nilfs_dat_inode(const struct the_nilfs *nilfs) | 193 | static inline struct inode *nilfs_dat_inode(const struct the_nilfs *nilfs) |
| 194 | { | 194 | { |
| 195 | return nilfs_doing_gc() ? nilfs->ns_gc_dat : nilfs->ns_dat; | 195 | return nilfs->ns_dat; |
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | /* | 198 | /* |
| @@ -200,12 +200,9 @@ static inline struct inode *nilfs_dat_inode(const struct the_nilfs *nilfs) | |||
| 200 | */ | 200 | */ |
| 201 | #ifdef CONFIG_NILFS_POSIX_ACL | 201 | #ifdef CONFIG_NILFS_POSIX_ACL |
| 202 | #error "NILFS: not yet supported POSIX ACL" | 202 | #error "NILFS: not yet supported POSIX ACL" |
| 203 | extern int nilfs_permission(struct inode *, int, struct nameidata *); | ||
| 204 | extern int nilfs_acl_chmod(struct inode *); | 203 | extern int nilfs_acl_chmod(struct inode *); |
| 205 | extern int nilfs_init_acl(struct inode *, struct inode *); | 204 | extern int nilfs_init_acl(struct inode *, struct inode *); |
| 206 | #else | 205 | #else |
| 207 | #define nilfs_permission NULL | ||
| 208 | |||
| 209 | static inline int nilfs_acl_chmod(struct inode *inode) | 206 | static inline int nilfs_acl_chmod(struct inode *inode) |
| 210 | { | 207 | { |
| 211 | return 0; | 208 | return 0; |
| @@ -247,11 +244,19 @@ extern int nilfs_get_block(struct inode *, sector_t, struct buffer_head *, int); | |||
| 247 | extern void nilfs_set_inode_flags(struct inode *); | 244 | extern void nilfs_set_inode_flags(struct inode *); |
| 248 | extern int nilfs_read_inode_common(struct inode *, struct nilfs_inode *); | 245 | extern int nilfs_read_inode_common(struct inode *, struct nilfs_inode *); |
| 249 | extern void nilfs_write_inode_common(struct inode *, struct nilfs_inode *, int); | 246 | extern void nilfs_write_inode_common(struct inode *, struct nilfs_inode *, int); |
| 250 | extern struct inode *nilfs_iget(struct super_block *, unsigned long); | 247 | struct inode *nilfs_ilookup(struct super_block *sb, struct nilfs_root *root, |
| 248 | unsigned long ino); | ||
| 249 | struct inode *nilfs_iget_locked(struct super_block *sb, struct nilfs_root *root, | ||
| 250 | unsigned long ino); | ||
| 251 | struct inode *nilfs_iget(struct super_block *sb, struct nilfs_root *root, | ||
| 252 | unsigned long ino); | ||
| 253 | extern struct inode *nilfs_iget_for_gc(struct super_block *sb, | ||
| 254 | unsigned long ino, __u64 cno); | ||
| 251 | extern void nilfs_update_inode(struct inode *, struct buffer_head *); | 255 | extern void nilfs_update_inode(struct inode *, struct buffer_head *); |
| 252 | extern void nilfs_truncate(struct inode *); | 256 | extern void nilfs_truncate(struct inode *); |
| 253 | extern void nilfs_evict_inode(struct inode *); | 257 | extern void nilfs_evict_inode(struct inode *); |
| 254 | extern int nilfs_setattr(struct dentry *, struct iattr *); | 258 | extern int nilfs_setattr(struct dentry *, struct iattr *); |
| 259 | int nilfs_permission(struct inode *inode, int mask); | ||
| 255 | extern int nilfs_load_inode_block(struct nilfs_sb_info *, struct inode *, | 260 | extern int nilfs_load_inode_block(struct nilfs_sb_info *, struct inode *, |
| 256 | struct buffer_head **); | 261 | struct buffer_head **); |
| 257 | extern int nilfs_inode_dirty(struct inode *); | 262 | extern int nilfs_inode_dirty(struct inode *); |
| @@ -260,11 +265,7 @@ extern int nilfs_set_file_dirty(struct nilfs_sb_info *, struct inode *, | |||
| 260 | extern int nilfs_mark_inode_dirty(struct inode *); | 265 | extern int nilfs_mark_inode_dirty(struct inode *); |
| 261 | extern void nilfs_dirty_inode(struct inode *); | 266 | extern void nilfs_dirty_inode(struct inode *); |
| 262 | 267 | ||
| 263 | /* namei.c */ | ||
| 264 | extern struct dentry *nilfs_get_parent(struct dentry *); | ||
| 265 | |||
| 266 | /* super.c */ | 268 | /* super.c */ |
| 267 | extern struct inode *nilfs_alloc_inode_common(struct the_nilfs *); | ||
| 268 | extern struct inode *nilfs_alloc_inode(struct super_block *); | 269 | extern struct inode *nilfs_alloc_inode(struct super_block *); |
| 269 | extern void nilfs_destroy_inode(struct inode *); | 270 | extern void nilfs_destroy_inode(struct inode *); |
| 270 | extern void nilfs_error(struct super_block *, const char *, const char *, ...) | 271 | extern void nilfs_error(struct super_block *, const char *, const char *, ...) |
| @@ -283,8 +284,9 @@ extern struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *, | |||
| 283 | int flip); | 284 | int flip); |
| 284 | extern int nilfs_commit_super(struct nilfs_sb_info *, int); | 285 | extern int nilfs_commit_super(struct nilfs_sb_info *, int); |
| 285 | extern int nilfs_cleanup_super(struct nilfs_sb_info *); | 286 | extern int nilfs_cleanup_super(struct nilfs_sb_info *); |
| 286 | extern int nilfs_attach_checkpoint(struct nilfs_sb_info *, __u64); | 287 | int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt, |
| 287 | extern void nilfs_detach_checkpoint(struct nilfs_sb_info *); | 288 | struct nilfs_root **root); |
| 289 | int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno); | ||
| 288 | 290 | ||
| 289 | /* gcinode.c */ | 291 | /* gcinode.c */ |
| 290 | int nilfs_gccache_submit_read_data(struct inode *, sector_t, sector_t, __u64, | 292 | int nilfs_gccache_submit_read_data(struct inode *, sector_t, sector_t, __u64, |
| @@ -292,16 +294,8 @@ int nilfs_gccache_submit_read_data(struct inode *, sector_t, sector_t, __u64, | |||
| 292 | int nilfs_gccache_submit_read_node(struct inode *, sector_t, __u64, | 294 | int nilfs_gccache_submit_read_node(struct inode *, sector_t, __u64, |
| 293 | struct buffer_head **); | 295 | struct buffer_head **); |
| 294 | int nilfs_gccache_wait_and_mark_dirty(struct buffer_head *); | 296 | int nilfs_gccache_wait_and_mark_dirty(struct buffer_head *); |
| 295 | int nilfs_init_gccache(struct the_nilfs *); | 297 | int nilfs_init_gcinode(struct inode *inode); |
| 296 | void nilfs_destroy_gccache(struct the_nilfs *); | 298 | void nilfs_remove_all_gcinodes(struct the_nilfs *nilfs); |
| 297 | void nilfs_clear_gcinode(struct inode *); | ||
| 298 | struct inode *nilfs_gc_iget(struct the_nilfs *, ino_t, __u64); | ||
| 299 | void nilfs_remove_all_gcinode(struct the_nilfs *); | ||
| 300 | |||
| 301 | /* gcdat.c */ | ||
| 302 | int nilfs_init_gcdat_inode(struct the_nilfs *); | ||
| 303 | void nilfs_commit_gcdat_inode(struct the_nilfs *); | ||
| 304 | void nilfs_clear_gcdat_inode(struct the_nilfs *); | ||
| 305 | 299 | ||
| 306 | /* | 300 | /* |
| 307 | * Inodes and files operations | 301 | * Inodes and files operations |
diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c index aab11db2cb08..a6c3c2e817f8 100644 --- a/fs/nilfs2/page.c +++ b/fs/nilfs2/page.c | |||
| @@ -79,8 +79,8 @@ struct buffer_head *nilfs_grab_buffer(struct inode *inode, | |||
| 79 | { | 79 | { |
| 80 | int blkbits = inode->i_blkbits; | 80 | int blkbits = inode->i_blkbits; |
| 81 | pgoff_t index = blkoff >> (PAGE_CACHE_SHIFT - blkbits); | 81 | pgoff_t index = blkoff >> (PAGE_CACHE_SHIFT - blkbits); |
| 82 | struct page *page, *opage; | 82 | struct page *page; |
| 83 | struct buffer_head *bh, *obh; | 83 | struct buffer_head *bh; |
| 84 | 84 | ||
| 85 | page = grab_cache_page(mapping, index); | 85 | page = grab_cache_page(mapping, index); |
| 86 | if (unlikely(!page)) | 86 | if (unlikely(!page)) |
| @@ -92,30 +92,6 @@ struct buffer_head *nilfs_grab_buffer(struct inode *inode, | |||
| 92 | page_cache_release(page); | 92 | page_cache_release(page); |
| 93 | return NULL; | 93 | return NULL; |
| 94 | } | 94 | } |
| 95 | if (!buffer_uptodate(bh) && mapping->assoc_mapping != NULL) { | ||
| 96 | /* | ||
| 97 | * Shadow page cache uses assoc_mapping to point its original | ||
| 98 | * page cache. The following code tries the original cache | ||
| 99 | * if the given cache is a shadow and it didn't hit. | ||
| 100 | */ | ||
| 101 | opage = find_lock_page(mapping->assoc_mapping, index); | ||
| 102 | if (!opage) | ||
| 103 | return bh; | ||
| 104 | |||
| 105 | obh = __nilfs_get_page_block(opage, blkoff, index, blkbits, | ||
| 106 | b_state); | ||
| 107 | if (buffer_uptodate(obh)) { | ||
| 108 | nilfs_copy_buffer(bh, obh); | ||
| 109 | if (buffer_dirty(obh)) { | ||
| 110 | nilfs_mark_buffer_dirty(bh); | ||
| 111 | if (!buffer_nilfs_node(bh) && NILFS_MDT(inode)) | ||
| 112 | nilfs_mdt_mark_dirty(inode); | ||
| 113 | } | ||
| 114 | } | ||
| 115 | brelse(obh); | ||
| 116 | unlock_page(opage); | ||
| 117 | page_cache_release(opage); | ||
| 118 | } | ||
| 119 | return bh; | 95 | return bh; |
| 120 | } | 96 | } |
| 121 | 97 | ||
| @@ -131,6 +107,7 @@ void nilfs_forget_buffer(struct buffer_head *bh) | |||
| 131 | lock_buffer(bh); | 107 | lock_buffer(bh); |
| 132 | clear_buffer_nilfs_volatile(bh); | 108 | clear_buffer_nilfs_volatile(bh); |
| 133 | clear_buffer_nilfs_checked(bh); | 109 | clear_buffer_nilfs_checked(bh); |
| 110 | clear_buffer_nilfs_redirected(bh); | ||
| 134 | clear_buffer_dirty(bh); | 111 | clear_buffer_dirty(bh); |
| 135 | if (nilfs_page_buffers_clean(page)) | 112 | if (nilfs_page_buffers_clean(page)) |
| 136 | __nilfs_clear_page_dirty(page); | 113 | __nilfs_clear_page_dirty(page); |
| @@ -483,6 +460,7 @@ void nilfs_clear_dirty_pages(struct address_space *mapping) | |||
| 483 | clear_buffer_dirty(bh); | 460 | clear_buffer_dirty(bh); |
| 484 | clear_buffer_nilfs_volatile(bh); | 461 | clear_buffer_nilfs_volatile(bh); |
| 485 | clear_buffer_nilfs_checked(bh); | 462 | clear_buffer_nilfs_checked(bh); |
| 463 | clear_buffer_nilfs_redirected(bh); | ||
| 486 | clear_buffer_uptodate(bh); | 464 | clear_buffer_uptodate(bh); |
| 487 | clear_buffer_mapped(bh); | 465 | clear_buffer_mapped(bh); |
| 488 | unlock_buffer(bh); | 466 | unlock_buffer(bh); |
| @@ -513,6 +491,31 @@ unsigned nilfs_page_count_clean_buffers(struct page *page, | |||
| 513 | } | 491 | } |
| 514 | return nc; | 492 | return nc; |
| 515 | } | 493 | } |
| 494 | |||
| 495 | void nilfs_mapping_init_once(struct address_space *mapping) | ||
| 496 | { | ||
| 497 | memset(mapping, 0, sizeof(*mapping)); | ||
| 498 | INIT_RADIX_TREE(&mapping->page_tree, GFP_ATOMIC); | ||
| 499 | spin_lock_init(&mapping->tree_lock); | ||
| 500 | INIT_LIST_HEAD(&mapping->private_list); | ||
| 501 | spin_lock_init(&mapping->private_lock); | ||
| 502 | |||
| 503 | spin_lock_init(&mapping->i_mmap_lock); | ||
| 504 | INIT_RAW_PRIO_TREE_ROOT(&mapping->i_mmap); | ||
| 505 | INIT_LIST_HEAD(&mapping->i_mmap_nonlinear); | ||
| 506 | } | ||
| 507 | |||
| 508 | void nilfs_mapping_init(struct address_space *mapping, | ||
| 509 | struct backing_dev_info *bdi, | ||
| 510 | const struct address_space_operations *aops) | ||
| 511 | { | ||
| 512 | mapping->host = NULL; | ||
| 513 | mapping->flags = 0; | ||
| 514 | mapping_set_gfp_mask(mapping, GFP_NOFS); | ||
| 515 | mapping->assoc_mapping = NULL; | ||
| 516 | mapping->backing_dev_info = bdi; | ||
| 517 | mapping->a_ops = aops; | ||
| 518 | } | ||
| 516 | 519 | ||
| 517 | /* | 520 | /* |
| 518 | * NILFS2 needs clear_page_dirty() in the following two cases: | 521 | * NILFS2 needs clear_page_dirty() in the following two cases: |
diff --git a/fs/nilfs2/page.h b/fs/nilfs2/page.h index f53d8da41ed7..fb9e8a8a2038 100644 --- a/fs/nilfs2/page.h +++ b/fs/nilfs2/page.h | |||
| @@ -35,12 +35,14 @@ enum { | |||
| 35 | BH_NILFS_Node, | 35 | BH_NILFS_Node, |
| 36 | BH_NILFS_Volatile, | 36 | BH_NILFS_Volatile, |
| 37 | BH_NILFS_Checked, | 37 | BH_NILFS_Checked, |
| 38 | BH_NILFS_Redirected, | ||
| 38 | }; | 39 | }; |
| 39 | 40 | ||
| 40 | BUFFER_FNS(NILFS_Allocated, nilfs_allocated) /* nilfs private buffers */ | 41 | BUFFER_FNS(NILFS_Allocated, nilfs_allocated) /* nilfs private buffers */ |
| 41 | BUFFER_FNS(NILFS_Node, nilfs_node) /* nilfs node buffers */ | 42 | BUFFER_FNS(NILFS_Node, nilfs_node) /* nilfs node buffers */ |
| 42 | BUFFER_FNS(NILFS_Volatile, nilfs_volatile) | 43 | BUFFER_FNS(NILFS_Volatile, nilfs_volatile) |
| 43 | BUFFER_FNS(NILFS_Checked, nilfs_checked) /* buffer is verified */ | 44 | BUFFER_FNS(NILFS_Checked, nilfs_checked) /* buffer is verified */ |
| 45 | BUFFER_FNS(NILFS_Redirected, nilfs_redirected) /* redirected to a copy */ | ||
| 44 | 46 | ||
| 45 | 47 | ||
| 46 | void nilfs_mark_buffer_dirty(struct buffer_head *bh); | 48 | void nilfs_mark_buffer_dirty(struct buffer_head *bh); |
| @@ -59,6 +61,10 @@ void nilfs_free_private_page(struct page *); | |||
| 59 | int nilfs_copy_dirty_pages(struct address_space *, struct address_space *); | 61 | int nilfs_copy_dirty_pages(struct address_space *, struct address_space *); |
| 60 | void nilfs_copy_back_pages(struct address_space *, struct address_space *); | 62 | void nilfs_copy_back_pages(struct address_space *, struct address_space *); |
| 61 | void nilfs_clear_dirty_pages(struct address_space *); | 63 | void nilfs_clear_dirty_pages(struct address_space *); |
| 64 | void nilfs_mapping_init_once(struct address_space *mapping); | ||
| 65 | void nilfs_mapping_init(struct address_space *mapping, | ||
| 66 | struct backing_dev_info *bdi, | ||
| 67 | const struct address_space_operations *aops); | ||
| 62 | unsigned nilfs_page_count_clean_buffers(struct page *, unsigned, unsigned); | 68 | unsigned nilfs_page_count_clean_buffers(struct page *, unsigned, unsigned); |
| 63 | 69 | ||
| 64 | #define NILFS_PAGE_BUG(page, m, a...) \ | 70 | #define NILFS_PAGE_BUG(page, m, a...) \ |
diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c index d0c35ef39f6a..5d2711c28da7 100644 --- a/fs/nilfs2/recovery.c +++ b/fs/nilfs2/recovery.c | |||
| @@ -440,7 +440,6 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs, | |||
| 440 | segnum[2] = ri->ri_segnum; | 440 | segnum[2] = ri->ri_segnum; |
| 441 | segnum[3] = ri->ri_nextnum; | 441 | segnum[3] = ri->ri_nextnum; |
| 442 | 442 | ||
| 443 | nilfs_attach_writer(nilfs, sbi); | ||
| 444 | /* | 443 | /* |
| 445 | * Releasing the next segment of the latest super root. | 444 | * Releasing the next segment of the latest super root. |
| 446 | * The next segment is invalidated by this recovery. | 445 | * The next segment is invalidated by this recovery. |
| @@ -480,7 +479,6 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs, | |||
| 480 | 479 | ||
| 481 | failed: | 480 | failed: |
| 482 | /* No need to recover sufile because it will be destroyed on error */ | 481 | /* No need to recover sufile because it will be destroyed on error */ |
| 483 | nilfs_detach_writer(nilfs, sbi); | ||
| 484 | return err; | 482 | return err; |
| 485 | } | 483 | } |
| 486 | 484 | ||
| @@ -504,6 +502,7 @@ static int nilfs_recovery_copy_block(struct the_nilfs *nilfs, | |||
| 504 | 502 | ||
| 505 | static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs, | 503 | static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs, |
| 506 | struct nilfs_sb_info *sbi, | 504 | struct nilfs_sb_info *sbi, |
| 505 | struct nilfs_root *root, | ||
| 507 | struct list_head *head, | 506 | struct list_head *head, |
| 508 | unsigned long *nr_salvaged_blocks) | 507 | unsigned long *nr_salvaged_blocks) |
| 509 | { | 508 | { |
| @@ -515,7 +514,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs, | |||
| 515 | int err = 0, err2 = 0; | 514 | int err = 0, err2 = 0; |
| 516 | 515 | ||
| 517 | list_for_each_entry_safe(rb, n, head, list) { | 516 | list_for_each_entry_safe(rb, n, head, list) { |
| 518 | inode = nilfs_iget(sbi->s_super, rb->ino); | 517 | inode = nilfs_iget(sbi->s_super, root, rb->ino); |
| 519 | if (IS_ERR(inode)) { | 518 | if (IS_ERR(inode)) { |
| 520 | err = PTR_ERR(inode); | 519 | err = PTR_ERR(inode); |
| 521 | inode = NULL; | 520 | inode = NULL; |
| @@ -578,6 +577,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs, | |||
| 578 | */ | 577 | */ |
| 579 | static int nilfs_do_roll_forward(struct the_nilfs *nilfs, | 578 | static int nilfs_do_roll_forward(struct the_nilfs *nilfs, |
| 580 | struct nilfs_sb_info *sbi, | 579 | struct nilfs_sb_info *sbi, |
| 580 | struct nilfs_root *root, | ||
| 581 | struct nilfs_recovery_info *ri) | 581 | struct nilfs_recovery_info *ri) |
| 582 | { | 582 | { |
| 583 | struct buffer_head *bh_sum = NULL; | 583 | struct buffer_head *bh_sum = NULL; |
| @@ -597,7 +597,6 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, | |||
| 597 | }; | 597 | }; |
| 598 | int state = RF_INIT_ST; | 598 | int state = RF_INIT_ST; |
| 599 | 599 | ||
| 600 | nilfs_attach_writer(nilfs, sbi); | ||
| 601 | pseg_start = ri->ri_lsegs_start; | 600 | pseg_start = ri->ri_lsegs_start; |
| 602 | seg_seq = ri->ri_lsegs_start_seq; | 601 | seg_seq = ri->ri_lsegs_start_seq; |
| 603 | segnum = nilfs_get_segnum_of_block(nilfs, pseg_start); | 602 | segnum = nilfs_get_segnum_of_block(nilfs, pseg_start); |
| @@ -649,7 +648,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, | |||
| 649 | goto failed; | 648 | goto failed; |
| 650 | if (flags & NILFS_SS_LOGEND) { | 649 | if (flags & NILFS_SS_LOGEND) { |
| 651 | err = nilfs_recover_dsync_blocks( | 650 | err = nilfs_recover_dsync_blocks( |
| 652 | nilfs, sbi, &dsync_blocks, | 651 | nilfs, sbi, root, &dsync_blocks, |
| 653 | &nsalvaged_blocks); | 652 | &nsalvaged_blocks); |
| 654 | if (unlikely(err)) | 653 | if (unlikely(err)) |
| 655 | goto failed; | 654 | goto failed; |
| @@ -688,7 +687,6 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, | |||
| 688 | out: | 687 | out: |
| 689 | brelse(bh_sum); | 688 | brelse(bh_sum); |
| 690 | dispose_recovery_list(&dsync_blocks); | 689 | dispose_recovery_list(&dsync_blocks); |
| 691 | nilfs_detach_writer(nilfs, sbi); | ||
| 692 | return err; | 690 | return err; |
| 693 | 691 | ||
| 694 | confused: | 692 | confused: |
| @@ -746,19 +744,20 @@ int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, | |||
| 746 | struct nilfs_sb_info *sbi, | 744 | struct nilfs_sb_info *sbi, |
| 747 | struct nilfs_recovery_info *ri) | 745 | struct nilfs_recovery_info *ri) |
| 748 | { | 746 | { |
| 747 | struct nilfs_root *root; | ||
| 749 | int err; | 748 | int err; |
| 750 | 749 | ||
| 751 | if (ri->ri_lsegs_start == 0 || ri->ri_lsegs_end == 0) | 750 | if (ri->ri_lsegs_start == 0 || ri->ri_lsegs_end == 0) |
| 752 | return 0; | 751 | return 0; |
| 753 | 752 | ||
| 754 | err = nilfs_attach_checkpoint(sbi, ri->ri_cno); | 753 | err = nilfs_attach_checkpoint(sbi, ri->ri_cno, true, &root); |
| 755 | if (unlikely(err)) { | 754 | if (unlikely(err)) { |
| 756 | printk(KERN_ERR | 755 | printk(KERN_ERR |
| 757 | "NILFS: error loading the latest checkpoint.\n"); | 756 | "NILFS: error loading the latest checkpoint.\n"); |
| 758 | return err; | 757 | return err; |
| 759 | } | 758 | } |
| 760 | 759 | ||
| 761 | err = nilfs_do_roll_forward(nilfs, sbi, ri); | 760 | err = nilfs_do_roll_forward(nilfs, sbi, root, ri); |
| 762 | if (unlikely(err)) | 761 | if (unlikely(err)) |
| 763 | goto failed; | 762 | goto failed; |
| 764 | 763 | ||
| @@ -770,7 +769,7 @@ int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, | |||
| 770 | goto failed; | 769 | goto failed; |
| 771 | } | 770 | } |
| 772 | 771 | ||
| 773 | err = nilfs_attach_segment_constructor(sbi); | 772 | err = nilfs_attach_segment_constructor(sbi, root); |
| 774 | if (unlikely(err)) | 773 | if (unlikely(err)) |
| 775 | goto failed; | 774 | goto failed; |
| 776 | 775 | ||
| @@ -788,7 +787,7 @@ int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, | |||
| 788 | } | 787 | } |
| 789 | 788 | ||
| 790 | failed: | 789 | failed: |
| 791 | nilfs_detach_checkpoint(sbi); | 790 | nilfs_put_root(root); |
| 792 | return err; | 791 | return err; |
| 793 | } | 792 | } |
| 794 | 793 | ||
diff --git a/fs/nilfs2/sb.h b/fs/nilfs2/sb.h index 0776ccc2504a..35a07157b980 100644 --- a/fs/nilfs2/sb.h +++ b/fs/nilfs2/sb.h | |||
| @@ -42,11 +42,6 @@ struct nilfs_sc_info; | |||
| 42 | * NILFS super-block data in memory | 42 | * NILFS super-block data in memory |
| 43 | */ | 43 | */ |
| 44 | struct nilfs_sb_info { | 44 | struct nilfs_sb_info { |
| 45 | /* Snapshot status */ | ||
| 46 | __u64 s_snapshot_cno; /* Checkpoint number */ | ||
| 47 | atomic_t s_inodes_count; | ||
| 48 | atomic_t s_blocks_count; /* Reserved (might be deleted) */ | ||
| 49 | |||
| 50 | /* Mount options */ | 45 | /* Mount options */ |
| 51 | unsigned long s_mount_opt; | 46 | unsigned long s_mount_opt; |
| 52 | uid_t s_resuid; | 47 | uid_t s_resuid; |
| @@ -59,8 +54,6 @@ struct nilfs_sb_info { | |||
| 59 | /* Fundamental members */ | 54 | /* Fundamental members */ |
| 60 | struct super_block *s_super; /* reverse pointer to super_block */ | 55 | struct super_block *s_super; /* reverse pointer to super_block */ |
| 61 | struct the_nilfs *s_nilfs; | 56 | struct the_nilfs *s_nilfs; |
| 62 | struct list_head s_list; /* list head for nilfs->ns_supers */ | ||
| 63 | atomic_t s_count; /* reference count */ | ||
| 64 | 57 | ||
| 65 | /* Segment constructor */ | 58 | /* Segment constructor */ |
| 66 | struct list_head s_dirty_files; /* dirty files list */ | 59 | struct list_head s_dirty_files; /* dirty files list */ |
| @@ -68,9 +61,6 @@ struct nilfs_sb_info { | |||
| 68 | spinlock_t s_inode_lock; /* Lock for the nilfs inode. | 61 | spinlock_t s_inode_lock; /* Lock for the nilfs inode. |
| 69 | It covers s_dirty_files list */ | 62 | It covers s_dirty_files list */ |
| 70 | 63 | ||
| 71 | /* Metadata files */ | ||
| 72 | struct inode *s_ifile; /* index file inode */ | ||
| 73 | |||
| 74 | /* Inode allocator */ | 64 | /* Inode allocator */ |
| 75 | spinlock_t s_next_gen_lock; | 65 | spinlock_t s_next_gen_lock; |
| 76 | u32 s_next_generation; | 66 | u32 s_next_generation; |
diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c index 4588fb9e93df..0f83e93935b2 100644 --- a/fs/nilfs2/segbuf.c +++ b/fs/nilfs2/segbuf.c | |||
| @@ -371,7 +371,8 @@ static int nilfs_segbuf_submit_bio(struct nilfs_segment_buffer *segbuf, | |||
| 371 | struct bio *bio = wi->bio; | 371 | struct bio *bio = wi->bio; |
| 372 | int err; | 372 | int err; |
| 373 | 373 | ||
| 374 | if (segbuf->sb_nbio > 0 && bdi_write_congested(wi->nilfs->ns_bdi)) { | 374 | if (segbuf->sb_nbio > 0 && |
| 375 | bdi_write_congested(segbuf->sb_super->s_bdi)) { | ||
| 375 | wait_for_completion(&segbuf->sb_bio_event); | 376 | wait_for_completion(&segbuf->sb_bio_event); |
| 376 | segbuf->sb_nbio--; | 377 | segbuf->sb_nbio--; |
| 377 | if (unlikely(atomic_read(&segbuf->sb_err))) { | 378 | if (unlikely(atomic_read(&segbuf->sb_err))) { |
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 9fd051a33c4f..d926af626177 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c | |||
| @@ -191,6 +191,8 @@ int nilfs_transaction_begin(struct super_block *sb, | |||
| 191 | if (ret > 0) | 191 | if (ret > 0) |
| 192 | return 0; | 192 | return 0; |
| 193 | 193 | ||
| 194 | vfs_check_frozen(sb, SB_FREEZE_WRITE); | ||
| 195 | |||
| 194 | sbi = NILFS_SB(sb); | 196 | sbi = NILFS_SB(sb); |
| 195 | nilfs = sbi->s_nilfs; | 197 | nilfs = sbi->s_nilfs; |
| 196 | down_read(&nilfs->ns_segctor_sem); | 198 | down_read(&nilfs->ns_segctor_sem); |
| @@ -366,8 +368,7 @@ static int nilfs_segctor_reset_segment_buffer(struct nilfs_sc_info *sci) | |||
| 366 | 368 | ||
| 367 | if (nilfs_doing_gc()) | 369 | if (nilfs_doing_gc()) |
| 368 | flags = NILFS_SS_GC; | 370 | flags = NILFS_SS_GC; |
| 369 | err = nilfs_segbuf_reset(segbuf, flags, sci->sc_seg_ctime, | 371 | err = nilfs_segbuf_reset(segbuf, flags, sci->sc_seg_ctime, sci->sc_cno); |
| 370 | sci->sc_sbi->s_nilfs->ns_cno); | ||
| 371 | if (unlikely(err)) | 372 | if (unlikely(err)) |
| 372 | return err; | 373 | return err; |
| 373 | 374 | ||
| @@ -440,17 +441,26 @@ static void nilfs_segctor_end_finfo(struct nilfs_sc_info *sci, | |||
| 440 | struct nilfs_finfo *finfo; | 441 | struct nilfs_finfo *finfo; |
| 441 | struct nilfs_inode_info *ii; | 442 | struct nilfs_inode_info *ii; |
| 442 | struct nilfs_segment_buffer *segbuf; | 443 | struct nilfs_segment_buffer *segbuf; |
| 444 | __u64 cno; | ||
| 443 | 445 | ||
| 444 | if (sci->sc_blk_cnt == 0) | 446 | if (sci->sc_blk_cnt == 0) |
| 445 | return; | 447 | return; |
| 446 | 448 | ||
| 447 | ii = NILFS_I(inode); | 449 | ii = NILFS_I(inode); |
| 450 | |||
| 451 | if (test_bit(NILFS_I_GCINODE, &ii->i_state)) | ||
| 452 | cno = ii->i_cno; | ||
| 453 | else if (NILFS_ROOT_METADATA_FILE(inode->i_ino)) | ||
| 454 | cno = 0; | ||
| 455 | else | ||
| 456 | cno = sci->sc_cno; | ||
| 457 | |||
| 448 | finfo = nilfs_segctor_map_segsum_entry(sci, &sci->sc_finfo_ptr, | 458 | finfo = nilfs_segctor_map_segsum_entry(sci, &sci->sc_finfo_ptr, |
| 449 | sizeof(*finfo)); | 459 | sizeof(*finfo)); |
| 450 | finfo->fi_ino = cpu_to_le64(inode->i_ino); | 460 | finfo->fi_ino = cpu_to_le64(inode->i_ino); |
| 451 | finfo->fi_nblocks = cpu_to_le32(sci->sc_blk_cnt); | 461 | finfo->fi_nblocks = cpu_to_le32(sci->sc_blk_cnt); |
| 452 | finfo->fi_ndatablk = cpu_to_le32(sci->sc_datablk_cnt); | 462 | finfo->fi_ndatablk = cpu_to_le32(sci->sc_datablk_cnt); |
| 453 | finfo->fi_cno = cpu_to_le64(ii->i_cno); | 463 | finfo->fi_cno = cpu_to_le64(cno); |
| 454 | 464 | ||
| 455 | segbuf = sci->sc_curseg; | 465 | segbuf = sci->sc_curseg; |
| 456 | segbuf->sb_sum.sumbytes = sci->sc_binfo_ptr.offset + | 466 | segbuf->sb_sum.sumbytes = sci->sc_binfo_ptr.offset + |
| @@ -755,12 +765,12 @@ static void nilfs_dispose_list(struct nilfs_sb_info *sbi, | |||
| 755 | } | 765 | } |
| 756 | } | 766 | } |
| 757 | 767 | ||
| 758 | static int nilfs_test_metadata_dirty(struct nilfs_sb_info *sbi) | 768 | static int nilfs_test_metadata_dirty(struct the_nilfs *nilfs, |
| 769 | struct nilfs_root *root) | ||
| 759 | { | 770 | { |
| 760 | struct the_nilfs *nilfs = sbi->s_nilfs; | ||
| 761 | int ret = 0; | 771 | int ret = 0; |
| 762 | 772 | ||
| 763 | if (nilfs_mdt_fetch_dirty(sbi->s_ifile)) | 773 | if (nilfs_mdt_fetch_dirty(root->ifile)) |
| 764 | ret++; | 774 | ret++; |
| 765 | if (nilfs_mdt_fetch_dirty(nilfs->ns_cpfile)) | 775 | if (nilfs_mdt_fetch_dirty(nilfs->ns_cpfile)) |
| 766 | ret++; | 776 | ret++; |
| @@ -785,7 +795,7 @@ static int nilfs_segctor_confirm(struct nilfs_sc_info *sci) | |||
| 785 | struct nilfs_sb_info *sbi = sci->sc_sbi; | 795 | struct nilfs_sb_info *sbi = sci->sc_sbi; |
| 786 | int ret = 0; | 796 | int ret = 0; |
| 787 | 797 | ||
| 788 | if (nilfs_test_metadata_dirty(sbi)) | 798 | if (nilfs_test_metadata_dirty(sbi->s_nilfs, sci->sc_root)) |
| 789 | set_bit(NILFS_SC_DIRTY, &sci->sc_flags); | 799 | set_bit(NILFS_SC_DIRTY, &sci->sc_flags); |
| 790 | 800 | ||
| 791 | spin_lock(&sbi->s_inode_lock); | 801 | spin_lock(&sbi->s_inode_lock); |
| @@ -801,7 +811,7 @@ static void nilfs_segctor_clear_metadata_dirty(struct nilfs_sc_info *sci) | |||
| 801 | struct nilfs_sb_info *sbi = sci->sc_sbi; | 811 | struct nilfs_sb_info *sbi = sci->sc_sbi; |
| 802 | struct the_nilfs *nilfs = sbi->s_nilfs; | 812 | struct the_nilfs *nilfs = sbi->s_nilfs; |
| 803 | 813 | ||
| 804 | nilfs_mdt_clear_dirty(sbi->s_ifile); | 814 | nilfs_mdt_clear_dirty(sci->sc_root->ifile); |
| 805 | nilfs_mdt_clear_dirty(nilfs->ns_cpfile); | 815 | nilfs_mdt_clear_dirty(nilfs->ns_cpfile); |
| 806 | nilfs_mdt_clear_dirty(nilfs->ns_sufile); | 816 | nilfs_mdt_clear_dirty(nilfs->ns_sufile); |
| 807 | nilfs_mdt_clear_dirty(nilfs_dat_inode(nilfs)); | 817 | nilfs_mdt_clear_dirty(nilfs_dat_inode(nilfs)); |
| @@ -848,9 +858,9 @@ static int nilfs_segctor_fill_in_checkpoint(struct nilfs_sc_info *sci) | |||
| 848 | raw_cp->cp_snapshot_list.ssl_next = 0; | 858 | raw_cp->cp_snapshot_list.ssl_next = 0; |
| 849 | raw_cp->cp_snapshot_list.ssl_prev = 0; | 859 | raw_cp->cp_snapshot_list.ssl_prev = 0; |
| 850 | raw_cp->cp_inodes_count = | 860 | raw_cp->cp_inodes_count = |
| 851 | cpu_to_le64(atomic_read(&sbi->s_inodes_count)); | 861 | cpu_to_le64(atomic_read(&sci->sc_root->inodes_count)); |
| 852 | raw_cp->cp_blocks_count = | 862 | raw_cp->cp_blocks_count = |
| 853 | cpu_to_le64(atomic_read(&sbi->s_blocks_count)); | 863 | cpu_to_le64(atomic_read(&sci->sc_root->blocks_count)); |
| 854 | raw_cp->cp_nblk_inc = | 864 | raw_cp->cp_nblk_inc = |
| 855 | cpu_to_le64(sci->sc_nblk_inc + sci->sc_nblk_this_inc); | 865 | cpu_to_le64(sci->sc_nblk_inc + sci->sc_nblk_this_inc); |
| 856 | raw_cp->cp_create = cpu_to_le64(sci->sc_seg_ctime); | 866 | raw_cp->cp_create = cpu_to_le64(sci->sc_seg_ctime); |
| @@ -861,7 +871,8 @@ static int nilfs_segctor_fill_in_checkpoint(struct nilfs_sc_info *sci) | |||
| 861 | else | 871 | else |
| 862 | nilfs_checkpoint_set_minor(raw_cp); | 872 | nilfs_checkpoint_set_minor(raw_cp); |
| 863 | 873 | ||
| 864 | nilfs_write_inode_common(sbi->s_ifile, &raw_cp->cp_ifile_inode, 1); | 874 | nilfs_write_inode_common(sci->sc_root->ifile, |
| 875 | &raw_cp->cp_ifile_inode, 1); | ||
| 865 | nilfs_cpfile_put_checkpoint(nilfs->ns_cpfile, nilfs->ns_cno, bh_cp); | 876 | nilfs_cpfile_put_checkpoint(nilfs->ns_cpfile, nilfs->ns_cno, bh_cp); |
| 866 | return 0; | 877 | return 0; |
| 867 | 878 | ||
| @@ -886,13 +897,12 @@ static void nilfs_fill_in_file_bmap(struct inode *ifile, | |||
| 886 | } | 897 | } |
| 887 | } | 898 | } |
| 888 | 899 | ||
| 889 | static void nilfs_segctor_fill_in_file_bmap(struct nilfs_sc_info *sci, | 900 | static void nilfs_segctor_fill_in_file_bmap(struct nilfs_sc_info *sci) |
| 890 | struct inode *ifile) | ||
| 891 | { | 901 | { |
| 892 | struct nilfs_inode_info *ii; | 902 | struct nilfs_inode_info *ii; |
| 893 | 903 | ||
| 894 | list_for_each_entry(ii, &sci->sc_dirty_files, i_dirty) { | 904 | list_for_each_entry(ii, &sci->sc_dirty_files, i_dirty) { |
| 895 | nilfs_fill_in_file_bmap(ifile, ii); | 905 | nilfs_fill_in_file_bmap(sci->sc_root->ifile, ii); |
| 896 | set_bit(NILFS_I_COLLECTED, &ii->i_state); | 906 | set_bit(NILFS_I_COLLECTED, &ii->i_state); |
| 897 | } | 907 | } |
| 898 | } | 908 | } |
| @@ -1135,7 +1145,7 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode) | |||
| 1135 | sci->sc_stage.flags |= NILFS_CF_IFILE_STARTED; | 1145 | sci->sc_stage.flags |= NILFS_CF_IFILE_STARTED; |
| 1136 | /* Fall through */ | 1146 | /* Fall through */ |
| 1137 | case NILFS_ST_IFILE: | 1147 | case NILFS_ST_IFILE: |
| 1138 | err = nilfs_segctor_scan_file(sci, sbi->s_ifile, | 1148 | err = nilfs_segctor_scan_file(sci, sci->sc_root->ifile, |
| 1139 | &nilfs_sc_file_ops); | 1149 | &nilfs_sc_file_ops); |
| 1140 | if (unlikely(err)) | 1150 | if (unlikely(err)) |
| 1141 | break; | 1151 | break; |
| @@ -1900,6 +1910,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) | |||
| 1900 | set_buffer_uptodate(bh); | 1910 | set_buffer_uptodate(bh); |
| 1901 | clear_buffer_dirty(bh); | 1911 | clear_buffer_dirty(bh); |
| 1902 | clear_buffer_nilfs_volatile(bh); | 1912 | clear_buffer_nilfs_volatile(bh); |
| 1913 | clear_buffer_nilfs_redirected(bh); | ||
| 1903 | if (bh == segbuf->sb_super_root) { | 1914 | if (bh == segbuf->sb_super_root) { |
| 1904 | if (bh->b_page != bd_page) { | 1915 | if (bh->b_page != bd_page) { |
| 1905 | end_page_writeback(bd_page); | 1916 | end_page_writeback(bd_page); |
| @@ -1936,11 +1947,9 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) | |||
| 1936 | 1947 | ||
| 1937 | nilfs_drop_collected_inodes(&sci->sc_dirty_files); | 1948 | nilfs_drop_collected_inodes(&sci->sc_dirty_files); |
| 1938 | 1949 | ||
| 1939 | if (nilfs_doing_gc()) { | 1950 | if (nilfs_doing_gc()) |
| 1940 | nilfs_drop_collected_inodes(&sci->sc_gc_inodes); | 1951 | nilfs_drop_collected_inodes(&sci->sc_gc_inodes); |
| 1941 | if (update_sr) | 1952 | else |
| 1942 | nilfs_commit_gcdat_inode(nilfs); | ||
| 1943 | } else | ||
| 1944 | nilfs->ns_nongc_ctime = sci->sc_seg_ctime; | 1953 | nilfs->ns_nongc_ctime = sci->sc_seg_ctime; |
| 1945 | 1954 | ||
| 1946 | sci->sc_nblk_inc += sci->sc_nblk_this_inc; | 1955 | sci->sc_nblk_inc += sci->sc_nblk_this_inc; |
| @@ -1976,7 +1985,7 @@ static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci, | |||
| 1976 | struct nilfs_sb_info *sbi) | 1985 | struct nilfs_sb_info *sbi) |
| 1977 | { | 1986 | { |
| 1978 | struct nilfs_inode_info *ii, *n; | 1987 | struct nilfs_inode_info *ii, *n; |
| 1979 | __u64 cno = sbi->s_nilfs->ns_cno; | 1988 | struct inode *ifile = sci->sc_root->ifile; |
| 1980 | 1989 | ||
| 1981 | spin_lock(&sbi->s_inode_lock); | 1990 | spin_lock(&sbi->s_inode_lock); |
| 1982 | retry: | 1991 | retry: |
| @@ -1987,14 +1996,14 @@ static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci, | |||
| 1987 | 1996 | ||
| 1988 | spin_unlock(&sbi->s_inode_lock); | 1997 | spin_unlock(&sbi->s_inode_lock); |
| 1989 | err = nilfs_ifile_get_inode_block( | 1998 | err = nilfs_ifile_get_inode_block( |
| 1990 | sbi->s_ifile, ii->vfs_inode.i_ino, &ibh); | 1999 | ifile, ii->vfs_inode.i_ino, &ibh); |
| 1991 | if (unlikely(err)) { | 2000 | if (unlikely(err)) { |
| 1992 | nilfs_warning(sbi->s_super, __func__, | 2001 | nilfs_warning(sbi->s_super, __func__, |
| 1993 | "failed to get inode block.\n"); | 2002 | "failed to get inode block.\n"); |
| 1994 | return err; | 2003 | return err; |
| 1995 | } | 2004 | } |
| 1996 | nilfs_mdt_mark_buffer_dirty(ibh); | 2005 | nilfs_mdt_mark_buffer_dirty(ibh); |
| 1997 | nilfs_mdt_mark_dirty(sbi->s_ifile); | 2006 | nilfs_mdt_mark_dirty(ifile); |
| 1998 | spin_lock(&sbi->s_inode_lock); | 2007 | spin_lock(&sbi->s_inode_lock); |
| 1999 | if (likely(!ii->i_bh)) | 2008 | if (likely(!ii->i_bh)) |
| 2000 | ii->i_bh = ibh; | 2009 | ii->i_bh = ibh; |
| @@ -2002,7 +2011,6 @@ static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci, | |||
| 2002 | brelse(ibh); | 2011 | brelse(ibh); |
| 2003 | goto retry; | 2012 | goto retry; |
| 2004 | } | 2013 | } |
| 2005 | ii->i_cno = cno; | ||
| 2006 | 2014 | ||
| 2007 | clear_bit(NILFS_I_QUEUED, &ii->i_state); | 2015 | clear_bit(NILFS_I_QUEUED, &ii->i_state); |
| 2008 | set_bit(NILFS_I_BUSY, &ii->i_state); | 2016 | set_bit(NILFS_I_BUSY, &ii->i_state); |
| @@ -2011,8 +2019,6 @@ static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci, | |||
| 2011 | } | 2019 | } |
| 2012 | spin_unlock(&sbi->s_inode_lock); | 2020 | spin_unlock(&sbi->s_inode_lock); |
| 2013 | 2021 | ||
| 2014 | NILFS_I(sbi->s_ifile)->i_cno = cno; | ||
| 2015 | |||
| 2016 | return 0; | 2022 | return 0; |
| 2017 | } | 2023 | } |
| 2018 | 2024 | ||
| @@ -2021,19 +2027,13 @@ static void nilfs_segctor_check_out_files(struct nilfs_sc_info *sci, | |||
| 2021 | { | 2027 | { |
| 2022 | struct nilfs_transaction_info *ti = current->journal_info; | 2028 | struct nilfs_transaction_info *ti = current->journal_info; |
| 2023 | struct nilfs_inode_info *ii, *n; | 2029 | struct nilfs_inode_info *ii, *n; |
| 2024 | __u64 cno = sbi->s_nilfs->ns_cno; | ||
| 2025 | 2030 | ||
| 2026 | spin_lock(&sbi->s_inode_lock); | 2031 | spin_lock(&sbi->s_inode_lock); |
| 2027 | list_for_each_entry_safe(ii, n, &sci->sc_dirty_files, i_dirty) { | 2032 | list_for_each_entry_safe(ii, n, &sci->sc_dirty_files, i_dirty) { |
| 2028 | if (!test_and_clear_bit(NILFS_I_UPDATED, &ii->i_state) || | 2033 | if (!test_and_clear_bit(NILFS_I_UPDATED, &ii->i_state) || |
| 2029 | test_bit(NILFS_I_DIRTY, &ii->i_state)) { | 2034 | test_bit(NILFS_I_DIRTY, &ii->i_state)) |
| 2030 | /* The current checkpoint number (=nilfs->ns_cno) is | ||
| 2031 | changed between check-in and check-out only if the | ||
| 2032 | super root is written out. So, we can update i_cno | ||
| 2033 | for the inodes that remain in the dirty list. */ | ||
| 2034 | ii->i_cno = cno; | ||
| 2035 | continue; | 2035 | continue; |
| 2036 | } | 2036 | |
| 2037 | clear_bit(NILFS_I_BUSY, &ii->i_state); | 2037 | clear_bit(NILFS_I_BUSY, &ii->i_state); |
| 2038 | brelse(ii->i_bh); | 2038 | brelse(ii->i_bh); |
| 2039 | ii->i_bh = NULL; | 2039 | ii->i_bh = NULL; |
| @@ -2054,12 +2054,13 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) | |||
| 2054 | int err; | 2054 | int err; |
| 2055 | 2055 | ||
| 2056 | sci->sc_stage.scnt = NILFS_ST_INIT; | 2056 | sci->sc_stage.scnt = NILFS_ST_INIT; |
| 2057 | sci->sc_cno = nilfs->ns_cno; | ||
| 2057 | 2058 | ||
| 2058 | err = nilfs_segctor_check_in_files(sci, sbi); | 2059 | err = nilfs_segctor_check_in_files(sci, sbi); |
| 2059 | if (unlikely(err)) | 2060 | if (unlikely(err)) |
| 2060 | goto out; | 2061 | goto out; |
| 2061 | 2062 | ||
| 2062 | if (nilfs_test_metadata_dirty(sbi)) | 2063 | if (nilfs_test_metadata_dirty(nilfs, sci->sc_root)) |
| 2063 | set_bit(NILFS_SC_DIRTY, &sci->sc_flags); | 2064 | set_bit(NILFS_SC_DIRTY, &sci->sc_flags); |
| 2064 | 2065 | ||
| 2065 | if (nilfs_segctor_clean(sci)) | 2066 | if (nilfs_segctor_clean(sci)) |
| @@ -2091,7 +2092,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) | |||
| 2091 | goto failed; | 2092 | goto failed; |
| 2092 | 2093 | ||
| 2093 | if (sci->sc_stage.flags & NILFS_CF_IFILE_STARTED) | 2094 | if (sci->sc_stage.flags & NILFS_CF_IFILE_STARTED) |
| 2094 | nilfs_segctor_fill_in_file_bmap(sci, sbi->s_ifile); | 2095 | nilfs_segctor_fill_in_file_bmap(sci); |
| 2095 | 2096 | ||
| 2096 | if (mode == SC_LSEG_SR && | 2097 | if (mode == SC_LSEG_SR && |
| 2097 | sci->sc_stage.scnt >= NILFS_ST_CPFILE) { | 2098 | sci->sc_stage.scnt >= NILFS_ST_CPFILE) { |
| @@ -2452,9 +2453,8 @@ nilfs_remove_written_gcinodes(struct the_nilfs *nilfs, struct list_head *head) | |||
| 2452 | list_for_each_entry_safe(ii, n, head, i_dirty) { | 2453 | list_for_each_entry_safe(ii, n, head, i_dirty) { |
| 2453 | if (!test_bit(NILFS_I_UPDATED, &ii->i_state)) | 2454 | if (!test_bit(NILFS_I_UPDATED, &ii->i_state)) |
| 2454 | continue; | 2455 | continue; |
| 2455 | hlist_del_init(&ii->vfs_inode.i_hash); | ||
| 2456 | list_del_init(&ii->i_dirty); | 2456 | list_del_init(&ii->i_dirty); |
| 2457 | nilfs_clear_gcinode(&ii->vfs_inode); | 2457 | iput(&ii->vfs_inode); |
| 2458 | } | 2458 | } |
| 2459 | } | 2459 | } |
| 2460 | 2460 | ||
| @@ -2472,13 +2472,15 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, | |||
| 2472 | 2472 | ||
| 2473 | nilfs_transaction_lock(sbi, &ti, 1); | 2473 | nilfs_transaction_lock(sbi, &ti, 1); |
| 2474 | 2474 | ||
| 2475 | err = nilfs_init_gcdat_inode(nilfs); | 2475 | err = nilfs_mdt_save_to_shadow_map(nilfs->ns_dat); |
| 2476 | if (unlikely(err)) | 2476 | if (unlikely(err)) |
| 2477 | goto out_unlock; | 2477 | goto out_unlock; |
| 2478 | 2478 | ||
| 2479 | err = nilfs_ioctl_prepare_clean_segments(nilfs, argv, kbufs); | 2479 | err = nilfs_ioctl_prepare_clean_segments(nilfs, argv, kbufs); |
| 2480 | if (unlikely(err)) | 2480 | if (unlikely(err)) { |
| 2481 | nilfs_mdt_restore_from_shadow_map(nilfs->ns_dat); | ||
| 2481 | goto out_unlock; | 2482 | goto out_unlock; |
| 2483 | } | ||
| 2482 | 2484 | ||
| 2483 | sci->sc_freesegs = kbufs[4]; | 2485 | sci->sc_freesegs = kbufs[4]; |
| 2484 | sci->sc_nfreesegs = argv[4].v_nmembs; | 2486 | sci->sc_nfreesegs = argv[4].v_nmembs; |
| @@ -2510,7 +2512,7 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, | |||
| 2510 | out_unlock: | 2512 | out_unlock: |
| 2511 | sci->sc_freesegs = NULL; | 2513 | sci->sc_freesegs = NULL; |
| 2512 | sci->sc_nfreesegs = 0; | 2514 | sci->sc_nfreesegs = 0; |
| 2513 | nilfs_clear_gcdat_inode(nilfs); | 2515 | nilfs_mdt_clear_shadow_map(nilfs->ns_dat); |
| 2514 | nilfs_transaction_unlock(sbi); | 2516 | nilfs_transaction_unlock(sbi); |
| 2515 | return err; | 2517 | return err; |
| 2516 | } | 2518 | } |
| @@ -2672,6 +2674,8 @@ static int nilfs_segctor_start_thread(struct nilfs_sc_info *sci) | |||
| 2672 | } | 2674 | } |
| 2673 | 2675 | ||
| 2674 | static void nilfs_segctor_kill_thread(struct nilfs_sc_info *sci) | 2676 | static void nilfs_segctor_kill_thread(struct nilfs_sc_info *sci) |
| 2677 | __acquires(&sci->sc_state_lock) | ||
| 2678 | __releases(&sci->sc_state_lock) | ||
| 2675 | { | 2679 | { |
| 2676 | sci->sc_state |= NILFS_SEGCTOR_QUIT; | 2680 | sci->sc_state |= NILFS_SEGCTOR_QUIT; |
| 2677 | 2681 | ||
| @@ -2686,7 +2690,8 @@ static void nilfs_segctor_kill_thread(struct nilfs_sc_info *sci) | |||
| 2686 | /* | 2690 | /* |
| 2687 | * Setup & clean-up functions | 2691 | * Setup & clean-up functions |
| 2688 | */ | 2692 | */ |
| 2689 | static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi) | 2693 | static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi, |
| 2694 | struct nilfs_root *root) | ||
| 2690 | { | 2695 | { |
| 2691 | struct nilfs_sc_info *sci; | 2696 | struct nilfs_sc_info *sci; |
| 2692 | 2697 | ||
| @@ -2697,6 +2702,9 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi) | |||
| 2697 | sci->sc_sbi = sbi; | 2702 | sci->sc_sbi = sbi; |
| 2698 | sci->sc_super = sbi->s_super; | 2703 | sci->sc_super = sbi->s_super; |
| 2699 | 2704 | ||
| 2705 | nilfs_get_root(root); | ||
| 2706 | sci->sc_root = root; | ||
| 2707 | |||
| 2700 | init_waitqueue_head(&sci->sc_wait_request); | 2708 | init_waitqueue_head(&sci->sc_wait_request); |
| 2701 | init_waitqueue_head(&sci->sc_wait_daemon); | 2709 | init_waitqueue_head(&sci->sc_wait_daemon); |
| 2702 | init_waitqueue_head(&sci->sc_wait_task); | 2710 | init_waitqueue_head(&sci->sc_wait_task); |
| @@ -2771,6 +2779,8 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) | |||
| 2771 | WARN_ON(!list_empty(&sci->sc_segbufs)); | 2779 | WARN_ON(!list_empty(&sci->sc_segbufs)); |
| 2772 | WARN_ON(!list_empty(&sci->sc_write_logs)); | 2780 | WARN_ON(!list_empty(&sci->sc_write_logs)); |
| 2773 | 2781 | ||
| 2782 | nilfs_put_root(sci->sc_root); | ||
| 2783 | |||
| 2774 | down_write(&sbi->s_nilfs->ns_segctor_sem); | 2784 | down_write(&sbi->s_nilfs->ns_segctor_sem); |
| 2775 | 2785 | ||
| 2776 | del_timer_sync(&sci->sc_timer); | 2786 | del_timer_sync(&sci->sc_timer); |
| @@ -2780,6 +2790,7 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) | |||
| 2780 | /** | 2790 | /** |
| 2781 | * nilfs_attach_segment_constructor - attach a segment constructor | 2791 | * nilfs_attach_segment_constructor - attach a segment constructor |
| 2782 | * @sbi: nilfs_sb_info | 2792 | * @sbi: nilfs_sb_info |
| 2793 | * @root: root object of the current filesystem tree | ||
| 2783 | * | 2794 | * |
| 2784 | * nilfs_attach_segment_constructor() allocates a struct nilfs_sc_info, | 2795 | * nilfs_attach_segment_constructor() allocates a struct nilfs_sc_info, |
| 2785 | * initializes it, and starts the segment constructor. | 2796 | * initializes it, and starts the segment constructor. |
| @@ -2789,9 +2800,9 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) | |||
| 2789 | * | 2800 | * |
| 2790 | * %-ENOMEM - Insufficient memory available. | 2801 | * %-ENOMEM - Insufficient memory available. |
| 2791 | */ | 2802 | */ |
| 2792 | int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi) | 2803 | int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi, |
| 2804 | struct nilfs_root *root) | ||
| 2793 | { | 2805 | { |
| 2794 | struct the_nilfs *nilfs = sbi->s_nilfs; | ||
| 2795 | int err; | 2806 | int err; |
| 2796 | 2807 | ||
| 2797 | if (NILFS_SC(sbi)) { | 2808 | if (NILFS_SC(sbi)) { |
| @@ -2803,14 +2814,12 @@ int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi) | |||
| 2803 | nilfs_detach_segment_constructor(sbi); | 2814 | nilfs_detach_segment_constructor(sbi); |
| 2804 | } | 2815 | } |
| 2805 | 2816 | ||
| 2806 | sbi->s_sc_info = nilfs_segctor_new(sbi); | 2817 | sbi->s_sc_info = nilfs_segctor_new(sbi, root); |
| 2807 | if (!sbi->s_sc_info) | 2818 | if (!sbi->s_sc_info) |
| 2808 | return -ENOMEM; | 2819 | return -ENOMEM; |
| 2809 | 2820 | ||
| 2810 | nilfs_attach_writer(nilfs, sbi); | ||
| 2811 | err = nilfs_segctor_start_thread(NILFS_SC(sbi)); | 2821 | err = nilfs_segctor_start_thread(NILFS_SC(sbi)); |
| 2812 | if (err) { | 2822 | if (err) { |
| 2813 | nilfs_detach_writer(nilfs, sbi); | ||
| 2814 | kfree(sbi->s_sc_info); | 2823 | kfree(sbi->s_sc_info); |
| 2815 | sbi->s_sc_info = NULL; | 2824 | sbi->s_sc_info = NULL; |
| 2816 | } | 2825 | } |
| @@ -2847,5 +2856,4 @@ void nilfs_detach_segment_constructor(struct nilfs_sb_info *sbi) | |||
| 2847 | up_write(&nilfs->ns_segctor_sem); | 2856 | up_write(&nilfs->ns_segctor_sem); |
| 2848 | 2857 | ||
| 2849 | nilfs_dispose_list(sbi, &garbage_list, 1); | 2858 | nilfs_dispose_list(sbi, &garbage_list, 1); |
| 2850 | nilfs_detach_writer(nilfs, sbi); | ||
| 2851 | } | 2859 | } |
diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h index 17c487bd8152..cd8056e7cbed 100644 --- a/fs/nilfs2/segment.h +++ b/fs/nilfs2/segment.h | |||
| @@ -29,6 +29,8 @@ | |||
| 29 | #include <linux/nilfs2_fs.h> | 29 | #include <linux/nilfs2_fs.h> |
| 30 | #include "sb.h" | 30 | #include "sb.h" |
| 31 | 31 | ||
| 32 | struct nilfs_root; | ||
| 33 | |||
| 32 | /** | 34 | /** |
| 33 | * struct nilfs_recovery_info - Recovery information | 35 | * struct nilfs_recovery_info - Recovery information |
| 34 | * @ri_need_recovery: Recovery status | 36 | * @ri_need_recovery: Recovery status |
| @@ -87,6 +89,7 @@ struct nilfs_segsum_pointer { | |||
| 87 | * struct nilfs_sc_info - Segment constructor information | 89 | * struct nilfs_sc_info - Segment constructor information |
| 88 | * @sc_super: Back pointer to super_block struct | 90 | * @sc_super: Back pointer to super_block struct |
| 89 | * @sc_sbi: Back pointer to nilfs_sb_info struct | 91 | * @sc_sbi: Back pointer to nilfs_sb_info struct |
| 92 | * @sc_root: root object of the current filesystem tree | ||
| 90 | * @sc_nblk_inc: Block count of current generation | 93 | * @sc_nblk_inc: Block count of current generation |
| 91 | * @sc_dirty_files: List of files to be written | 94 | * @sc_dirty_files: List of files to be written |
| 92 | * @sc_gc_inodes: List of GC inodes having blocks to be written | 95 | * @sc_gc_inodes: List of GC inodes having blocks to be written |
| @@ -107,6 +110,7 @@ struct nilfs_segsum_pointer { | |||
| 107 | * @sc_datablk_cnt: Data block count of a file | 110 | * @sc_datablk_cnt: Data block count of a file |
| 108 | * @sc_nblk_this_inc: Number of blocks included in the current logical segment | 111 | * @sc_nblk_this_inc: Number of blocks included in the current logical segment |
| 109 | * @sc_seg_ctime: Creation time | 112 | * @sc_seg_ctime: Creation time |
| 113 | * @sc_cno: checkpoint number of current log | ||
| 110 | * @sc_flags: Internal flags | 114 | * @sc_flags: Internal flags |
| 111 | * @sc_state_lock: spinlock for sc_state and so on | 115 | * @sc_state_lock: spinlock for sc_state and so on |
| 112 | * @sc_state: Segctord state flags | 116 | * @sc_state: Segctord state flags |
| @@ -128,6 +132,7 @@ struct nilfs_segsum_pointer { | |||
| 128 | struct nilfs_sc_info { | 132 | struct nilfs_sc_info { |
| 129 | struct super_block *sc_super; | 133 | struct super_block *sc_super; |
| 130 | struct nilfs_sb_info *sc_sbi; | 134 | struct nilfs_sb_info *sc_sbi; |
| 135 | struct nilfs_root *sc_root; | ||
| 131 | 136 | ||
| 132 | unsigned long sc_nblk_inc; | 137 | unsigned long sc_nblk_inc; |
| 133 | 138 | ||
| @@ -156,7 +161,7 @@ struct nilfs_sc_info { | |||
| 156 | unsigned long sc_datablk_cnt; | 161 | unsigned long sc_datablk_cnt; |
| 157 | unsigned long sc_nblk_this_inc; | 162 | unsigned long sc_nblk_this_inc; |
| 158 | time_t sc_seg_ctime; | 163 | time_t sc_seg_ctime; |
| 159 | 164 | __u64 sc_cno; | |
| 160 | unsigned long sc_flags; | 165 | unsigned long sc_flags; |
| 161 | 166 | ||
| 162 | spinlock_t sc_state_lock; | 167 | spinlock_t sc_state_lock; |
| @@ -230,7 +235,8 @@ extern void nilfs_flush_segment(struct super_block *, ino_t); | |||
| 230 | extern int nilfs_clean_segments(struct super_block *, struct nilfs_argv *, | 235 | extern int nilfs_clean_segments(struct super_block *, struct nilfs_argv *, |
| 231 | void **); | 236 | void **); |
| 232 | 237 | ||
| 233 | extern int nilfs_attach_segment_constructor(struct nilfs_sb_info *); | 238 | int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi, |
| 239 | struct nilfs_root *root); | ||
| 234 | extern void nilfs_detach_segment_constructor(struct nilfs_sb_info *); | 240 | extern void nilfs_detach_segment_constructor(struct nilfs_sb_info *); |
| 235 | 241 | ||
| 236 | /* recovery.c */ | 242 | /* recovery.c */ |
diff --git a/fs/nilfs2/sufile.c b/fs/nilfs2/sufile.c index 3c6cc6005c2e..1d6f488ccae8 100644 --- a/fs/nilfs2/sufile.c +++ b/fs/nilfs2/sufile.c | |||
| @@ -505,7 +505,7 @@ int nilfs_sufile_get_stat(struct inode *sufile, struct nilfs_sustat *sustat) | |||
| 505 | { | 505 | { |
| 506 | struct buffer_head *header_bh; | 506 | struct buffer_head *header_bh; |
| 507 | struct nilfs_sufile_header *header; | 507 | struct nilfs_sufile_header *header; |
| 508 | struct the_nilfs *nilfs = NILFS_MDT(sufile)->mi_nilfs; | 508 | struct the_nilfs *nilfs = NILFS_I_NILFS(sufile); |
| 509 | void *kaddr; | 509 | void *kaddr; |
| 510 | int ret; | 510 | int ret; |
| 511 | 511 | ||
| @@ -583,7 +583,7 @@ ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf, | |||
| 583 | struct nilfs_segment_usage *su; | 583 | struct nilfs_segment_usage *su; |
| 584 | struct nilfs_suinfo *si = buf; | 584 | struct nilfs_suinfo *si = buf; |
| 585 | size_t susz = NILFS_MDT(sufile)->mi_entry_size; | 585 | size_t susz = NILFS_MDT(sufile)->mi_entry_size; |
| 586 | struct the_nilfs *nilfs = NILFS_MDT(sufile)->mi_nilfs; | 586 | struct the_nilfs *nilfs = NILFS_I_NILFS(sufile); |
| 587 | void *kaddr; | 587 | void *kaddr; |
| 588 | unsigned long nsegs, segusages_per_block; | 588 | unsigned long nsegs, segusages_per_block; |
| 589 | ssize_t n; | 589 | ssize_t n; |
| @@ -635,46 +635,55 @@ ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf, | |||
| 635 | } | 635 | } |
| 636 | 636 | ||
| 637 | /** | 637 | /** |
| 638 | * nilfs_sufile_read - read sufile inode | 638 | * nilfs_sufile_read - read or get sufile inode |
| 639 | * @sufile: sufile inode | 639 | * @sb: super block instance |
| 640 | * @susize: size of a segment usage entry | ||
| 640 | * @raw_inode: on-disk sufile inode | 641 | * @raw_inode: on-disk sufile inode |
| 642 | * @inodep: buffer to store the inode | ||
| 641 | */ | 643 | */ |
| 642 | int nilfs_sufile_read(struct inode *sufile, struct nilfs_inode *raw_inode) | 644 | int nilfs_sufile_read(struct super_block *sb, size_t susize, |
| 645 | struct nilfs_inode *raw_inode, struct inode **inodep) | ||
| 643 | { | 646 | { |
| 644 | struct nilfs_sufile_info *sui = NILFS_SUI(sufile); | 647 | struct inode *sufile; |
| 648 | struct nilfs_sufile_info *sui; | ||
| 645 | struct buffer_head *header_bh; | 649 | struct buffer_head *header_bh; |
| 646 | struct nilfs_sufile_header *header; | 650 | struct nilfs_sufile_header *header; |
| 647 | void *kaddr; | 651 | void *kaddr; |
| 648 | int ret; | 652 | int err; |
| 649 | 653 | ||
| 650 | ret = nilfs_read_inode_common(sufile, raw_inode); | 654 | sufile = nilfs_iget_locked(sb, NULL, NILFS_SUFILE_INO); |
| 651 | if (ret < 0) | 655 | if (unlikely(!sufile)) |
| 652 | return ret; | 656 | return -ENOMEM; |
| 657 | if (!(sufile->i_state & I_NEW)) | ||
| 658 | goto out; | ||
| 653 | 659 | ||
| 654 | ret = nilfs_sufile_get_header_block(sufile, &header_bh); | 660 | err = nilfs_mdt_init(sufile, NILFS_MDT_GFP, sizeof(*sui)); |
| 655 | if (!ret) { | 661 | if (err) |
| 656 | kaddr = kmap_atomic(header_bh->b_page, KM_USER0); | 662 | goto failed; |
| 657 | header = kaddr + bh_offset(header_bh); | ||
| 658 | sui->ncleansegs = le64_to_cpu(header->sh_ncleansegs); | ||
| 659 | kunmap_atomic(kaddr, KM_USER0); | ||
| 660 | brelse(header_bh); | ||
| 661 | } | ||
| 662 | return ret; | ||
| 663 | } | ||
| 664 | 663 | ||
| 665 | /** | 664 | nilfs_mdt_set_entry_size(sufile, susize, |
| 666 | * nilfs_sufile_new - create sufile | 665 | sizeof(struct nilfs_sufile_header)); |
| 667 | * @nilfs: nilfs object | 666 | |
| 668 | * @susize: size of a segment usage entry | 667 | err = nilfs_read_inode_common(sufile, raw_inode); |
| 669 | */ | 668 | if (err) |
| 670 | struct inode *nilfs_sufile_new(struct the_nilfs *nilfs, size_t susize) | 669 | goto failed; |
| 671 | { | 670 | |
| 672 | struct inode *sufile; | 671 | err = nilfs_sufile_get_header_block(sufile, &header_bh); |
| 672 | if (err) | ||
| 673 | goto failed; | ||
| 673 | 674 | ||
| 674 | sufile = nilfs_mdt_new(nilfs, NULL, NILFS_SUFILE_INO, | 675 | sui = NILFS_SUI(sufile); |
| 675 | sizeof(struct nilfs_sufile_info)); | 676 | kaddr = kmap_atomic(header_bh->b_page, KM_USER0); |
| 676 | if (sufile) | 677 | header = kaddr + bh_offset(header_bh); |
| 677 | nilfs_mdt_set_entry_size(sufile, susize, | 678 | sui->ncleansegs = le64_to_cpu(header->sh_ncleansegs); |
| 678 | sizeof(struct nilfs_sufile_header)); | 679 | kunmap_atomic(kaddr, KM_USER0); |
| 679 | return sufile; | 680 | brelse(header_bh); |
| 681 | |||
| 682 | unlock_new_inode(sufile); | ||
| 683 | out: | ||
| 684 | *inodep = sufile; | ||
| 685 | return 0; | ||
| 686 | failed: | ||
| 687 | iget_failed(sufile); | ||
| 688 | return err; | ||
| 680 | } | 689 | } |
diff --git a/fs/nilfs2/sufile.h b/fs/nilfs2/sufile.h index 15163b8aff7d..a943fbacb45b 100644 --- a/fs/nilfs2/sufile.h +++ b/fs/nilfs2/sufile.h | |||
| @@ -31,7 +31,7 @@ | |||
| 31 | 31 | ||
| 32 | static inline unsigned long nilfs_sufile_get_nsegments(struct inode *sufile) | 32 | static inline unsigned long nilfs_sufile_get_nsegments(struct inode *sufile) |
| 33 | { | 33 | { |
| 34 | return NILFS_MDT(sufile)->mi_nilfs->ns_nsegments; | 34 | return NILFS_I_NILFS(sufile)->ns_nsegments; |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | unsigned long nilfs_sufile_get_ncleansegs(struct inode *sufile); | 37 | unsigned long nilfs_sufile_get_ncleansegs(struct inode *sufile); |
| @@ -61,8 +61,8 @@ void nilfs_sufile_do_cancel_free(struct inode *, __u64, struct buffer_head *, | |||
| 61 | void nilfs_sufile_do_set_error(struct inode *, __u64, struct buffer_head *, | 61 | void nilfs_sufile_do_set_error(struct inode *, __u64, struct buffer_head *, |
| 62 | struct buffer_head *); | 62 | struct buffer_head *); |
| 63 | 63 | ||
| 64 | int nilfs_sufile_read(struct inode *sufile, struct nilfs_inode *raw_inode); | 64 | int nilfs_sufile_read(struct super_block *sb, size_t susize, |
| 65 | struct inode *nilfs_sufile_new(struct the_nilfs *nilfs, size_t susize); | 65 | struct nilfs_inode *raw_inode, struct inode **inodep); |
| 66 | 66 | ||
| 67 | /** | 67 | /** |
| 68 | * nilfs_sufile_scrap - make a segment garbage | 68 | * nilfs_sufile_scrap - make a segment garbage |
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index f3b75206e956..35ae03c0db86 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
| @@ -48,10 +48,10 @@ | |||
| 48 | #include <linux/vfs.h> | 48 | #include <linux/vfs.h> |
| 49 | #include <linux/writeback.h> | 49 | #include <linux/writeback.h> |
| 50 | #include <linux/kobject.h> | 50 | #include <linux/kobject.h> |
| 51 | #include <linux/exportfs.h> | ||
| 52 | #include <linux/seq_file.h> | 51 | #include <linux/seq_file.h> |
| 53 | #include <linux/mount.h> | 52 | #include <linux/mount.h> |
| 54 | #include "nilfs.h" | 53 | #include "nilfs.h" |
| 54 | #include "export.h" | ||
| 55 | #include "mdt.h" | 55 | #include "mdt.h" |
| 56 | #include "alloc.h" | 56 | #include "alloc.h" |
| 57 | #include "btree.h" | 57 | #include "btree.h" |
| @@ -68,11 +68,12 @@ MODULE_DESCRIPTION("A New Implementation of the Log-structured Filesystem " | |||
| 68 | "(NILFS)"); | 68 | "(NILFS)"); |
| 69 | MODULE_LICENSE("GPL"); | 69 | MODULE_LICENSE("GPL"); |
| 70 | 70 | ||
| 71 | struct kmem_cache *nilfs_inode_cachep; | 71 | static struct kmem_cache *nilfs_inode_cachep; |
| 72 | struct kmem_cache *nilfs_transaction_cachep; | 72 | struct kmem_cache *nilfs_transaction_cachep; |
| 73 | struct kmem_cache *nilfs_segbuf_cachep; | 73 | struct kmem_cache *nilfs_segbuf_cachep; |
| 74 | struct kmem_cache *nilfs_btree_path_cache; | 74 | struct kmem_cache *nilfs_btree_path_cache; |
| 75 | 75 | ||
| 76 | static int nilfs_setup_super(struct nilfs_sb_info *sbi, int is_mount); | ||
| 76 | static int nilfs_remount(struct super_block *sb, int *flags, char *data); | 77 | static int nilfs_remount(struct super_block *sb, int *flags, char *data); |
| 77 | 78 | ||
| 78 | static void nilfs_set_error(struct nilfs_sb_info *sbi) | 79 | static void nilfs_set_error(struct nilfs_sb_info *sbi) |
| @@ -146,7 +147,7 @@ void nilfs_warning(struct super_block *sb, const char *function, | |||
| 146 | } | 147 | } |
| 147 | 148 | ||
| 148 | 149 | ||
| 149 | struct inode *nilfs_alloc_inode_common(struct the_nilfs *nilfs) | 150 | struct inode *nilfs_alloc_inode(struct super_block *sb) |
| 150 | { | 151 | { |
| 151 | struct nilfs_inode_info *ii; | 152 | struct nilfs_inode_info *ii; |
| 152 | 153 | ||
| @@ -155,18 +156,20 @@ struct inode *nilfs_alloc_inode_common(struct the_nilfs *nilfs) | |||
| 155 | return NULL; | 156 | return NULL; |
| 156 | ii->i_bh = NULL; | 157 | ii->i_bh = NULL; |
| 157 | ii->i_state = 0; | 158 | ii->i_state = 0; |
| 159 | ii->i_cno = 0; | ||
| 158 | ii->vfs_inode.i_version = 1; | 160 | ii->vfs_inode.i_version = 1; |
| 159 | nilfs_btnode_cache_init(&ii->i_btnode_cache, nilfs->ns_bdi); | 161 | nilfs_btnode_cache_init(&ii->i_btnode_cache, sb->s_bdi); |
| 160 | return &ii->vfs_inode; | 162 | return &ii->vfs_inode; |
| 161 | } | 163 | } |
| 162 | 164 | ||
| 163 | struct inode *nilfs_alloc_inode(struct super_block *sb) | ||
| 164 | { | ||
| 165 | return nilfs_alloc_inode_common(NILFS_SB(sb)->s_nilfs); | ||
| 166 | } | ||
| 167 | |||
| 168 | void nilfs_destroy_inode(struct inode *inode) | 165 | void nilfs_destroy_inode(struct inode *inode) |
| 169 | { | 166 | { |
| 167 | struct nilfs_mdt_info *mdi = NILFS_MDT(inode); | ||
| 168 | |||
| 169 | if (mdi) { | ||
| 170 | kfree(mdi->mi_bgl); /* kfree(NULL) is safe */ | ||
| 171 | kfree(mdi); | ||
| 172 | } | ||
| 170 | kmem_cache_free(nilfs_inode_cachep, NILFS_I(inode)); | 173 | kmem_cache_free(nilfs_inode_cachep, NILFS_I(inode)); |
| 171 | } | 174 | } |
| 172 | 175 | ||
| @@ -340,16 +343,15 @@ static void nilfs_put_super(struct super_block *sb) | |||
| 340 | nilfs_cleanup_super(sbi); | 343 | nilfs_cleanup_super(sbi); |
| 341 | up_write(&nilfs->ns_sem); | 344 | up_write(&nilfs->ns_sem); |
| 342 | } | 345 | } |
| 343 | down_write(&nilfs->ns_super_sem); | ||
| 344 | if (nilfs->ns_current == sbi) | ||
| 345 | nilfs->ns_current = NULL; | ||
| 346 | up_write(&nilfs->ns_super_sem); | ||
| 347 | 346 | ||
| 348 | nilfs_detach_checkpoint(sbi); | 347 | iput(nilfs->ns_sufile); |
| 349 | put_nilfs(sbi->s_nilfs); | 348 | iput(nilfs->ns_cpfile); |
| 349 | iput(nilfs->ns_dat); | ||
| 350 | |||
| 351 | destroy_nilfs(nilfs); | ||
| 350 | sbi->s_super = NULL; | 352 | sbi->s_super = NULL; |
| 351 | sb->s_fs_info = NULL; | 353 | sb->s_fs_info = NULL; |
| 352 | nilfs_put_sbinfo(sbi); | 354 | kfree(sbi); |
| 353 | } | 355 | } |
| 354 | 356 | ||
| 355 | static int nilfs_sync_fs(struct super_block *sb, int wait) | 357 | static int nilfs_sync_fs(struct super_block *sb, int wait) |
| @@ -376,21 +378,22 @@ static int nilfs_sync_fs(struct super_block *sb, int wait) | |||
| 376 | return err; | 378 | return err; |
| 377 | } | 379 | } |
| 378 | 380 | ||
| 379 | int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno) | 381 | int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt, |
| 382 | struct nilfs_root **rootp) | ||
| 380 | { | 383 | { |
| 381 | struct the_nilfs *nilfs = sbi->s_nilfs; | 384 | struct the_nilfs *nilfs = sbi->s_nilfs; |
| 385 | struct nilfs_root *root; | ||
| 382 | struct nilfs_checkpoint *raw_cp; | 386 | struct nilfs_checkpoint *raw_cp; |
| 383 | struct buffer_head *bh_cp; | 387 | struct buffer_head *bh_cp; |
| 384 | int err; | 388 | int err = -ENOMEM; |
| 385 | 389 | ||
| 386 | down_write(&nilfs->ns_super_sem); | 390 | root = nilfs_find_or_create_root( |
| 387 | list_add(&sbi->s_list, &nilfs->ns_supers); | 391 | nilfs, curr_mnt ? NILFS_CPTREE_CURRENT_CNO : cno); |
| 388 | up_write(&nilfs->ns_super_sem); | 392 | if (!root) |
| 393 | return err; | ||
| 389 | 394 | ||
| 390 | err = -ENOMEM; | 395 | if (root->ifile) |
| 391 | sbi->s_ifile = nilfs_ifile_new(sbi, nilfs->ns_inode_size); | 396 | goto reuse; /* already attached checkpoint */ |
| 392 | if (!sbi->s_ifile) | ||
| 393 | goto delist; | ||
| 394 | 397 | ||
| 395 | down_read(&nilfs->ns_segctor_sem); | 398 | down_read(&nilfs->ns_segctor_sem); |
| 396 | err = nilfs_cpfile_get_checkpoint(nilfs->ns_cpfile, cno, 0, &raw_cp, | 399 | err = nilfs_cpfile_get_checkpoint(nilfs->ns_cpfile, cno, 0, &raw_cp, |
| @@ -406,45 +409,64 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno) | |||
| 406 | } | 409 | } |
| 407 | goto failed; | 410 | goto failed; |
| 408 | } | 411 | } |
| 409 | err = nilfs_read_inode_common(sbi->s_ifile, &raw_cp->cp_ifile_inode); | 412 | |
| 410 | if (unlikely(err)) | 413 | err = nilfs_ifile_read(sbi->s_super, root, nilfs->ns_inode_size, |
| 414 | &raw_cp->cp_ifile_inode, &root->ifile); | ||
| 415 | if (err) | ||
| 411 | goto failed_bh; | 416 | goto failed_bh; |
| 412 | atomic_set(&sbi->s_inodes_count, le64_to_cpu(raw_cp->cp_inodes_count)); | 417 | |
| 413 | atomic_set(&sbi->s_blocks_count, le64_to_cpu(raw_cp->cp_blocks_count)); | 418 | atomic_set(&root->inodes_count, le64_to_cpu(raw_cp->cp_inodes_count)); |
| 419 | atomic_set(&root->blocks_count, le64_to_cpu(raw_cp->cp_blocks_count)); | ||
| 414 | 420 | ||
| 415 | nilfs_cpfile_put_checkpoint(nilfs->ns_cpfile, cno, bh_cp); | 421 | nilfs_cpfile_put_checkpoint(nilfs->ns_cpfile, cno, bh_cp); |
| 422 | |||
| 423 | reuse: | ||
| 424 | *rootp = root; | ||
| 416 | return 0; | 425 | return 0; |
| 417 | 426 | ||
| 418 | failed_bh: | 427 | failed_bh: |
| 419 | nilfs_cpfile_put_checkpoint(nilfs->ns_cpfile, cno, bh_cp); | 428 | nilfs_cpfile_put_checkpoint(nilfs->ns_cpfile, cno, bh_cp); |
| 420 | failed: | 429 | failed: |
| 421 | nilfs_mdt_destroy(sbi->s_ifile); | 430 | nilfs_put_root(root); |
| 422 | sbi->s_ifile = NULL; | 431 | |
| 432 | return err; | ||
| 433 | } | ||
| 423 | 434 | ||
| 424 | delist: | 435 | static int nilfs_freeze(struct super_block *sb) |
| 425 | down_write(&nilfs->ns_super_sem); | 436 | { |
| 426 | list_del_init(&sbi->s_list); | 437 | struct nilfs_sb_info *sbi = NILFS_SB(sb); |
| 427 | up_write(&nilfs->ns_super_sem); | 438 | struct the_nilfs *nilfs = sbi->s_nilfs; |
| 439 | int err; | ||
| 440 | |||
| 441 | if (sb->s_flags & MS_RDONLY) | ||
| 442 | return 0; | ||
| 428 | 443 | ||
| 444 | /* Mark super block clean */ | ||
| 445 | down_write(&nilfs->ns_sem); | ||
| 446 | err = nilfs_cleanup_super(sbi); | ||
| 447 | up_write(&nilfs->ns_sem); | ||
| 429 | return err; | 448 | return err; |
| 430 | } | 449 | } |
| 431 | 450 | ||
| 432 | void nilfs_detach_checkpoint(struct nilfs_sb_info *sbi) | 451 | static int nilfs_unfreeze(struct super_block *sb) |
| 433 | { | 452 | { |
| 453 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | ||
| 434 | struct the_nilfs *nilfs = sbi->s_nilfs; | 454 | struct the_nilfs *nilfs = sbi->s_nilfs; |
| 435 | 455 | ||
| 436 | nilfs_mdt_destroy(sbi->s_ifile); | 456 | if (sb->s_flags & MS_RDONLY) |
| 437 | sbi->s_ifile = NULL; | 457 | return 0; |
| 438 | down_write(&nilfs->ns_super_sem); | 458 | |
| 439 | list_del_init(&sbi->s_list); | 459 | down_write(&nilfs->ns_sem); |
| 440 | up_write(&nilfs->ns_super_sem); | 460 | nilfs_setup_super(sbi, false); |
| 461 | up_write(&nilfs->ns_sem); | ||
| 462 | return 0; | ||
| 441 | } | 463 | } |
| 442 | 464 | ||
| 443 | static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) | 465 | static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
| 444 | { | 466 | { |
| 445 | struct super_block *sb = dentry->d_sb; | 467 | struct super_block *sb = dentry->d_sb; |
| 446 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 468 | struct nilfs_root *root = NILFS_I(dentry->d_inode)->i_root; |
| 447 | struct the_nilfs *nilfs = sbi->s_nilfs; | 469 | struct the_nilfs *nilfs = root->nilfs; |
| 448 | u64 id = huge_encode_dev(sb->s_bdev->bd_dev); | 470 | u64 id = huge_encode_dev(sb->s_bdev->bd_dev); |
| 449 | unsigned long long blocks; | 471 | unsigned long long blocks; |
| 450 | unsigned long overhead; | 472 | unsigned long overhead; |
| @@ -480,7 +502,7 @@ static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
| 480 | buf->f_bfree = nfreeblocks; | 502 | buf->f_bfree = nfreeblocks; |
| 481 | buf->f_bavail = (buf->f_bfree >= nrsvblocks) ? | 503 | buf->f_bavail = (buf->f_bfree >= nrsvblocks) ? |
| 482 | (buf->f_bfree - nrsvblocks) : 0; | 504 | (buf->f_bfree - nrsvblocks) : 0; |
| 483 | buf->f_files = atomic_read(&sbi->s_inodes_count); | 505 | buf->f_files = atomic_read(&root->inodes_count); |
| 484 | buf->f_ffree = 0; /* nilfs_count_free_inodes(sb); */ | 506 | buf->f_ffree = 0; /* nilfs_count_free_inodes(sb); */ |
| 485 | buf->f_namelen = NILFS_NAME_LEN; | 507 | buf->f_namelen = NILFS_NAME_LEN; |
| 486 | buf->f_fsid.val[0] = (u32)id; | 508 | buf->f_fsid.val[0] = (u32)id; |
| @@ -493,12 +515,12 @@ static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
| 493 | { | 515 | { |
| 494 | struct super_block *sb = vfs->mnt_sb; | 516 | struct super_block *sb = vfs->mnt_sb; |
| 495 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 517 | struct nilfs_sb_info *sbi = NILFS_SB(sb); |
| 518 | struct nilfs_root *root = NILFS_I(vfs->mnt_root->d_inode)->i_root; | ||
| 496 | 519 | ||
| 497 | if (!nilfs_test_opt(sbi, BARRIER)) | 520 | if (!nilfs_test_opt(sbi, BARRIER)) |
| 498 | seq_puts(seq, ",nobarrier"); | 521 | seq_puts(seq, ",nobarrier"); |
| 499 | if (nilfs_test_opt(sbi, SNAPSHOT)) | 522 | if (root->cno != NILFS_CPTREE_CURRENT_CNO) |
| 500 | seq_printf(seq, ",cp=%llu", | 523 | seq_printf(seq, ",cp=%llu", (unsigned long long)root->cno); |
| 501 | (unsigned long long int)sbi->s_snapshot_cno); | ||
| 502 | if (nilfs_test_opt(sbi, ERRORS_PANIC)) | 524 | if (nilfs_test_opt(sbi, ERRORS_PANIC)) |
| 503 | seq_puts(seq, ",errors=panic"); | 525 | seq_puts(seq, ",errors=panic"); |
| 504 | if (nilfs_test_opt(sbi, ERRORS_CONT)) | 526 | if (nilfs_test_opt(sbi, ERRORS_CONT)) |
| @@ -524,6 +546,8 @@ static const struct super_operations nilfs_sops = { | |||
| 524 | .put_super = nilfs_put_super, | 546 | .put_super = nilfs_put_super, |
| 525 | /* .write_super = nilfs_write_super, */ | 547 | /* .write_super = nilfs_write_super, */ |
| 526 | .sync_fs = nilfs_sync_fs, | 548 | .sync_fs = nilfs_sync_fs, |
| 549 | .freeze_fs = nilfs_freeze, | ||
| 550 | .unfreeze_fs = nilfs_unfreeze, | ||
| 527 | /* .write_super_lockfs */ | 551 | /* .write_super_lockfs */ |
| 528 | /* .unlockfs */ | 552 | /* .unlockfs */ |
| 529 | .statfs = nilfs_statfs, | 553 | .statfs = nilfs_statfs, |
| @@ -532,48 +556,6 @@ static const struct super_operations nilfs_sops = { | |||
| 532 | .show_options = nilfs_show_options | 556 | .show_options = nilfs_show_options |
| 533 | }; | 557 | }; |
| 534 | 558 | ||
| 535 | static struct inode * | ||
| 536 | nilfs_nfs_get_inode(struct super_block *sb, u64 ino, u32 generation) | ||
| 537 | { | ||
| 538 | struct inode *inode; | ||
| 539 | |||
| 540 | if (ino < NILFS_FIRST_INO(sb) && ino != NILFS_ROOT_INO && | ||
| 541 | ino != NILFS_SKETCH_INO) | ||
| 542 | return ERR_PTR(-ESTALE); | ||
| 543 | |||
| 544 | inode = nilfs_iget(sb, ino); | ||
| 545 | if (IS_ERR(inode)) | ||
| 546 | return ERR_CAST(inode); | ||
| 547 | if (generation && inode->i_generation != generation) { | ||
| 548 | iput(inode); | ||
| 549 | return ERR_PTR(-ESTALE); | ||
| 550 | } | ||
| 551 | |||
| 552 | return inode; | ||
| 553 | } | ||
| 554 | |||
| 555 | static struct dentry * | ||
| 556 | nilfs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len, | ||
| 557 | int fh_type) | ||
| 558 | { | ||
| 559 | return generic_fh_to_dentry(sb, fid, fh_len, fh_type, | ||
| 560 | nilfs_nfs_get_inode); | ||
| 561 | } | ||
| 562 | |||
| 563 | static struct dentry * | ||
| 564 | nilfs_fh_to_parent(struct super_block *sb, struct fid *fid, int fh_len, | ||
| 565 | int fh_type) | ||
| 566 | { | ||
| 567 | return generic_fh_to_parent(sb, fid, fh_len, fh_type, | ||
| 568 | nilfs_nfs_get_inode); | ||
| 569 | } | ||
| 570 | |||
| 571 | static const struct export_operations nilfs_export_ops = { | ||
| 572 | .fh_to_dentry = nilfs_fh_to_dentry, | ||
| 573 | .fh_to_parent = nilfs_fh_to_parent, | ||
| 574 | .get_parent = nilfs_get_parent, | ||
| 575 | }; | ||
| 576 | |||
| 577 | enum { | 559 | enum { |
| 578 | Opt_err_cont, Opt_err_panic, Opt_err_ro, | 560 | Opt_err_cont, Opt_err_panic, Opt_err_ro, |
| 579 | Opt_barrier, Opt_nobarrier, Opt_snapshot, Opt_order, Opt_norecovery, | 561 | Opt_barrier, Opt_nobarrier, Opt_snapshot, Opt_order, Opt_norecovery, |
| @@ -599,7 +581,6 @@ static int parse_options(char *options, struct super_block *sb, int is_remount) | |||
| 599 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 581 | struct nilfs_sb_info *sbi = NILFS_SB(sb); |
| 600 | char *p; | 582 | char *p; |
| 601 | substring_t args[MAX_OPT_ARGS]; | 583 | substring_t args[MAX_OPT_ARGS]; |
| 602 | int option; | ||
| 603 | 584 | ||
| 604 | if (!options) | 585 | if (!options) |
| 605 | return 1; | 586 | return 1; |
| @@ -637,30 +618,12 @@ static int parse_options(char *options, struct super_block *sb, int is_remount) | |||
| 637 | nilfs_write_opt(sbi, ERROR_MODE, ERRORS_CONT); | 618 | nilfs_write_opt(sbi, ERROR_MODE, ERRORS_CONT); |
| 638 | break; | 619 | break; |
| 639 | case Opt_snapshot: | 620 | case Opt_snapshot: |
| 640 | if (match_int(&args[0], &option) || option <= 0) | ||
| 641 | return 0; | ||
| 642 | if (is_remount) { | 621 | if (is_remount) { |
| 643 | if (!nilfs_test_opt(sbi, SNAPSHOT)) { | 622 | printk(KERN_ERR |
| 644 | printk(KERN_ERR | 623 | "NILFS: \"%s\" option is invalid " |
| 645 | "NILFS: cannot change regular " | 624 | "for remount.\n", p); |
| 646 | "mount to snapshot.\n"); | ||
| 647 | return 0; | ||
| 648 | } else if (option != sbi->s_snapshot_cno) { | ||
| 649 | printk(KERN_ERR | ||
| 650 | "NILFS: cannot remount to a " | ||
| 651 | "different snapshot.\n"); | ||
| 652 | return 0; | ||
| 653 | } | ||
| 654 | break; | ||
| 655 | } | ||
| 656 | if (!(sb->s_flags & MS_RDONLY)) { | ||
| 657 | printk(KERN_ERR "NILFS: cannot mount snapshot " | ||
| 658 | "read/write. A read-only option is " | ||
| 659 | "required.\n"); | ||
| 660 | return 0; | 625 | return 0; |
| 661 | } | 626 | } |
| 662 | sbi->s_snapshot_cno = option; | ||
| 663 | nilfs_set_opt(sbi, SNAPSHOT); | ||
| 664 | break; | 627 | break; |
| 665 | case Opt_norecovery: | 628 | case Opt_norecovery: |
| 666 | nilfs_set_opt(sbi, NORECOVERY); | 629 | nilfs_set_opt(sbi, NORECOVERY); |
| @@ -688,7 +651,7 @@ nilfs_set_default_options(struct nilfs_sb_info *sbi, | |||
| 688 | NILFS_MOUNT_ERRORS_RO | NILFS_MOUNT_BARRIER; | 651 | NILFS_MOUNT_ERRORS_RO | NILFS_MOUNT_BARRIER; |
| 689 | } | 652 | } |
| 690 | 653 | ||
| 691 | static int nilfs_setup_super(struct nilfs_sb_info *sbi) | 654 | static int nilfs_setup_super(struct nilfs_sb_info *sbi, int is_mount) |
| 692 | { | 655 | { |
| 693 | struct the_nilfs *nilfs = sbi->s_nilfs; | 656 | struct the_nilfs *nilfs = sbi->s_nilfs; |
| 694 | struct nilfs_super_block **sbp; | 657 | struct nilfs_super_block **sbp; |
| @@ -700,6 +663,9 @@ static int nilfs_setup_super(struct nilfs_sb_info *sbi) | |||
| 700 | if (!sbp) | 663 | if (!sbp) |
| 701 | return -EIO; | 664 | return -EIO; |
| 702 | 665 | ||
| 666 | if (!is_mount) | ||
| 667 | goto skip_mount_setup; | ||
| 668 | |||
| 703 | max_mnt_count = le16_to_cpu(sbp[0]->s_max_mnt_count); | 669 | max_mnt_count = le16_to_cpu(sbp[0]->s_max_mnt_count); |
| 704 | mnt_count = le16_to_cpu(sbp[0]->s_mnt_count); | 670 | mnt_count = le16_to_cpu(sbp[0]->s_mnt_count); |
| 705 | 671 | ||
| @@ -716,9 +682,11 @@ static int nilfs_setup_super(struct nilfs_sb_info *sbi) | |||
| 716 | sbp[0]->s_max_mnt_count = cpu_to_le16(NILFS_DFL_MAX_MNT_COUNT); | 682 | sbp[0]->s_max_mnt_count = cpu_to_le16(NILFS_DFL_MAX_MNT_COUNT); |
| 717 | 683 | ||
| 718 | sbp[0]->s_mnt_count = cpu_to_le16(mnt_count + 1); | 684 | sbp[0]->s_mnt_count = cpu_to_le16(mnt_count + 1); |
| 685 | sbp[0]->s_mtime = cpu_to_le64(get_seconds()); | ||
| 686 | |||
| 687 | skip_mount_setup: | ||
| 719 | sbp[0]->s_state = | 688 | sbp[0]->s_state = |
| 720 | cpu_to_le16(le16_to_cpu(sbp[0]->s_state) & ~NILFS_VALID_FS); | 689 | cpu_to_le16(le16_to_cpu(sbp[0]->s_state) & ~NILFS_VALID_FS); |
| 721 | sbp[0]->s_mtime = cpu_to_le64(get_seconds()); | ||
| 722 | /* synchronize sbp[1] with sbp[0] */ | 690 | /* synchronize sbp[1] with sbp[0] */ |
| 723 | memcpy(sbp[1], sbp[0], nilfs->ns_sbsize); | 691 | memcpy(sbp[1], sbp[0], nilfs->ns_sbsize); |
| 724 | return nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL); | 692 | return nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL); |
| @@ -785,22 +753,156 @@ int nilfs_check_feature_compatibility(struct super_block *sb, | |||
| 785 | return 0; | 753 | return 0; |
| 786 | } | 754 | } |
| 787 | 755 | ||
| 756 | static int nilfs_get_root_dentry(struct super_block *sb, | ||
| 757 | struct nilfs_root *root, | ||
| 758 | struct dentry **root_dentry) | ||
| 759 | { | ||
| 760 | struct inode *inode; | ||
| 761 | struct dentry *dentry; | ||
| 762 | int ret = 0; | ||
| 763 | |||
| 764 | inode = nilfs_iget(sb, root, NILFS_ROOT_INO); | ||
| 765 | if (IS_ERR(inode)) { | ||
| 766 | printk(KERN_ERR "NILFS: get root inode failed\n"); | ||
| 767 | ret = PTR_ERR(inode); | ||
| 768 | goto out; | ||
| 769 | } | ||
| 770 | if (!S_ISDIR(inode->i_mode) || !inode->i_blocks || !inode->i_size) { | ||
| 771 | iput(inode); | ||
| 772 | printk(KERN_ERR "NILFS: corrupt root inode.\n"); | ||
| 773 | ret = -EINVAL; | ||
| 774 | goto out; | ||
| 775 | } | ||
| 776 | |||
| 777 | if (root->cno == NILFS_CPTREE_CURRENT_CNO) { | ||
| 778 | dentry = d_find_alias(inode); | ||
| 779 | if (!dentry) { | ||
| 780 | dentry = d_alloc_root(inode); | ||
| 781 | if (!dentry) { | ||
| 782 | iput(inode); | ||
| 783 | ret = -ENOMEM; | ||
| 784 | goto failed_dentry; | ||
| 785 | } | ||
| 786 | } else { | ||
| 787 | iput(inode); | ||
| 788 | } | ||
| 789 | } else { | ||
| 790 | dentry = d_obtain_alias(inode); | ||
| 791 | if (IS_ERR(dentry)) { | ||
| 792 | ret = PTR_ERR(dentry); | ||
| 793 | goto failed_dentry; | ||
| 794 | } | ||
| 795 | } | ||
| 796 | *root_dentry = dentry; | ||
| 797 | out: | ||
| 798 | return ret; | ||
| 799 | |||
| 800 | failed_dentry: | ||
| 801 | printk(KERN_ERR "NILFS: get root dentry failed\n"); | ||
| 802 | goto out; | ||
| 803 | } | ||
| 804 | |||
| 805 | static int nilfs_attach_snapshot(struct super_block *s, __u64 cno, | ||
| 806 | struct dentry **root_dentry) | ||
| 807 | { | ||
| 808 | struct the_nilfs *nilfs = NILFS_SB(s)->s_nilfs; | ||
| 809 | struct nilfs_root *root; | ||
| 810 | int ret; | ||
| 811 | |||
| 812 | down_read(&nilfs->ns_segctor_sem); | ||
| 813 | ret = nilfs_cpfile_is_snapshot(nilfs->ns_cpfile, cno); | ||
| 814 | up_read(&nilfs->ns_segctor_sem); | ||
| 815 | if (ret < 0) { | ||
| 816 | ret = (ret == -ENOENT) ? -EINVAL : ret; | ||
| 817 | goto out; | ||
| 818 | } else if (!ret) { | ||
| 819 | printk(KERN_ERR "NILFS: The specified checkpoint is " | ||
| 820 | "not a snapshot (checkpoint number=%llu).\n", | ||
| 821 | (unsigned long long)cno); | ||
| 822 | ret = -EINVAL; | ||
| 823 | goto out; | ||
| 824 | } | ||
| 825 | |||
| 826 | ret = nilfs_attach_checkpoint(NILFS_SB(s), cno, false, &root); | ||
| 827 | if (ret) { | ||
| 828 | printk(KERN_ERR "NILFS: error loading snapshot " | ||
| 829 | "(checkpoint number=%llu).\n", | ||
| 830 | (unsigned long long)cno); | ||
| 831 | goto out; | ||
| 832 | } | ||
| 833 | ret = nilfs_get_root_dentry(s, root, root_dentry); | ||
| 834 | nilfs_put_root(root); | ||
| 835 | out: | ||
| 836 | return ret; | ||
| 837 | } | ||
| 838 | |||
| 839 | static int nilfs_tree_was_touched(struct dentry *root_dentry) | ||
| 840 | { | ||
| 841 | return atomic_read(&root_dentry->d_count) > 1; | ||
| 842 | } | ||
| 843 | |||
| 844 | /** | ||
| 845 | * nilfs_try_to_shrink_tree() - try to shrink dentries of a checkpoint | ||
| 846 | * @root_dentry: root dentry of the tree to be shrunk | ||
| 847 | * | ||
| 848 | * This function returns true if the tree was in-use. | ||
| 849 | */ | ||
| 850 | static int nilfs_try_to_shrink_tree(struct dentry *root_dentry) | ||
| 851 | { | ||
| 852 | if (have_submounts(root_dentry)) | ||
| 853 | return true; | ||
| 854 | shrink_dcache_parent(root_dentry); | ||
| 855 | return nilfs_tree_was_touched(root_dentry); | ||
| 856 | } | ||
| 857 | |||
| 858 | int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno) | ||
| 859 | { | ||
| 860 | struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; | ||
| 861 | struct nilfs_root *root; | ||
| 862 | struct inode *inode; | ||
| 863 | struct dentry *dentry; | ||
| 864 | int ret; | ||
| 865 | |||
| 866 | if (cno < 0 || cno > nilfs->ns_cno) | ||
| 867 | return false; | ||
| 868 | |||
| 869 | if (cno >= nilfs_last_cno(nilfs)) | ||
| 870 | return true; /* protect recent checkpoints */ | ||
| 871 | |||
| 872 | ret = false; | ||
| 873 | root = nilfs_lookup_root(NILFS_SB(sb)->s_nilfs, cno); | ||
| 874 | if (root) { | ||
| 875 | inode = nilfs_ilookup(sb, root, NILFS_ROOT_INO); | ||
| 876 | if (inode) { | ||
| 877 | dentry = d_find_alias(inode); | ||
| 878 | if (dentry) { | ||
| 879 | if (nilfs_tree_was_touched(dentry)) | ||
| 880 | ret = nilfs_try_to_shrink_tree(dentry); | ||
| 881 | dput(dentry); | ||
| 882 | } | ||
| 883 | iput(inode); | ||
| 884 | } | ||
| 885 | nilfs_put_root(root); | ||
| 886 | } | ||
| 887 | return ret; | ||
| 888 | } | ||
| 889 | |||
| 788 | /** | 890 | /** |
| 789 | * nilfs_fill_super() - initialize a super block instance | 891 | * nilfs_fill_super() - initialize a super block instance |
| 790 | * @sb: super_block | 892 | * @sb: super_block |
| 791 | * @data: mount options | 893 | * @data: mount options |
| 792 | * @silent: silent mode flag | 894 | * @silent: silent mode flag |
| 793 | * @nilfs: the_nilfs struct | ||
| 794 | * | 895 | * |
| 795 | * This function is called exclusively by nilfs->ns_mount_mutex. | 896 | * This function is called exclusively by nilfs->ns_mount_mutex. |
| 796 | * So, the recovery process is protected from other simultaneous mounts. | 897 | * So, the recovery process is protected from other simultaneous mounts. |
| 797 | */ | 898 | */ |
| 798 | static int | 899 | static int |
| 799 | nilfs_fill_super(struct super_block *sb, void *data, int silent, | 900 | nilfs_fill_super(struct super_block *sb, void *data, int silent) |
| 800 | struct the_nilfs *nilfs) | ||
| 801 | { | 901 | { |
| 902 | struct the_nilfs *nilfs; | ||
| 802 | struct nilfs_sb_info *sbi; | 903 | struct nilfs_sb_info *sbi; |
| 803 | struct inode *root; | 904 | struct nilfs_root *fsroot; |
| 905 | struct backing_dev_info *bdi; | ||
| 804 | __u64 cno; | 906 | __u64 cno; |
| 805 | int err; | 907 | int err; |
| 806 | 908 | ||
| @@ -809,19 +911,21 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
| 809 | return -ENOMEM; | 911 | return -ENOMEM; |
| 810 | 912 | ||
| 811 | sb->s_fs_info = sbi; | 913 | sb->s_fs_info = sbi; |
| 914 | sbi->s_super = sb; | ||
| 812 | 915 | ||
| 813 | get_nilfs(nilfs); | 916 | nilfs = alloc_nilfs(sb->s_bdev); |
| 917 | if (!nilfs) { | ||
| 918 | err = -ENOMEM; | ||
| 919 | goto failed_sbi; | ||
| 920 | } | ||
| 814 | sbi->s_nilfs = nilfs; | 921 | sbi->s_nilfs = nilfs; |
| 815 | sbi->s_super = sb; | ||
| 816 | atomic_set(&sbi->s_count, 1); | ||
| 817 | 922 | ||
| 818 | err = init_nilfs(nilfs, sbi, (char *)data); | 923 | err = init_nilfs(nilfs, sbi, (char *)data); |
| 819 | if (err) | 924 | if (err) |
| 820 | goto failed_sbi; | 925 | goto failed_nilfs; |
| 821 | 926 | ||
| 822 | spin_lock_init(&sbi->s_inode_lock); | 927 | spin_lock_init(&sbi->s_inode_lock); |
| 823 | INIT_LIST_HEAD(&sbi->s_dirty_files); | 928 | INIT_LIST_HEAD(&sbi->s_dirty_files); |
| 824 | INIT_LIST_HEAD(&sbi->s_list); | ||
| 825 | 929 | ||
| 826 | /* | 930 | /* |
| 827 | * Following initialization is overlapped because | 931 | * Following initialization is overlapped because |
| @@ -837,94 +941,59 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
| 837 | sb->s_export_op = &nilfs_export_ops; | 941 | sb->s_export_op = &nilfs_export_ops; |
| 838 | sb->s_root = NULL; | 942 | sb->s_root = NULL; |
| 839 | sb->s_time_gran = 1; | 943 | sb->s_time_gran = 1; |
| 840 | sb->s_bdi = nilfs->ns_bdi; | 944 | |
| 945 | bdi = sb->s_bdev->bd_inode->i_mapping->backing_dev_info; | ||
| 946 | sb->s_bdi = bdi ? : &default_backing_dev_info; | ||
| 841 | 947 | ||
| 842 | err = load_nilfs(nilfs, sbi); | 948 | err = load_nilfs(nilfs, sbi); |
| 843 | if (err) | 949 | if (err) |
| 844 | goto failed_sbi; | 950 | goto failed_nilfs; |
| 845 | 951 | ||
| 846 | cno = nilfs_last_cno(nilfs); | 952 | cno = nilfs_last_cno(nilfs); |
| 847 | 953 | err = nilfs_attach_checkpoint(sbi, cno, true, &fsroot); | |
| 848 | if (sb->s_flags & MS_RDONLY) { | ||
| 849 | if (nilfs_test_opt(sbi, SNAPSHOT)) { | ||
| 850 | down_read(&nilfs->ns_segctor_sem); | ||
| 851 | err = nilfs_cpfile_is_snapshot(nilfs->ns_cpfile, | ||
| 852 | sbi->s_snapshot_cno); | ||
| 853 | up_read(&nilfs->ns_segctor_sem); | ||
| 854 | if (err < 0) { | ||
| 855 | if (err == -ENOENT) | ||
| 856 | err = -EINVAL; | ||
| 857 | goto failed_sbi; | ||
| 858 | } | ||
| 859 | if (!err) { | ||
| 860 | printk(KERN_ERR | ||
| 861 | "NILFS: The specified checkpoint is " | ||
| 862 | "not a snapshot " | ||
| 863 | "(checkpoint number=%llu).\n", | ||
| 864 | (unsigned long long)sbi->s_snapshot_cno); | ||
| 865 | err = -EINVAL; | ||
| 866 | goto failed_sbi; | ||
| 867 | } | ||
| 868 | cno = sbi->s_snapshot_cno; | ||
| 869 | } | ||
| 870 | } | ||
| 871 | |||
| 872 | err = nilfs_attach_checkpoint(sbi, cno); | ||
| 873 | if (err) { | 954 | if (err) { |
| 874 | printk(KERN_ERR "NILFS: error loading a checkpoint" | 955 | printk(KERN_ERR "NILFS: error loading last checkpoint " |
| 875 | " (checkpoint number=%llu).\n", (unsigned long long)cno); | 956 | "(checkpoint number=%llu).\n", (unsigned long long)cno); |
| 876 | goto failed_sbi; | 957 | goto failed_unload; |
| 877 | } | 958 | } |
| 878 | 959 | ||
| 879 | if (!(sb->s_flags & MS_RDONLY)) { | 960 | if (!(sb->s_flags & MS_RDONLY)) { |
| 880 | err = nilfs_attach_segment_constructor(sbi); | 961 | err = nilfs_attach_segment_constructor(sbi, fsroot); |
| 881 | if (err) | 962 | if (err) |
| 882 | goto failed_checkpoint; | 963 | goto failed_checkpoint; |
| 883 | } | 964 | } |
| 884 | 965 | ||
| 885 | root = nilfs_iget(sb, NILFS_ROOT_INO); | 966 | err = nilfs_get_root_dentry(sb, fsroot, &sb->s_root); |
| 886 | if (IS_ERR(root)) { | 967 | if (err) |
| 887 | printk(KERN_ERR "NILFS: get root inode failed\n"); | ||
| 888 | err = PTR_ERR(root); | ||
| 889 | goto failed_segctor; | ||
| 890 | } | ||
| 891 | if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) { | ||
| 892 | iput(root); | ||
| 893 | printk(KERN_ERR "NILFS: corrupt root inode.\n"); | ||
| 894 | err = -EINVAL; | ||
| 895 | goto failed_segctor; | ||
| 896 | } | ||
| 897 | sb->s_root = d_alloc_root(root); | ||
| 898 | if (!sb->s_root) { | ||
| 899 | iput(root); | ||
| 900 | printk(KERN_ERR "NILFS: get root dentry failed\n"); | ||
| 901 | err = -ENOMEM; | ||
| 902 | goto failed_segctor; | 968 | goto failed_segctor; |
| 903 | } | 969 | |
| 970 | nilfs_put_root(fsroot); | ||
| 904 | 971 | ||
| 905 | if (!(sb->s_flags & MS_RDONLY)) { | 972 | if (!(sb->s_flags & MS_RDONLY)) { |
| 906 | down_write(&nilfs->ns_sem); | 973 | down_write(&nilfs->ns_sem); |
| 907 | nilfs_setup_super(sbi); | 974 | nilfs_setup_super(sbi, true); |
| 908 | up_write(&nilfs->ns_sem); | 975 | up_write(&nilfs->ns_sem); |
| 909 | } | 976 | } |
| 910 | 977 | ||
| 911 | down_write(&nilfs->ns_super_sem); | ||
| 912 | if (!nilfs_test_opt(sbi, SNAPSHOT)) | ||
| 913 | nilfs->ns_current = sbi; | ||
| 914 | up_write(&nilfs->ns_super_sem); | ||
| 915 | |||
| 916 | return 0; | 978 | return 0; |
| 917 | 979 | ||
| 918 | failed_segctor: | 980 | failed_segctor: |
| 919 | nilfs_detach_segment_constructor(sbi); | 981 | nilfs_detach_segment_constructor(sbi); |
| 920 | 982 | ||
| 921 | failed_checkpoint: | 983 | failed_checkpoint: |
| 922 | nilfs_detach_checkpoint(sbi); | 984 | nilfs_put_root(fsroot); |
| 985 | |||
| 986 | failed_unload: | ||
| 987 | iput(nilfs->ns_sufile); | ||
| 988 | iput(nilfs->ns_cpfile); | ||
| 989 | iput(nilfs->ns_dat); | ||
| 990 | |||
| 991 | failed_nilfs: | ||
| 992 | destroy_nilfs(nilfs); | ||
| 923 | 993 | ||
| 924 | failed_sbi: | 994 | failed_sbi: |
| 925 | put_nilfs(nilfs); | ||
| 926 | sb->s_fs_info = NULL; | 995 | sb->s_fs_info = NULL; |
| 927 | nilfs_put_sbinfo(sbi); | 996 | kfree(sbi); |
| 928 | return err; | 997 | return err; |
| 929 | } | 998 | } |
| 930 | 999 | ||
| @@ -934,13 +1003,10 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
| 934 | struct the_nilfs *nilfs = sbi->s_nilfs; | 1003 | struct the_nilfs *nilfs = sbi->s_nilfs; |
| 935 | unsigned long old_sb_flags; | 1004 | unsigned long old_sb_flags; |
| 936 | struct nilfs_mount_options old_opts; | 1005 | struct nilfs_mount_options old_opts; |
| 937 | int was_snapshot, err; | 1006 | int err; |
| 938 | 1007 | ||
| 939 | down_write(&nilfs->ns_super_sem); | ||
| 940 | old_sb_flags = sb->s_flags; | 1008 | old_sb_flags = sb->s_flags; |
| 941 | old_opts.mount_opt = sbi->s_mount_opt; | 1009 | old_opts.mount_opt = sbi->s_mount_opt; |
| 942 | old_opts.snapshot_cno = sbi->s_snapshot_cno; | ||
| 943 | was_snapshot = nilfs_test_opt(sbi, SNAPSHOT); | ||
| 944 | 1010 | ||
| 945 | if (!parse_options(data, sb, 1)) { | 1011 | if (!parse_options(data, sb, 1)) { |
| 946 | err = -EINVAL; | 1012 | err = -EINVAL; |
| @@ -949,11 +1015,6 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
| 949 | sb->s_flags = (sb->s_flags & ~MS_POSIXACL); | 1015 | sb->s_flags = (sb->s_flags & ~MS_POSIXACL); |
| 950 | 1016 | ||
| 951 | err = -EINVAL; | 1017 | err = -EINVAL; |
| 952 | if (was_snapshot && !(*flags & MS_RDONLY)) { | ||
| 953 | printk(KERN_ERR "NILFS (device %s): cannot remount snapshot " | ||
| 954 | "read/write.\n", sb->s_id); | ||
| 955 | goto restore_opts; | ||
| 956 | } | ||
| 957 | 1018 | ||
| 958 | if (!nilfs_valid_fs(nilfs)) { | 1019 | if (!nilfs_valid_fs(nilfs)) { |
| 959 | printk(KERN_WARNING "NILFS (device %s): couldn't " | 1020 | printk(KERN_WARNING "NILFS (device %s): couldn't " |
| @@ -978,6 +1039,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
| 978 | up_write(&nilfs->ns_sem); | 1039 | up_write(&nilfs->ns_sem); |
| 979 | } else { | 1040 | } else { |
| 980 | __u64 features; | 1041 | __u64 features; |
| 1042 | struct nilfs_root *root; | ||
| 981 | 1043 | ||
| 982 | /* | 1044 | /* |
| 983 | * Mounting a RDONLY partition read-write, so reread and | 1045 | * Mounting a RDONLY partition read-write, so reread and |
| @@ -999,23 +1061,21 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
| 999 | 1061 | ||
| 1000 | sb->s_flags &= ~MS_RDONLY; | 1062 | sb->s_flags &= ~MS_RDONLY; |
| 1001 | 1063 | ||
| 1002 | err = nilfs_attach_segment_constructor(sbi); | 1064 | root = NILFS_I(sb->s_root->d_inode)->i_root; |
| 1065 | err = nilfs_attach_segment_constructor(sbi, root); | ||
| 1003 | if (err) | 1066 | if (err) |
| 1004 | goto restore_opts; | 1067 | goto restore_opts; |
| 1005 | 1068 | ||
| 1006 | down_write(&nilfs->ns_sem); | 1069 | down_write(&nilfs->ns_sem); |
| 1007 | nilfs_setup_super(sbi); | 1070 | nilfs_setup_super(sbi, true); |
| 1008 | up_write(&nilfs->ns_sem); | 1071 | up_write(&nilfs->ns_sem); |
| 1009 | } | 1072 | } |
| 1010 | out: | 1073 | out: |
| 1011 | up_write(&nilfs->ns_super_sem); | ||
| 1012 | return 0; | 1074 | return 0; |
| 1013 | 1075 | ||
| 1014 | restore_opts: | 1076 | restore_opts: |
| 1015 | sb->s_flags = old_sb_flags; | 1077 | sb->s_flags = old_sb_flags; |
| 1016 | sbi->s_mount_opt = old_opts.mount_opt; | 1078 | sbi->s_mount_opt = old_opts.mount_opt; |
| 1017 | sbi->s_snapshot_cno = old_opts.snapshot_cno; | ||
| 1018 | up_write(&nilfs->ns_super_sem); | ||
| 1019 | return err; | 1079 | return err; |
| 1020 | } | 1080 | } |
| 1021 | 1081 | ||
| @@ -1035,7 +1095,7 @@ static int nilfs_identify(char *data, struct nilfs_super_data *sd) | |||
| 1035 | { | 1095 | { |
| 1036 | char *p, *options = data; | 1096 | char *p, *options = data; |
| 1037 | substring_t args[MAX_OPT_ARGS]; | 1097 | substring_t args[MAX_OPT_ARGS]; |
| 1038 | int option, token; | 1098 | int token; |
| 1039 | int ret = 0; | 1099 | int ret = 0; |
| 1040 | 1100 | ||
| 1041 | do { | 1101 | do { |
| @@ -1043,16 +1103,18 @@ static int nilfs_identify(char *data, struct nilfs_super_data *sd) | |||
| 1043 | if (p != NULL && *p) { | 1103 | if (p != NULL && *p) { |
| 1044 | token = match_token(p, tokens, args); | 1104 | token = match_token(p, tokens, args); |
| 1045 | if (token == Opt_snapshot) { | 1105 | if (token == Opt_snapshot) { |
| 1046 | if (!(sd->flags & MS_RDONLY)) | 1106 | if (!(sd->flags & MS_RDONLY)) { |
| 1047 | ret++; | 1107 | ret++; |
| 1048 | else { | 1108 | } else { |
| 1049 | ret = match_int(&args[0], &option); | 1109 | sd->cno = simple_strtoull(args[0].from, |
| 1050 | if (!ret) { | 1110 | NULL, 0); |
| 1051 | if (option > 0) | 1111 | /* |
| 1052 | sd->cno = option; | 1112 | * No need to see the end pointer; |
| 1053 | else | 1113 | * match_token() has done syntax |
| 1054 | ret++; | 1114 | * checking. |
| 1055 | } | 1115 | */ |
| 1116 | if (sd->cno == 0) | ||
| 1117 | ret++; | ||
| 1056 | } | 1118 | } |
| 1057 | } | 1119 | } |
| 1058 | if (ret) | 1120 | if (ret) |
| @@ -1069,18 +1131,14 @@ static int nilfs_identify(char *data, struct nilfs_super_data *sd) | |||
| 1069 | 1131 | ||
| 1070 | static int nilfs_set_bdev_super(struct super_block *s, void *data) | 1132 | static int nilfs_set_bdev_super(struct super_block *s, void *data) |
| 1071 | { | 1133 | { |
| 1072 | struct nilfs_super_data *sd = data; | 1134 | s->s_bdev = data; |
| 1073 | |||
| 1074 | s->s_bdev = sd->bdev; | ||
| 1075 | s->s_dev = s->s_bdev->bd_dev; | 1135 | s->s_dev = s->s_bdev->bd_dev; |
| 1076 | return 0; | 1136 | return 0; |
| 1077 | } | 1137 | } |
| 1078 | 1138 | ||
| 1079 | static int nilfs_test_bdev_super(struct super_block *s, void *data) | 1139 | static int nilfs_test_bdev_super(struct super_block *s, void *data) |
| 1080 | { | 1140 | { |
| 1081 | struct nilfs_super_data *sd = data; | 1141 | return (void *)s->s_bdev == data; |
| 1082 | |||
| 1083 | return sd->sbi && s->s_fs_info == (void *)sd->sbi; | ||
| 1084 | } | 1142 | } |
| 1085 | 1143 | ||
| 1086 | static int | 1144 | static int |
| @@ -1090,8 +1148,8 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
| 1090 | struct nilfs_super_data sd; | 1148 | struct nilfs_super_data sd; |
| 1091 | struct super_block *s; | 1149 | struct super_block *s; |
| 1092 | fmode_t mode = FMODE_READ; | 1150 | fmode_t mode = FMODE_READ; |
| 1093 | struct the_nilfs *nilfs; | 1151 | struct dentry *root_dentry; |
| 1094 | int err, need_to_close = 1; | 1152 | int err, s_new = false; |
| 1095 | 1153 | ||
| 1096 | if (!(flags & MS_RDONLY)) | 1154 | if (!(flags & MS_RDONLY)) |
| 1097 | mode |= FMODE_WRITE; | 1155 | mode |= FMODE_WRITE; |
| @@ -1100,12 +1158,6 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
| 1100 | if (IS_ERR(sd.bdev)) | 1158 | if (IS_ERR(sd.bdev)) |
| 1101 | return PTR_ERR(sd.bdev); | 1159 | return PTR_ERR(sd.bdev); |
| 1102 | 1160 | ||
| 1103 | /* | ||
| 1104 | * To get mount instance using sget() vfs-routine, NILFS needs | ||
| 1105 | * much more information than normal filesystems to identify mount | ||
| 1106 | * instance. For snapshot mounts, not only a mount type (ro-mount | ||
| 1107 | * or rw-mount) but also a checkpoint number is required. | ||
| 1108 | */ | ||
| 1109 | sd.cno = 0; | 1161 | sd.cno = 0; |
| 1110 | sd.flags = flags; | 1162 | sd.flags = flags; |
| 1111 | if (nilfs_identify((char *)data, &sd)) { | 1163 | if (nilfs_identify((char *)data, &sd)) { |
| @@ -1113,93 +1165,86 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
| 1113 | goto failed; | 1165 | goto failed; |
| 1114 | } | 1166 | } |
| 1115 | 1167 | ||
| 1116 | nilfs = find_or_create_nilfs(sd.bdev); | ||
| 1117 | if (!nilfs) { | ||
| 1118 | err = -ENOMEM; | ||
| 1119 | goto failed; | ||
| 1120 | } | ||
| 1121 | |||
| 1122 | mutex_lock(&nilfs->ns_mount_mutex); | ||
| 1123 | |||
| 1124 | if (!sd.cno) { | ||
| 1125 | /* | ||
| 1126 | * Check if an exclusive mount exists or not. | ||
| 1127 | * Snapshot mounts coexist with a current mount | ||
| 1128 | * (i.e. rw-mount or ro-mount), whereas rw-mount and | ||
| 1129 | * ro-mount are mutually exclusive. | ||
| 1130 | */ | ||
| 1131 | down_read(&nilfs->ns_super_sem); | ||
| 1132 | if (nilfs->ns_current && | ||
| 1133 | ((nilfs->ns_current->s_super->s_flags ^ flags) | ||
| 1134 | & MS_RDONLY)) { | ||
| 1135 | up_read(&nilfs->ns_super_sem); | ||
| 1136 | err = -EBUSY; | ||
| 1137 | goto failed_unlock; | ||
| 1138 | } | ||
| 1139 | up_read(&nilfs->ns_super_sem); | ||
| 1140 | } | ||
| 1141 | |||
| 1142 | /* | ||
| 1143 | * Find existing nilfs_sb_info struct | ||
| 1144 | */ | ||
| 1145 | sd.sbi = nilfs_find_sbinfo(nilfs, !(flags & MS_RDONLY), sd.cno); | ||
| 1146 | |||
| 1147 | /* | 1168 | /* |
| 1148 | * Get super block instance holding the nilfs_sb_info struct. | 1169 | * once the super is inserted into the list by sget, s_umount |
| 1149 | * A new instance is allocated if no existing mount is present or | 1170 | * will protect the lockfs code from trying to start a snapshot |
| 1150 | * existing instance has been unmounted. | 1171 | * while we are mounting |
| 1151 | */ | 1172 | */ |
| 1152 | s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, &sd); | 1173 | mutex_lock(&sd.bdev->bd_fsfreeze_mutex); |
| 1153 | if (sd.sbi) | 1174 | if (sd.bdev->bd_fsfreeze_count > 0) { |
| 1154 | nilfs_put_sbinfo(sd.sbi); | 1175 | mutex_unlock(&sd.bdev->bd_fsfreeze_mutex); |
| 1155 | 1176 | err = -EBUSY; | |
| 1177 | goto failed; | ||
| 1178 | } | ||
| 1179 | s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, sd.bdev); | ||
| 1180 | mutex_unlock(&sd.bdev->bd_fsfreeze_mutex); | ||
| 1156 | if (IS_ERR(s)) { | 1181 | if (IS_ERR(s)) { |
| 1157 | err = PTR_ERR(s); | 1182 | err = PTR_ERR(s); |
| 1158 | goto failed_unlock; | 1183 | goto failed; |
| 1159 | } | 1184 | } |
| 1160 | 1185 | ||
| 1161 | if (!s->s_root) { | 1186 | if (!s->s_root) { |
| 1162 | char b[BDEVNAME_SIZE]; | 1187 | char b[BDEVNAME_SIZE]; |
| 1163 | 1188 | ||
| 1189 | s_new = true; | ||
| 1190 | |||
| 1164 | /* New superblock instance created */ | 1191 | /* New superblock instance created */ |
| 1165 | s->s_flags = flags; | 1192 | s->s_flags = flags; |
| 1166 | s->s_mode = mode; | 1193 | s->s_mode = mode; |
| 1167 | strlcpy(s->s_id, bdevname(sd.bdev, b), sizeof(s->s_id)); | 1194 | strlcpy(s->s_id, bdevname(sd.bdev, b), sizeof(s->s_id)); |
| 1168 | sb_set_blocksize(s, block_size(sd.bdev)); | 1195 | sb_set_blocksize(s, block_size(sd.bdev)); |
| 1169 | 1196 | ||
| 1170 | err = nilfs_fill_super(s, data, flags & MS_SILENT ? 1 : 0, | 1197 | err = nilfs_fill_super(s, data, flags & MS_SILENT ? 1 : 0); |
| 1171 | nilfs); | ||
| 1172 | if (err) | 1198 | if (err) |
| 1173 | goto cancel_new; | 1199 | goto failed_super; |
| 1174 | 1200 | ||
| 1175 | s->s_flags |= MS_ACTIVE; | 1201 | s->s_flags |= MS_ACTIVE; |
| 1176 | need_to_close = 0; | 1202 | } else if (!sd.cno) { |
| 1203 | int busy = false; | ||
| 1204 | |||
| 1205 | if (nilfs_tree_was_touched(s->s_root)) { | ||
| 1206 | busy = nilfs_try_to_shrink_tree(s->s_root); | ||
| 1207 | if (busy && (flags ^ s->s_flags) & MS_RDONLY) { | ||
| 1208 | printk(KERN_ERR "NILFS: the device already " | ||
| 1209 | "has a %s mount.\n", | ||
| 1210 | (s->s_flags & MS_RDONLY) ? | ||
| 1211 | "read-only" : "read/write"); | ||
| 1212 | err = -EBUSY; | ||
| 1213 | goto failed_super; | ||
| 1214 | } | ||
| 1215 | } | ||
| 1216 | if (!busy) { | ||
| 1217 | /* | ||
| 1218 | * Try remount to setup mount states if the current | ||
| 1219 | * tree is not mounted and only snapshots use this sb. | ||
| 1220 | */ | ||
| 1221 | err = nilfs_remount(s, &flags, data); | ||
| 1222 | if (err) | ||
| 1223 | goto failed_super; | ||
| 1224 | } | ||
| 1177 | } | 1225 | } |
| 1178 | 1226 | ||
| 1179 | mutex_unlock(&nilfs->ns_mount_mutex); | 1227 | if (sd.cno) { |
| 1180 | put_nilfs(nilfs); | 1228 | err = nilfs_attach_snapshot(s, sd.cno, &root_dentry); |
| 1181 | if (need_to_close) | 1229 | if (err) |
| 1230 | goto failed_super; | ||
| 1231 | } else { | ||
| 1232 | root_dentry = dget(s->s_root); | ||
| 1233 | } | ||
| 1234 | |||
| 1235 | if (!s_new) | ||
| 1182 | close_bdev_exclusive(sd.bdev, mode); | 1236 | close_bdev_exclusive(sd.bdev, mode); |
| 1183 | simple_set_mnt(mnt, s); | ||
| 1184 | return 0; | ||
| 1185 | 1237 | ||
| 1186 | failed_unlock: | 1238 | mnt->mnt_sb = s; |
| 1187 | mutex_unlock(&nilfs->ns_mount_mutex); | 1239 | mnt->mnt_root = root_dentry; |
| 1188 | put_nilfs(nilfs); | 1240 | return 0; |
| 1189 | failed: | ||
| 1190 | close_bdev_exclusive(sd.bdev, mode); | ||
| 1191 | return err; | ||
| 1192 | 1241 | ||
| 1193 | cancel_new: | 1242 | failed_super: |
| 1194 | /* Abandoning the newly allocated superblock */ | ||
| 1195 | mutex_unlock(&nilfs->ns_mount_mutex); | ||
| 1196 | put_nilfs(nilfs); | ||
| 1197 | deactivate_locked_super(s); | 1243 | deactivate_locked_super(s); |
| 1198 | /* | 1244 | |
| 1199 | * deactivate_locked_super() invokes close_bdev_exclusive(). | 1245 | failed: |
| 1200 | * We must finish all post-cleaning before this call; | 1246 | if (!s_new) |
| 1201 | * put_nilfs() needs the block device. | 1247 | close_bdev_exclusive(sd.bdev, mode); |
| 1202 | */ | ||
| 1203 | return err; | 1248 | return err; |
| 1204 | } | 1249 | } |
| 1205 | 1250 | ||
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index d27715103376..0254be2d73c6 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c | |||
| @@ -35,9 +35,6 @@ | |||
| 35 | #include "segbuf.h" | 35 | #include "segbuf.h" |
| 36 | 36 | ||
| 37 | 37 | ||
| 38 | static LIST_HEAD(nilfs_objects); | ||
| 39 | static DEFINE_SPINLOCK(nilfs_lock); | ||
| 40 | |||
| 41 | static int nilfs_valid_sb(struct nilfs_super_block *sbp); | 38 | static int nilfs_valid_sb(struct nilfs_super_block *sbp); |
| 42 | 39 | ||
| 43 | void nilfs_set_last_segment(struct the_nilfs *nilfs, | 40 | void nilfs_set_last_segment(struct the_nilfs *nilfs, |
| @@ -61,16 +58,13 @@ void nilfs_set_last_segment(struct the_nilfs *nilfs, | |||
| 61 | } | 58 | } |
| 62 | 59 | ||
| 63 | /** | 60 | /** |
| 64 | * alloc_nilfs - allocate the_nilfs structure | 61 | * alloc_nilfs - allocate a nilfs object |
| 65 | * @bdev: block device to which the_nilfs is related | 62 | * @bdev: block device to which the_nilfs is related |
| 66 | * | 63 | * |
| 67 | * alloc_nilfs() allocates memory for the_nilfs and | ||
| 68 | * initializes its reference count and locks. | ||
| 69 | * | ||
| 70 | * Return Value: On success, pointer to the_nilfs is returned. | 64 | * Return Value: On success, pointer to the_nilfs is returned. |
| 71 | * On error, NULL is returned. | 65 | * On error, NULL is returned. |
| 72 | */ | 66 | */ |
| 73 | static struct the_nilfs *alloc_nilfs(struct block_device *bdev) | 67 | struct the_nilfs *alloc_nilfs(struct block_device *bdev) |
| 74 | { | 68 | { |
| 75 | struct the_nilfs *nilfs; | 69 | struct the_nilfs *nilfs; |
| 76 | 70 | ||
| @@ -79,103 +73,38 @@ static struct the_nilfs *alloc_nilfs(struct block_device *bdev) | |||
| 79 | return NULL; | 73 | return NULL; |
| 80 | 74 | ||
| 81 | nilfs->ns_bdev = bdev; | 75 | nilfs->ns_bdev = bdev; |
| 82 | atomic_set(&nilfs->ns_count, 1); | ||
| 83 | atomic_set(&nilfs->ns_ndirtyblks, 0); | 76 | atomic_set(&nilfs->ns_ndirtyblks, 0); |
| 84 | init_rwsem(&nilfs->ns_sem); | 77 | init_rwsem(&nilfs->ns_sem); |
| 85 | init_rwsem(&nilfs->ns_super_sem); | 78 | INIT_LIST_HEAD(&nilfs->ns_gc_inodes); |
| 86 | mutex_init(&nilfs->ns_mount_mutex); | ||
| 87 | init_rwsem(&nilfs->ns_writer_sem); | ||
| 88 | INIT_LIST_HEAD(&nilfs->ns_list); | ||
| 89 | INIT_LIST_HEAD(&nilfs->ns_supers); | ||
| 90 | spin_lock_init(&nilfs->ns_last_segment_lock); | 79 | spin_lock_init(&nilfs->ns_last_segment_lock); |
| 91 | nilfs->ns_gc_inodes_h = NULL; | 80 | nilfs->ns_cptree = RB_ROOT; |
| 81 | spin_lock_init(&nilfs->ns_cptree_lock); | ||
| 92 | init_rwsem(&nilfs->ns_segctor_sem); | 82 | init_rwsem(&nilfs->ns_segctor_sem); |
| 93 | 83 | ||
| 94 | return nilfs; | 84 | return nilfs; |
| 95 | } | 85 | } |
| 96 | 86 | ||
| 97 | /** | 87 | /** |
| 98 | * find_or_create_nilfs - find or create nilfs object | 88 | * destroy_nilfs - destroy nilfs object |
| 99 | * @bdev: block device to which the_nilfs is related | 89 | * @nilfs: nilfs object to be released |
| 100 | * | ||
| 101 | * find_nilfs() looks up an existent nilfs object created on the | ||
| 102 | * device and gets the reference count of the object. If no nilfs object | ||
| 103 | * is found on the device, a new nilfs object is allocated. | ||
| 104 | * | ||
| 105 | * Return Value: On success, pointer to the nilfs object is returned. | ||
| 106 | * On error, NULL is returned. | ||
| 107 | */ | ||
| 108 | struct the_nilfs *find_or_create_nilfs(struct block_device *bdev) | ||
| 109 | { | ||
| 110 | struct the_nilfs *nilfs, *new = NULL; | ||
| 111 | |||
| 112 | retry: | ||
| 113 | spin_lock(&nilfs_lock); | ||
| 114 | list_for_each_entry(nilfs, &nilfs_objects, ns_list) { | ||
| 115 | if (nilfs->ns_bdev == bdev) { | ||
| 116 | get_nilfs(nilfs); | ||
| 117 | spin_unlock(&nilfs_lock); | ||
| 118 | if (new) | ||
| 119 | put_nilfs(new); | ||
| 120 | return nilfs; /* existing object */ | ||
| 121 | } | ||
| 122 | } | ||
| 123 | if (new) { | ||
| 124 | list_add_tail(&new->ns_list, &nilfs_objects); | ||
| 125 | spin_unlock(&nilfs_lock); | ||
| 126 | return new; /* new object */ | ||
| 127 | } | ||
| 128 | spin_unlock(&nilfs_lock); | ||
| 129 | |||
| 130 | new = alloc_nilfs(bdev); | ||
| 131 | if (new) | ||
| 132 | goto retry; | ||
| 133 | return NULL; /* insufficient memory */ | ||
| 134 | } | ||
| 135 | |||
| 136 | /** | ||
| 137 | * put_nilfs - release a reference to the_nilfs | ||
| 138 | * @nilfs: the_nilfs structure to be released | ||
| 139 | * | ||
| 140 | * put_nilfs() decrements a reference counter of the_nilfs. | ||
| 141 | * If the reference count reaches zero, the_nilfs is freed. | ||
| 142 | */ | 90 | */ |
| 143 | void put_nilfs(struct the_nilfs *nilfs) | 91 | void destroy_nilfs(struct the_nilfs *nilfs) |
| 144 | { | 92 | { |
| 145 | spin_lock(&nilfs_lock); | ||
| 146 | if (!atomic_dec_and_test(&nilfs->ns_count)) { | ||
| 147 | spin_unlock(&nilfs_lock); | ||
| 148 | return; | ||
| 149 | } | ||
| 150 | list_del_init(&nilfs->ns_list); | ||
| 151 | spin_unlock(&nilfs_lock); | ||
| 152 | |||
| 153 | /* | ||
| 154 | * Increment of ns_count never occurs below because the caller | ||
| 155 | * of get_nilfs() holds at least one reference to the_nilfs. | ||
| 156 | * Thus its exclusion control is not required here. | ||
| 157 | */ | ||
| 158 | |||
| 159 | might_sleep(); | 93 | might_sleep(); |
| 160 | if (nilfs_loaded(nilfs)) { | ||
| 161 | nilfs_mdt_destroy(nilfs->ns_sufile); | ||
| 162 | nilfs_mdt_destroy(nilfs->ns_cpfile); | ||
| 163 | nilfs_mdt_destroy(nilfs->ns_dat); | ||
| 164 | nilfs_mdt_destroy(nilfs->ns_gc_dat); | ||
| 165 | } | ||
| 166 | if (nilfs_init(nilfs)) { | 94 | if (nilfs_init(nilfs)) { |
| 167 | nilfs_destroy_gccache(nilfs); | ||
| 168 | brelse(nilfs->ns_sbh[0]); | 95 | brelse(nilfs->ns_sbh[0]); |
| 169 | brelse(nilfs->ns_sbh[1]); | 96 | brelse(nilfs->ns_sbh[1]); |
| 170 | } | 97 | } |
| 171 | kfree(nilfs); | 98 | kfree(nilfs); |
| 172 | } | 99 | } |
| 173 | 100 | ||
| 174 | static int nilfs_load_super_root(struct the_nilfs *nilfs, sector_t sr_block) | 101 | static int nilfs_load_super_root(struct the_nilfs *nilfs, |
| 102 | struct super_block *sb, sector_t sr_block) | ||
| 175 | { | 103 | { |
| 176 | struct buffer_head *bh_sr; | 104 | struct buffer_head *bh_sr; |
| 177 | struct nilfs_super_root *raw_sr; | 105 | struct nilfs_super_root *raw_sr; |
| 178 | struct nilfs_super_block **sbp = nilfs->ns_sbp; | 106 | struct nilfs_super_block **sbp = nilfs->ns_sbp; |
| 107 | struct nilfs_inode *rawi; | ||
| 179 | unsigned dat_entry_size, segment_usage_size, checkpoint_size; | 108 | unsigned dat_entry_size, segment_usage_size, checkpoint_size; |
| 180 | unsigned inode_size; | 109 | unsigned inode_size; |
| 181 | int err; | 110 | int err; |
| @@ -192,40 +121,22 @@ static int nilfs_load_super_root(struct the_nilfs *nilfs, sector_t sr_block) | |||
| 192 | 121 | ||
| 193 | inode_size = nilfs->ns_inode_size; | 122 | inode_size = nilfs->ns_inode_size; |
| 194 | 123 | ||
| 195 | err = -ENOMEM; | 124 | rawi = (void *)bh_sr->b_data + NILFS_SR_DAT_OFFSET(inode_size); |
| 196 | nilfs->ns_dat = nilfs_dat_new(nilfs, dat_entry_size); | 125 | err = nilfs_dat_read(sb, dat_entry_size, rawi, &nilfs->ns_dat); |
| 197 | if (unlikely(!nilfs->ns_dat)) | 126 | if (err) |
| 198 | goto failed; | 127 | goto failed; |
| 199 | 128 | ||
| 200 | nilfs->ns_gc_dat = nilfs_dat_new(nilfs, dat_entry_size); | 129 | rawi = (void *)bh_sr->b_data + NILFS_SR_CPFILE_OFFSET(inode_size); |
| 201 | if (unlikely(!nilfs->ns_gc_dat)) | 130 | err = nilfs_cpfile_read(sb, checkpoint_size, rawi, &nilfs->ns_cpfile); |
| 131 | if (err) | ||
| 202 | goto failed_dat; | 132 | goto failed_dat; |
| 203 | 133 | ||
| 204 | nilfs->ns_cpfile = nilfs_cpfile_new(nilfs, checkpoint_size); | 134 | rawi = (void *)bh_sr->b_data + NILFS_SR_SUFILE_OFFSET(inode_size); |
| 205 | if (unlikely(!nilfs->ns_cpfile)) | 135 | err = nilfs_sufile_read(sb, segment_usage_size, rawi, |
| 206 | goto failed_gc_dat; | 136 | &nilfs->ns_sufile); |
| 207 | 137 | if (err) | |
| 208 | nilfs->ns_sufile = nilfs_sufile_new(nilfs, segment_usage_size); | ||
| 209 | if (unlikely(!nilfs->ns_sufile)) | ||
| 210 | goto failed_cpfile; | 138 | goto failed_cpfile; |
| 211 | 139 | ||
| 212 | nilfs_mdt_set_shadow(nilfs->ns_dat, nilfs->ns_gc_dat); | ||
| 213 | |||
| 214 | err = nilfs_dat_read(nilfs->ns_dat, (void *)bh_sr->b_data + | ||
| 215 | NILFS_SR_DAT_OFFSET(inode_size)); | ||
| 216 | if (unlikely(err)) | ||
| 217 | goto failed_sufile; | ||
| 218 | |||
| 219 | err = nilfs_cpfile_read(nilfs->ns_cpfile, (void *)bh_sr->b_data + | ||
| 220 | NILFS_SR_CPFILE_OFFSET(inode_size)); | ||
| 221 | if (unlikely(err)) | ||
| 222 | goto failed_sufile; | ||
| 223 | |||
| 224 | err = nilfs_sufile_read(nilfs->ns_sufile, (void *)bh_sr->b_data + | ||
| 225 | NILFS_SR_SUFILE_OFFSET(inode_size)); | ||
| 226 | if (unlikely(err)) | ||
| 227 | goto failed_sufile; | ||
| 228 | |||
| 229 | raw_sr = (struct nilfs_super_root *)bh_sr->b_data; | 140 | raw_sr = (struct nilfs_super_root *)bh_sr->b_data; |
| 230 | nilfs->ns_nongc_ctime = le64_to_cpu(raw_sr->sr_nongc_ctime); | 141 | nilfs->ns_nongc_ctime = le64_to_cpu(raw_sr->sr_nongc_ctime); |
| 231 | 142 | ||
| @@ -233,17 +144,11 @@ static int nilfs_load_super_root(struct the_nilfs *nilfs, sector_t sr_block) | |||
| 233 | brelse(bh_sr); | 144 | brelse(bh_sr); |
| 234 | return err; | 145 | return err; |
| 235 | 146 | ||
| 236 | failed_sufile: | ||
| 237 | nilfs_mdt_destroy(nilfs->ns_sufile); | ||
| 238 | |||
| 239 | failed_cpfile: | 147 | failed_cpfile: |
| 240 | nilfs_mdt_destroy(nilfs->ns_cpfile); | 148 | iput(nilfs->ns_cpfile); |
| 241 | |||
| 242 | failed_gc_dat: | ||
| 243 | nilfs_mdt_destroy(nilfs->ns_gc_dat); | ||
| 244 | 149 | ||
| 245 | failed_dat: | 150 | failed_dat: |
| 246 | nilfs_mdt_destroy(nilfs->ns_dat); | 151 | iput(nilfs->ns_dat); |
| 247 | goto failed; | 152 | goto failed; |
| 248 | } | 153 | } |
| 249 | 154 | ||
| @@ -306,15 +211,6 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | |||
| 306 | int valid_fs = nilfs_valid_fs(nilfs); | 211 | int valid_fs = nilfs_valid_fs(nilfs); |
| 307 | int err; | 212 | int err; |
| 308 | 213 | ||
| 309 | if (nilfs_loaded(nilfs)) { | ||
| 310 | if (valid_fs || | ||
| 311 | ((s_flags & MS_RDONLY) && nilfs_test_opt(sbi, NORECOVERY))) | ||
| 312 | return 0; | ||
| 313 | printk(KERN_ERR "NILFS: the filesystem is in an incomplete " | ||
| 314 | "recovery state.\n"); | ||
| 315 | return -EINVAL; | ||
| 316 | } | ||
| 317 | |||
| 318 | if (!valid_fs) { | 214 | if (!valid_fs) { |
| 319 | printk(KERN_WARNING "NILFS warning: mounting unchecked fs\n"); | 215 | printk(KERN_WARNING "NILFS warning: mounting unchecked fs\n"); |
| 320 | if (s_flags & MS_RDONLY) { | 216 | if (s_flags & MS_RDONLY) { |
| @@ -375,7 +271,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | |||
| 375 | goto scan_error; | 271 | goto scan_error; |
| 376 | } | 272 | } |
| 377 | 273 | ||
| 378 | err = nilfs_load_super_root(nilfs, ri.ri_super_root); | 274 | err = nilfs_load_super_root(nilfs, sbi->s_super, ri.ri_super_root); |
| 379 | if (unlikely(err)) { | 275 | if (unlikely(err)) { |
| 380 | printk(KERN_ERR "NILFS: error loading super root.\n"); | 276 | printk(KERN_ERR "NILFS: error loading super root.\n"); |
| 381 | goto failed; | 277 | goto failed; |
| @@ -443,10 +339,9 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | |||
| 443 | goto failed; | 339 | goto failed; |
| 444 | 340 | ||
| 445 | failed_unload: | 341 | failed_unload: |
| 446 | nilfs_mdt_destroy(nilfs->ns_cpfile); | 342 | iput(nilfs->ns_cpfile); |
| 447 | nilfs_mdt_destroy(nilfs->ns_sufile); | 343 | iput(nilfs->ns_sufile); |
| 448 | nilfs_mdt_destroy(nilfs->ns_dat); | 344 | iput(nilfs->ns_dat); |
| 449 | nilfs_mdt_destroy(nilfs->ns_gc_dat); | ||
| 450 | 345 | ||
| 451 | failed: | 346 | failed: |
| 452 | nilfs_clear_recovery_info(&ri); | 347 | nilfs_clear_recovery_info(&ri); |
| @@ -468,8 +363,8 @@ static unsigned long long nilfs_max_size(unsigned int blkbits) | |||
| 468 | static int nilfs_store_disk_layout(struct the_nilfs *nilfs, | 363 | static int nilfs_store_disk_layout(struct the_nilfs *nilfs, |
| 469 | struct nilfs_super_block *sbp) | 364 | struct nilfs_super_block *sbp) |
| 470 | { | 365 | { |
| 471 | if (le32_to_cpu(sbp->s_rev_level) != NILFS_CURRENT_REV) { | 366 | if (le32_to_cpu(sbp->s_rev_level) < NILFS_MIN_SUPP_REV) { |
| 472 | printk(KERN_ERR "NILFS: revision mismatch " | 367 | printk(KERN_ERR "NILFS: unsupported revision " |
| 473 | "(superblock rev.=%d.%d, current rev.=%d.%d). " | 368 | "(superblock rev.=%d.%d, current rev.=%d.%d). " |
| 474 | "Please check the version of mkfs.nilfs.\n", | 369 | "Please check the version of mkfs.nilfs.\n", |
| 475 | le32_to_cpu(sbp->s_rev_level), | 370 | le32_to_cpu(sbp->s_rev_level), |
| @@ -631,12 +526,7 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs, | |||
| 631 | * | 526 | * |
| 632 | * init_nilfs() performs common initialization per block device (e.g. | 527 | * init_nilfs() performs common initialization per block device (e.g. |
| 633 | * reading the super block, getting disk layout information, initializing | 528 | * reading the super block, getting disk layout information, initializing |
| 634 | * shared fields in the_nilfs). It takes on some portion of the jobs | 529 | * shared fields in the_nilfs). |
| 635 | * typically done by a fill_super() routine. This division arises from | ||
| 636 | * the nature that multiple NILFS instances may be simultaneously | ||
| 637 | * mounted on a device. | ||
| 638 | * For multiple mounts on the same device, only the first mount | ||
| 639 | * invokes these tasks. | ||
| 640 | * | 530 | * |
| 641 | * Return Value: On success, 0 is returned. On error, a negative error | 531 | * Return Value: On success, 0 is returned. On error, a negative error |
| 642 | * code is returned. | 532 | * code is returned. |
| @@ -645,32 +535,10 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) | |||
| 645 | { | 535 | { |
| 646 | struct super_block *sb = sbi->s_super; | 536 | struct super_block *sb = sbi->s_super; |
| 647 | struct nilfs_super_block *sbp; | 537 | struct nilfs_super_block *sbp; |
| 648 | struct backing_dev_info *bdi; | ||
| 649 | int blocksize; | 538 | int blocksize; |
| 650 | int err; | 539 | int err; |
| 651 | 540 | ||
| 652 | down_write(&nilfs->ns_sem); | 541 | down_write(&nilfs->ns_sem); |
| 653 | if (nilfs_init(nilfs)) { | ||
| 654 | /* Load values from existing the_nilfs */ | ||
| 655 | sbp = nilfs->ns_sbp[0]; | ||
| 656 | err = nilfs_store_magic_and_option(sb, sbp, data); | ||
| 657 | if (err) | ||
| 658 | goto out; | ||
| 659 | |||
| 660 | err = nilfs_check_feature_compatibility(sb, sbp); | ||
| 661 | if (err) | ||
| 662 | goto out; | ||
| 663 | |||
| 664 | blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size); | ||
| 665 | if (sb->s_blocksize != blocksize && | ||
| 666 | !sb_set_blocksize(sb, blocksize)) { | ||
| 667 | printk(KERN_ERR "NILFS: blocksize %d unfit to device\n", | ||
| 668 | blocksize); | ||
| 669 | err = -EINVAL; | ||
| 670 | } | ||
| 671 | sb->s_maxbytes = nilfs_max_size(sb->s_blocksize_bits); | ||
| 672 | goto out; | ||
| 673 | } | ||
| 674 | 542 | ||
| 675 | blocksize = sb_min_blocksize(sb, NILFS_MIN_BLOCK_SIZE); | 543 | blocksize = sb_min_blocksize(sb, NILFS_MIN_BLOCK_SIZE); |
| 676 | if (!blocksize) { | 544 | if (!blocksize) { |
| @@ -729,18 +597,10 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) | |||
| 729 | 597 | ||
| 730 | nilfs->ns_mount_state = le16_to_cpu(sbp->s_state); | 598 | nilfs->ns_mount_state = le16_to_cpu(sbp->s_state); |
| 731 | 599 | ||
| 732 | bdi = nilfs->ns_bdev->bd_inode->i_mapping->backing_dev_info; | ||
| 733 | nilfs->ns_bdi = bdi ? : &default_backing_dev_info; | ||
| 734 | |||
| 735 | err = nilfs_store_log_cursor(nilfs, sbp); | 600 | err = nilfs_store_log_cursor(nilfs, sbp); |
| 736 | if (err) | 601 | if (err) |
| 737 | goto failed_sbh; | 602 | goto failed_sbh; |
| 738 | 603 | ||
| 739 | /* Initialize gcinode cache */ | ||
| 740 | err = nilfs_init_gccache(nilfs); | ||
| 741 | if (err) | ||
| 742 | goto failed_sbh; | ||
| 743 | |||
| 744 | set_nilfs_init(nilfs); | 604 | set_nilfs_init(nilfs); |
| 745 | err = 0; | 605 | err = 0; |
| 746 | out: | 606 | out: |
| @@ -812,79 +672,92 @@ int nilfs_near_disk_full(struct the_nilfs *nilfs) | |||
| 812 | return ncleansegs <= nilfs->ns_nrsvsegs + nincsegs; | 672 | return ncleansegs <= nilfs->ns_nrsvsegs + nincsegs; |
| 813 | } | 673 | } |
| 814 | 674 | ||
| 815 | /** | 675 | struct nilfs_root *nilfs_lookup_root(struct the_nilfs *nilfs, __u64 cno) |
| 816 | * nilfs_find_sbinfo - find existing nilfs_sb_info structure | ||
| 817 | * @nilfs: nilfs object | ||
| 818 | * @rw_mount: mount type (non-zero value for read/write mount) | ||
| 819 | * @cno: checkpoint number (zero for read-only mount) | ||
| 820 | * | ||
| 821 | * nilfs_find_sbinfo() returns the nilfs_sb_info structure which | ||
| 822 | * @rw_mount and @cno (in case of snapshots) matched. If no instance | ||
| 823 | * was found, NULL is returned. Although the super block instance can | ||
| 824 | * be unmounted after this function returns, the nilfs_sb_info struct | ||
| 825 | * is kept on memory until nilfs_put_sbinfo() is called. | ||
| 826 | */ | ||
| 827 | struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *nilfs, | ||
| 828 | int rw_mount, __u64 cno) | ||
| 829 | { | 676 | { |
| 830 | struct nilfs_sb_info *sbi; | 677 | struct rb_node *n; |
| 831 | 678 | struct nilfs_root *root; | |
| 832 | down_read(&nilfs->ns_super_sem); | 679 | |
| 833 | /* | 680 | spin_lock(&nilfs->ns_cptree_lock); |
| 834 | * The SNAPSHOT flag and sb->s_flags are supposed to be | 681 | n = nilfs->ns_cptree.rb_node; |
| 835 | * protected with nilfs->ns_super_sem. | 682 | while (n) { |
| 836 | */ | 683 | root = rb_entry(n, struct nilfs_root, rb_node); |
| 837 | sbi = nilfs->ns_current; | 684 | |
| 838 | if (rw_mount) { | 685 | if (cno < root->cno) { |
| 839 | if (sbi && !(sbi->s_super->s_flags & MS_RDONLY)) | 686 | n = n->rb_left; |
| 840 | goto found; /* read/write mount */ | 687 | } else if (cno > root->cno) { |
| 841 | else | 688 | n = n->rb_right; |
| 842 | goto out; | 689 | } else { |
| 843 | } else if (cno == 0) { | 690 | atomic_inc(&root->count); |
| 844 | if (sbi && (sbi->s_super->s_flags & MS_RDONLY)) | 691 | spin_unlock(&nilfs->ns_cptree_lock); |
| 845 | goto found; /* read-only mount */ | 692 | return root; |
| 846 | else | 693 | } |
| 847 | goto out; | ||
| 848 | } | 694 | } |
| 695 | spin_unlock(&nilfs->ns_cptree_lock); | ||
| 849 | 696 | ||
| 850 | list_for_each_entry(sbi, &nilfs->ns_supers, s_list) { | ||
| 851 | if (nilfs_test_opt(sbi, SNAPSHOT) && | ||
| 852 | sbi->s_snapshot_cno == cno) | ||
| 853 | goto found; /* snapshot mount */ | ||
| 854 | } | ||
| 855 | out: | ||
| 856 | up_read(&nilfs->ns_super_sem); | ||
| 857 | return NULL; | 697 | return NULL; |
| 858 | |||
| 859 | found: | ||
| 860 | atomic_inc(&sbi->s_count); | ||
| 861 | up_read(&nilfs->ns_super_sem); | ||
| 862 | return sbi; | ||
| 863 | } | 698 | } |
| 864 | 699 | ||
| 865 | int nilfs_checkpoint_is_mounted(struct the_nilfs *nilfs, __u64 cno, | 700 | struct nilfs_root * |
| 866 | int snapshot_mount) | 701 | nilfs_find_or_create_root(struct the_nilfs *nilfs, __u64 cno) |
| 867 | { | 702 | { |
| 868 | struct nilfs_sb_info *sbi; | 703 | struct rb_node **p, *parent; |
| 869 | int ret = 0; | 704 | struct nilfs_root *root, *new; |
| 870 | 705 | ||
| 871 | down_read(&nilfs->ns_super_sem); | 706 | root = nilfs_lookup_root(nilfs, cno); |
| 872 | if (cno == 0 || cno > nilfs->ns_cno) | 707 | if (root) |
| 873 | goto out_unlock; | 708 | return root; |
| 874 | 709 | ||
| 875 | list_for_each_entry(sbi, &nilfs->ns_supers, s_list) { | 710 | new = kmalloc(sizeof(*root), GFP_KERNEL); |
| 876 | if (sbi->s_snapshot_cno == cno && | 711 | if (!new) |
| 877 | (!snapshot_mount || nilfs_test_opt(sbi, SNAPSHOT))) { | 712 | return NULL; |
| 878 | /* exclude read-only mounts */ | 713 | |
| 879 | ret++; | 714 | spin_lock(&nilfs->ns_cptree_lock); |
| 880 | break; | 715 | |
| 716 | p = &nilfs->ns_cptree.rb_node; | ||
| 717 | parent = NULL; | ||
| 718 | |||
| 719 | while (*p) { | ||
| 720 | parent = *p; | ||
| 721 | root = rb_entry(parent, struct nilfs_root, rb_node); | ||
| 722 | |||
| 723 | if (cno < root->cno) { | ||
| 724 | p = &(*p)->rb_left; | ||
| 725 | } else if (cno > root->cno) { | ||
| 726 | p = &(*p)->rb_right; | ||
| 727 | } else { | ||
| 728 | atomic_inc(&root->count); | ||
| 729 | spin_unlock(&nilfs->ns_cptree_lock); | ||
| 730 | kfree(new); | ||
| 731 | return root; | ||
| 881 | } | 732 | } |
| 882 | } | 733 | } |
| 883 | /* for protecting recent checkpoints */ | ||
| 884 | if (cno >= nilfs_last_cno(nilfs)) | ||
| 885 | ret++; | ||
| 886 | 734 | ||
| 887 | out_unlock: | 735 | new->cno = cno; |
| 888 | up_read(&nilfs->ns_super_sem); | 736 | new->ifile = NULL; |
| 889 | return ret; | 737 | new->nilfs = nilfs; |
| 738 | atomic_set(&new->count, 1); | ||
| 739 | atomic_set(&new->inodes_count, 0); | ||
| 740 | atomic_set(&new->blocks_count, 0); | ||
| 741 | |||
| 742 | rb_link_node(&new->rb_node, parent, p); | ||
| 743 | rb_insert_color(&new->rb_node, &nilfs->ns_cptree); | ||
| 744 | |||
| 745 | spin_unlock(&nilfs->ns_cptree_lock); | ||
| 746 | |||
| 747 | return new; | ||
| 748 | } | ||
| 749 | |||
| 750 | void nilfs_put_root(struct nilfs_root *root) | ||
| 751 | { | ||
| 752 | if (atomic_dec_and_test(&root->count)) { | ||
| 753 | struct the_nilfs *nilfs = root->nilfs; | ||
| 754 | |||
| 755 | spin_lock(&nilfs->ns_cptree_lock); | ||
| 756 | rb_erase(&root->rb_node, &nilfs->ns_cptree); | ||
| 757 | spin_unlock(&nilfs->ns_cptree_lock); | ||
| 758 | if (root->ifile) | ||
| 759 | iput(root->ifile); | ||
| 760 | |||
| 761 | kfree(root); | ||
| 762 | } | ||
| 890 | } | 763 | } |
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index f785a7b0ab99..69226e14b745 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | 26 | ||
| 27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
| 28 | #include <linux/buffer_head.h> | 28 | #include <linux/buffer_head.h> |
| 29 | #include <linux/rbtree.h> | ||
| 29 | #include <linux/fs.h> | 30 | #include <linux/fs.h> |
| 30 | #include <linux/blkdev.h> | 31 | #include <linux/blkdev.h> |
| 31 | #include <linux/backing-dev.h> | 32 | #include <linux/backing-dev.h> |
| @@ -45,22 +46,13 @@ enum { | |||
| 45 | /** | 46 | /** |
| 46 | * struct the_nilfs - struct to supervise multiple nilfs mount points | 47 | * struct the_nilfs - struct to supervise multiple nilfs mount points |
| 47 | * @ns_flags: flags | 48 | * @ns_flags: flags |
| 48 | * @ns_count: reference count | ||
| 49 | * @ns_list: list head for nilfs_list | ||
| 50 | * @ns_bdev: block device | 49 | * @ns_bdev: block device |
| 51 | * @ns_bdi: backing dev info | ||
| 52 | * @ns_writer: back pointer to writable nilfs_sb_info | ||
| 53 | * @ns_sem: semaphore for shared states | 50 | * @ns_sem: semaphore for shared states |
| 54 | * @ns_super_sem: semaphore for global operations across super block instances | ||
| 55 | * @ns_mount_mutex: mutex protecting mount process of nilfs | ||
| 56 | * @ns_writer_sem: semaphore protecting ns_writer attach/detach | ||
| 57 | * @ns_current: back pointer to current mount | ||
| 58 | * @ns_sbh: buffer heads of on-disk super blocks | 51 | * @ns_sbh: buffer heads of on-disk super blocks |
| 59 | * @ns_sbp: pointers to super block data | 52 | * @ns_sbp: pointers to super block data |
| 60 | * @ns_sbwtime: previous write time of super block | 53 | * @ns_sbwtime: previous write time of super block |
| 61 | * @ns_sbwcount: write count of super block | 54 | * @ns_sbwcount: write count of super block |
| 62 | * @ns_sbsize: size of valid data in super block | 55 | * @ns_sbsize: size of valid data in super block |
| 63 | * @ns_supers: list of nilfs super block structs | ||
| 64 | * @ns_seg_seq: segment sequence counter | 56 | * @ns_seg_seq: segment sequence counter |
| 65 | * @ns_segnum: index number of the latest full segment. | 57 | * @ns_segnum: index number of the latest full segment. |
| 66 | * @ns_nextnum: index number of the full segment index to be used next | 58 | * @ns_nextnum: index number of the full segment index to be used next |
| @@ -79,9 +71,9 @@ enum { | |||
| 79 | * @ns_dat: DAT file inode | 71 | * @ns_dat: DAT file inode |
| 80 | * @ns_cpfile: checkpoint file inode | 72 | * @ns_cpfile: checkpoint file inode |
| 81 | * @ns_sufile: segusage file inode | 73 | * @ns_sufile: segusage file inode |
| 82 | * @ns_gc_dat: shadow inode of the DAT file inode for GC | 74 | * @ns_cptree: rb-tree of all mounted checkpoints (nilfs_root) |
| 75 | * @ns_cptree_lock: lock protecting @ns_cptree | ||
| 83 | * @ns_gc_inodes: dummy inodes to keep live blocks | 76 | * @ns_gc_inodes: dummy inodes to keep live blocks |
| 84 | * @ns_gc_inodes_h: hash list to keep dummy inode holding live blocks | ||
| 85 | * @ns_blocksize_bits: bit length of block size | 77 | * @ns_blocksize_bits: bit length of block size |
| 86 | * @ns_blocksize: block size | 78 | * @ns_blocksize: block size |
| 87 | * @ns_nsegments: number of segments in filesystem | 79 | * @ns_nsegments: number of segments in filesystem |
| @@ -95,22 +87,9 @@ enum { | |||
| 95 | */ | 87 | */ |
| 96 | struct the_nilfs { | 88 | struct the_nilfs { |
| 97 | unsigned long ns_flags; | 89 | unsigned long ns_flags; |
| 98 | atomic_t ns_count; | ||
| 99 | struct list_head ns_list; | ||
| 100 | 90 | ||
| 101 | struct block_device *ns_bdev; | 91 | struct block_device *ns_bdev; |
| 102 | struct backing_dev_info *ns_bdi; | ||
| 103 | struct nilfs_sb_info *ns_writer; | ||
| 104 | struct rw_semaphore ns_sem; | 92 | struct rw_semaphore ns_sem; |
| 105 | struct rw_semaphore ns_super_sem; | ||
| 106 | struct mutex ns_mount_mutex; | ||
| 107 | struct rw_semaphore ns_writer_sem; | ||
| 108 | |||
| 109 | /* | ||
| 110 | * components protected by ns_super_sem | ||
| 111 | */ | ||
| 112 | struct nilfs_sb_info *ns_current; | ||
| 113 | struct list_head ns_supers; | ||
| 114 | 93 | ||
| 115 | /* | 94 | /* |
| 116 | * used for | 95 | * used for |
| @@ -163,11 +142,13 @@ struct the_nilfs { | |||
| 163 | struct inode *ns_dat; | 142 | struct inode *ns_dat; |
| 164 | struct inode *ns_cpfile; | 143 | struct inode *ns_cpfile; |
| 165 | struct inode *ns_sufile; | 144 | struct inode *ns_sufile; |
| 166 | struct inode *ns_gc_dat; | ||
| 167 | 145 | ||
| 168 | /* GC inode list and hash table head */ | 146 | /* Checkpoint tree */ |
| 147 | struct rb_root ns_cptree; | ||
| 148 | spinlock_t ns_cptree_lock; | ||
| 149 | |||
| 150 | /* GC inode list */ | ||
| 169 | struct list_head ns_gc_inodes; | 151 | struct list_head ns_gc_inodes; |
| 170 | struct hlist_head *ns_gc_inodes_h; | ||
| 171 | 152 | ||
| 172 | /* Disk layout information (static) */ | 153 | /* Disk layout information (static) */ |
| 173 | unsigned int ns_blocksize_bits; | 154 | unsigned int ns_blocksize_bits; |
| @@ -182,9 +163,6 @@ struct the_nilfs { | |||
| 182 | u32 ns_crc_seed; | 163 | u32 ns_crc_seed; |
| 183 | }; | 164 | }; |
| 184 | 165 | ||
| 185 | #define NILFS_GCINODE_HASH_BITS 8 | ||
| 186 | #define NILFS_GCINODE_HASH_SIZE (1<<NILFS_GCINODE_HASH_BITS) | ||
| 187 | |||
| 188 | #define THE_NILFS_FNS(bit, name) \ | 166 | #define THE_NILFS_FNS(bit, name) \ |
| 189 | static inline void set_nilfs_##name(struct the_nilfs *nilfs) \ | 167 | static inline void set_nilfs_##name(struct the_nilfs *nilfs) \ |
| 190 | { \ | 168 | { \ |
| @@ -205,6 +183,32 @@ THE_NILFS_FNS(DISCONTINUED, discontinued) | |||
| 205 | THE_NILFS_FNS(GC_RUNNING, gc_running) | 183 | THE_NILFS_FNS(GC_RUNNING, gc_running) |
| 206 | THE_NILFS_FNS(SB_DIRTY, sb_dirty) | 184 | THE_NILFS_FNS(SB_DIRTY, sb_dirty) |
| 207 | 185 | ||
| 186 | /** | ||
| 187 | * struct nilfs_root - nilfs root object | ||
| 188 | * @cno: checkpoint number | ||
| 189 | * @rb_node: red-black tree node | ||
| 190 | * @count: refcount of this structure | ||
| 191 | * @nilfs: nilfs object | ||
| 192 | * @ifile: inode file | ||
| 193 | * @root: root inode | ||
| 194 | * @inodes_count: number of inodes | ||
| 195 | * @blocks_count: number of blocks (Reserved) | ||
| 196 | */ | ||
| 197 | struct nilfs_root { | ||
| 198 | __u64 cno; | ||
| 199 | struct rb_node rb_node; | ||
| 200 | |||
| 201 | atomic_t count; | ||
| 202 | struct the_nilfs *nilfs; | ||
| 203 | struct inode *ifile; | ||
| 204 | |||
| 205 | atomic_t inodes_count; | ||
| 206 | atomic_t blocks_count; | ||
| 207 | }; | ||
| 208 | |||
| 209 | /* Special checkpoint number */ | ||
| 210 | #define NILFS_CPTREE_CURRENT_CNO 0 | ||
| 211 | |||
| 208 | /* Minimum interval of periodical update of superblocks (in seconds) */ | 212 | /* Minimum interval of periodical update of superblocks (in seconds) */ |
| 209 | #define NILFS_SB_FREQ 10 | 213 | #define NILFS_SB_FREQ 10 |
| 210 | 214 | ||
| @@ -221,46 +225,25 @@ static inline int nilfs_sb_will_flip(struct the_nilfs *nilfs) | |||
| 221 | } | 225 | } |
| 222 | 226 | ||
| 223 | void nilfs_set_last_segment(struct the_nilfs *, sector_t, u64, __u64); | 227 | void nilfs_set_last_segment(struct the_nilfs *, sector_t, u64, __u64); |
| 224 | struct the_nilfs *find_or_create_nilfs(struct block_device *); | 228 | struct the_nilfs *alloc_nilfs(struct block_device *bdev); |
| 225 | void put_nilfs(struct the_nilfs *); | 229 | void destroy_nilfs(struct the_nilfs *nilfs); |
| 226 | int init_nilfs(struct the_nilfs *, struct nilfs_sb_info *, char *); | 230 | int init_nilfs(struct the_nilfs *, struct nilfs_sb_info *, char *); |
| 227 | int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *); | 231 | int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *); |
| 228 | int nilfs_discard_segments(struct the_nilfs *, __u64 *, size_t); | 232 | int nilfs_discard_segments(struct the_nilfs *, __u64 *, size_t); |
| 229 | int nilfs_count_free_blocks(struct the_nilfs *, sector_t *); | 233 | int nilfs_count_free_blocks(struct the_nilfs *, sector_t *); |
| 234 | struct nilfs_root *nilfs_lookup_root(struct the_nilfs *nilfs, __u64 cno); | ||
| 235 | struct nilfs_root *nilfs_find_or_create_root(struct the_nilfs *nilfs, | ||
| 236 | __u64 cno); | ||
| 237 | void nilfs_put_root(struct nilfs_root *root); | ||
| 230 | struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *, int, __u64); | 238 | struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *, int, __u64); |
| 231 | int nilfs_checkpoint_is_mounted(struct the_nilfs *, __u64, int); | ||
| 232 | int nilfs_near_disk_full(struct the_nilfs *); | 239 | int nilfs_near_disk_full(struct the_nilfs *); |
| 233 | void nilfs_fall_back_super_block(struct the_nilfs *); | 240 | void nilfs_fall_back_super_block(struct the_nilfs *); |
| 234 | void nilfs_swap_super_block(struct the_nilfs *); | 241 | void nilfs_swap_super_block(struct the_nilfs *); |
| 235 | 242 | ||
| 236 | 243 | ||
| 237 | static inline void get_nilfs(struct the_nilfs *nilfs) | 244 | static inline void nilfs_get_root(struct nilfs_root *root) |
| 238 | { | ||
| 239 | /* Caller must have at least one reference of the_nilfs. */ | ||
| 240 | atomic_inc(&nilfs->ns_count); | ||
| 241 | } | ||
| 242 | |||
| 243 | static inline void | ||
| 244 | nilfs_attach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | ||
| 245 | { | ||
| 246 | down_write(&nilfs->ns_writer_sem); | ||
| 247 | nilfs->ns_writer = sbi; | ||
| 248 | up_write(&nilfs->ns_writer_sem); | ||
| 249 | } | ||
| 250 | |||
| 251 | static inline void | ||
| 252 | nilfs_detach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | ||
| 253 | { | ||
| 254 | down_write(&nilfs->ns_writer_sem); | ||
| 255 | if (sbi == nilfs->ns_writer) | ||
| 256 | nilfs->ns_writer = NULL; | ||
| 257 | up_write(&nilfs->ns_writer_sem); | ||
| 258 | } | ||
| 259 | |||
| 260 | static inline void nilfs_put_sbinfo(struct nilfs_sb_info *sbi) | ||
| 261 | { | 245 | { |
| 262 | if (atomic_dec_and_test(&sbi->s_count)) | 246 | atomic_inc(&root->count); |
| 263 | kfree(sbi); | ||
| 264 | } | 247 | } |
| 265 | 248 | ||
| 266 | static inline int nilfs_valid_fs(struct the_nilfs *nilfs) | 249 | static inline int nilfs_valid_fs(struct the_nilfs *nilfs) |
diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h index a9cd507f8cd2..28028988c862 100644 --- a/include/linux/exportfs.h +++ b/include/linux/exportfs.h | |||
| @@ -67,6 +67,19 @@ enum fid_type { | |||
| 67 | * 32 bit parent block number, 32 bit parent generation number | 67 | * 32 bit parent block number, 32 bit parent generation number |
| 68 | */ | 68 | */ |
| 69 | FILEID_UDF_WITH_PARENT = 0x52, | 69 | FILEID_UDF_WITH_PARENT = 0x52, |
| 70 | |||
| 71 | /* | ||
| 72 | * 64 bit checkpoint number, 64 bit inode number, | ||
| 73 | * 32 bit generation number. | ||
| 74 | */ | ||
| 75 | FILEID_NILFS_WITHOUT_PARENT = 0x61, | ||
| 76 | |||
| 77 | /* | ||
| 78 | * 64 bit checkpoint number, 64 bit inode number, | ||
| 79 | * 32 bit generation number, 32 bit parent generation. | ||
| 80 | * 64 bit parent inode number. | ||
| 81 | */ | ||
| 82 | FILEID_NILFS_WITH_PARENT = 0x62, | ||
| 70 | }; | 83 | }; |
| 71 | 84 | ||
| 72 | struct fid { | 85 | struct fid { |
diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h index f5487b6f91ed..227e49dd5720 100644 --- a/include/linux/nilfs2_fs.h +++ b/include/linux/nilfs2_fs.h | |||
| @@ -4,16 +4,16 @@ | |||
| 4 | * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation. | 4 | * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU Lesser General Public License as published |
| 8 | * the Free Software Foundation; either version 2 of the License, or | 8 | * by the Free Software Foundation; either version 2.1 of the License, or |
| 9 | * (at your option) any later version. | 9 | * (at your option) any later version. |
| 10 | * | 10 | * |
| 11 | * This program is distributed in the hope that it will be useful, | 11 | * This program is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | * GNU General Public License for more details. | 14 | * GNU Lesser General Public License for more details. |
| 15 | * | 15 | * |
| 16 | * You should have received a copy of the GNU General Public License | 16 | * You should have received a copy of the GNU Lesser General Public License |
| 17 | * along with this program; if not, write to the Free Software | 17 | * along with this program; if not, write to the Free Software |
| 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| 19 | * | 19 | * |
| @@ -147,7 +147,6 @@ struct nilfs_super_root { | |||
| 147 | #define NILFS_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */ | 147 | #define NILFS_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */ |
| 148 | #define NILFS_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */ | 148 | #define NILFS_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */ |
| 149 | #define NILFS_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */ | 149 | #define NILFS_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */ |
| 150 | #define NILFS_MOUNT_SNAPSHOT 0x0080 /* Snapshot flag */ | ||
| 151 | #define NILFS_MOUNT_BARRIER 0x1000 /* Use block barriers */ | 150 | #define NILFS_MOUNT_BARRIER 0x1000 /* Use block barriers */ |
| 152 | #define NILFS_MOUNT_STRICT_ORDER 0x2000 /* Apply strict in-order | 151 | #define NILFS_MOUNT_STRICT_ORDER 0x2000 /* Apply strict in-order |
| 153 | semantics also for data */ | 152 | semantics also for data */ |
| @@ -229,6 +228,7 @@ struct nilfs_super_block { | |||
| 229 | */ | 228 | */ |
| 230 | #define NILFS_CURRENT_REV 2 /* current major revision */ | 229 | #define NILFS_CURRENT_REV 2 /* current major revision */ |
| 231 | #define NILFS_MINOR_REV 0 /* minor revision */ | 230 | #define NILFS_MINOR_REV 0 /* minor revision */ |
| 231 | #define NILFS_MIN_SUPP_REV 2 /* minimum supported revision */ | ||
| 232 | 232 | ||
| 233 | /* | 233 | /* |
| 234 | * Feature set definitions | 234 | * Feature set definitions |
| @@ -270,6 +270,14 @@ struct nilfs_super_block { | |||
| 270 | segments */ | 270 | segments */ |
| 271 | 271 | ||
| 272 | /* | 272 | /* |
| 273 | * We call DAT, cpfile, and sufile root metadata files. Inodes of | ||
| 274 | * these files are written in super root block instead of ifile, and | ||
| 275 | * garbage collector doesn't keep any past versions of these files. | ||
| 276 | */ | ||
| 277 | #define NILFS_ROOT_METADATA_FILE(ino) \ | ||
| 278 | ((ino) >= NILFS_DAT_INO && (ino) <= NILFS_SUFILE_INO) | ||
| 279 | |||
| 280 | /* | ||
| 273 | * bytes offset of secondary super block | 281 | * bytes offset of secondary super block |
| 274 | */ | 282 | */ |
| 275 | #define NILFS_SB2_OFFSET_BYTES(devsize) ((((devsize) >> 12) - 1) << 12) | 283 | #define NILFS_SB2_OFFSET_BYTES(devsize) ((((devsize) >> 12) - 1) << 12) |
