1 /*
2 * Copyright (c) 1989, 1990, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 *
7 * @(#)mfs_vfsops.c 8.11 (Berkeley) 06/19/95
8 */
9
10 #include <sys/param.h>
11 #include <sys/systm.h>
12 #include <sys/time.h>
13 #include <sys/kernel.h>
14 #include <sys/proc.h>
15 #include <sys/buf.h>
16 #include <sys/mount.h>
17 #include <sys/signalvar.h>
18 #include <sys/vnode.h>
19 #include <sys/malloc.h>
20
21 #include <ufs/ufs/quota.h>
22 #include <ufs/ufs/inode.h>
23 #include <ufs/ufs/ufsmount.h>
24 #include <ufs/ufs/ufs_extern.h>
25
26 #include <ufs/ffs/fs.h>
27 #include <ufs/ffs/ffs_extern.h>
28
29 #include <ufs/mfs/mfsnode.h>
30 #include <ufs/mfs/mfs_extern.h>
31
32 caddr_t mfs_rootbase; /* address of mini-root in kernel virtual memory */
33 u_long mfs_rootsize; /* size of mini-root in bytes */
34
35 static int mfs_minor; /* used for building internal dev_t */
36
37 extern int (**mfs_vnodeop_p)();
38
39 /*
40 * mfs vfs operations.
41 */
42 struct vfsops mfs_vfsops = {
43 mfs_mount,
44 mfs_start,
45 ffs_unmount,
46 ufs_root,
47 ufs_quotactl,
48 mfs_statfs,
49 ffs_sync,
50 ffs_vget,
51 ffs_fhtovp,
52 ffs_vptofh,
53 mfs_init,
54 ffs_sysctl,
55 };
56
57 /*
58 * Called by main() when mfs is going to be mounted as root.
59 */
mfs_mountroot()60 mfs_mountroot()
61 {
62 extern struct vnode *rootvp;
63 struct fs *fs;
64 struct mount *mp;
65 struct proc *p = curproc; /* XXX */
66 struct ufsmount *ump;
67 struct mfsnode *mfsp;
68 int error;
69
70 /*
71 * Get vnodes for swapdev and rootdev.
72 */
73 if ((error = bdevvp(swapdev, &swapdev_vp)) ||
74 (error = bdevvp(rootdev, &rootvp))) {
75 printf("mfs_mountroot: can't setup bdevvp's");
76 return (error);
77 }
78 if (error = vfs_rootmountalloc("mfs", "mfs_root", &mp))
79 return (error);
80 mfsp = malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK);
81 rootvp->v_data = mfsp;
82 rootvp->v_op = mfs_vnodeop_p;
83 rootvp->v_tag = VT_MFS;
84 mfsp->mfs_baseoff = mfs_rootbase;
85 mfsp->mfs_size = mfs_rootsize;
86 mfsp->mfs_vnode = rootvp;
87 mfsp->mfs_pid = p->p_pid;
88 mfsp->mfs_buflist = (struct buf *)0;
89 if (error = ffs_mountfs(rootvp, mp, p)) {
90 mp->mnt_vfc->vfc_refcount--;
91 vfs_unbusy(mp, p);
92 free(mp, M_MOUNT);
93 free(mfsp, M_MFSNODE);
94 return (error);
95 }
96 simple_lock(&mountlist_slock);
97 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
98 simple_unlock(&mountlist_slock);
99 ump = VFSTOUFS(mp);
100 fs = ump->um_fs;
101 (void) copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0);
102 (void)ffs_statfs(mp, &mp->mnt_stat, p);
103 vfs_unbusy(mp, p);
104 inittodr((time_t)0);
105 return (0);
106 }
107
108 /*
109 * This is called early in boot to set the base address and size
110 * of the mini-root.
111 */
mfs_initminiroot(base)112 mfs_initminiroot(base)
113 caddr_t base;
114 {
115 struct fs *fs = (struct fs *)(base + SBOFF);
116 extern int (*mountroot)();
117
118 /* check for valid super block */
119 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
120 fs->fs_bsize < sizeof(struct fs))
121 return (0);
122 mountroot = mfs_mountroot;
123 mfs_rootbase = base;
124 mfs_rootsize = fs->fs_fsize * fs->fs_size;
125 rootdev = makedev(255, mfs_minor++);
126 return (mfs_rootsize);
127 }
128
129 /*
130 * VFS Operations.
131 *
132 * mount system call
133 */
134 /* ARGSUSED */
135 int
mfs_mount(mp,path,data,ndp,p)136 mfs_mount(mp, path, data, ndp, p)
137 register struct mount *mp;
138 char *path;
139 caddr_t data;
140 struct nameidata *ndp;
141 struct proc *p;
142 {
143 struct vnode *devvp;
144 struct mfs_args args;
145 struct ufsmount *ump;
146 register struct fs *fs;
147 register struct mfsnode *mfsp;
148 u_int size;
149 int flags, error;
150
151 if (error = copyin(data, (caddr_t)&args, sizeof (struct mfs_args)))
152 return (error);
153
154 /*
155 * If updating, check whether changing from read-only to
156 * read/write; if there is no device name, that's all we do.
157 */
158 if (mp->mnt_flag & MNT_UPDATE) {
159 ump = VFSTOUFS(mp);
160 fs = ump->um_fs;
161 if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
162 flags = WRITECLOSE;
163 if (mp->mnt_flag & MNT_FORCE)
164 flags |= FORCECLOSE;
165 if (error = ffs_flushfiles(mp, flags, p))
166 return (error);
167 }
168 if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR))
169 fs->fs_ronly = 0;
170 #ifdef EXPORTMFS
171 if (args.fspec == 0)
172 return (vfs_export(mp, &ump->um_export, &args.export));
173 #endif
174 return (0);
175 }
176 error = getnewvnode(VT_MFS, (struct mount *)0, mfs_vnodeop_p, &devvp);
177 if (error)
178 return (error);
179 devvp->v_type = VBLK;
180 if (checkalias(devvp, makedev(255, mfs_minor++), (struct mount *)0))
181 panic("mfs_mount: dup dev");
182 mfsp = (struct mfsnode *)malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK);
183 devvp->v_data = mfsp;
184 mfsp->mfs_baseoff = args.base;
185 mfsp->mfs_size = args.size;
186 mfsp->mfs_vnode = devvp;
187 mfsp->mfs_pid = p->p_pid;
188 mfsp->mfs_buflist = (struct buf *)0;
189 if (error = ffs_mountfs(devvp, mp, p)) {
190 mfsp->mfs_buflist = (struct buf *)-1;
191 vrele(devvp);
192 return (error);
193 }
194 ump = VFSTOUFS(mp);
195 fs = ump->um_fs;
196 (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
197 bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
198 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
199 MNAMELEN);
200 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
201 &size);
202 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
203 (void) mfs_statfs(mp, &mp->mnt_stat, p);
204 return (0);
205 }
206
207 int mfs_pri = PWAIT | PCATCH; /* XXX prob. temp */
208
209 /*
210 * Used to grab the process and keep it in the kernel to service
211 * memory filesystem I/O requests.
212 *
213 * Loop servicing I/O requests.
214 * Copy the requested data into or out of the memory filesystem
215 * address space.
216 */
217 /* ARGSUSED */
218 int
mfs_start(mp,flags,p)219 mfs_start(mp, flags, p)
220 struct mount *mp;
221 int flags;
222 struct proc *p;
223 {
224 register struct vnode *vp = VFSTOUFS(mp)->um_devvp;
225 register struct mfsnode *mfsp = VTOMFS(vp);
226 register struct buf *bp;
227 register caddr_t base;
228
229 base = mfsp->mfs_baseoff;
230 while (mfsp->mfs_buflist != (struct buf *)(-1)) {
231 while (bp = mfsp->mfs_buflist) {
232 mfsp->mfs_buflist = bp->b_actf;
233 mfs_doio(bp, base);
234 wakeup((caddr_t)bp);
235 }
236 /*
237 * If a non-ignored signal is received, try to unmount.
238 * If that fails, clear the signal (it has been "processed"),
239 * otherwise we will loop here, as tsleep will always return
240 * EINTR/ERESTART.
241 */
242 if (tsleep((caddr_t)vp, mfs_pri, "mfsidl", 0) &&
243 dounmount(mp, 0, p) != 0)
244 CLRSIG(p, CURSIG(p));
245 }
246 return (0);
247 }
248
249 /*
250 * Get file system statistics.
251 */
252 mfs_statfs(mp, sbp, p)
253 struct mount *mp;
254 struct statfs *sbp;
255 struct proc *p;
256 {
257 int error;
258
259 error = ffs_statfs(mp, sbp, p);
260 sbp->f_type = mp->mnt_vfc->vfc_typenum;
261 return (error);
262 }
263