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