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