diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-23 04:26:47 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-23 04:26:47 -0400 |
commit | ab34c02afeafd047a831e6fe2a4dd875ce86bee0 (patch) | |
tree | 833e385e8387e3d4d4531ade23c1d92fba8ed075 /fs | |
parent | 7f3883962870dd28b5f2322ac44a9d03640ef448 (diff) | |
parent | 6b81e14e645016597c81e71cd27ee5c57c3a3c36 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ryusuke/nilfs2
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ryusuke/nilfs2: (36 commits)
nilfs2: eliminate sparse warning - "context imbalance"
nilfs2: eliminate sparse warnings - "symbol not declared"
nilfs2: get rid of bdi from nilfs object
nilfs2: change license of exported header file
nilfs2: add bdev freeze/thaw support
nilfs2: accept 64-bit checkpoint numbers in cp mount option
nilfs2: remove own inode allocator and destructor for metadata files
nilfs2: get rid of back pointer to writable sb instance
nilfs2: get rid of mi_nilfs back pointer to nilfs object
nilfs2: see state of root dentry for mount check of snapshots
nilfs2: use iget for all metadata files
nilfs2: get rid of GCDAT inode
nilfs2: add routines to redirect access to buffers of DAT file
nilfs2: add routines to roll back state of DAT file
nilfs2: add routines to save and restore bmap state
nilfs2: do not allocate nilfs_mdt_info structure to gc-inodes
nilfs2: allow nilfs_clear_inode to clear metadata file inodes
nilfs2: get rid of snapshot mount flag
nilfs2: simplify life cycle management of nilfs object
nilfs2: do not allocate multiple super block instances for a device
...
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nilfs2/Makefile | 2 | ||||
-rw-r--r-- | fs/nilfs2/bmap.c | 22 | ||||
-rw-r--r-- | fs/nilfs2/bmap.h | 10 | ||||
-rw-r--r-- | fs/nilfs2/btnode.c | 17 | ||||
-rw-r--r-- | fs/nilfs2/cpfile.c | 72 | ||||
-rw-r--r-- | fs/nilfs2/cpfile.h | 4 | ||||
-rw-r--r-- | fs/nilfs2/dat.c | 92 | ||||
-rw-r--r-- | fs/nilfs2/dat.h | 4 | ||||
-rw-r--r-- | fs/nilfs2/export.h | 17 | ||||
-rw-r--r-- | fs/nilfs2/gcdat.c | 87 | ||||
-rw-r--r-- | fs/nilfs2/gcinode.c | 134 | ||||
-rw-r--r-- | fs/nilfs2/ifile.c | 51 | ||||
-rw-r--r-- | fs/nilfs2/ifile.h | 4 | ||||
-rw-r--r-- | fs/nilfs2/inode.c | 167 | ||||
-rw-r--r-- | fs/nilfs2/ioctl.c | 23 | ||||
-rw-r--r-- | fs/nilfs2/mdt.c | 313 | ||||
-rw-r--r-- | fs/nilfs2/mdt.h | 32 | ||||
-rw-r--r-- | fs/nilfs2/namei.c | 139 | ||||
-rw-r--r-- | fs/nilfs2/nilfs.h | 38 | ||||
-rw-r--r-- | fs/nilfs2/page.c | 55 | ||||
-rw-r--r-- | fs/nilfs2/page.h | 6 | ||||
-rw-r--r-- | fs/nilfs2/recovery.c | 19 | ||||
-rw-r--r-- | fs/nilfs2/sb.h | 10 | ||||
-rw-r--r-- | fs/nilfs2/segbuf.c | 3 | ||||
-rw-r--r-- | fs/nilfs2/segment.c | 102 | ||||
-rw-r--r-- | fs/nilfs2/segment.h | 10 | ||||
-rw-r--r-- | fs/nilfs2/sufile.c | 77 | ||||
-rw-r--r-- | fs/nilfs2/sufile.h | 6 | ||||
-rw-r--r-- | fs/nilfs2/super.c | 609 | ||||
-rw-r--r-- | fs/nilfs2/the_nilfs.c | 339 | ||||
-rw-r--r-- | fs/nilfs2/the_nilfs.h | 101 |
31 files changed, 1313 insertions, 1252 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) |