diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2011-12-06 12:21:54 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-01-03 22:57:13 -0500 |
commit | 0226f4923f6c9b40cfa1c1c1b19a6ac6b3924ead (patch) | |
tree | cb0f26e6329e2222a9f3b8f85887f63980a01d37 /fs/namespace.c | |
parent | 3a2393d71d77b034669d495b49c212a87e04abdc (diff) |
vfs: take /proc/*/mounts and friends to fs/proc_namespace.c
rationale: that stuff is far tighter bound to fs/namespace.c than to
the guts of procfs proper.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 218 |
1 files changed, 7 insertions, 211 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index cd6389387d1f..21a8261256dd 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -898,10 +898,10 @@ void replace_mount_options(struct super_block *sb, char *options) | |||
898 | EXPORT_SYMBOL(replace_mount_options); | 898 | EXPORT_SYMBOL(replace_mount_options); |
899 | 899 | ||
900 | #ifdef CONFIG_PROC_FS | 900 | #ifdef CONFIG_PROC_FS |
901 | /* iterator */ | 901 | /* iterator; we want it to have access to namespace_sem, thus here... */ |
902 | static void *m_start(struct seq_file *m, loff_t *pos) | 902 | static void *m_start(struct seq_file *m, loff_t *pos) |
903 | { | 903 | { |
904 | struct proc_mounts *p = m->private; | 904 | struct proc_mounts *p = container_of(m, struct proc_mounts, m); |
905 | 905 | ||
906 | down_read(&namespace_sem); | 906 | down_read(&namespace_sem); |
907 | return seq_list_start(&p->ns->list, *pos); | 907 | return seq_list_start(&p->ns->list, *pos); |
@@ -909,7 +909,7 @@ static void *m_start(struct seq_file *m, loff_t *pos) | |||
909 | 909 | ||
910 | static void *m_next(struct seq_file *m, void *v, loff_t *pos) | 910 | static void *m_next(struct seq_file *m, void *v, loff_t *pos) |
911 | { | 911 | { |
912 | struct proc_mounts *p = m->private; | 912 | struct proc_mounts *p = container_of(m, struct proc_mounts, m); |
913 | 913 | ||
914 | return seq_list_next(v, &p->ns->list, pos); | 914 | return seq_list_next(v, &p->ns->list, pos); |
915 | } | 915 | } |
@@ -919,222 +919,18 @@ static void m_stop(struct seq_file *m, void *v) | |||
919 | up_read(&namespace_sem); | 919 | up_read(&namespace_sem); |
920 | } | 920 | } |
921 | 921 | ||
922 | int mnt_had_events(struct proc_mounts *p) | 922 | static int m_show(struct seq_file *m, void *v) |
923 | { | ||
924 | struct mnt_namespace *ns = p->ns; | ||
925 | int res = 0; | ||
926 | |||
927 | br_read_lock(vfsmount_lock); | ||
928 | if (p->m.poll_event != ns->event) { | ||
929 | p->m.poll_event = ns->event; | ||
930 | res = 1; | ||
931 | } | ||
932 | br_read_unlock(vfsmount_lock); | ||
933 | |||
934 | return res; | ||
935 | } | ||
936 | |||
937 | struct proc_fs_info { | ||
938 | int flag; | ||
939 | const char *str; | ||
940 | }; | ||
941 | |||
942 | static int show_sb_opts(struct seq_file *m, struct super_block *sb) | ||
943 | { | ||
944 | static const struct proc_fs_info fs_info[] = { | ||
945 | { MS_SYNCHRONOUS, ",sync" }, | ||
946 | { MS_DIRSYNC, ",dirsync" }, | ||
947 | { MS_MANDLOCK, ",mand" }, | ||
948 | { 0, NULL } | ||
949 | }; | ||
950 | const struct proc_fs_info *fs_infop; | ||
951 | |||
952 | for (fs_infop = fs_info; fs_infop->flag; fs_infop++) { | ||
953 | if (sb->s_flags & fs_infop->flag) | ||
954 | seq_puts(m, fs_infop->str); | ||
955 | } | ||
956 | |||
957 | return security_sb_show_options(m, sb); | ||
958 | } | ||
959 | |||
960 | static void show_mnt_opts(struct seq_file *m, struct vfsmount *mnt) | ||
961 | { | ||
962 | static const struct proc_fs_info mnt_info[] = { | ||
963 | { MNT_NOSUID, ",nosuid" }, | ||
964 | { MNT_NODEV, ",nodev" }, | ||
965 | { MNT_NOEXEC, ",noexec" }, | ||
966 | { MNT_NOATIME, ",noatime" }, | ||
967 | { MNT_NODIRATIME, ",nodiratime" }, | ||
968 | { MNT_RELATIME, ",relatime" }, | ||
969 | { 0, NULL } | ||
970 | }; | ||
971 | const struct proc_fs_info *fs_infop; | ||
972 | |||
973 | for (fs_infop = mnt_info; fs_infop->flag; fs_infop++) { | ||
974 | if (mnt->mnt_flags & fs_infop->flag) | ||
975 | seq_puts(m, fs_infop->str); | ||
976 | } | ||
977 | } | ||
978 | |||
979 | static void show_type(struct seq_file *m, struct super_block *sb) | ||
980 | { | ||
981 | mangle(m, sb->s_type->name); | ||
982 | if (sb->s_subtype && sb->s_subtype[0]) { | ||
983 | seq_putc(m, '.'); | ||
984 | mangle(m, sb->s_subtype); | ||
985 | } | ||
986 | } | ||
987 | |||
988 | static int show_vfsmnt(struct seq_file *m, void *v) | ||
989 | { | 923 | { |
924 | struct proc_mounts *p = container_of(m, struct proc_mounts, m); | ||
990 | struct mount *r = list_entry(v, struct mount, mnt_list); | 925 | struct mount *r = list_entry(v, struct mount, mnt_list); |
991 | struct vfsmount *mnt = &r->mnt; | 926 | return p->show(m, &r->mnt); |
992 | int err = 0; | ||
993 | struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; | ||
994 | |||
995 | if (mnt->mnt_sb->s_op->show_devname) { | ||
996 | err = mnt->mnt_sb->s_op->show_devname(m, mnt); | ||
997 | if (err) | ||
998 | goto out; | ||
999 | } else { | ||
1000 | mangle(m, r->mnt_devname ? r->mnt_devname : "none"); | ||
1001 | } | ||
1002 | seq_putc(m, ' '); | ||
1003 | seq_path(m, &mnt_path, " \t\n\\"); | ||
1004 | seq_putc(m, ' '); | ||
1005 | show_type(m, mnt->mnt_sb); | ||
1006 | seq_puts(m, __mnt_is_readonly(mnt) ? " ro" : " rw"); | ||
1007 | err = show_sb_opts(m, mnt->mnt_sb); | ||
1008 | if (err) | ||
1009 | goto out; | ||
1010 | show_mnt_opts(m, mnt); | ||
1011 | if (mnt->mnt_sb->s_op->show_options) | ||
1012 | err = mnt->mnt_sb->s_op->show_options(m, mnt); | ||
1013 | seq_puts(m, " 0 0\n"); | ||
1014 | out: | ||
1015 | return err; | ||
1016 | } | 927 | } |
1017 | 928 | ||
1018 | const struct seq_operations mounts_op = { | 929 | const struct seq_operations mounts_op = { |
1019 | .start = m_start, | 930 | .start = m_start, |
1020 | .next = m_next, | 931 | .next = m_next, |
1021 | .stop = m_stop, | 932 | .stop = m_stop, |
1022 | .show = show_vfsmnt | 933 | .show = m_show, |
1023 | }; | ||
1024 | |||
1025 | static int show_mountinfo(struct seq_file *m, void *v) | ||
1026 | { | ||
1027 | struct proc_mounts *p = m->private; | ||
1028 | struct mount *r = list_entry(v, struct mount, mnt_list); | ||
1029 | struct vfsmount *mnt = &r->mnt; | ||
1030 | struct super_block *sb = mnt->mnt_sb; | ||
1031 | struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; | ||
1032 | struct path root = p->root; | ||
1033 | int err = 0; | ||
1034 | |||
1035 | seq_printf(m, "%i %i %u:%u ", r->mnt_id, r->mnt_parent->mnt_id, | ||
1036 | MAJOR(sb->s_dev), MINOR(sb->s_dev)); | ||
1037 | if (sb->s_op->show_path) | ||
1038 | err = sb->s_op->show_path(m, mnt); | ||
1039 | else | ||
1040 | seq_dentry(m, mnt->mnt_root, " \t\n\\"); | ||
1041 | if (err) | ||
1042 | goto out; | ||
1043 | seq_putc(m, ' '); | ||
1044 | |||
1045 | /* mountpoints outside of chroot jail will give SEQ_SKIP on this */ | ||
1046 | err = seq_path_root(m, &mnt_path, &root, " \t\n\\"); | ||
1047 | if (err) | ||
1048 | goto out; | ||
1049 | |||
1050 | seq_puts(m, mnt->mnt_flags & MNT_READONLY ? " ro" : " rw"); | ||
1051 | show_mnt_opts(m, mnt); | ||
1052 | |||
1053 | /* Tagged fields ("foo:X" or "bar") */ | ||
1054 | if (IS_MNT_SHARED(r)) | ||
1055 | seq_printf(m, " shared:%i", r->mnt_group_id); | ||
1056 | if (IS_MNT_SLAVE(r)) { | ||
1057 | int master = r->mnt_master->mnt_group_id; | ||
1058 | int dom = get_dominating_id(r, &p->root); | ||
1059 | seq_printf(m, " master:%i", master); | ||
1060 | if (dom && dom != master) | ||
1061 | seq_printf(m, " propagate_from:%i", dom); | ||
1062 | } | ||
1063 | if (IS_MNT_UNBINDABLE(r)) | ||
1064 | seq_puts(m, " unbindable"); | ||
1065 | |||
1066 | /* Filesystem specific data */ | ||
1067 | seq_puts(m, " - "); | ||
1068 | show_type(m, sb); | ||
1069 | seq_putc(m, ' '); | ||
1070 | if (sb->s_op->show_devname) | ||
1071 | err = sb->s_op->show_devname(m, mnt); | ||
1072 | else | ||
1073 | mangle(m, r->mnt_devname ? r->mnt_devname : "none"); | ||
1074 | if (err) | ||
1075 | goto out; | ||
1076 | seq_puts(m, sb->s_flags & MS_RDONLY ? " ro" : " rw"); | ||
1077 | err = show_sb_opts(m, sb); | ||
1078 | if (err) | ||
1079 | goto out; | ||
1080 | if (sb->s_op->show_options) | ||
1081 | err = sb->s_op->show_options(m, mnt); | ||
1082 | seq_putc(m, '\n'); | ||
1083 | out: | ||
1084 | return err; | ||
1085 | } | ||
1086 | |||
1087 | const struct seq_operations mountinfo_op = { | ||
1088 | .start = m_start, | ||
1089 | .next = m_next, | ||
1090 | .stop = m_stop, | ||
1091 | .show = show_mountinfo, | ||
1092 | }; | ||
1093 | |||
1094 | static int show_vfsstat(struct seq_file *m, void *v) | ||
1095 | { | ||
1096 | struct mount *r = list_entry(v, struct mount, mnt_list); | ||
1097 | struct vfsmount *mnt = &r->mnt; | ||
1098 | struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; | ||
1099 | int err = 0; | ||
1100 | |||
1101 | /* device */ | ||
1102 | if (mnt->mnt_sb->s_op->show_devname) { | ||
1103 | seq_puts(m, "device "); | ||
1104 | err = mnt->mnt_sb->s_op->show_devname(m, mnt); | ||
1105 | } else { | ||
1106 | if (r->mnt_devname) { | ||
1107 | seq_puts(m, "device "); | ||
1108 | mangle(m, r->mnt_devname); | ||
1109 | } else | ||
1110 | seq_puts(m, "no device"); | ||
1111 | } | ||
1112 | |||
1113 | /* mount point */ | ||
1114 | seq_puts(m, " mounted on "); | ||
1115 | seq_path(m, &mnt_path, " \t\n\\"); | ||
1116 | seq_putc(m, ' '); | ||
1117 | |||
1118 | /* file system type */ | ||
1119 | seq_puts(m, "with fstype "); | ||
1120 | show_type(m, mnt->mnt_sb); | ||
1121 | |||
1122 | /* optional statistics */ | ||
1123 | if (mnt->mnt_sb->s_op->show_stats) { | ||
1124 | seq_putc(m, ' '); | ||
1125 | if (!err) | ||
1126 | err = mnt->mnt_sb->s_op->show_stats(m, mnt); | ||
1127 | } | ||
1128 | |||
1129 | seq_putc(m, '\n'); | ||
1130 | return err; | ||
1131 | } | ||
1132 | |||
1133 | const struct seq_operations mountstats_op = { | ||
1134 | .start = m_start, | ||
1135 | .next = m_next, | ||
1136 | .stop = m_stop, | ||
1137 | .show = show_vfsstat, | ||
1138 | }; | 934 | }; |
1139 | #endif /* CONFIG_PROC_FS */ | 935 | #endif /* CONFIG_PROC_FS */ |
1140 | 936 | ||