diff options
Diffstat (limited to 'fs/nilfs2/super.c')
-rw-r--r-- | fs/nilfs2/super.c | 639 |
1 files changed, 332 insertions, 307 deletions
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 922263393c76..f804d41ec9d3 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
@@ -45,14 +45,13 @@ | |||
45 | #include <linux/parser.h> | 45 | #include <linux/parser.h> |
46 | #include <linux/random.h> | 46 | #include <linux/random.h> |
47 | #include <linux/crc32.h> | 47 | #include <linux/crc32.h> |
48 | #include <linux/smp_lock.h> | ||
49 | #include <linux/vfs.h> | 48 | #include <linux/vfs.h> |
50 | #include <linux/writeback.h> | 49 | #include <linux/writeback.h> |
51 | #include <linux/kobject.h> | 50 | #include <linux/kobject.h> |
52 | #include <linux/exportfs.h> | ||
53 | #include <linux/seq_file.h> | 51 | #include <linux/seq_file.h> |
54 | #include <linux/mount.h> | 52 | #include <linux/mount.h> |
55 | #include "nilfs.h" | 53 | #include "nilfs.h" |
54 | #include "export.h" | ||
56 | #include "mdt.h" | 55 | #include "mdt.h" |
57 | #include "alloc.h" | 56 | #include "alloc.h" |
58 | #include "btree.h" | 57 | #include "btree.h" |
@@ -69,11 +68,12 @@ MODULE_DESCRIPTION("A New Implementation of the Log-structured Filesystem " | |||
69 | "(NILFS)"); | 68 | "(NILFS)"); |
70 | MODULE_LICENSE("GPL"); | 69 | MODULE_LICENSE("GPL"); |
71 | 70 | ||
72 | struct kmem_cache *nilfs_inode_cachep; | 71 | static struct kmem_cache *nilfs_inode_cachep; |
73 | struct kmem_cache *nilfs_transaction_cachep; | 72 | struct kmem_cache *nilfs_transaction_cachep; |
74 | struct kmem_cache *nilfs_segbuf_cachep; | 73 | struct kmem_cache *nilfs_segbuf_cachep; |
75 | struct kmem_cache *nilfs_btree_path_cache; | 74 | struct kmem_cache *nilfs_btree_path_cache; |
76 | 75 | ||
76 | static int nilfs_setup_super(struct nilfs_sb_info *sbi, int is_mount); | ||
77 | 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); |
78 | 78 | ||
79 | static void nilfs_set_error(struct nilfs_sb_info *sbi) | 79 | static void nilfs_set_error(struct nilfs_sb_info *sbi) |
@@ -147,7 +147,7 @@ void nilfs_warning(struct super_block *sb, const char *function, | |||
147 | } | 147 | } |
148 | 148 | ||
149 | 149 | ||
150 | struct inode *nilfs_alloc_inode_common(struct the_nilfs *nilfs) | 150 | struct inode *nilfs_alloc_inode(struct super_block *sb) |
151 | { | 151 | { |
152 | struct nilfs_inode_info *ii; | 152 | struct nilfs_inode_info *ii; |
153 | 153 | ||
@@ -156,18 +156,20 @@ struct inode *nilfs_alloc_inode_common(struct the_nilfs *nilfs) | |||
156 | return NULL; | 156 | return NULL; |
157 | ii->i_bh = NULL; | 157 | ii->i_bh = NULL; |
158 | ii->i_state = 0; | 158 | ii->i_state = 0; |
159 | ii->i_cno = 0; | ||
159 | ii->vfs_inode.i_version = 1; | 160 | ii->vfs_inode.i_version = 1; |
160 | nilfs_btnode_cache_init(&ii->i_btnode_cache, nilfs->ns_bdi); | 161 | nilfs_btnode_cache_init(&ii->i_btnode_cache, sb->s_bdi); |
161 | return &ii->vfs_inode; | 162 | return &ii->vfs_inode; |
162 | } | 163 | } |
163 | 164 | ||
164 | struct inode *nilfs_alloc_inode(struct super_block *sb) | ||
165 | { | ||
166 | return nilfs_alloc_inode_common(NILFS_SB(sb)->s_nilfs); | ||
167 | } | ||
168 | |||
169 | void nilfs_destroy_inode(struct inode *inode) | 165 | void nilfs_destroy_inode(struct inode *inode) |
170 | { | 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 | } | ||
171 | kmem_cache_free(nilfs_inode_cachep, NILFS_I(inode)); | 173 | kmem_cache_free(nilfs_inode_cachep, NILFS_I(inode)); |
172 | } | 174 | } |
173 | 175 | ||
@@ -178,17 +180,9 @@ static int nilfs_sync_super(struct nilfs_sb_info *sbi, int flag) | |||
178 | 180 | ||
179 | retry: | 181 | retry: |
180 | set_buffer_dirty(nilfs->ns_sbh[0]); | 182 | set_buffer_dirty(nilfs->ns_sbh[0]); |
181 | |||
182 | if (nilfs_test_opt(sbi, BARRIER)) { | 183 | if (nilfs_test_opt(sbi, BARRIER)) { |
183 | err = __sync_dirty_buffer(nilfs->ns_sbh[0], | 184 | err = __sync_dirty_buffer(nilfs->ns_sbh[0], |
184 | WRITE_SYNC | WRITE_BARRIER); | 185 | WRITE_SYNC | WRITE_FLUSH_FUA); |
185 | if (err == -EOPNOTSUPP) { | ||
186 | nilfs_warning(sbi->s_super, __func__, | ||
187 | "barrier-based sync failed. " | ||
188 | "disabling barriers\n"); | ||
189 | nilfs_clear_opt(sbi, BARRIER); | ||
190 | goto retry; | ||
191 | } | ||
192 | } else { | 186 | } else { |
193 | err = sync_dirty_buffer(nilfs->ns_sbh[0]); | 187 | err = sync_dirty_buffer(nilfs->ns_sbh[0]); |
194 | } | 188 | } |
@@ -342,8 +336,6 @@ static void nilfs_put_super(struct super_block *sb) | |||
342 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 336 | struct nilfs_sb_info *sbi = NILFS_SB(sb); |
343 | struct the_nilfs *nilfs = sbi->s_nilfs; | 337 | struct the_nilfs *nilfs = sbi->s_nilfs; |
344 | 338 | ||
345 | lock_kernel(); | ||
346 | |||
347 | nilfs_detach_segment_constructor(sbi); | 339 | nilfs_detach_segment_constructor(sbi); |
348 | 340 | ||
349 | if (!(sb->s_flags & MS_RDONLY)) { | 341 | if (!(sb->s_flags & MS_RDONLY)) { |
@@ -351,18 +343,15 @@ static void nilfs_put_super(struct super_block *sb) | |||
351 | nilfs_cleanup_super(sbi); | 343 | nilfs_cleanup_super(sbi); |
352 | up_write(&nilfs->ns_sem); | 344 | up_write(&nilfs->ns_sem); |
353 | } | 345 | } |
354 | down_write(&nilfs->ns_super_sem); | ||
355 | if (nilfs->ns_current == sbi) | ||
356 | nilfs->ns_current = NULL; | ||
357 | up_write(&nilfs->ns_super_sem); | ||
358 | 346 | ||
359 | nilfs_detach_checkpoint(sbi); | 347 | iput(nilfs->ns_sufile); |
360 | put_nilfs(sbi->s_nilfs); | 348 | iput(nilfs->ns_cpfile); |
349 | iput(nilfs->ns_dat); | ||
350 | |||
351 | destroy_nilfs(nilfs); | ||
361 | sbi->s_super = NULL; | 352 | sbi->s_super = NULL; |
362 | sb->s_fs_info = NULL; | 353 | sb->s_fs_info = NULL; |
363 | nilfs_put_sbinfo(sbi); | 354 | kfree(sbi); |
364 | |||
365 | unlock_kernel(); | ||
366 | } | 355 | } |
367 | 356 | ||
368 | static int nilfs_sync_fs(struct super_block *sb, int wait) | 357 | static int nilfs_sync_fs(struct super_block *sb, int wait) |
@@ -389,21 +378,22 @@ static int nilfs_sync_fs(struct super_block *sb, int wait) | |||
389 | return err; | 378 | return err; |
390 | } | 379 | } |
391 | 380 | ||
392 | 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) | ||
393 | { | 383 | { |
394 | struct the_nilfs *nilfs = sbi->s_nilfs; | 384 | struct the_nilfs *nilfs = sbi->s_nilfs; |
385 | struct nilfs_root *root; | ||
395 | struct nilfs_checkpoint *raw_cp; | 386 | struct nilfs_checkpoint *raw_cp; |
396 | struct buffer_head *bh_cp; | 387 | struct buffer_head *bh_cp; |
397 | int err; | 388 | int err = -ENOMEM; |
398 | 389 | ||
399 | down_write(&nilfs->ns_super_sem); | 390 | root = nilfs_find_or_create_root( |
400 | list_add(&sbi->s_list, &nilfs->ns_supers); | 391 | nilfs, curr_mnt ? NILFS_CPTREE_CURRENT_CNO : cno); |
401 | up_write(&nilfs->ns_super_sem); | 392 | if (!root) |
393 | return err; | ||
402 | 394 | ||
403 | err = -ENOMEM; | 395 | if (root->ifile) |
404 | sbi->s_ifile = nilfs_ifile_new(sbi, nilfs->ns_inode_size); | 396 | goto reuse; /* already attached checkpoint */ |
405 | if (!sbi->s_ifile) | ||
406 | goto delist; | ||
407 | 397 | ||
408 | down_read(&nilfs->ns_segctor_sem); | 398 | down_read(&nilfs->ns_segctor_sem); |
409 | 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, |
@@ -419,45 +409,64 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno) | |||
419 | } | 409 | } |
420 | goto failed; | 410 | goto failed; |
421 | } | 411 | } |
422 | err = nilfs_read_inode_common(sbi->s_ifile, &raw_cp->cp_ifile_inode); | 412 | |
423 | 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) | ||
424 | goto failed_bh; | 416 | goto failed_bh; |
425 | atomic_set(&sbi->s_inodes_count, le64_to_cpu(raw_cp->cp_inodes_count)); | 417 | |
426 | 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)); | ||
427 | 420 | ||
428 | 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; | ||
429 | return 0; | 425 | return 0; |
430 | 426 | ||
431 | failed_bh: | 427 | failed_bh: |
432 | nilfs_cpfile_put_checkpoint(nilfs->ns_cpfile, cno, bh_cp); | 428 | nilfs_cpfile_put_checkpoint(nilfs->ns_cpfile, cno, bh_cp); |
433 | failed: | 429 | failed: |
434 | nilfs_mdt_destroy(sbi->s_ifile); | 430 | nilfs_put_root(root); |
435 | sbi->s_ifile = NULL; | 431 | |
432 | return err; | ||
433 | } | ||
434 | |||
435 | static int nilfs_freeze(struct super_block *sb) | ||
436 | { | ||
437 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | ||
438 | struct the_nilfs *nilfs = sbi->s_nilfs; | ||
439 | int err; | ||
436 | 440 | ||
437 | delist: | 441 | if (sb->s_flags & MS_RDONLY) |
438 | down_write(&nilfs->ns_super_sem); | 442 | return 0; |
439 | list_del_init(&sbi->s_list); | ||
440 | up_write(&nilfs->ns_super_sem); | ||
441 | 443 | ||
444 | /* Mark super block clean */ | ||
445 | down_write(&nilfs->ns_sem); | ||
446 | err = nilfs_cleanup_super(sbi); | ||
447 | up_write(&nilfs->ns_sem); | ||
442 | return err; | 448 | return err; |
443 | } | 449 | } |
444 | 450 | ||
445 | void nilfs_detach_checkpoint(struct nilfs_sb_info *sbi) | 451 | static int nilfs_unfreeze(struct super_block *sb) |
446 | { | 452 | { |
453 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | ||
447 | struct the_nilfs *nilfs = sbi->s_nilfs; | 454 | struct the_nilfs *nilfs = sbi->s_nilfs; |
448 | 455 | ||
449 | nilfs_mdt_destroy(sbi->s_ifile); | 456 | if (sb->s_flags & MS_RDONLY) |
450 | sbi->s_ifile = NULL; | 457 | return 0; |
451 | down_write(&nilfs->ns_super_sem); | 458 | |
452 | list_del_init(&sbi->s_list); | 459 | down_write(&nilfs->ns_sem); |
453 | up_write(&nilfs->ns_super_sem); | 460 | nilfs_setup_super(sbi, false); |
461 | up_write(&nilfs->ns_sem); | ||
462 | return 0; | ||
454 | } | 463 | } |
455 | 464 | ||
456 | static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) | 465 | static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
457 | { | 466 | { |
458 | struct super_block *sb = dentry->d_sb; | 467 | struct super_block *sb = dentry->d_sb; |
459 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 468 | struct nilfs_root *root = NILFS_I(dentry->d_inode)->i_root; |
460 | struct the_nilfs *nilfs = sbi->s_nilfs; | 469 | struct the_nilfs *nilfs = root->nilfs; |
461 | u64 id = huge_encode_dev(sb->s_bdev->bd_dev); | 470 | u64 id = huge_encode_dev(sb->s_bdev->bd_dev); |
462 | unsigned long long blocks; | 471 | unsigned long long blocks; |
463 | unsigned long overhead; | 472 | unsigned long overhead; |
@@ -493,7 +502,7 @@ static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
493 | buf->f_bfree = nfreeblocks; | 502 | buf->f_bfree = nfreeblocks; |
494 | buf->f_bavail = (buf->f_bfree >= nrsvblocks) ? | 503 | buf->f_bavail = (buf->f_bfree >= nrsvblocks) ? |
495 | (buf->f_bfree - nrsvblocks) : 0; | 504 | (buf->f_bfree - nrsvblocks) : 0; |
496 | buf->f_files = atomic_read(&sbi->s_inodes_count); | 505 | buf->f_files = atomic_read(&root->inodes_count); |
497 | buf->f_ffree = 0; /* nilfs_count_free_inodes(sb); */ | 506 | buf->f_ffree = 0; /* nilfs_count_free_inodes(sb); */ |
498 | buf->f_namelen = NILFS_NAME_LEN; | 507 | buf->f_namelen = NILFS_NAME_LEN; |
499 | buf->f_fsid.val[0] = (u32)id; | 508 | buf->f_fsid.val[0] = (u32)id; |
@@ -506,12 +515,12 @@ static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
506 | { | 515 | { |
507 | struct super_block *sb = vfs->mnt_sb; | 516 | struct super_block *sb = vfs->mnt_sb; |
508 | 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; | ||
509 | 519 | ||
510 | if (!nilfs_test_opt(sbi, BARRIER)) | 520 | if (!nilfs_test_opt(sbi, BARRIER)) |
511 | seq_puts(seq, ",nobarrier"); | 521 | seq_puts(seq, ",nobarrier"); |
512 | if (nilfs_test_opt(sbi, SNAPSHOT)) | 522 | if (root->cno != NILFS_CPTREE_CURRENT_CNO) |
513 | seq_printf(seq, ",cp=%llu", | 523 | seq_printf(seq, ",cp=%llu", (unsigned long long)root->cno); |
514 | (unsigned long long int)sbi->s_snapshot_cno); | ||
515 | if (nilfs_test_opt(sbi, ERRORS_PANIC)) | 524 | if (nilfs_test_opt(sbi, ERRORS_PANIC)) |
516 | seq_puts(seq, ",errors=panic"); | 525 | seq_puts(seq, ",errors=panic"); |
517 | if (nilfs_test_opt(sbi, ERRORS_CONT)) | 526 | if (nilfs_test_opt(sbi, ERRORS_CONT)) |
@@ -537,6 +546,8 @@ static const struct super_operations nilfs_sops = { | |||
537 | .put_super = nilfs_put_super, | 546 | .put_super = nilfs_put_super, |
538 | /* .write_super = nilfs_write_super, */ | 547 | /* .write_super = nilfs_write_super, */ |
539 | .sync_fs = nilfs_sync_fs, | 548 | .sync_fs = nilfs_sync_fs, |
549 | .freeze_fs = nilfs_freeze, | ||
550 | .unfreeze_fs = nilfs_unfreeze, | ||
540 | /* .write_super_lockfs */ | 551 | /* .write_super_lockfs */ |
541 | /* .unlockfs */ | 552 | /* .unlockfs */ |
542 | .statfs = nilfs_statfs, | 553 | .statfs = nilfs_statfs, |
@@ -545,48 +556,6 @@ static const struct super_operations nilfs_sops = { | |||
545 | .show_options = nilfs_show_options | 556 | .show_options = nilfs_show_options |
546 | }; | 557 | }; |
547 | 558 | ||
548 | static struct inode * | ||
549 | nilfs_nfs_get_inode(struct super_block *sb, u64 ino, u32 generation) | ||
550 | { | ||
551 | struct inode *inode; | ||
552 | |||
553 | if (ino < NILFS_FIRST_INO(sb) && ino != NILFS_ROOT_INO && | ||
554 | ino != NILFS_SKETCH_INO) | ||
555 | return ERR_PTR(-ESTALE); | ||
556 | |||
557 | inode = nilfs_iget(sb, ino); | ||
558 | if (IS_ERR(inode)) | ||
559 | return ERR_CAST(inode); | ||
560 | if (generation && inode->i_generation != generation) { | ||
561 | iput(inode); | ||
562 | return ERR_PTR(-ESTALE); | ||
563 | } | ||
564 | |||
565 | return inode; | ||
566 | } | ||
567 | |||
568 | static struct dentry * | ||
569 | nilfs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len, | ||
570 | int fh_type) | ||
571 | { | ||
572 | return generic_fh_to_dentry(sb, fid, fh_len, fh_type, | ||
573 | nilfs_nfs_get_inode); | ||
574 | } | ||
575 | |||
576 | static struct dentry * | ||
577 | nilfs_fh_to_parent(struct super_block *sb, struct fid *fid, int fh_len, | ||
578 | int fh_type) | ||
579 | { | ||
580 | return generic_fh_to_parent(sb, fid, fh_len, fh_type, | ||
581 | nilfs_nfs_get_inode); | ||
582 | } | ||
583 | |||
584 | static const struct export_operations nilfs_export_ops = { | ||
585 | .fh_to_dentry = nilfs_fh_to_dentry, | ||
586 | .fh_to_parent = nilfs_fh_to_parent, | ||
587 | .get_parent = nilfs_get_parent, | ||
588 | }; | ||
589 | |||
590 | enum { | 559 | enum { |
591 | Opt_err_cont, Opt_err_panic, Opt_err_ro, | 560 | Opt_err_cont, Opt_err_panic, Opt_err_ro, |
592 | Opt_barrier, Opt_nobarrier, Opt_snapshot, Opt_order, Opt_norecovery, | 561 | Opt_barrier, Opt_nobarrier, Opt_snapshot, Opt_order, Opt_norecovery, |
@@ -612,7 +581,6 @@ static int parse_options(char *options, struct super_block *sb, int is_remount) | |||
612 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 581 | struct nilfs_sb_info *sbi = NILFS_SB(sb); |
613 | char *p; | 582 | char *p; |
614 | substring_t args[MAX_OPT_ARGS]; | 583 | substring_t args[MAX_OPT_ARGS]; |
615 | int option; | ||
616 | 584 | ||
617 | if (!options) | 585 | if (!options) |
618 | return 1; | 586 | return 1; |
@@ -650,30 +618,12 @@ static int parse_options(char *options, struct super_block *sb, int is_remount) | |||
650 | nilfs_write_opt(sbi, ERROR_MODE, ERRORS_CONT); | 618 | nilfs_write_opt(sbi, ERROR_MODE, ERRORS_CONT); |
651 | break; | 619 | break; |
652 | case Opt_snapshot: | 620 | case Opt_snapshot: |
653 | if (match_int(&args[0], &option) || option <= 0) | ||
654 | return 0; | ||
655 | if (is_remount) { | 621 | if (is_remount) { |
656 | if (!nilfs_test_opt(sbi, SNAPSHOT)) { | 622 | printk(KERN_ERR |
657 | printk(KERN_ERR | 623 | "NILFS: \"%s\" option is invalid " |
658 | "NILFS: cannot change regular " | 624 | "for remount.\n", p); |
659 | "mount to snapshot.\n"); | ||
660 | return 0; | ||
661 | } else if (option != sbi->s_snapshot_cno) { | ||
662 | printk(KERN_ERR | ||
663 | "NILFS: cannot remount to a " | ||
664 | "different snapshot.\n"); | ||
665 | return 0; | ||
666 | } | ||
667 | break; | ||
668 | } | ||
669 | if (!(sb->s_flags & MS_RDONLY)) { | ||
670 | printk(KERN_ERR "NILFS: cannot mount snapshot " | ||
671 | "read/write. A read-only option is " | ||
672 | "required.\n"); | ||
673 | return 0; | 625 | return 0; |
674 | } | 626 | } |
675 | sbi->s_snapshot_cno = option; | ||
676 | nilfs_set_opt(sbi, SNAPSHOT); | ||
677 | break; | 627 | break; |
678 | case Opt_norecovery: | 628 | case Opt_norecovery: |
679 | nilfs_set_opt(sbi, NORECOVERY); | 629 | nilfs_set_opt(sbi, NORECOVERY); |
@@ -701,7 +651,7 @@ nilfs_set_default_options(struct nilfs_sb_info *sbi, | |||
701 | NILFS_MOUNT_ERRORS_RO | NILFS_MOUNT_BARRIER; | 651 | NILFS_MOUNT_ERRORS_RO | NILFS_MOUNT_BARRIER; |
702 | } | 652 | } |
703 | 653 | ||
704 | static int nilfs_setup_super(struct nilfs_sb_info *sbi) | 654 | static int nilfs_setup_super(struct nilfs_sb_info *sbi, int is_mount) |
705 | { | 655 | { |
706 | struct the_nilfs *nilfs = sbi->s_nilfs; | 656 | struct the_nilfs *nilfs = sbi->s_nilfs; |
707 | struct nilfs_super_block **sbp; | 657 | struct nilfs_super_block **sbp; |
@@ -713,6 +663,9 @@ static int nilfs_setup_super(struct nilfs_sb_info *sbi) | |||
713 | if (!sbp) | 663 | if (!sbp) |
714 | return -EIO; | 664 | return -EIO; |
715 | 665 | ||
666 | if (!is_mount) | ||
667 | goto skip_mount_setup; | ||
668 | |||
716 | 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); |
717 | mnt_count = le16_to_cpu(sbp[0]->s_mnt_count); | 670 | mnt_count = le16_to_cpu(sbp[0]->s_mnt_count); |
718 | 671 | ||
@@ -729,9 +682,11 @@ static int nilfs_setup_super(struct nilfs_sb_info *sbi) | |||
729 | 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); |
730 | 683 | ||
731 | 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: | ||
732 | sbp[0]->s_state = | 688 | sbp[0]->s_state = |
733 | 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); |
734 | sbp[0]->s_mtime = cpu_to_le64(get_seconds()); | ||
735 | /* synchronize sbp[1] with sbp[0] */ | 690 | /* synchronize sbp[1] with sbp[0] */ |
736 | memcpy(sbp[1], sbp[0], nilfs->ns_sbsize); | 691 | memcpy(sbp[1], sbp[0], nilfs->ns_sbsize); |
737 | return nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL); | 692 | return nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL); |
@@ -798,22 +753,156 @@ int nilfs_check_feature_compatibility(struct super_block *sb, | |||
798 | return 0; | 753 | return 0; |
799 | } | 754 | } |
800 | 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 | |||
801 | /** | 890 | /** |
802 | * nilfs_fill_super() - initialize a super block instance | 891 | * nilfs_fill_super() - initialize a super block instance |
803 | * @sb: super_block | 892 | * @sb: super_block |
804 | * @data: mount options | 893 | * @data: mount options |
805 | * @silent: silent mode flag | 894 | * @silent: silent mode flag |
806 | * @nilfs: the_nilfs struct | ||
807 | * | 895 | * |
808 | * This function is called exclusively by nilfs->ns_mount_mutex. | 896 | * This function is called exclusively by nilfs->ns_mount_mutex. |
809 | * So, the recovery process is protected from other simultaneous mounts. | 897 | * So, the recovery process is protected from other simultaneous mounts. |
810 | */ | 898 | */ |
811 | static int | 899 | static int |
812 | nilfs_fill_super(struct super_block *sb, void *data, int silent, | 900 | nilfs_fill_super(struct super_block *sb, void *data, int silent) |
813 | struct the_nilfs *nilfs) | ||
814 | { | 901 | { |
902 | struct the_nilfs *nilfs; | ||
815 | struct nilfs_sb_info *sbi; | 903 | struct nilfs_sb_info *sbi; |
816 | struct inode *root; | 904 | struct nilfs_root *fsroot; |
905 | struct backing_dev_info *bdi; | ||
817 | __u64 cno; | 906 | __u64 cno; |
818 | int err; | 907 | int err; |
819 | 908 | ||
@@ -822,19 +911,21 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
822 | return -ENOMEM; | 911 | return -ENOMEM; |
823 | 912 | ||
824 | sb->s_fs_info = sbi; | 913 | sb->s_fs_info = sbi; |
914 | sbi->s_super = sb; | ||
825 | 915 | ||
826 | get_nilfs(nilfs); | 916 | nilfs = alloc_nilfs(sb->s_bdev); |
917 | if (!nilfs) { | ||
918 | err = -ENOMEM; | ||
919 | goto failed_sbi; | ||
920 | } | ||
827 | sbi->s_nilfs = nilfs; | 921 | sbi->s_nilfs = nilfs; |
828 | sbi->s_super = sb; | ||
829 | atomic_set(&sbi->s_count, 1); | ||
830 | 922 | ||
831 | err = init_nilfs(nilfs, sbi, (char *)data); | 923 | err = init_nilfs(nilfs, sbi, (char *)data); |
832 | if (err) | 924 | if (err) |
833 | goto failed_sbi; | 925 | goto failed_nilfs; |
834 | 926 | ||
835 | spin_lock_init(&sbi->s_inode_lock); | 927 | spin_lock_init(&sbi->s_inode_lock); |
836 | INIT_LIST_HEAD(&sbi->s_dirty_files); | 928 | INIT_LIST_HEAD(&sbi->s_dirty_files); |
837 | INIT_LIST_HEAD(&sbi->s_list); | ||
838 | 929 | ||
839 | /* | 930 | /* |
840 | * Following initialization is overlapped because | 931 | * Following initialization is overlapped because |
@@ -850,94 +941,59 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
850 | sb->s_export_op = &nilfs_export_ops; | 941 | sb->s_export_op = &nilfs_export_ops; |
851 | sb->s_root = NULL; | 942 | sb->s_root = NULL; |
852 | sb->s_time_gran = 1; | 943 | sb->s_time_gran = 1; |
853 | 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; | ||
854 | 947 | ||
855 | err = load_nilfs(nilfs, sbi); | 948 | err = load_nilfs(nilfs, sbi); |
856 | if (err) | 949 | if (err) |
857 | goto failed_sbi; | 950 | goto failed_nilfs; |
858 | 951 | ||
859 | cno = nilfs_last_cno(nilfs); | 952 | cno = nilfs_last_cno(nilfs); |
860 | 953 | err = nilfs_attach_checkpoint(sbi, cno, true, &fsroot); | |
861 | if (sb->s_flags & MS_RDONLY) { | ||
862 | if (nilfs_test_opt(sbi, SNAPSHOT)) { | ||
863 | down_read(&nilfs->ns_segctor_sem); | ||
864 | err = nilfs_cpfile_is_snapshot(nilfs->ns_cpfile, | ||
865 | sbi->s_snapshot_cno); | ||
866 | up_read(&nilfs->ns_segctor_sem); | ||
867 | if (err < 0) { | ||
868 | if (err == -ENOENT) | ||
869 | err = -EINVAL; | ||
870 | goto failed_sbi; | ||
871 | } | ||
872 | if (!err) { | ||
873 | printk(KERN_ERR | ||
874 | "NILFS: The specified checkpoint is " | ||
875 | "not a snapshot " | ||
876 | "(checkpoint number=%llu).\n", | ||
877 | (unsigned long long)sbi->s_snapshot_cno); | ||
878 | err = -EINVAL; | ||
879 | goto failed_sbi; | ||
880 | } | ||
881 | cno = sbi->s_snapshot_cno; | ||
882 | } | ||
883 | } | ||
884 | |||
885 | err = nilfs_attach_checkpoint(sbi, cno); | ||
886 | if (err) { | 954 | if (err) { |
887 | printk(KERN_ERR "NILFS: error loading a checkpoint" | 955 | printk(KERN_ERR "NILFS: error loading last checkpoint " |
888 | " (checkpoint number=%llu).\n", (unsigned long long)cno); | 956 | "(checkpoint number=%llu).\n", (unsigned long long)cno); |
889 | goto failed_sbi; | 957 | goto failed_unload; |
890 | } | 958 | } |
891 | 959 | ||
892 | if (!(sb->s_flags & MS_RDONLY)) { | 960 | if (!(sb->s_flags & MS_RDONLY)) { |
893 | err = nilfs_attach_segment_constructor(sbi); | 961 | err = nilfs_attach_segment_constructor(sbi, fsroot); |
894 | if (err) | 962 | if (err) |
895 | goto failed_checkpoint; | 963 | goto failed_checkpoint; |
896 | } | 964 | } |
897 | 965 | ||
898 | root = nilfs_iget(sb, NILFS_ROOT_INO); | 966 | err = nilfs_get_root_dentry(sb, fsroot, &sb->s_root); |
899 | if (IS_ERR(root)) { | 967 | if (err) |
900 | printk(KERN_ERR "NILFS: get root inode failed\n"); | ||
901 | err = PTR_ERR(root); | ||
902 | goto failed_segctor; | ||
903 | } | ||
904 | if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) { | ||
905 | iput(root); | ||
906 | printk(KERN_ERR "NILFS: corrupt root inode.\n"); | ||
907 | err = -EINVAL; | ||
908 | goto failed_segctor; | ||
909 | } | ||
910 | sb->s_root = d_alloc_root(root); | ||
911 | if (!sb->s_root) { | ||
912 | iput(root); | ||
913 | printk(KERN_ERR "NILFS: get root dentry failed\n"); | ||
914 | err = -ENOMEM; | ||
915 | goto failed_segctor; | 968 | goto failed_segctor; |
916 | } | 969 | |
970 | nilfs_put_root(fsroot); | ||
917 | 971 | ||
918 | if (!(sb->s_flags & MS_RDONLY)) { | 972 | if (!(sb->s_flags & MS_RDONLY)) { |
919 | down_write(&nilfs->ns_sem); | 973 | down_write(&nilfs->ns_sem); |
920 | nilfs_setup_super(sbi); | 974 | nilfs_setup_super(sbi, true); |
921 | up_write(&nilfs->ns_sem); | 975 | up_write(&nilfs->ns_sem); |
922 | } | 976 | } |
923 | 977 | ||
924 | down_write(&nilfs->ns_super_sem); | ||
925 | if (!nilfs_test_opt(sbi, SNAPSHOT)) | ||
926 | nilfs->ns_current = sbi; | ||
927 | up_write(&nilfs->ns_super_sem); | ||
928 | |||
929 | return 0; | 978 | return 0; |
930 | 979 | ||
931 | failed_segctor: | 980 | failed_segctor: |
932 | nilfs_detach_segment_constructor(sbi); | 981 | nilfs_detach_segment_constructor(sbi); |
933 | 982 | ||
934 | failed_checkpoint: | 983 | failed_checkpoint: |
935 | 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); | ||
936 | 993 | ||
937 | failed_sbi: | 994 | failed_sbi: |
938 | put_nilfs(nilfs); | ||
939 | sb->s_fs_info = NULL; | 995 | sb->s_fs_info = NULL; |
940 | nilfs_put_sbinfo(sbi); | 996 | kfree(sbi); |
941 | return err; | 997 | return err; |
942 | } | 998 | } |
943 | 999 | ||
@@ -947,15 +1003,10 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
947 | struct the_nilfs *nilfs = sbi->s_nilfs; | 1003 | struct the_nilfs *nilfs = sbi->s_nilfs; |
948 | unsigned long old_sb_flags; | 1004 | unsigned long old_sb_flags; |
949 | struct nilfs_mount_options old_opts; | 1005 | struct nilfs_mount_options old_opts; |
950 | int was_snapshot, err; | 1006 | int err; |
951 | |||
952 | lock_kernel(); | ||
953 | 1007 | ||
954 | down_write(&nilfs->ns_super_sem); | ||
955 | old_sb_flags = sb->s_flags; | 1008 | old_sb_flags = sb->s_flags; |
956 | old_opts.mount_opt = sbi->s_mount_opt; | 1009 | old_opts.mount_opt = sbi->s_mount_opt; |
957 | old_opts.snapshot_cno = sbi->s_snapshot_cno; | ||
958 | was_snapshot = nilfs_test_opt(sbi, SNAPSHOT); | ||
959 | 1010 | ||
960 | if (!parse_options(data, sb, 1)) { | 1011 | if (!parse_options(data, sb, 1)) { |
961 | err = -EINVAL; | 1012 | err = -EINVAL; |
@@ -964,11 +1015,6 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
964 | sb->s_flags = (sb->s_flags & ~MS_POSIXACL); | 1015 | sb->s_flags = (sb->s_flags & ~MS_POSIXACL); |
965 | 1016 | ||
966 | err = -EINVAL; | 1017 | err = -EINVAL; |
967 | if (was_snapshot && !(*flags & MS_RDONLY)) { | ||
968 | printk(KERN_ERR "NILFS (device %s): cannot remount snapshot " | ||
969 | "read/write.\n", sb->s_id); | ||
970 | goto restore_opts; | ||
971 | } | ||
972 | 1018 | ||
973 | if (!nilfs_valid_fs(nilfs)) { | 1019 | if (!nilfs_valid_fs(nilfs)) { |
974 | printk(KERN_WARNING "NILFS (device %s): couldn't " | 1020 | printk(KERN_WARNING "NILFS (device %s): couldn't " |
@@ -993,6 +1039,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
993 | up_write(&nilfs->ns_sem); | 1039 | up_write(&nilfs->ns_sem); |
994 | } else { | 1040 | } else { |
995 | __u64 features; | 1041 | __u64 features; |
1042 | struct nilfs_root *root; | ||
996 | 1043 | ||
997 | /* | 1044 | /* |
998 | * Mounting a RDONLY partition read-write, so reread and | 1045 | * Mounting a RDONLY partition read-write, so reread and |
@@ -1014,25 +1061,21 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
1014 | 1061 | ||
1015 | sb->s_flags &= ~MS_RDONLY; | 1062 | sb->s_flags &= ~MS_RDONLY; |
1016 | 1063 | ||
1017 | 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); | ||
1018 | if (err) | 1066 | if (err) |
1019 | goto restore_opts; | 1067 | goto restore_opts; |
1020 | 1068 | ||
1021 | down_write(&nilfs->ns_sem); | 1069 | down_write(&nilfs->ns_sem); |
1022 | nilfs_setup_super(sbi); | 1070 | nilfs_setup_super(sbi, true); |
1023 | up_write(&nilfs->ns_sem); | 1071 | up_write(&nilfs->ns_sem); |
1024 | } | 1072 | } |
1025 | out: | 1073 | out: |
1026 | up_write(&nilfs->ns_super_sem); | ||
1027 | unlock_kernel(); | ||
1028 | return 0; | 1074 | return 0; |
1029 | 1075 | ||
1030 | restore_opts: | 1076 | restore_opts: |
1031 | sb->s_flags = old_sb_flags; | 1077 | sb->s_flags = old_sb_flags; |
1032 | sbi->s_mount_opt = old_opts.mount_opt; | 1078 | sbi->s_mount_opt = old_opts.mount_opt; |
1033 | sbi->s_snapshot_cno = old_opts.snapshot_cno; | ||
1034 | up_write(&nilfs->ns_super_sem); | ||
1035 | unlock_kernel(); | ||
1036 | return err; | 1079 | return err; |
1037 | } | 1080 | } |
1038 | 1081 | ||
@@ -1052,7 +1095,7 @@ static int nilfs_identify(char *data, struct nilfs_super_data *sd) | |||
1052 | { | 1095 | { |
1053 | char *p, *options = data; | 1096 | char *p, *options = data; |
1054 | substring_t args[MAX_OPT_ARGS]; | 1097 | substring_t args[MAX_OPT_ARGS]; |
1055 | int option, token; | 1098 | int token; |
1056 | int ret = 0; | 1099 | int ret = 0; |
1057 | 1100 | ||
1058 | do { | 1101 | do { |
@@ -1060,16 +1103,18 @@ static int nilfs_identify(char *data, struct nilfs_super_data *sd) | |||
1060 | if (p != NULL && *p) { | 1103 | if (p != NULL && *p) { |
1061 | token = match_token(p, tokens, args); | 1104 | token = match_token(p, tokens, args); |
1062 | if (token == Opt_snapshot) { | 1105 | if (token == Opt_snapshot) { |
1063 | if (!(sd->flags & MS_RDONLY)) | 1106 | if (!(sd->flags & MS_RDONLY)) { |
1064 | ret++; | 1107 | ret++; |
1065 | else { | 1108 | } else { |
1066 | ret = match_int(&args[0], &option); | 1109 | sd->cno = simple_strtoull(args[0].from, |
1067 | if (!ret) { | 1110 | NULL, 0); |
1068 | if (option > 0) | 1111 | /* |
1069 | sd->cno = option; | 1112 | * No need to see the end pointer; |
1070 | else | 1113 | * match_token() has done syntax |
1071 | ret++; | 1114 | * checking. |
1072 | } | 1115 | */ |
1116 | if (sd->cno == 0) | ||
1117 | ret++; | ||
1073 | } | 1118 | } |
1074 | } | 1119 | } |
1075 | if (ret) | 1120 | if (ret) |
@@ -1086,43 +1131,33 @@ static int nilfs_identify(char *data, struct nilfs_super_data *sd) | |||
1086 | 1131 | ||
1087 | 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) |
1088 | { | 1133 | { |
1089 | struct nilfs_super_data *sd = data; | 1134 | s->s_bdev = data; |
1090 | |||
1091 | s->s_bdev = sd->bdev; | ||
1092 | s->s_dev = s->s_bdev->bd_dev; | 1135 | s->s_dev = s->s_bdev->bd_dev; |
1093 | return 0; | 1136 | return 0; |
1094 | } | 1137 | } |
1095 | 1138 | ||
1096 | 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) |
1097 | { | 1140 | { |
1098 | struct nilfs_super_data *sd = data; | 1141 | return (void *)s->s_bdev == data; |
1099 | |||
1100 | return sd->sbi && s->s_fs_info == (void *)sd->sbi; | ||
1101 | } | 1142 | } |
1102 | 1143 | ||
1103 | static int | 1144 | static struct dentry * |
1104 | nilfs_get_sb(struct file_system_type *fs_type, int flags, | 1145 | nilfs_mount(struct file_system_type *fs_type, int flags, |
1105 | const char *dev_name, void *data, struct vfsmount *mnt) | 1146 | const char *dev_name, void *data) |
1106 | { | 1147 | { |
1107 | struct nilfs_super_data sd; | 1148 | struct nilfs_super_data sd; |
1108 | struct super_block *s; | 1149 | struct super_block *s; |
1109 | fmode_t mode = FMODE_READ; | 1150 | fmode_t mode = FMODE_READ; |
1110 | struct the_nilfs *nilfs; | 1151 | struct dentry *root_dentry; |
1111 | int err, need_to_close = 1; | 1152 | int err, s_new = false; |
1112 | 1153 | ||
1113 | if (!(flags & MS_RDONLY)) | 1154 | if (!(flags & MS_RDONLY)) |
1114 | mode |= FMODE_WRITE; | 1155 | mode |= FMODE_WRITE; |
1115 | 1156 | ||
1116 | sd.bdev = open_bdev_exclusive(dev_name, mode, fs_type); | 1157 | sd.bdev = open_bdev_exclusive(dev_name, mode, fs_type); |
1117 | if (IS_ERR(sd.bdev)) | 1158 | if (IS_ERR(sd.bdev)) |
1118 | return PTR_ERR(sd.bdev); | 1159 | return ERR_CAST(sd.bdev); |
1119 | 1160 | ||
1120 | /* | ||
1121 | * To get mount instance using sget() vfs-routine, NILFS needs | ||
1122 | * much more information than normal filesystems to identify mount | ||
1123 | * instance. For snapshot mounts, not only a mount type (ro-mount | ||
1124 | * or rw-mount) but also a checkpoint number is required. | ||
1125 | */ | ||
1126 | sd.cno = 0; | 1161 | sd.cno = 0; |
1127 | sd.flags = flags; | 1162 | sd.flags = flags; |
1128 | if (nilfs_identify((char *)data, &sd)) { | 1163 | if (nilfs_identify((char *)data, &sd)) { |
@@ -1130,101 +1165,91 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1130 | goto failed; | 1165 | goto failed; |
1131 | } | 1166 | } |
1132 | 1167 | ||
1133 | nilfs = find_or_create_nilfs(sd.bdev); | ||
1134 | if (!nilfs) { | ||
1135 | err = -ENOMEM; | ||
1136 | goto failed; | ||
1137 | } | ||
1138 | |||
1139 | mutex_lock(&nilfs->ns_mount_mutex); | ||
1140 | |||
1141 | if (!sd.cno) { | ||
1142 | /* | ||
1143 | * Check if an exclusive mount exists or not. | ||
1144 | * Snapshot mounts coexist with a current mount | ||
1145 | * (i.e. rw-mount or ro-mount), whereas rw-mount and | ||
1146 | * ro-mount are mutually exclusive. | ||
1147 | */ | ||
1148 | down_read(&nilfs->ns_super_sem); | ||
1149 | if (nilfs->ns_current && | ||
1150 | ((nilfs->ns_current->s_super->s_flags ^ flags) | ||
1151 | & MS_RDONLY)) { | ||
1152 | up_read(&nilfs->ns_super_sem); | ||
1153 | err = -EBUSY; | ||
1154 | goto failed_unlock; | ||
1155 | } | ||
1156 | up_read(&nilfs->ns_super_sem); | ||
1157 | } | ||
1158 | |||
1159 | /* | ||
1160 | * Find existing nilfs_sb_info struct | ||
1161 | */ | ||
1162 | sd.sbi = nilfs_find_sbinfo(nilfs, !(flags & MS_RDONLY), sd.cno); | ||
1163 | |||
1164 | /* | 1168 | /* |
1165 | * Get super block instance holding the nilfs_sb_info struct. | 1169 | * once the super is inserted into the list by sget, s_umount |
1166 | * A new instance is allocated if no existing mount is present or | 1170 | * will protect the lockfs code from trying to start a snapshot |
1167 | * existing instance has been unmounted. | 1171 | * while we are mounting |
1168 | */ | 1172 | */ |
1169 | s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, &sd); | 1173 | mutex_lock(&sd.bdev->bd_fsfreeze_mutex); |
1170 | if (sd.sbi) | 1174 | if (sd.bdev->bd_fsfreeze_count > 0) { |
1171 | nilfs_put_sbinfo(sd.sbi); | 1175 | mutex_unlock(&sd.bdev->bd_fsfreeze_mutex); |
1172 | 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); | ||
1173 | if (IS_ERR(s)) { | 1181 | if (IS_ERR(s)) { |
1174 | err = PTR_ERR(s); | 1182 | err = PTR_ERR(s); |
1175 | goto failed_unlock; | 1183 | goto failed; |
1176 | } | 1184 | } |
1177 | 1185 | ||
1178 | if (!s->s_root) { | 1186 | if (!s->s_root) { |
1179 | char b[BDEVNAME_SIZE]; | 1187 | char b[BDEVNAME_SIZE]; |
1180 | 1188 | ||
1189 | s_new = true; | ||
1190 | |||
1181 | /* New superblock instance created */ | 1191 | /* New superblock instance created */ |
1182 | s->s_flags = flags; | 1192 | s->s_flags = flags; |
1183 | s->s_mode = mode; | 1193 | s->s_mode = mode; |
1184 | 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)); |
1185 | sb_set_blocksize(s, block_size(sd.bdev)); | 1195 | sb_set_blocksize(s, block_size(sd.bdev)); |
1186 | 1196 | ||
1187 | err = nilfs_fill_super(s, data, flags & MS_SILENT ? 1 : 0, | 1197 | err = nilfs_fill_super(s, data, flags & MS_SILENT ? 1 : 0); |
1188 | nilfs); | ||
1189 | if (err) | 1198 | if (err) |
1190 | goto cancel_new; | 1199 | goto failed_super; |
1191 | 1200 | ||
1192 | s->s_flags |= MS_ACTIVE; | 1201 | s->s_flags |= MS_ACTIVE; |
1193 | 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 | } | ||
1194 | } | 1225 | } |
1195 | 1226 | ||
1196 | mutex_unlock(&nilfs->ns_mount_mutex); | 1227 | if (sd.cno) { |
1197 | put_nilfs(nilfs); | 1228 | err = nilfs_attach_snapshot(s, sd.cno, &root_dentry); |
1198 | if (need_to_close) | 1229 | if (err) |
1199 | close_bdev_exclusive(sd.bdev, mode); | 1230 | goto failed_super; |
1200 | simple_set_mnt(mnt, s); | 1231 | } else { |
1201 | return 0; | 1232 | root_dentry = dget(s->s_root); |
1233 | } | ||
1202 | 1234 | ||
1203 | failed_unlock: | 1235 | if (!s_new) |
1204 | mutex_unlock(&nilfs->ns_mount_mutex); | 1236 | close_bdev_exclusive(sd.bdev, mode); |
1205 | put_nilfs(nilfs); | ||
1206 | failed: | ||
1207 | close_bdev_exclusive(sd.bdev, mode); | ||
1208 | 1237 | ||
1209 | return err; | 1238 | return root_dentry; |
1210 | 1239 | ||
1211 | cancel_new: | 1240 | failed_super: |
1212 | /* Abandoning the newly allocated superblock */ | ||
1213 | mutex_unlock(&nilfs->ns_mount_mutex); | ||
1214 | put_nilfs(nilfs); | ||
1215 | deactivate_locked_super(s); | 1241 | deactivate_locked_super(s); |
1216 | /* | 1242 | |
1217 | * deactivate_locked_super() invokes close_bdev_exclusive(). | 1243 | failed: |
1218 | * We must finish all post-cleaning before this call; | 1244 | if (!s_new) |
1219 | * put_nilfs() needs the block device. | 1245 | close_bdev_exclusive(sd.bdev, mode); |
1220 | */ | 1246 | return ERR_PTR(err); |
1221 | return err; | ||
1222 | } | 1247 | } |
1223 | 1248 | ||
1224 | struct file_system_type nilfs_fs_type = { | 1249 | struct file_system_type nilfs_fs_type = { |
1225 | .owner = THIS_MODULE, | 1250 | .owner = THIS_MODULE, |
1226 | .name = "nilfs2", | 1251 | .name = "nilfs2", |
1227 | .get_sb = nilfs_get_sb, | 1252 | .mount = nilfs_mount, |
1228 | .kill_sb = kill_block_super, | 1253 | .kill_sb = kill_block_super, |
1229 | .fs_flags = FS_REQUIRES_DEV, | 1254 | .fs_flags = FS_REQUIRES_DEV, |
1230 | }; | 1255 | }; |