aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namespace.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2011-12-06 12:21:54 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2012-01-03 22:57:13 -0500
commit0226f4923f6c9b40cfa1c1c1b19a6ac6b3924ead (patch)
treecb0f26e6329e2222a9f3b8f85887f63980a01d37 /fs/namespace.c
parent3a2393d71d77b034669d495b49c212a87e04abdc (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.c218
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)
898EXPORT_SYMBOL(replace_mount_options); 898EXPORT_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... */
902static void *m_start(struct seq_file *m, loff_t *pos) 902static 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
910static void *m_next(struct seq_file *m, void *v, loff_t *pos) 910static 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
922int mnt_had_events(struct proc_mounts *p) 922static 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
937struct proc_fs_info {
938 int flag;
939 const char *str;
940};
941
942static 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
960static 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
979static 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
988static 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");
1014out:
1015 return err;
1016} 927}
1017 928
1018const struct seq_operations mounts_op = { 929const 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
1025static 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');
1083out:
1084 return err;
1085}
1086
1087const struct seq_operations mountinfo_op = {
1088 .start = m_start,
1089 .next = m_next,
1090 .stop = m_stop,
1091 .show = show_mountinfo,
1092};
1093
1094static 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
1133const 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