diff options
-rw-r--r-- | fs/gfs2/glock.c | 6 | ||||
-rw-r--r-- | fs/gfs2/incore.h | 2 | ||||
-rw-r--r-- | fs/gfs2/ops_fstype.c | 147 | ||||
-rw-r--r-- | fs/gfs2/ops_super.c | 3 |
4 files changed, 155 insertions, 3 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 005788fb361f..ef713dbff601 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
@@ -1165,7 +1165,13 @@ static void add_to_queue(struct gfs2_holder *gh) | |||
1165 | existing = find_holder_by_owner(&gl->gl_holders, gh->gh_owner); | 1165 | existing = find_holder_by_owner(&gl->gl_holders, gh->gh_owner); |
1166 | if (existing) { | 1166 | if (existing) { |
1167 | print_symbol(KERN_WARNING "original: %s\n", existing->gh_ip); | 1167 | print_symbol(KERN_WARNING "original: %s\n", existing->gh_ip); |
1168 | printk(KERN_INFO "pid : %d\n", existing->gh_owner->pid); | ||
1169 | printk(KERN_INFO "lock type : %d lock state : %d\n", | ||
1170 | existing->gh_gl->gl_name.ln_type, existing->gh_gl->gl_state); | ||
1168 | print_symbol(KERN_WARNING "new: %s\n", gh->gh_ip); | 1171 | print_symbol(KERN_WARNING "new: %s\n", gh->gh_ip); |
1172 | printk(KERN_INFO "pid : %d\n", gh->gh_owner->pid); | ||
1173 | printk(KERN_INFO "lock type : %d lock state : %d\n", | ||
1174 | gl->gl_name.ln_type, gl->gl_state); | ||
1169 | BUG(); | 1175 | BUG(); |
1170 | } | 1176 | } |
1171 | 1177 | ||
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 78d3cb511eb8..77f0903d2f3e 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
@@ -472,6 +472,7 @@ enum { | |||
472 | 472 | ||
473 | struct gfs2_sbd { | 473 | struct gfs2_sbd { |
474 | struct super_block *sd_vfs; | 474 | struct super_block *sd_vfs; |
475 | struct super_block *sd_vfs_meta; | ||
475 | struct kobject sd_kobj; | 476 | struct kobject sd_kobj; |
476 | unsigned long sd_flags; /* SDF_... */ | 477 | unsigned long sd_flags; /* SDF_... */ |
477 | struct gfs2_sb sd_sb; | 478 | struct gfs2_sb sd_sb; |
@@ -652,6 +653,7 @@ struct gfs2_sbd { | |||
652 | /* Debugging crud */ | 653 | /* Debugging crud */ |
653 | 654 | ||
654 | unsigned long sd_last_warning; | 655 | unsigned long sd_last_warning; |
656 | struct vfsmount *sd_gfs2mnt; | ||
655 | }; | 657 | }; |
656 | 658 | ||
657 | #endif /* __INCORE_DOT_H__ */ | 659 | #endif /* __INCORE_DOT_H__ */ |
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index c66067c84bcf..e5a91ead250c 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -15,6 +15,8 @@ | |||
15 | #include <linux/vmalloc.h> | 15 | #include <linux/vmalloc.h> |
16 | #include <linux/blkdev.h> | 16 | #include <linux/blkdev.h> |
17 | #include <linux/kthread.h> | 17 | #include <linux/kthread.h> |
18 | #include <linux/namei.h> | ||
19 | #include <linux/mount.h> | ||
18 | #include <linux/gfs2_ondisk.h> | 20 | #include <linux/gfs2_ondisk.h> |
19 | 21 | ||
20 | #include "gfs2.h" | 22 | #include "gfs2.h" |
@@ -813,7 +815,138 @@ static int fill_super(struct super_block *sb, void *data, int silent) | |||
813 | static int gfs2_get_sb(struct file_system_type *fs_type, int flags, | 815 | static int gfs2_get_sb(struct file_system_type *fs_type, int flags, |
814 | const char *dev_name, void *data, struct vfsmount *mnt) | 816 | const char *dev_name, void *data, struct vfsmount *mnt) |
815 | { | 817 | { |
816 | return get_sb_bdev(fs_type, flags, dev_name, data, fill_super, mnt); | 818 | struct super_block *sb; |
819 | struct gfs2_sbd *sdp; | ||
820 | int error = get_sb_bdev(fs_type, flags, dev_name, data, fill_super, mnt); | ||
821 | if (error) | ||
822 | goto out; | ||
823 | sb = mnt->mnt_sb; | ||
824 | sdp = (struct gfs2_sbd*)sb->s_fs_info; | ||
825 | sdp->sd_gfs2mnt = mnt; | ||
826 | out: | ||
827 | return error; | ||
828 | } | ||
829 | |||
830 | static int fill_super_meta(struct super_block *sb, struct super_block *new, | ||
831 | void *data, int silent) | ||
832 | { | ||
833 | struct gfs2_sbd *sdp = sb->s_fs_info; | ||
834 | struct inode *inode; | ||
835 | int error = 0; | ||
836 | |||
837 | new->s_fs_info = sdp; | ||
838 | sdp->sd_vfs_meta = sb; | ||
839 | |||
840 | init_vfs(new, SDF_NOATIME); | ||
841 | |||
842 | /* Get the master inode */ | ||
843 | inode = igrab(sdp->sd_master_dir); | ||
844 | |||
845 | new->s_root = d_alloc_root(inode); | ||
846 | if (!new->s_root) { | ||
847 | fs_err(sdp, "can't get root dentry\n"); | ||
848 | error = -ENOMEM; | ||
849 | iput(inode); | ||
850 | } | ||
851 | new->s_root->d_op = &gfs2_dops; | ||
852 | |||
853 | return error; | ||
854 | } | ||
855 | static int set_bdev_super(struct super_block *s, void *data) | ||
856 | { | ||
857 | s->s_bdev = data; | ||
858 | s->s_dev = s->s_bdev->bd_dev; | ||
859 | return 0; | ||
860 | } | ||
861 | |||
862 | static int test_bdev_super(struct super_block *s, void *data) | ||
863 | { | ||
864 | return (void *)s->s_bdev == data; | ||
865 | } | ||
866 | |||
867 | static struct super_block* get_gfs2_sb(const char *dev_name) | ||
868 | { | ||
869 | struct kstat stat; | ||
870 | struct nameidata nd; | ||
871 | struct file_system_type *fstype; | ||
872 | struct super_block *sb = NULL, *s; | ||
873 | struct list_head *l; | ||
874 | int error; | ||
875 | |||
876 | error = path_lookup(dev_name, LOOKUP_FOLLOW, &nd); | ||
877 | if (error) { | ||
878 | printk(KERN_WARNING "GFS2: path_lookup on %s returned error\n", | ||
879 | dev_name); | ||
880 | goto out; | ||
881 | } | ||
882 | error = vfs_getattr(nd.mnt, nd.dentry, &stat); | ||
883 | |||
884 | fstype = get_fs_type("gfs2"); | ||
885 | list_for_each(l, &fstype->fs_supers) { | ||
886 | s = list_entry(l, struct super_block, s_instances); | ||
887 | if ((S_ISBLK(stat.mode) && s->s_dev == stat.rdev) || | ||
888 | (S_ISDIR(stat.mode) && s == nd.dentry->d_inode->i_sb)) { | ||
889 | sb = s; | ||
890 | goto free_nd; | ||
891 | } | ||
892 | } | ||
893 | |||
894 | printk(KERN_WARNING "GFS2: Unrecognized block device or " | ||
895 | "mount point %s", dev_name); | ||
896 | |||
897 | free_nd: | ||
898 | path_release(&nd); | ||
899 | out: | ||
900 | return sb; | ||
901 | } | ||
902 | |||
903 | static int gfs2_get_sb_meta(struct file_system_type *fs_type, int flags, | ||
904 | const char *dev_name, void *data, struct vfsmount *mnt) | ||
905 | { | ||
906 | int error = 0; | ||
907 | struct super_block *sb = NULL, *new; | ||
908 | struct gfs2_sbd *sdp; | ||
909 | char *gfs2mnt = NULL; | ||
910 | |||
911 | sb = get_gfs2_sb(dev_name); | ||
912 | if (!sb) { | ||
913 | printk(KERN_WARNING "GFS2: gfs2 mount does not exist\n"); | ||
914 | error = -ENOENT; | ||
915 | goto error; | ||
916 | } | ||
917 | sdp = (struct gfs2_sbd*) sb->s_fs_info; | ||
918 | if (sdp->sd_vfs_meta) { | ||
919 | printk(KERN_WARNING "GFS2: gfs2meta mount already exists\n"); | ||
920 | error = -EBUSY; | ||
921 | goto error; | ||
922 | } | ||
923 | mutex_lock(&sb->s_bdev->bd_mount_mutex); | ||
924 | new = sget(fs_type, test_bdev_super, set_bdev_super, sb->s_bdev); | ||
925 | mutex_unlock(&sb->s_bdev->bd_mount_mutex); | ||
926 | if (IS_ERR(new)) { | ||
927 | error = PTR_ERR(new); | ||
928 | goto error; | ||
929 | } | ||
930 | module_put(fs_type->owner); | ||
931 | new->s_flags = flags; | ||
932 | strlcpy(new->s_id, sb->s_id, sizeof(new->s_id)); | ||
933 | sb_set_blocksize(new, sb->s_blocksize); | ||
934 | error = fill_super_meta(sb, new, data, flags & MS_SILENT ? 1 : 0); | ||
935 | if (error) { | ||
936 | up_write(&new->s_umount); | ||
937 | deactivate_super(new); | ||
938 | goto error; | ||
939 | } | ||
940 | |||
941 | new->s_flags |= MS_ACTIVE; | ||
942 | |||
943 | /* Grab a reference to the gfs2 mount point */ | ||
944 | atomic_inc(&sdp->sd_gfs2mnt->mnt_count); | ||
945 | return simple_set_mnt(mnt, new); | ||
946 | error: | ||
947 | if (gfs2mnt) | ||
948 | kfree(gfs2mnt); | ||
949 | return error; | ||
817 | } | 950 | } |
818 | 951 | ||
819 | static void gfs2_kill_sb(struct super_block *sb) | 952 | static void gfs2_kill_sb(struct super_block *sb) |
@@ -821,6 +954,14 @@ static void gfs2_kill_sb(struct super_block *sb) | |||
821 | kill_block_super(sb); | 954 | kill_block_super(sb); |
822 | } | 955 | } |
823 | 956 | ||
957 | static void gfs2_kill_sb_meta(struct super_block *sb) | ||
958 | { | ||
959 | struct gfs2_sbd *sdp = sb->s_fs_info; | ||
960 | generic_shutdown_super(sb); | ||
961 | sdp->sd_vfs_meta = NULL; | ||
962 | atomic_dec(&sdp->sd_gfs2mnt->mnt_count); | ||
963 | } | ||
964 | |||
824 | struct file_system_type gfs2_fs_type = { | 965 | struct file_system_type gfs2_fs_type = { |
825 | .name = "gfs2", | 966 | .name = "gfs2", |
826 | .fs_flags = FS_REQUIRES_DEV, | 967 | .fs_flags = FS_REQUIRES_DEV, |
@@ -832,8 +973,8 @@ struct file_system_type gfs2_fs_type = { | |||
832 | struct file_system_type gfs2meta_fs_type = { | 973 | struct file_system_type gfs2meta_fs_type = { |
833 | .name = "gfs2meta", | 974 | .name = "gfs2meta", |
834 | .fs_flags = FS_REQUIRES_DEV, | 975 | .fs_flags = FS_REQUIRES_DEV, |
835 | .get_sb = gfs2_get_sb, | 976 | .get_sb = gfs2_get_sb_meta, |
836 | .kill_sb = gfs2_kill_sb, | 977 | .kill_sb = gfs2_kill_sb_meta, |
837 | .owner = THIS_MODULE, | 978 | .owner = THIS_MODULE, |
838 | }; | 979 | }; |
839 | 980 | ||
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index 2e392c994ab1..18ed18c729e8 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c | |||
@@ -78,6 +78,9 @@ static void gfs2_put_super(struct super_block *sb) | |||
78 | if (!sdp) | 78 | if (!sdp) |
79 | return; | 79 | return; |
80 | 80 | ||
81 | if (!strncmp(sb->s_type->name, "gfs2meta", 8)) | ||
82 | return; /* meta fs. don't do nothin' */ | ||
83 | |||
81 | /* Unfreeze the filesystem, if we need to */ | 84 | /* Unfreeze the filesystem, if we need to */ |
82 | 85 | ||
83 | mutex_lock(&sdp->sd_freeze_lock); | 86 | mutex_lock(&sdp->sd_freeze_lock); |