aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nilfs2/cpfile.c23
-rw-r--r--fs/nilfs2/inode.c10
-rw-r--r--fs/nilfs2/nilfs.h3
-rw-r--r--fs/nilfs2/super.c32
-rw-r--r--fs/nilfs2/the_nilfs.c21
-rw-r--r--fs/nilfs2/the_nilfs.h1
6 files changed, 53 insertions, 37 deletions
diff --git a/fs/nilfs2/cpfile.c b/fs/nilfs2/cpfile.c
index 03de1da8795b..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 */
864int nilfs_cpfile_change_cpmode(struct inode *cpfile, __u64 cno, int mode) 864int 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:
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index 5b3d43fb4e12..71d4bc8464e0 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -506,6 +506,16 @@ static int nilfs_iget_set(struct inode *inode, void *opaque)
506 return 0; 506 return 0;
507} 507}
508 508
509struct 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
509struct inode *nilfs_iget_locked(struct super_block *sb, struct nilfs_root *root, 519struct inode *nilfs_iget_locked(struct super_block *sb, struct nilfs_root *root,
510 unsigned long ino) 520 unsigned long ino)
511{ 521{
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
index 2ca2ca5ca848..f6e276eaaf6f 100644
--- a/fs/nilfs2/nilfs.h
+++ b/fs/nilfs2/nilfs.h
@@ -244,6 +244,8 @@ extern int nilfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
244extern void nilfs_set_inode_flags(struct inode *); 244extern void nilfs_set_inode_flags(struct inode *);
245extern int nilfs_read_inode_common(struct inode *, struct nilfs_inode *); 245extern int nilfs_read_inode_common(struct inode *, struct nilfs_inode *);
246extern void nilfs_write_inode_common(struct inode *, struct nilfs_inode *, int); 246extern void nilfs_write_inode_common(struct inode *, struct nilfs_inode *, int);
247struct inode *nilfs_ilookup(struct super_block *sb, struct nilfs_root *root,
248 unsigned long ino);
247struct inode *nilfs_iget_locked(struct super_block *sb, struct nilfs_root *root, 249struct inode *nilfs_iget_locked(struct super_block *sb, struct nilfs_root *root,
248 unsigned long ino); 250 unsigned long ino);
249struct inode *nilfs_iget(struct super_block *sb, struct nilfs_root *root, 251struct inode *nilfs_iget(struct super_block *sb, struct nilfs_root *root,
@@ -285,6 +287,7 @@ extern int nilfs_commit_super(struct nilfs_sb_info *, int);
285extern int nilfs_cleanup_super(struct nilfs_sb_info *); 287extern int nilfs_cleanup_super(struct nilfs_sb_info *);
286int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt, 288int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt,
287 struct nilfs_root **root); 289 struct nilfs_root **root);
290int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno);
288 291
289/* gcinode.c */ 292/* gcinode.c */
290int nilfs_gccache_submit_read_data(struct inode *, sector_t, sector_t, __u64, 293int nilfs_gccache_submit_read_data(struct inode *, sector_t, sector_t, __u64,
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index 39e7d7f8eda0..ab96d26bf7e9 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -833,6 +833,38 @@ static int nilfs_try_to_shrink_tree(struct dentry *root_dentry)
833 return nilfs_tree_was_touched(root_dentry); 833 return nilfs_tree_was_touched(root_dentry);
834} 834}
835 835
836int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno)
837{
838 struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs;
839 struct nilfs_root *root;
840 struct inode *inode;
841 struct dentry *dentry;
842 int ret;
843
844 if (cno < 0 || cno > nilfs->ns_cno)
845 return false;
846
847 if (cno >= nilfs_last_cno(nilfs))
848 return true; /* protect recent checkpoints */
849
850 ret = false;
851 root = nilfs_lookup_root(NILFS_SB(sb)->s_nilfs, cno);
852 if (root) {
853 inode = nilfs_ilookup(sb, root, NILFS_ROOT_INO);
854 if (inode) {
855 dentry = d_find_alias(inode);
856 if (dentry) {
857 if (nilfs_tree_was_touched(dentry))
858 ret = nilfs_try_to_shrink_tree(dentry);
859 dput(dentry);
860 }
861 iput(inode);
862 }
863 nilfs_put_root(root);
864 }
865 return ret;
866}
867
836/** 868/**
837 * nilfs_fill_super() - initialize a super block instance 869 * nilfs_fill_super() - initialize a super block instance
838 * @sb: super_block 870 * @sb: super_block
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index 4d6763e28eb5..4cc705a1d135 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -769,24 +769,3 @@ void nilfs_put_root(struct nilfs_root *root)
769 kfree(root); 769 kfree(root);
770 } 770 }
771} 771}
772
773int nilfs_checkpoint_is_mounted(struct the_nilfs *nilfs, __u64 cno,
774 int snapshot_mount)
775{
776 struct nilfs_root *root;
777 int ret;
778
779 if (cno < 0 || cno > nilfs->ns_cno)
780 return false;
781
782 if (cno >= nilfs_last_cno(nilfs))
783 return true; /* protect recent checkpoints */
784
785 ret = false;
786 root = nilfs_lookup_root(nilfs, cno);
787 if (root) {
788 ret = true;
789 nilfs_put_root(root);
790 }
791 return ret;
792}
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h
index a5178dc43dfd..cae56f338b64 100644
--- a/fs/nilfs2/the_nilfs.h
+++ b/fs/nilfs2/the_nilfs.h
@@ -242,7 +242,6 @@ struct nilfs_root *nilfs_find_or_create_root(struct the_nilfs *nilfs,
242 __u64 cno); 242 __u64 cno);
243void nilfs_put_root(struct nilfs_root *root); 243void nilfs_put_root(struct nilfs_root *root);
244struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *, int, __u64); 244struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *, int, __u64);
245int nilfs_checkpoint_is_mounted(struct the_nilfs *, __u64, int);
246int nilfs_near_disk_full(struct the_nilfs *); 245int nilfs_near_disk_full(struct the_nilfs *);
247void nilfs_fall_back_super_block(struct the_nilfs *); 246void nilfs_fall_back_super_block(struct the_nilfs *);
248void nilfs_swap_super_block(struct the_nilfs *); 247void nilfs_swap_super_block(struct the_nilfs *);