ffs_vfsops.c revision 1.31 1 /* $NetBSD: ffs_vfsops.c,v 1.31 1997/10/16 18:29:11 mjacob Exp $ */
2
3 /*
4 * Copyright (c) 1989, 1991, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)ffs_vfsops.c 8.14 (Berkeley) 11/28/94
36 */
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/namei.h>
41 #include <sys/proc.h>
42 #include <sys/kernel.h>
43 #include <sys/vnode.h>
44 #include <sys/socket.h>
45 #include <sys/mount.h>
46 #include <sys/buf.h>
47 #include <sys/device.h>
48 #include <sys/mbuf.h>
49 #include <sys/file.h>
50 #include <sys/disklabel.h>
51 #include <sys/ioctl.h>
52 #include <sys/errno.h>
53 #include <sys/malloc.h>
54 #include <sys/lock.h>
55
56 #include <miscfs/specfs/specdev.h>
57
58 #include <ufs/ufs/quota.h>
59 #include <ufs/ufs/ufsmount.h>
60 #include <ufs/ufs/inode.h>
61 #include <ufs/ufs/dir.h>
62 #include <ufs/ufs/ufs_extern.h>
63
64 #include <ufs/ffs/fs.h>
65 #include <ufs/ffs/ffs_extern.h>
66
67 extern struct lock ufs_hashlock;
68
69 int ffs_sbupdate __P((struct ufsmount *, int));
70
71 struct vfsops ffs_vfsops = {
72 MOUNT_FFS,
73 ffs_mount,
74 ufs_start,
75 ffs_unmount,
76 ufs_root,
77 ufs_quotactl,
78 ffs_statfs,
79 ffs_sync,
80 ffs_vget,
81 ffs_fhtovp,
82 ffs_vptofh,
83 ffs_init,
84 ffs_mountroot,
85 };
86
87 /*
88 * Called by main() when ufs is going to be mounted as root.
89 *
90 * Name is updated by mount(8) after booting.
91 */
92 #define ROOTNAME "root_device"
93
94 int
95 ffs_mountroot()
96 {
97 extern struct vnode *rootvp;
98 register struct fs *fs;
99 register struct mount *mp;
100 struct proc *p = curproc; /* XXX */
101 struct ufsmount *ump;
102 size_t size;
103 int error;
104
105 if (root_device->dv_class != DV_DISK)
106 return (ENODEV);
107
108 /*
109 * Get vnodes for rootdev.
110 */
111 if (bdevvp(rootdev, &rootvp))
112 panic("ffs_mountroot: can't setup bdevvp's");
113
114 mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK);
115 bzero((char *)mp, (u_long)sizeof(struct mount));
116 mp->mnt_op = &ffs_vfsops;
117 mp->mnt_flag = MNT_RDONLY;
118 if ((error = ffs_mountfs(rootvp, mp, p)) != 0) {
119 free(mp, M_MOUNT);
120 return (error);
121 }
122 if ((error = vfs_lock(mp)) != 0) {
123 (void)ffs_unmount(mp, 0, p);
124 free(mp, M_MOUNT);
125 return (error);
126 }
127 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
128 mp->mnt_vnodecovered = NULLVP;
129 ump = VFSTOUFS(mp);
130 fs = ump->um_fs;
131 bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt));
132 fs->fs_fsmnt[0] = '/';
133 bcopy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname, MNAMELEN);
134 (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
135 &size);
136 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
137 (void)ffs_statfs(mp, &mp->mnt_stat, p);
138 vfs_unlock(mp);
139 inittodr(fs->fs_time);
140 return (0);
141 }
142
143 /*
144 * VFS Operations.
145 *
146 * mount system call
147 */
148 int
149 ffs_mount(mp, path, data, ndp, p)
150 register struct mount *mp;
151 const char *path;
152 void *data;
153 struct nameidata *ndp;
154 struct proc *p;
155 {
156 struct vnode *devvp;
157 struct ufs_args args;
158 struct ufsmount *ump = NULL;
159 register struct fs *fs;
160 size_t size;
161 int error, flags;
162 mode_t accessmode;
163
164 error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args));
165 if (error)
166 return (error);
167 /*
168 * If updating, check whether changing from read-only to
169 * read/write; if there is no device name, that's all we do.
170 */
171 if (mp->mnt_flag & MNT_UPDATE) {
172 ump = VFSTOUFS(mp);
173 fs = ump->um_fs;
174 if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
175 flags = WRITECLOSE;
176 if (mp->mnt_flag & MNT_FORCE)
177 flags |= FORCECLOSE;
178 if (vfs_busy(mp))
179 return (EBUSY);
180 error = ffs_flushfiles(mp, flags, p);
181 if (error == 0 &&
182 ffs_cgupdate(ump, MNT_WAIT) == 0 &&
183 fs->fs_clean & FS_WASCLEAN) {
184 fs->fs_clean = FS_ISCLEAN;
185 (void) ffs_sbupdate(ump, MNT_WAIT);
186 }
187 vfs_unbusy(mp);
188 if (error)
189 return (error);
190 fs->fs_ronly = 1;
191 }
192 if (mp->mnt_flag & MNT_RELOAD) {
193 error = ffs_reload(mp, ndp->ni_cnd.cn_cred, p);
194 if (error)
195 return (error);
196 }
197 if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) {
198 /*
199 * If upgrade to read-write by non-root, then verify
200 * that user has necessary permissions on the device.
201 */
202 if (p->p_ucred->cr_uid != 0) {
203 devvp = ump->um_devvp;
204 VOP_LOCK(devvp);
205 error = VOP_ACCESS(devvp, VREAD | VWRITE,
206 p->p_ucred, p);
207 if (error) {
208 VOP_UNLOCK(devvp);
209 return (error);
210 }
211 VOP_UNLOCK(devvp);
212 }
213 fs->fs_ronly = 0;
214 fs->fs_clean <<= 1;
215 fs->fs_fmod = 1;
216 }
217 if (args.fspec == 0) {
218 /*
219 * Process export requests.
220 */
221 return (vfs_export(mp, &ump->um_export, &args.export));
222 }
223 }
224 /*
225 * Not an update, or updating the name: look up the name
226 * and verify that it refers to a sensible block device.
227 */
228 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
229 if ((error = namei(ndp)) != 0)
230 return (error);
231 devvp = ndp->ni_vp;
232
233 if (devvp->v_type != VBLK) {
234 vrele(devvp);
235 return (ENOTBLK);
236 }
237 if (major(devvp->v_rdev) >= nblkdev) {
238 vrele(devvp);
239 return (ENXIO);
240 }
241 /*
242 * If mount by non-root, then verify that user has necessary
243 * permissions on the device.
244 */
245 if (p->p_ucred->cr_uid != 0) {
246 accessmode = VREAD;
247 if ((mp->mnt_flag & MNT_RDONLY) == 0)
248 accessmode |= VWRITE;
249 VOP_LOCK(devvp);
250 error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p);
251 if (error) {
252 vput(devvp);
253 return (error);
254 }
255 VOP_UNLOCK(devvp);
256 }
257 if ((mp->mnt_flag & MNT_UPDATE) == 0)
258 error = ffs_mountfs(devvp, mp, p);
259 else {
260 if (devvp != ump->um_devvp)
261 error = EINVAL; /* needs translation */
262 else
263 vrele(devvp);
264 }
265 if (error) {
266 vrele(devvp);
267 return (error);
268 }
269 ump = VFSTOUFS(mp);
270 fs = ump->um_fs;
271 (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
272 bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
273 bcopy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname, MNAMELEN);
274 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
275 &size);
276 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
277 if (fs->fs_fmod != 0) { /* XXX */
278 fs->fs_fmod = 0;
279 if (fs->fs_clean & FS_WASCLEAN)
280 fs->fs_time = time.tv_sec;
281 else
282 printf("%s: file system not clean; please fsck(8)\n",
283 mp->mnt_stat.f_mntfromname);
284 (void) ffs_cgupdate(ump, MNT_WAIT);
285 }
286 return (0);
287 }
288
289 /*
290 * Reload all incore data for a filesystem (used after running fsck on
291 * the root filesystem and finding things to fix). The filesystem must
292 * be mounted read-only.
293 *
294 * Things to do to update the mount:
295 * 1) invalidate all cached meta-data.
296 * 2) re-read superblock from disk.
297 * 3) re-read summary information from disk.
298 * 4) invalidate all inactive vnodes.
299 * 5) invalidate all cached file data.
300 * 6) re-read inode data for all active vnodes.
301 */
302 int
303 ffs_reload(mountp, cred, p)
304 register struct mount *mountp;
305 struct ucred *cred;
306 struct proc *p;
307 {
308 register struct vnode *vp, *nvp, *devvp;
309 struct inode *ip;
310 struct csum *space;
311 struct buf *bp;
312 struct fs *fs, *newfs;
313 struct partinfo dpart;
314 int i, blks, size, error;
315 int32_t *lp;
316
317 if ((mountp->mnt_flag & MNT_RDONLY) == 0)
318 return (EINVAL);
319 /*
320 * Step 1: invalidate all cached meta-data.
321 */
322 devvp = VFSTOUFS(mountp)->um_devvp;
323 if (vinvalbuf(devvp, 0, cred, p, 0, 0))
324 panic("ffs_reload: dirty1");
325 /*
326 * Step 2: re-read superblock from disk.
327 */
328 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
329 size = DEV_BSIZE;
330 else
331 size = dpart.disklab->d_secsize;
332 error = bread(devvp, (daddr_t)(SBOFF / size), SBSIZE, NOCRED, &bp);
333 if (error)
334 return (error);
335 newfs = (struct fs *)bp->b_data;
336 if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE ||
337 newfs->fs_bsize < sizeof(struct fs)) {
338 brelse(bp);
339 return (EIO); /* XXX needs translation */
340 }
341 fs = VFSTOUFS(mountp)->um_fs;
342 /*
343 * Copy pointer fields back into superblock before copying in XXX
344 * new superblock. These should really be in the ufsmount. XXX
345 * Note that important parameters (eg fs_ncg) are unchanged.
346 */
347 bcopy(&fs->fs_csp[0], &newfs->fs_csp[0], sizeof(fs->fs_csp));
348 newfs->fs_maxcluster = fs->fs_maxcluster;
349 bcopy(newfs, fs, (u_int)fs->fs_sbsize);
350 if (fs->fs_sbsize < SBSIZE)
351 bp->b_flags |= B_INVAL;
352 brelse(bp);
353 mountp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
354 ffs_oldfscompat(fs);
355 /*
356 * Step 3: re-read summary information from disk.
357 */
358 blks = howmany(fs->fs_cssize, fs->fs_fsize);
359 space = fs->fs_csp[0];
360 for (i = 0; i < blks; i += fs->fs_frag) {
361 size = fs->fs_bsize;
362 if (i + fs->fs_frag > blks)
363 size = (blks - i) * fs->fs_fsize;
364 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
365 NOCRED, &bp);
366 if (error)
367 return (error);
368 bcopy(bp->b_data, fs->fs_csp[fragstoblks(fs, i)], (u_int)size);
369 brelse(bp);
370 }
371 /*
372 * We no longer know anything about clusters per cylinder group.
373 */
374 if (fs->fs_contigsumsize > 0) {
375 lp = fs->fs_maxcluster;
376 for (i = 0; i < fs->fs_ncg; i++)
377 *lp++ = fs->fs_contigsumsize;
378 }
379
380 loop:
381 for (vp = mountp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
382 nvp = vp->v_mntvnodes.le_next;
383 /*
384 * Step 4: invalidate all inactive vnodes.
385 */
386 if (vp->v_usecount == 0) {
387 vgone(vp);
388 continue;
389 }
390 /*
391 * Step 5: invalidate all cached file data.
392 */
393 if (vget(vp, 1))
394 goto loop;
395 if (vinvalbuf(vp, 0, cred, p, 0, 0))
396 panic("ffs_reload: dirty2");
397 /*
398 * Step 6: re-read inode data for all active vnodes.
399 */
400 ip = VTOI(vp);
401 error = bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
402 (int)fs->fs_bsize, NOCRED, &bp);
403 if (error) {
404 vput(vp);
405 return (error);
406 }
407 ip->i_din.ffs_din = *((struct dinode *)bp->b_data +
408 ino_to_fsbo(fs, ip->i_number));
409 brelse(bp);
410 vput(vp);
411 if (vp->v_mount != mountp)
412 goto loop;
413 }
414 return (0);
415 }
416
417 /*
418 * Common code for mount and mountroot
419 */
420 int
421 ffs_mountfs(devvp, mp, p)
422 register struct vnode *devvp;
423 struct mount *mp;
424 struct proc *p;
425 {
426 register struct ufsmount *ump;
427 struct buf *bp;
428 register struct fs *fs;
429 dev_t dev;
430 struct partinfo dpart;
431 caddr_t base, space;
432 int blks;
433 int error, i, size, ronly;
434 int32_t *lp;
435 struct ucred *cred;
436 extern struct vnode *rootvp;
437 u_int64_t maxfilesize; /* XXX */
438
439 dev = devvp->v_rdev;
440 cred = p ? p->p_ucred : NOCRED;
441 /*
442 * Disallow multiple mounts of the same device.
443 * Disallow mounting of a device that is currently in use
444 * (except for root, which might share swap device for miniroot).
445 * Flush out any old buffers remaining from a previous use.
446 */
447 if ((error = vfs_mountedon(devvp)) != 0)
448 return (error);
449 if (vcount(devvp) > 1 && devvp != rootvp)
450 return (EBUSY);
451 if ((error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0)) != 0)
452 return (error);
453
454 ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
455 error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
456 if (error)
457 return (error);
458 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0)
459 size = DEV_BSIZE;
460 else
461 size = dpart.disklab->d_secsize;
462
463 bp = NULL;
464 ump = NULL;
465 error = bread(devvp, (daddr_t)(SBOFF / size), SBSIZE, cred, &bp);
466 if (error)
467 goto out;
468 fs = (struct fs *)bp->b_data;
469 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
470 fs->fs_bsize < sizeof(struct fs)) {
471 error = EINVAL; /* XXX needs translation */
472 goto out;
473 }
474 /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */
475 if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) {
476 error = EROFS; /* XXX what should be returned? */
477 goto out;
478 }
479 ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
480 bzero((caddr_t)ump, sizeof *ump);
481 ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT,
482 M_WAITOK);
483 bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize);
484 if (fs->fs_sbsize < SBSIZE)
485 bp->b_flags |= B_INVAL;
486 brelse(bp);
487 bp = NULL;
488 fs = ump->um_fs;
489 fs->fs_ronly = ronly;
490 if (ronly == 0) {
491 fs->fs_clean <<= 1;
492 fs->fs_fmod = 1;
493 }
494 size = fs->fs_cssize;
495 blks = howmany(size, fs->fs_fsize);
496 if (fs->fs_contigsumsize > 0)
497 size += fs->fs_ncg * sizeof(int32_t);
498 base = space = malloc((u_long)size, M_UFSMNT, M_WAITOK);
499 for (i = 0; i < blks; i += fs->fs_frag) {
500 size = fs->fs_bsize;
501 if (i + fs->fs_frag > blks)
502 size = (blks - i) * fs->fs_fsize;
503 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
504 cred, &bp);
505 if (error) {
506 free(base, M_UFSMNT);
507 goto out;
508 }
509 bcopy(bp->b_data, space, (u_int)size);
510 fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space;
511 space += size;
512 brelse(bp);
513 bp = NULL;
514 }
515 if (fs->fs_contigsumsize > 0) {
516 fs->fs_maxcluster = lp = (int32_t *)space;
517 for (i = 0; i < fs->fs_ncg; i++)
518 *lp++ = fs->fs_contigsumsize;
519 }
520 mp->mnt_data = (qaddr_t)ump;
521 mp->mnt_stat.f_fsid.val[0] = (long)dev;
522 mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_FFS);
523 mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
524 mp->mnt_flag |= MNT_LOCAL;
525 ump->um_mountp = mp;
526 ump->um_dev = dev;
527 ump->um_devvp = devvp;
528 ump->um_nindir = fs->fs_nindir;
529 ump->um_bptrtodb = fs->fs_fsbtodb;
530 ump->um_seqinc = fs->fs_frag;
531 for (i = 0; i < MAXQUOTAS; i++)
532 ump->um_quotas[i] = NULLVP;
533 devvp->v_specflags |= SI_MOUNTEDON;
534 ffs_oldfscompat(fs);
535 ump->um_savedmaxfilesize = fs->fs_maxfilesize; /* XXX */
536 maxfilesize = (u_int64_t)0x80000000 * fs->fs_bsize - 1; /* XXX */
537 if (fs->fs_maxfilesize > maxfilesize) /* XXX */
538 fs->fs_maxfilesize = maxfilesize; /* XXX */
539 return (0);
540 out:
541 if (bp)
542 brelse(bp);
543 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
544 if (ump) {
545 free(ump->um_fs, M_UFSMNT);
546 free(ump, M_UFSMNT);
547 mp->mnt_data = (qaddr_t)0;
548 }
549 return (error);
550 }
551
552 /*
553 * Sanity checks for old file systems.
554 *
555 * XXX - goes away some day.
556 */
557 int
558 ffs_oldfscompat(fs)
559 struct fs *fs;
560 {
561 int i;
562
563 fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */
564 fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */
565 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
566 fs->fs_nrpos = 8; /* XXX */
567 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
568 u_int64_t sizepb = fs->fs_bsize; /* XXX */
569 /* XXX */
570 fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
571 for (i = 0; i < NIADDR; i++) { /* XXX */
572 sizepb *= NINDIR(fs); /* XXX */
573 fs->fs_maxfilesize += sizepb; /* XXX */
574 } /* XXX */
575 fs->fs_qbmask = ~fs->fs_bmask; /* XXX */
576 fs->fs_qfmask = ~fs->fs_fmask; /* XXX */
577 } /* XXX */
578 return (0);
579 }
580
581 /*
582 * unmount system call
583 */
584 int
585 ffs_unmount(mp, mntflags, p)
586 struct mount *mp;
587 int mntflags;
588 struct proc *p;
589 {
590 register struct ufsmount *ump;
591 register struct fs *fs;
592 int error, flags;
593
594 flags = 0;
595 if (mntflags & MNT_FORCE)
596 flags |= FORCECLOSE;
597 if ((error = ffs_flushfiles(mp, flags, p)) != 0)
598 return (error);
599 ump = VFSTOUFS(mp);
600 fs = ump->um_fs;
601 if (fs->fs_ronly == 0 &&
602 ffs_cgupdate(ump, MNT_WAIT) == 0 &&
603 fs->fs_clean & FS_WASCLEAN) {
604 fs->fs_clean = FS_ISCLEAN;
605 (void) ffs_sbupdate(ump, MNT_WAIT);
606 }
607 ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
608 error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
609 NOCRED, p);
610 vrele(ump->um_devvp);
611 free(fs->fs_csp[0], M_UFSMNT);
612 free(fs, M_UFSMNT);
613 free(ump, M_UFSMNT);
614 mp->mnt_data = (qaddr_t)0;
615 mp->mnt_flag &= ~MNT_LOCAL;
616 return (error);
617 }
618
619 /*
620 * Flush out all the files in a filesystem.
621 */
622 int
623 ffs_flushfiles(mp, flags, p)
624 register struct mount *mp;
625 int flags;
626 struct proc *p;
627 {
628 extern int doforce;
629 register struct ufsmount *ump;
630 int error;
631
632 if (!doforce)
633 flags &= ~FORCECLOSE;
634 ump = VFSTOUFS(mp);
635 #ifdef QUOTA
636 if (mp->mnt_flag & MNT_QUOTA) {
637 int i;
638 if ((error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) != 0)
639 return (error);
640 for (i = 0; i < MAXQUOTAS; i++) {
641 if (ump->um_quotas[i] == NULLVP)
642 continue;
643 quotaoff(p, mp, i);
644 }
645 /*
646 * Here we fall through to vflush again to ensure
647 * that we have gotten rid of all the system vnodes.
648 */
649 }
650 #endif
651 error = vflush(mp, NULLVP, flags);
652 return (error);
653 }
654
655 /*
656 * Get file system statistics.
657 */
658 int
659 ffs_statfs(mp, sbp, p)
660 struct mount *mp;
661 register struct statfs *sbp;
662 struct proc *p;
663 {
664 register struct ufsmount *ump;
665 register struct fs *fs;
666
667 ump = VFSTOUFS(mp);
668 fs = ump->um_fs;
669 if (fs->fs_magic != FS_MAGIC)
670 panic("ffs_statfs");
671 #ifdef COMPAT_09
672 sbp->f_type = 1;
673 #else
674 sbp->f_type = 0;
675 #endif
676 sbp->f_bsize = fs->fs_fsize;
677 sbp->f_iosize = fs->fs_bsize;
678 sbp->f_blocks = fs->fs_dsize;
679 sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
680 fs->fs_cstotal.cs_nffree;
681 sbp->f_bavail = (long) (((u_int64_t) fs->fs_dsize * (u_int64_t)
682 (100 - fs->fs_minfree) / (u_int64_t) 100) -
683 (u_int64_t) (fs->fs_dsize - sbp->f_bfree));
684 sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
685 sbp->f_ffree = fs->fs_cstotal.cs_nifree;
686 if (sbp != &mp->mnt_stat) {
687 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
688 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
689 }
690 strncpy(sbp->f_fstypename, mp->mnt_op->vfs_name, MFSNAMELEN);
691 return (0);
692 }
693
694 /*
695 * Go through the disk queues to initiate sandbagged IO;
696 * go through the inodes to write those that have been modified;
697 * initiate the writing of the super block if it has been modified.
698 *
699 * Note: we are always called with the filesystem marked `MPBUSY'.
700 */
701 int
702 ffs_sync(mp, waitfor, cred, p)
703 struct mount *mp;
704 int waitfor;
705 struct ucred *cred;
706 struct proc *p;
707 {
708 register struct vnode *vp;
709 register struct inode *ip;
710 register struct ufsmount *ump = VFSTOUFS(mp);
711 register struct fs *fs;
712 int error, allerror = 0;
713
714 fs = ump->um_fs;
715 /*
716 * Write back modified superblock.
717 * Consistency check that the superblock
718 * is still in the buffer cache.
719 */
720 if (fs->fs_fmod != 0) {
721 if (fs->fs_ronly != 0) { /* XXX */
722 printf("fs = %s\n", fs->fs_fsmnt);
723 panic("update: rofs mod");
724 }
725 fs->fs_fmod = 0;
726 fs->fs_time = time.tv_sec;
727 allerror = ffs_cgupdate(ump, waitfor);
728 }
729 /*
730 * Write back each (modified) inode.
731 */
732 loop:
733 for (vp = mp->mnt_vnodelist.lh_first;
734 vp != NULL;
735 vp = vp->v_mntvnodes.le_next) {
736 /*
737 * If the vnode that we are about to sync is no longer
738 * associated with this mount point, start over.
739 */
740 if (vp->v_mount != mp)
741 goto loop;
742 if (VOP_ISLOCKED(vp))
743 continue;
744 ip = VTOI(vp);
745 if ((ip->i_flag &
746 (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
747 vp->v_dirtyblkhd.lh_first == NULL)
748 continue;
749 if (vget(vp, 1))
750 goto loop;
751 if ((error = VOP_FSYNC(vp, cred, waitfor, p)) != 0)
752 allerror = error;
753 vput(vp);
754 }
755 /*
756 * Force stale file system control information to be flushed.
757 */
758 if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0)
759 allerror = error;
760 #ifdef QUOTA
761 qsync(mp);
762 #endif
763 return (allerror);
764 }
765
766 /*
767 * Look up a FFS dinode number to find its incore vnode, otherwise read it
768 * in from disk. If it is in core, wait for the lock bit to clear, then
769 * return the inode locked. Detection and handling of mount points must be
770 * done by the calling routine.
771 */
772 int
773 ffs_vget(mp, ino, vpp)
774 struct mount *mp;
775 ino_t ino;
776 struct vnode **vpp;
777 {
778 register struct fs *fs;
779 register struct inode *ip;
780 struct ufsmount *ump;
781 struct buf *bp;
782 struct vnode *vp;
783 dev_t dev;
784 int type, error;
785
786 ump = VFSTOUFS(mp);
787 dev = ump->um_dev;
788 do {
789 if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
790 return (0);
791 } while (lockmgr(&ufs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0, curproc));
792
793 /* Allocate a new vnode/inode. */
794 if ((error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp)) != 0) {
795 *vpp = NULL;
796 lockmgr(&ufs_hashlock, LK_RELEASE, 0, curproc);
797 return (error);
798 }
799 type = ump->um_devvp->v_tag == VT_MFS ? M_MFSNODE : M_FFSNODE; /* XXX */
800 MALLOC(ip, struct inode *, sizeof(struct inode), type, M_WAITOK);
801 bzero((caddr_t)ip, sizeof(struct inode));
802 vp->v_data = ip;
803 ip->i_vnode = vp;
804 ip->i_fs = fs = ump->um_fs;
805 ip->i_dev = dev;
806 ip->i_number = ino;
807 #ifdef QUOTA
808 {
809 int i;
810
811 for (i = 0; i < MAXQUOTAS; i++)
812 ip->i_dquot[i] = NODQUOT;
813 }
814 #endif
815 /*
816 * Put it onto its hash chain and lock it so that other requests for
817 * this inode will block if they arrive while we are sleeping waiting
818 * for old data structures to be purged or for the contents of the
819 * disk portion of this inode to be read.
820 */
821 ufs_ihashins(ip);
822 lockmgr(&ufs_hashlock, LK_RELEASE, 0, curproc);
823
824 /* Read in the disk contents for the inode, copy into the inode. */
825 error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
826 (int)fs->fs_bsize, NOCRED, &bp);
827 if (error) {
828 /*
829 * The inode does not contain anything useful, so it would
830 * be misleading to leave it on its hash chain. With mode
831 * still zero, it will be unlinked and returned to the free
832 * list by vput().
833 */
834 vput(vp);
835 brelse(bp);
836 *vpp = NULL;
837 return (error);
838 }
839 ip->i_din.ffs_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino));
840 brelse(bp);
841
842 /*
843 * Initialize the vnode from the inode, check for aliases.
844 * Note that the underlying vnode may have changed.
845 */
846 error = ufs_vinit(mp, ffs_specop_p, FFS_FIFOOPS, &vp);
847 if (error) {
848 vput(vp);
849 *vpp = NULL;
850 return (error);
851 }
852 /*
853 * Finish inode initialization now that aliasing has been resolved.
854 */
855 ip->i_devvp = ump->um_devvp;
856 VREF(ip->i_devvp);
857 /*
858 * Ensure that uid and gid are correct. This is a temporary
859 * fix until fsck has been changed to do the update.
860 */
861 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
862 ip->i_ffs_uid = ip->i_din.ffs_din.di_ouid; /* XXX */
863 ip->i_ffs_gid = ip->i_din.ffs_din.di_ogid; /* XXX */
864 } /* XXX */
865
866 *vpp = vp;
867 return (0);
868 }
869
870 /*
871 * File handle to vnode
872 *
873 * Have to be really careful about stale file handles:
874 * - check that the inode number is valid
875 * - call ffs_vget() to get the locked inode
876 * - check for an unallocated inode (i_mode == 0)
877 * - check that the given client host has export rights and return
878 * those rights via. exflagsp and credanonp
879 */
880 int
881 ffs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
882 register struct mount *mp;
883 struct fid *fhp;
884 struct mbuf *nam;
885 struct vnode **vpp;
886 int *exflagsp;
887 struct ucred **credanonp;
888 {
889 register struct ufid *ufhp;
890 struct fs *fs;
891
892 ufhp = (struct ufid *)fhp;
893 fs = VFSTOUFS(mp)->um_fs;
894 if (ufhp->ufid_ino < ROOTINO ||
895 ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg)
896 return (ESTALE);
897 return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp));
898 }
899
900 /*
901 * Vnode pointer to File handle
902 */
903 /* ARGSUSED */
904 int
905 ffs_vptofh(vp, fhp)
906 struct vnode *vp;
907 struct fid *fhp;
908 {
909 register struct inode *ip;
910 register struct ufid *ufhp;
911
912 ip = VTOI(vp);
913 ufhp = (struct ufid *)fhp;
914 ufhp->ufid_len = sizeof(struct ufid);
915 ufhp->ufid_ino = ip->i_number;
916 ufhp->ufid_gen = ip->i_ffs_gen;
917 return (0);
918 }
919
920 /*
921 * Write a superblock and associated information back to disk.
922 */
923 int
924 ffs_sbupdate(mp, waitfor)
925 struct ufsmount *mp;
926 int waitfor;
927 {
928 register struct fs *dfs, *fs = mp->um_fs;
929 register struct buf *bp;
930 int i, error = 0;
931
932 bp = getblk(mp->um_devvp, SBOFF >> (fs->fs_fshift - fs->fs_fsbtodb),
933 (int)fs->fs_sbsize, 0, 0);
934 bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
935 /* Restore compatibility to old file systems. XXX */
936 dfs = (struct fs *)bp->b_data; /* XXX */
937 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
938 dfs->fs_nrpos = -1; /* XXX */
939 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
940 int32_t *lp, tmp; /* XXX */
941 /* XXX */
942 lp = (int32_t *)&dfs->fs_qbmask; /* XXX */
943 tmp = lp[4]; /* XXX */
944 for (i = 4; i > 0; i--) /* XXX */
945 lp[i] = lp[i-1]; /* XXX */
946 lp[0] = tmp; /* XXX */
947 } /* XXX */
948 dfs->fs_maxfilesize = mp->um_savedmaxfilesize; /* XXX */
949 if (waitfor == MNT_WAIT)
950 error = bwrite(bp);
951 else
952 bawrite(bp);
953 return (error);
954 }
955
956 int
957 ffs_cgupdate(mp, waitfor)
958 struct ufsmount *mp;
959 int waitfor;
960 {
961 register struct fs *fs = mp->um_fs;
962 register struct buf *bp;
963 int blks;
964 caddr_t space;
965 int i, size, error = 0, allerror = 0;
966
967 allerror = ffs_sbupdate(mp, waitfor);
968 blks = howmany(fs->fs_cssize, fs->fs_fsize);
969 space = (caddr_t)fs->fs_csp[0];
970 for (i = 0; i < blks; i += fs->fs_frag) {
971 size = fs->fs_bsize;
972 if (i + fs->fs_frag > blks)
973 size = (blks - i) * fs->fs_fsize;
974 bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
975 size, 0, 0);
976 bcopy(space, bp->b_data, (u_int)size);
977 space += size;
978 if (waitfor == MNT_WAIT)
979 error = bwrite(bp);
980 else
981 bawrite(bp);
982 }
983 if (!allerror && error)
984 allerror = error;
985 return (allerror);
986 }
987