diff options
Diffstat (limited to 'fs/nilfs2/the_nilfs.c')
-rw-r--r-- | fs/nilfs2/the_nilfs.c | 155 |
1 files changed, 83 insertions, 72 deletions
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index ad391a8c3e7e..6241e1722efc 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c | |||
@@ -146,13 +146,9 @@ void put_nilfs(struct the_nilfs *nilfs) | |||
146 | 146 | ||
147 | might_sleep(); | 147 | might_sleep(); |
148 | if (nilfs_loaded(nilfs)) { | 148 | if (nilfs_loaded(nilfs)) { |
149 | nilfs_mdt_clear(nilfs->ns_sufile); | ||
150 | nilfs_mdt_destroy(nilfs->ns_sufile); | 149 | nilfs_mdt_destroy(nilfs->ns_sufile); |
151 | nilfs_mdt_clear(nilfs->ns_cpfile); | ||
152 | nilfs_mdt_destroy(nilfs->ns_cpfile); | 150 | nilfs_mdt_destroy(nilfs->ns_cpfile); |
153 | nilfs_mdt_clear(nilfs->ns_dat); | ||
154 | nilfs_mdt_destroy(nilfs->ns_dat); | 151 | nilfs_mdt_destroy(nilfs->ns_dat); |
155 | /* XXX: how and when to clear nilfs->ns_gc_dat? */ | ||
156 | nilfs_mdt_destroy(nilfs->ns_gc_dat); | 152 | nilfs_mdt_destroy(nilfs->ns_gc_dat); |
157 | } | 153 | } |
158 | if (nilfs_init(nilfs)) { | 154 | if (nilfs_init(nilfs)) { |
@@ -166,7 +162,6 @@ void put_nilfs(struct the_nilfs *nilfs) | |||
166 | static int nilfs_load_super_root(struct the_nilfs *nilfs, | 162 | static int nilfs_load_super_root(struct the_nilfs *nilfs, |
167 | struct nilfs_sb_info *sbi, sector_t sr_block) | 163 | struct nilfs_sb_info *sbi, sector_t sr_block) |
168 | { | 164 | { |
169 | static struct lock_class_key dat_lock_key; | ||
170 | struct buffer_head *bh_sr; | 165 | struct buffer_head *bh_sr; |
171 | struct nilfs_super_root *raw_sr; | 166 | struct nilfs_super_root *raw_sr; |
172 | struct nilfs_super_block **sbp = nilfs->ns_sbp; | 167 | struct nilfs_super_block **sbp = nilfs->ns_sbp; |
@@ -187,51 +182,36 @@ static int nilfs_load_super_root(struct the_nilfs *nilfs, | |||
187 | inode_size = nilfs->ns_inode_size; | 182 | inode_size = nilfs->ns_inode_size; |
188 | 183 | ||
189 | err = -ENOMEM; | 184 | err = -ENOMEM; |
190 | nilfs->ns_dat = nilfs_mdt_new(nilfs, NULL, NILFS_DAT_INO); | 185 | nilfs->ns_dat = nilfs_dat_new(nilfs, dat_entry_size); |
191 | if (unlikely(!nilfs->ns_dat)) | 186 | if (unlikely(!nilfs->ns_dat)) |
192 | goto failed; | 187 | goto failed; |
193 | 188 | ||
194 | nilfs->ns_gc_dat = nilfs_mdt_new(nilfs, NULL, NILFS_DAT_INO); | 189 | nilfs->ns_gc_dat = nilfs_dat_new(nilfs, dat_entry_size); |
195 | if (unlikely(!nilfs->ns_gc_dat)) | 190 | if (unlikely(!nilfs->ns_gc_dat)) |
196 | goto failed_dat; | 191 | goto failed_dat; |
197 | 192 | ||
198 | nilfs->ns_cpfile = nilfs_mdt_new(nilfs, NULL, NILFS_CPFILE_INO); | 193 | nilfs->ns_cpfile = nilfs_cpfile_new(nilfs, checkpoint_size); |
199 | if (unlikely(!nilfs->ns_cpfile)) | 194 | if (unlikely(!nilfs->ns_cpfile)) |
200 | goto failed_gc_dat; | 195 | goto failed_gc_dat; |
201 | 196 | ||
202 | nilfs->ns_sufile = nilfs_mdt_new(nilfs, NULL, NILFS_SUFILE_INO); | 197 | nilfs->ns_sufile = nilfs_sufile_new(nilfs, segment_usage_size); |
203 | if (unlikely(!nilfs->ns_sufile)) | 198 | if (unlikely(!nilfs->ns_sufile)) |
204 | goto failed_cpfile; | 199 | goto failed_cpfile; |
205 | 200 | ||
206 | err = nilfs_palloc_init_blockgroup(nilfs->ns_dat, dat_entry_size); | ||
207 | if (unlikely(err)) | ||
208 | goto failed_sufile; | ||
209 | |||
210 | err = nilfs_palloc_init_blockgroup(nilfs->ns_gc_dat, dat_entry_size); | ||
211 | if (unlikely(err)) | ||
212 | goto failed_sufile; | ||
213 | |||
214 | lockdep_set_class(&NILFS_MDT(nilfs->ns_dat)->mi_sem, &dat_lock_key); | ||
215 | lockdep_set_class(&NILFS_MDT(nilfs->ns_gc_dat)->mi_sem, &dat_lock_key); | ||
216 | |||
217 | nilfs_mdt_set_shadow(nilfs->ns_dat, nilfs->ns_gc_dat); | 201 | nilfs_mdt_set_shadow(nilfs->ns_dat, nilfs->ns_gc_dat); |
218 | nilfs_mdt_set_entry_size(nilfs->ns_cpfile, checkpoint_size, | ||
219 | sizeof(struct nilfs_cpfile_header)); | ||
220 | nilfs_mdt_set_entry_size(nilfs->ns_sufile, segment_usage_size, | ||
221 | sizeof(struct nilfs_sufile_header)); | ||
222 | 202 | ||
223 | err = nilfs_mdt_read_inode_direct( | 203 | err = nilfs_dat_read(nilfs->ns_dat, (void *)bh_sr->b_data + |
224 | nilfs->ns_dat, bh_sr, NILFS_SR_DAT_OFFSET(inode_size)); | 204 | NILFS_SR_DAT_OFFSET(inode_size)); |
225 | if (unlikely(err)) | 205 | if (unlikely(err)) |
226 | goto failed_sufile; | 206 | goto failed_sufile; |
227 | 207 | ||
228 | err = nilfs_mdt_read_inode_direct( | 208 | err = nilfs_cpfile_read(nilfs->ns_cpfile, (void *)bh_sr->b_data + |
229 | nilfs->ns_cpfile, bh_sr, NILFS_SR_CPFILE_OFFSET(inode_size)); | 209 | NILFS_SR_CPFILE_OFFSET(inode_size)); |
230 | if (unlikely(err)) | 210 | if (unlikely(err)) |
231 | goto failed_sufile; | 211 | goto failed_sufile; |
232 | 212 | ||
233 | err = nilfs_mdt_read_inode_direct( | 213 | err = nilfs_sufile_read(nilfs->ns_sufile, (void *)bh_sr->b_data + |
234 | nilfs->ns_sufile, bh_sr, NILFS_SR_SUFILE_OFFSET(inode_size)); | 214 | NILFS_SR_SUFILE_OFFSET(inode_size)); |
235 | if (unlikely(err)) | 215 | if (unlikely(err)) |
236 | goto failed_sufile; | 216 | goto failed_sufile; |
237 | 217 | ||
@@ -281,29 +261,30 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | |||
281 | struct nilfs_recovery_info ri; | 261 | struct nilfs_recovery_info ri; |
282 | unsigned int s_flags = sbi->s_super->s_flags; | 262 | unsigned int s_flags = sbi->s_super->s_flags; |
283 | int really_read_only = bdev_read_only(nilfs->ns_bdev); | 263 | int really_read_only = bdev_read_only(nilfs->ns_bdev); |
284 | unsigned valid_fs; | 264 | int valid_fs = nilfs_valid_fs(nilfs); |
285 | int err = 0; | 265 | int err; |
286 | |||
287 | nilfs_init_recovery_info(&ri); | ||
288 | 266 | ||
289 | down_write(&nilfs->ns_sem); | 267 | if (nilfs_loaded(nilfs)) { |
290 | valid_fs = (nilfs->ns_mount_state & NILFS_VALID_FS); | 268 | if (valid_fs || |
291 | up_write(&nilfs->ns_sem); | 269 | ((s_flags & MS_RDONLY) && nilfs_test_opt(sbi, NORECOVERY))) |
270 | return 0; | ||
271 | printk(KERN_ERR "NILFS: the filesystem is in an incomplete " | ||
272 | "recovery state.\n"); | ||
273 | return -EINVAL; | ||
274 | } | ||
292 | 275 | ||
293 | if (!valid_fs && (s_flags & MS_RDONLY)) { | 276 | if (!valid_fs) { |
294 | printk(KERN_INFO "NILFS: INFO: recovery " | 277 | printk(KERN_WARNING "NILFS warning: mounting unchecked fs\n"); |
295 | "required for readonly filesystem.\n"); | 278 | if (s_flags & MS_RDONLY) { |
296 | if (really_read_only) { | 279 | printk(KERN_INFO "NILFS: INFO: recovery " |
297 | printk(KERN_ERR "NILFS: write access " | 280 | "required for readonly filesystem.\n"); |
298 | "unavailable, cannot proceed.\n"); | 281 | printk(KERN_INFO "NILFS: write access will " |
299 | err = -EROFS; | 282 | "be enabled during recovery.\n"); |
300 | goto failed; | ||
301 | } | 283 | } |
302 | printk(KERN_INFO "NILFS: write access will " | ||
303 | "be enabled during recovery.\n"); | ||
304 | sbi->s_super->s_flags &= ~MS_RDONLY; | ||
305 | } | 284 | } |
306 | 285 | ||
286 | nilfs_init_recovery_info(&ri); | ||
287 | |||
307 | err = nilfs_search_super_root(nilfs, sbi, &ri); | 288 | err = nilfs_search_super_root(nilfs, sbi, &ri); |
308 | if (unlikely(err)) { | 289 | if (unlikely(err)) { |
309 | printk(KERN_ERR "NILFS: error searching super root.\n"); | 290 | printk(KERN_ERR "NILFS: error searching super root.\n"); |
@@ -316,19 +297,56 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | |||
316 | goto failed; | 297 | goto failed; |
317 | } | 298 | } |
318 | 299 | ||
319 | if (!valid_fs) { | 300 | if (valid_fs) |
320 | err = nilfs_recover_logical_segments(nilfs, sbi, &ri); | 301 | goto skip_recovery; |
321 | if (unlikely(err)) { | 302 | |
322 | nilfs_mdt_destroy(nilfs->ns_cpfile); | 303 | if (s_flags & MS_RDONLY) { |
323 | nilfs_mdt_destroy(nilfs->ns_sufile); | 304 | if (nilfs_test_opt(sbi, NORECOVERY)) { |
324 | nilfs_mdt_destroy(nilfs->ns_dat); | 305 | printk(KERN_INFO "NILFS: norecovery option specified. " |
325 | goto failed; | 306 | "skipping roll-forward recovery\n"); |
307 | goto skip_recovery; | ||
326 | } | 308 | } |
327 | if (ri.ri_need_recovery == NILFS_RECOVERY_SR_UPDATED) | 309 | if (really_read_only) { |
328 | sbi->s_super->s_dirt = 1; | 310 | printk(KERN_ERR "NILFS: write access " |
311 | "unavailable, cannot proceed.\n"); | ||
312 | err = -EROFS; | ||
313 | goto failed_unload; | ||
314 | } | ||
315 | sbi->s_super->s_flags &= ~MS_RDONLY; | ||
316 | } else if (nilfs_test_opt(sbi, NORECOVERY)) { | ||
317 | printk(KERN_ERR "NILFS: recovery cancelled because norecovery " | ||
318 | "option was specified for a read/write mount\n"); | ||
319 | err = -EINVAL; | ||
320 | goto failed_unload; | ||
329 | } | 321 | } |
330 | 322 | ||
323 | err = nilfs_recover_logical_segments(nilfs, sbi, &ri); | ||
324 | if (err) | ||
325 | goto failed_unload; | ||
326 | |||
327 | down_write(&nilfs->ns_sem); | ||
328 | nilfs->ns_mount_state |= NILFS_VALID_FS; | ||
329 | nilfs->ns_sbp[0]->s_state = cpu_to_le16(nilfs->ns_mount_state); | ||
330 | err = nilfs_commit_super(sbi, 1); | ||
331 | up_write(&nilfs->ns_sem); | ||
332 | |||
333 | if (err) { | ||
334 | printk(KERN_ERR "NILFS: failed to update super block. " | ||
335 | "recovery unfinished.\n"); | ||
336 | goto failed_unload; | ||
337 | } | ||
338 | printk(KERN_INFO "NILFS: recovery complete.\n"); | ||
339 | |||
340 | skip_recovery: | ||
331 | set_nilfs_loaded(nilfs); | 341 | set_nilfs_loaded(nilfs); |
342 | nilfs_clear_recovery_info(&ri); | ||
343 | sbi->s_super->s_flags = s_flags; | ||
344 | return 0; | ||
345 | |||
346 | failed_unload: | ||
347 | nilfs_mdt_destroy(nilfs->ns_cpfile); | ||
348 | nilfs_mdt_destroy(nilfs->ns_sufile); | ||
349 | nilfs_mdt_destroy(nilfs->ns_dat); | ||
332 | 350 | ||
333 | failed: | 351 | failed: |
334 | nilfs_clear_recovery_info(&ri); | 352 | nilfs_clear_recovery_info(&ri); |
@@ -632,30 +650,23 @@ int nilfs_count_free_blocks(struct the_nilfs *nilfs, sector_t *nblocks) | |||
632 | { | 650 | { |
633 | struct inode *dat = nilfs_dat_inode(nilfs); | 651 | struct inode *dat = nilfs_dat_inode(nilfs); |
634 | unsigned long ncleansegs; | 652 | unsigned long ncleansegs; |
635 | int err; | ||
636 | 653 | ||
637 | down_read(&NILFS_MDT(dat)->mi_sem); /* XXX */ | 654 | down_read(&NILFS_MDT(dat)->mi_sem); /* XXX */ |
638 | err = nilfs_sufile_get_ncleansegs(nilfs->ns_sufile, &ncleansegs); | 655 | ncleansegs = nilfs_sufile_get_ncleansegs(nilfs->ns_sufile); |
639 | up_read(&NILFS_MDT(dat)->mi_sem); /* XXX */ | 656 | up_read(&NILFS_MDT(dat)->mi_sem); /* XXX */ |
640 | if (likely(!err)) | 657 | *nblocks = (sector_t)ncleansegs * nilfs->ns_blocks_per_segment; |
641 | *nblocks = (sector_t)ncleansegs * nilfs->ns_blocks_per_segment; | 658 | return 0; |
642 | return err; | ||
643 | } | 659 | } |
644 | 660 | ||
645 | int nilfs_near_disk_full(struct the_nilfs *nilfs) | 661 | int nilfs_near_disk_full(struct the_nilfs *nilfs) |
646 | { | 662 | { |
647 | struct inode *sufile = nilfs->ns_sufile; | ||
648 | unsigned long ncleansegs, nincsegs; | 663 | unsigned long ncleansegs, nincsegs; |
649 | int ret; | ||
650 | 664 | ||
651 | ret = nilfs_sufile_get_ncleansegs(sufile, &ncleansegs); | 665 | ncleansegs = nilfs_sufile_get_ncleansegs(nilfs->ns_sufile); |
652 | if (likely(!ret)) { | 666 | nincsegs = atomic_read(&nilfs->ns_ndirtyblks) / |
653 | nincsegs = atomic_read(&nilfs->ns_ndirtyblks) / | 667 | nilfs->ns_blocks_per_segment + 1; |
654 | nilfs->ns_blocks_per_segment + 1; | 668 | |
655 | if (ncleansegs <= nilfs->ns_nrsvsegs + nincsegs) | 669 | return ncleansegs <= nilfs->ns_nrsvsegs + nincsegs; |
656 | ret++; | ||
657 | } | ||
658 | return ret; | ||
659 | } | 670 | } |
660 | 671 | ||
661 | /** | 672 | /** |