ffs_vfsops.c revision 1.29 1 /* ffs_vfsops.c,v 1.28 1997/07/07 11:47:06 fvdl 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 = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) -
682 (fs->fs_dsize - sbp->f_bfree);
683 sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
684 sbp->f_ffree = fs->fs_cstotal.cs_nifree;
685 if (sbp != &mp->mnt_stat) {
686 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
687 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
688 }
689 strncpy(sbp->f_fstypename, mp->mnt_op->vfs_name, MFSNAMELEN);
690 return (0);
691 }
692
693 /*
694 * Go through the disk queues to initiate sandbagged IO;
695 * go through the inodes to write those that have been modified;
696 * initiate the writing of the super block if it has been modified.
697 *
698 * Note: we are always called with the filesystem marked `MPBUSY'.
699 */
700 int
701 ffs_sync(mp, waitfor, cred, p)
702 struct mount *mp;
703 int waitfor;
704 struct ucred *cred;
705 struct proc *p;
706 {
707 register struct vnode *vp;
708 register struct inode *ip;
709 register struct ufsmount *ump = VFSTOUFS(mp);
710 register struct fs *fs;
711 int error, allerror = 0;
712
713 fs = ump->um_fs;
714 /*
715 * Write back modified superblock.
716 * Consistency check that the superblock
717 * is still in the buffer cache.
718 */
719 if (fs->fs_fmod != 0) {
720 if (fs->fs_ronly != 0) { /* XXX */
721 printf("fs = %s\n", fs->fs_fsmnt);
722 panic("update: rofs mod");
723 }
724 fs->fs_fmod = 0;
725 fs->fs_time = time.tv_sec;
726 allerror = ffs_cgupdate(ump, waitfor);
727 }
728 /*
729 * Write back each (modified) inode.
730 */
731 loop:
732 for (vp = mp->mnt_vnodelist.lh_first;
733 vp != NULL;
734 vp = vp->v_mntvnodes.le_next) {
735 /*
736 * If the vnode that we are about to sync is no longer
737 * associated with this mount point, start over.
738 */
739 if (vp->v_mount != mp)
740 goto loop;
741 if (VOP_ISLOCKED(vp))
742 continue;
743 ip = VTOI(vp);
744 if ((ip->i_flag &
745 (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
746 vp->v_dirtyblkhd.lh_first == NULL)
747 continue;
748 if (vget(vp, 1))
749 goto loop;
750 if ((error = VOP_FSYNC(vp, cred, waitfor, p)) != 0)
751 allerror = error;
752 vput(vp);
753 }
754 /*
755 * Force stale file system control information to be flushed.
756 */
757 if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0)
758 allerror = error;
759 #ifdef QUOTA
760 qsync(mp);
761 #endif
762 return (allerror);
763 }
764
765 /*
766 * Look up a FFS dinode number to find its incore vnode, otherwise read it
767 * in from disk. If it is in core, wait for the lock bit to clear, then
768 * return the inode locked. Detection and handling of mount points must be
769 * done by the calling routine.
770 */
771 int
772 ffs_vget(mp, ino, vpp)
773 struct mount *mp;
774 ino_t ino;
775 struct vnode **vpp;
776 {
777 register struct fs *fs;
778 register struct inode *ip;
779 struct ufsmount *ump;
780 struct buf *bp;
781 struct vnode *vp;
782 dev_t dev;
783 int type, error;
784
785 ump = VFSTOUFS(mp);
786 dev = ump->um_dev;
787 do {
788 if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
789 return (0);
790 } while (lockmgr(&ufs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0, curproc));
791
792 /* Allocate a new vnode/inode. */
793 if ((error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp)) != 0) {
794 *vpp = NULL;
795 lockmgr(&ufs_hashlock, LK_RELEASE, 0, curproc);
796 return (error);
797 }
798 type = ump->um_devvp->v_tag == VT_MFS ? M_MFSNODE : M_FFSNODE; /* XXX */
799 MALLOC(ip, struct inode *, sizeof(struct inode), type, M_WAITOK);
800 bzero((caddr_t)ip, sizeof(struct inode));
801 vp->v_data = ip;
802 ip->i_vnode = vp;
803 ip->i_fs = fs = ump->um_fs;
804 ip->i_dev = dev;
805 ip->i_number = ino;
806 #ifdef QUOTA
807 {
808 int i;
809
810 for (i = 0; i < MAXQUOTAS; i++)
811 ip->i_dquot[i] = NODQUOT;
812 }
813 #endif
814 /*
815 * Put it onto its hash chain and lock it so that other requests for
816 * this inode will block if they arrive while we are sleeping waiting
817 * for old data structures to be purged or for the contents of the
818 * disk portion of this inode to be read.
819 */
820 ufs_ihashins(ip);
821 lockmgr(&ufs_hashlock, LK_RELEASE, 0, curproc);
822
823 /* Read in the disk contents for the inode, copy into the inode. */
824 error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
825 (int)fs->fs_bsize, NOCRED, &bp);
826 if (error) {
827 /*
828 * The inode does not contain anything useful, so it would
829 * be misleading to leave it on its hash chain. With mode
830 * still zero, it will be unlinked and returned to the free
831 * list by vput().
832 */
833 vput(vp);
834 brelse(bp);
835 *vpp = NULL;
836 return (error);
837 }
838 ip->i_din.ffs_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino));
839 brelse(bp);
840
841 /*
842 * Initialize the vnode from the inode, check for aliases.
843 * Note that the underlying vnode may have changed.
844 */
845 error = ufs_vinit(mp, ffs_specop_p, FFS_FIFOOPS, &vp);
846 if (error) {
847 vput(vp);
848 *vpp = NULL;
849 return (error);
850 }
851 /*
852 * Finish inode initialization now that aliasing has been resolved.
853 */
854 ip->i_devvp = ump->um_devvp;
855 VREF(ip->i_devvp);
856 /*
857 * Ensure that uid and gid are correct. This is a temporary
858 * fix until fsck has been changed to do the update.
859 */
860 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
861 ip->i_ffs_uid = ip->i_din.ffs_din.di_ouid; /* XXX */
862 ip->i_ffs_gid = ip->i_din.ffs_din.di_ogid; /* XXX */
863 } /* XXX */
864
865 *vpp = vp;
866 return (0);
867 }
868
869 /*
870 * File handle to vnode
871 *
872 * Have to be really careful about stale file handles:
873 * - check that the inode number is valid
874 * - call ffs_vget() to get the locked inode
875 * - check for an unallocated inode (i_mode == 0)
876 * - check that the given client host has export rights and return
877 * those rights via. exflagsp and credanonp
878 */
879 int
880 ffs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
881 register struct mount *mp;
882 struct fid *fhp;
883 struct mbuf *nam;
884 struct vnode **vpp;
885 int *exflagsp;
886 struct ucred **credanonp;
887 {
888 register struct ufid *ufhp;
889 struct fs *fs;
890
891 ufhp = (struct ufid *)fhp;
892 fs = VFSTOUFS(mp)->um_fs;
893 if (ufhp->ufid_ino < ROOTINO ||
894 ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg)
895 return (ESTALE);
896 return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp));
897 }
898
899 /*
900 * Vnode pointer to File handle
901 */
902 /* ARGSUSED */
903 int
904 ffs_vptofh(vp, fhp)
905 struct vnode *vp;
906 struct fid *fhp;
907 {
908 register struct inode *ip;
909 register struct ufid *ufhp;
910
911 ip = VTOI(vp);
912 ufhp = (struct ufid *)fhp;
913 ufhp->ufid_len = sizeof(struct ufid);
914 ufhp->ufid_ino = ip->i_number;
915 ufhp->ufid_gen = ip->i_ffs_gen;
916 return (0);
917 }
918
919 /*
920 * Write a superblock and associated information back to disk.
921 */
922 int
923 ffs_sbupdate(mp, waitfor)
924 struct ufsmount *mp;
925 int waitfor;
926 {
927 register struct fs *dfs, *fs = mp->um_fs;
928 register struct buf *bp;
929 int i, error = 0;
930
931 bp = getblk(mp->um_devvp, SBOFF >> (fs->fs_fshift - fs->fs_fsbtodb),
932 (int)fs->fs_sbsize, 0, 0);
933 bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
934 /* Restore compatibility to old file systems. XXX */
935 dfs = (struct fs *)bp->b_data; /* XXX */
936 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
937 dfs->fs_nrpos = -1; /* XXX */
938 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
939 int32_t *lp, tmp; /* XXX */
940 /* XXX */
941 lp = (int32_t *)&dfs->fs_qbmask; /* XXX */
942 tmp = lp[4]; /* XXX */
943 for (i = 4; i > 0; i--) /* XXX */
944 lp[i] = lp[i-1]; /* XXX */
945 lp[0] = tmp; /* XXX */
946 } /* XXX */
947 dfs->fs_maxfilesize = mp->um_savedmaxfilesize; /* XXX */
948 if (waitfor == MNT_WAIT)
949 error = bwrite(bp);
950 else
951 bawrite(bp);
952 return (error);
953 }
954
955 int
956 ffs_cgupdate(mp, waitfor)
957 struct ufsmount *mp;
958 int waitfor;
959 {
960 register struct fs *fs = mp->um_fs;
961 register struct buf *bp;
962 int blks;
963 caddr_t space;
964 int i, size, error = 0, allerror = 0;
965
966 allerror = ffs_sbupdate(mp, waitfor);
967 blks = howmany(fs->fs_cssize, fs->fs_fsize);
968 space = (caddr_t)fs->fs_csp[0];
969 for (i = 0; i < blks; i += fs->fs_frag) {
970 size = fs->fs_bsize;
971 if (i + fs->fs_frag > blks)
972 size = (blks - i) * fs->fs_fsize;
973 bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
974 size, 0, 0);
975 bcopy(space, bp->b_data, (u_int)size);
976 space += size;
977 if (waitfor == MNT_WAIT)
978 error = bwrite(bp);
979 else
980 bawrite(bp);
981 }
982 if (!allerror && error)
983 allerror = error;
984 return (allerror);
985 }
986