Deleted Added
full compact
ffs_vfsops.c (59794) ffs_vfsops.c (60041)
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
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 * $FreeBSD: head/sys/ufs/ffs/ffs_vfsops.c 59794 2000-04-30 18:52:11Z phk $
34 * $FreeBSD: head/sys/ufs/ffs/ffs_vfsops.c 60041 2000-05-05 09:59:14Z phk $
35 */
36
37#include "opt_ffs.h"
38#include "opt_quota.h"
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/namei.h>
43#include <sys/proc.h>
44#include <sys/kernel.h>
45#include <sys/vnode.h>
46#include <sys/mount.h>
35 */
36
37#include "opt_ffs.h"
38#include "opt_quota.h"
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/namei.h>
43#include <sys/proc.h>
44#include <sys/kernel.h>
45#include <sys/vnode.h>
46#include <sys/mount.h>
47#include <sys/bio.h>
47#include <sys/buf.h>
48#include <sys/conf.h>
49#include <sys/fcntl.h>
50#include <sys/disklabel.h>
51#include <sys/malloc.h>
52
53#include <ufs/ufs/extattr.h>
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#include <vm/vm.h>
63#include <vm/vm_page.h>
64
65static MALLOC_DEFINE(M_FFSNODE, "FFS node", "FFS vnode private part");
66
67static int ffs_sbupdate __P((struct ufsmount *, int));
68static int ffs_reload __P((struct mount *,struct ucred *,struct proc *));
69static int ffs_oldfscompat __P((struct fs *));
70static int ffs_mount __P((struct mount *, char *, caddr_t,
71 struct nameidata *, struct proc *));
72static int ffs_init __P((struct vfsconf *));
73
74static struct vfsops ufs_vfsops = {
75 ffs_mount,
76 ufs_start,
77 ffs_unmount,
78 ufs_root,
79 ufs_quotactl,
80 ffs_statfs,
81 ffs_sync,
82 ffs_vget,
83 ffs_fhtovp,
84 ufs_check_export,
85 ffs_vptofh,
86 ffs_init,
87 vfs_stduninit,
88#ifdef FFS_EXTATTR
89 ufs_extattrctl,
90#else
91 vfs_stdextattrctl,
92#endif
93};
94
95VFS_SET(ufs_vfsops, ufs, 0);
96
97/*
98 * ffs_mount
99 *
100 * Called when mounting local physical media
101 *
102 * PARAMETERS:
103 * mountroot
104 * mp mount point structure
105 * path NULL (flag for root mount!!!)
106 * data <unused>
107 * ndp <unused>
108 * p process (user credentials check [statfs])
109 *
110 * mount
111 * mp mount point structure
112 * path path to mount point
113 * data pointer to argument struct in user space
114 * ndp mount point namei() return (used for
115 * credentials on reload), reused to look
116 * up block device.
117 * p process (user credentials check)
118 *
119 * RETURNS: 0 Success
120 * !0 error number (errno.h)
121 *
122 * LOCK STATE:
123 *
124 * ENTRY
125 * mount point is locked
126 * EXIT
127 * mount point is locked
128 *
129 * NOTES:
130 * A NULL path can be used for a flag since the mount
131 * system call will fail with EFAULT in copyinstr in
132 * namei() if it is a genuine NULL from the user.
133 */
134static int
135ffs_mount( mp, path, data, ndp, p)
136 struct mount *mp; /* mount struct pointer*/
137 char *path; /* path to mount point*/
138 caddr_t data; /* arguments to FS specific mount*/
139 struct nameidata *ndp; /* mount point credentials*/
140 struct proc *p; /* process requesting mount*/
141{
142 size_t size;
143 int err = 0;
144 struct vnode *devvp;
145
146 struct ufs_args args;
147 struct ufsmount *ump = 0;
148 register struct fs *fs;
149 int error, flags, ronly = 0;
150 mode_t accessmode;
151
152 /*
153 * Use NULL path to flag a root mount
154 */
155 if( path == NULL) {
156 /*
157 ***
158 * Mounting root file system
159 ***
160 */
161
162 if ((err = bdevvp(rootdev, &rootvp))) {
163 printf("ffs_mountroot: can't find rootvp\n");
164 return (err);
165 }
166
167 if( ( err = ffs_mountfs(rootvp, mp, p, M_FFSNODE)) != 0) {
168 /* fs specific cleanup (if any)*/
169 goto error_1;
170 }
171
172 goto dostatfs; /* success*/
173
174 }
175
176 /*
177 ***
178 * Mounting non-root file system or updating a file system
179 ***
180 */
181
182 /* copy in user arguments*/
183 err = copyin(data, (caddr_t)&args, sizeof (struct ufs_args));
184 if (err)
185 goto error_1; /* can't get arguments*/
186
187 /*
188 * If updating, check whether changing from read-only to
189 * read/write; if there is no device name, that's all we do.
190 */
191 if (mp->mnt_flag & MNT_UPDATE) {
192 ump = VFSTOUFS(mp);
193 fs = ump->um_fs;
194 devvp = ump->um_devvp;
195 err = 0;
196 ronly = fs->fs_ronly; /* MNT_RELOAD might change this */
197 if (ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
198 flags = WRITECLOSE;
199 if (mp->mnt_flag & MNT_FORCE)
200 flags |= FORCECLOSE;
201 if (mp->mnt_flag & MNT_SOFTDEP) {
202 err = softdep_flushfiles(mp, flags, p);
203 } else {
204 err = ffs_flushfiles(mp, flags, p);
205 }
206 ronly = 1;
207 }
208 if (!err && (mp->mnt_flag & MNT_RELOAD))
209 err = ffs_reload(mp, ndp->ni_cnd.cn_cred, p);
210 if (err) {
211 goto error_1;
212 }
213 if (ronly && (mp->mnt_kern_flag & MNTK_WANTRDWR)) {
214 /*
215 * If upgrade to read-write by non-root, then verify
216 * that user has necessary permissions on the device.
217 */
218 if (p->p_ucred->cr_uid != 0) {
219 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
220 if ((error = VOP_ACCESS(devvp, VREAD | VWRITE,
221 p->p_ucred, p)) != 0) {
222 VOP_UNLOCK(devvp, 0, p);
223 return (error);
224 }
225 VOP_UNLOCK(devvp, 0, p);
226 }
227
228 fs->fs_flags &= ~FS_UNCLEAN;
229 if (fs->fs_clean == 0) {
230 fs->fs_flags |= FS_UNCLEAN;
231 if (mp->mnt_flag & MNT_FORCE) {
232 printf(
233"WARNING: %s was not properly dismounted\n",
234 fs->fs_fsmnt);
235 } else {
236 printf(
237"WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n",
238 fs->fs_fsmnt);
239 err = EPERM;
240 goto error_1;
241 }
242 }
243
244 /* check to see if we need to start softdep */
245 if (fs->fs_flags & FS_DOSOFTDEP) {
246 err = softdep_mount(devvp, mp, fs, p->p_ucred);
247 if (err)
248 goto error_1;
249 }
250
251 ronly = 0;
252 }
253 /*
254 * Soft updates is incompatible with "async",
255 * so if we are doing softupdates stop the user
256 * from setting the async flag in an update.
257 * Softdep_mount() clears it in an initial mount
258 * or ro->rw remount.
259 */
260 if (mp->mnt_flag & MNT_SOFTDEP) {
261 mp->mnt_flag &= ~MNT_ASYNC;
262 }
263 /* if not updating name...*/
264 if (args.fspec == 0) {
265 /*
266 * Process export requests. Jumping to "success"
267 * will return the vfs_export() error code.
268 */
269 err = vfs_export(mp, &ump->um_export, &args.export);
270 goto success;
271 }
272 }
273
274 /*
275 * Not an update, or updating the name: look up the name
276 * and verify that it refers to a sensible block device.
277 */
278 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
279 err = namei(ndp);
280 if (err) {
281 /* can't get devvp!*/
282 goto error_1;
283 }
284
285 NDFREE(ndp, NDF_ONLY_PNBUF);
286 devvp = ndp->ni_vp;
287
288 if (!vn_isdisk(devvp, &err))
289 goto error_2;
290
291 /*
292 * If mount by non-root, then verify that user has necessary
293 * permissions on the device.
294 */
295 if (p->p_ucred->cr_uid != 0) {
296 accessmode = VREAD;
297 if ((mp->mnt_flag & MNT_RDONLY) == 0)
298 accessmode |= VWRITE;
299 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
300 if ((error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) != 0) {
301 vput(devvp);
302 return (error);
303 }
304 VOP_UNLOCK(devvp, 0, p);
305 }
306
307 if (mp->mnt_flag & MNT_UPDATE) {
308 /*
309 ********************
310 * UPDATE
311 * If it's not the same vnode, or at least the same device
312 * then it's not correct.
313 ********************
314 */
315
316 if (devvp != ump->um_devvp) {
317 if ( devvp->v_rdev == ump->um_devvp->v_rdev) {
318 vrele(devvp);
319 } else {
320 err = EINVAL; /* needs translation */
321 }
322 } else
323 vrele(devvp);
324 /*
325 * Update device name only on success
326 */
327 if( !err) {
328 /* Save "mounted from" info for mount point (NULL pad)*/
329 copyinstr( args.fspec,
330 mp->mnt_stat.f_mntfromname,
331 MNAMELEN - 1,
332 &size);
333 bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
334 }
335 } else {
336 /*
337 ********************
338 * NEW MOUNT
339 ********************
340 */
341
342 /*
343 * Since this is a new mount, we want the names for
344 * the device and the mount point copied in. If an
345 * error occurs, the mountpoint is discarded by the
346 * upper level code.
347 */
348 /* Save "last mounted on" info for mount point (NULL pad)*/
349 copyinstr( path, /* mount point*/
350 mp->mnt_stat.f_mntonname, /* save area*/
351 MNAMELEN - 1, /* max size*/
352 &size); /* real size*/
353 bzero( mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
354
355 /* Save "mounted from" info for mount point (NULL pad)*/
356 copyinstr( args.fspec, /* device name*/
357 mp->mnt_stat.f_mntfromname, /* save area*/
358 MNAMELEN - 1, /* max size*/
359 &size); /* real size*/
360 bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
361
362 err = ffs_mountfs(devvp, mp, p, M_FFSNODE);
363 }
364 if (err) {
365 goto error_2;
366 }
367
368dostatfs:
369 /*
370 * Initialize FS stat information in mount struct; uses both
371 * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname
372 *
373 * This code is common to root and non-root mounts
374 */
375 (void)VFS_STATFS(mp, &mp->mnt_stat, p);
376
377 goto success;
378
379
380error_2: /* error with devvp held*/
381
382 /* release devvp before failing*/
383 vrele(devvp);
384
385error_1: /* no state to back out*/
386
387success:
388 if (!err && path && (mp->mnt_flag & MNT_UPDATE)) {
389 /* Update clean flag after changing read-onlyness. */
390 fs = ump->um_fs;
391 if (ronly != fs->fs_ronly) {
392 fs->fs_ronly = ronly;
393 fs->fs_clean = ronly &&
394 (fs->fs_flags & FS_UNCLEAN) == 0 ? 1 : 0;
395 ffs_sbupdate(ump, MNT_WAIT);
396 }
397 }
398 return (err);
399}
400
401/*
402 * Reload all incore data for a filesystem (used after running fsck on
403 * the root filesystem and finding things to fix). The filesystem must
404 * be mounted read-only.
405 *
406 * Things to do to update the mount:
407 * 1) invalidate all cached meta-data.
408 * 2) re-read superblock from disk.
409 * 3) re-read summary information from disk.
410 * 4) invalidate all inactive vnodes.
411 * 5) invalidate all cached file data.
412 * 6) re-read inode data for all active vnodes.
413 */
414static int
415ffs_reload(mp, cred, p)
416 register struct mount *mp;
417 struct ucred *cred;
418 struct proc *p;
419{
420 register struct vnode *vp, *nvp, *devvp;
421 struct inode *ip;
422 struct csum *space;
423 struct buf *bp;
424 struct fs *fs, *newfs;
425 struct partinfo dpart;
426 dev_t dev;
427 int i, blks, size, error;
428 int32_t *lp;
429
430 if ((mp->mnt_flag & MNT_RDONLY) == 0)
431 return (EINVAL);
432 /*
433 * Step 1: invalidate all cached meta-data.
434 */
435 devvp = VFSTOUFS(mp)->um_devvp;
436 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
437 error = vinvalbuf(devvp, 0, cred, p, 0, 0);
438 VOP_UNLOCK(devvp, 0, p);
439 if (error)
440 panic("ffs_reload: dirty1");
441
442 dev = devvp->v_rdev;
443
444 /*
445 * Only VMIO the backing device if the backing device is a real
446 * block device. See ffs_mountmfs() for more details.
447 */
448 if (devvp->v_tag != VT_MFS && vn_isdisk(devvp, NULL)) {
449 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
450 vfs_object_create(devvp, p, p->p_ucred);
451 simple_lock(&devvp->v_interlock);
452 VOP_UNLOCK(devvp, LK_INTERLOCK, p);
453 }
454
455 /*
456 * Step 2: re-read superblock from disk.
457 */
458 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
459 size = DEV_BSIZE;
460 else
461 size = dpart.disklab->d_secsize;
462 if ((error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, NOCRED,&bp)) != 0)
463 return (error);
464 newfs = (struct fs *)bp->b_data;
465 if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE ||
466 newfs->fs_bsize < sizeof(struct fs)) {
467 brelse(bp);
468 return (EIO); /* XXX needs translation */
469 }
470 fs = VFSTOUFS(mp)->um_fs;
471 /*
472 * Copy pointer fields back into superblock before copying in XXX
473 * new superblock. These should really be in the ufsmount. XXX
474 * Note that important parameters (eg fs_ncg) are unchanged.
475 */
476 bcopy(&fs->fs_csp[0], &newfs->fs_csp[0], sizeof(fs->fs_csp));
477 newfs->fs_maxcluster = fs->fs_maxcluster;
478 bcopy(newfs, fs, (u_int)fs->fs_sbsize);
479 if (fs->fs_sbsize < SBSIZE)
480 bp->b_flags |= B_INVAL;
481 brelse(bp);
482 mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
483 ffs_oldfscompat(fs);
484
485 /*
486 * Step 3: re-read summary information from disk.
487 */
488 blks = howmany(fs->fs_cssize, fs->fs_fsize);
489 space = fs->fs_csp[0];
490 for (i = 0; i < blks; i += fs->fs_frag) {
491 size = fs->fs_bsize;
492 if (i + fs->fs_frag > blks)
493 size = (blks - i) * fs->fs_fsize;
494 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
495 NOCRED, &bp);
496 if (error)
497 return (error);
498 bcopy(bp->b_data, fs->fs_csp[fragstoblks(fs, i)], (u_int)size);
499 brelse(bp);
500 }
501 /*
502 * We no longer know anything about clusters per cylinder group.
503 */
504 if (fs->fs_contigsumsize > 0) {
505 lp = fs->fs_maxcluster;
506 for (i = 0; i < fs->fs_ncg; i++)
507 *lp++ = fs->fs_contigsumsize;
508 }
509
510loop:
511 simple_lock(&mntvnode_slock);
512 for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
513 if (vp->v_mount != mp) {
514 simple_unlock(&mntvnode_slock);
515 goto loop;
516 }
517 nvp = vp->v_mntvnodes.le_next;
518 /*
519 * Step 4: invalidate all inactive vnodes.
520 */
521 if (vrecycle(vp, &mntvnode_slock, p))
522 goto loop;
523 /*
524 * Step 5: invalidate all cached file data.
525 */
526 simple_lock(&vp->v_interlock);
527 simple_unlock(&mntvnode_slock);
528 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) {
529 goto loop;
530 }
531 if (vinvalbuf(vp, 0, cred, p, 0, 0))
532 panic("ffs_reload: dirty2");
533 /*
534 * Step 6: re-read inode data for all active vnodes.
535 */
536 ip = VTOI(vp);
537 error =
538 bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
539 (int)fs->fs_bsize, NOCRED, &bp);
540 if (error) {
541 vput(vp);
542 return (error);
543 }
544 ip->i_din = *((struct dinode *)bp->b_data +
545 ino_to_fsbo(fs, ip->i_number));
546 ip->i_effnlink = ip->i_nlink;
547 brelse(bp);
548 vput(vp);
549 simple_lock(&mntvnode_slock);
550 }
551 simple_unlock(&mntvnode_slock);
552 return (0);
553}
554
555/*
556 * Common code for mount and mountroot
557 */
558int
559ffs_mountfs(devvp, mp, p, malloctype)
560 register struct vnode *devvp;
561 struct mount *mp;
562 struct proc *p;
563 struct malloc_type *malloctype;
564{
565 register struct ufsmount *ump;
566 struct buf *bp;
567 register struct fs *fs;
568 dev_t dev;
569 struct partinfo dpart;
570 caddr_t base, space;
571 int error, i, blks, size, ronly;
572 int32_t *lp;
573 struct ucred *cred;
574 u_int64_t maxfilesize; /* XXX */
575 size_t strsize;
576 int ncount;
577
578 dev = devvp->v_rdev;
579 cred = p ? p->p_ucred : NOCRED;
580 /*
581 * Disallow multiple mounts of the same device.
582 * Disallow mounting of a device that is currently in use
583 * (except for root, which might share swap device for miniroot).
584 * Flush out any old buffers remaining from a previous use.
585 */
586 error = vfs_mountedon(devvp);
587 if (error)
588 return (error);
589 ncount = vcount(devvp);
590
591 if (ncount > 1 && devvp != rootvp)
592 return (EBUSY);
593 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
594 error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0);
595 VOP_UNLOCK(devvp, 0, p);
596 if (error)
597 return (error);
598
599 /*
600 * Only VMIO the backing device if the backing device is a real
601 * block device. This excludes the original MFS implementation.
602 * Note that it is optional that the backing device be VMIOed. This
603 * increases the opportunity for metadata caching.
604 */
605 if (devvp->v_tag != VT_MFS && vn_isdisk(devvp, NULL)) {
606 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
607 vfs_object_create(devvp, p, p->p_ucred);
608 simple_lock(&devvp->v_interlock);
609 VOP_UNLOCK(devvp, LK_INTERLOCK, p);
610 }
611
612 ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
613 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
614 error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
615 VOP_UNLOCK(devvp, 0, p);
616 if (error)
617 return (error);
618 if (devvp->v_rdev->si_iosize_max > mp->mnt_iosize_max)
619 mp->mnt_iosize_max = devvp->v_rdev->si_iosize_max;
620 if (mp->mnt_iosize_max > MAXPHYS)
621 mp->mnt_iosize_max = MAXPHYS;
622
623 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0)
624 size = DEV_BSIZE;
625 else
626 size = dpart.disklab->d_secsize;
627
628 bp = NULL;
629 ump = NULL;
630 if ((error = bread(devvp, SBLOCK, SBSIZE, cred, &bp)) != 0)
631 goto out;
632 fs = (struct fs *)bp->b_data;
633 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
634 fs->fs_bsize < sizeof(struct fs)) {
635 error = EINVAL; /* XXX needs translation */
636 goto out;
637 }
638 fs->fs_fmod = 0;
639 fs->fs_flags &= ~FS_UNCLEAN;
640 if (fs->fs_clean == 0) {
641 fs->fs_flags |= FS_UNCLEAN;
642 if (ronly || (mp->mnt_flag & MNT_FORCE)) {
643 printf(
644"WARNING: %s was not properly dismounted\n",
645 fs->fs_fsmnt);
646 } else {
647 printf(
648"WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n",
649 fs->fs_fsmnt);
650 error = EPERM;
651 goto out;
652 }
653 }
654 /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */
655 if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) {
656 error = EROFS; /* needs translation */
657 goto out;
658 }
659 ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
660 bzero((caddr_t)ump, sizeof *ump);
661 ump->um_malloctype = malloctype;
662 ump->um_i_effnlink_valid = 1;
663 ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT,
664 M_WAITOK);
665 ump->um_blkatoff = ffs_blkatoff;
666 ump->um_truncate = ffs_truncate;
667 ump->um_update = ffs_update;
668 ump->um_valloc = ffs_valloc;
669 ump->um_vfree = ffs_vfree;
670 bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize);
671 if (fs->fs_sbsize < SBSIZE)
672 bp->b_flags |= B_INVAL;
673 brelse(bp);
674 bp = NULL;
675 fs = ump->um_fs;
676 fs->fs_ronly = ronly;
677 size = fs->fs_cssize;
678 blks = howmany(size, fs->fs_fsize);
679 if (fs->fs_contigsumsize > 0)
680 size += fs->fs_ncg * sizeof(int32_t);
681 base = space = malloc((u_long)size, M_UFSMNT, M_WAITOK);
682 for (i = 0; i < blks; i += fs->fs_frag) {
683 size = fs->fs_bsize;
684 if (i + fs->fs_frag > blks)
685 size = (blks - i) * fs->fs_fsize;
686 if ((error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
687 cred, &bp)) != 0) {
688 free(base, M_UFSMNT);
689 goto out;
690 }
691 bcopy(bp->b_data, space, (u_int)size);
692 fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space;
693 space += size;
694 brelse(bp);
695 bp = NULL;
696 }
697 if (fs->fs_contigsumsize > 0) {
698 fs->fs_maxcluster = lp = (int32_t *)space;
699 for (i = 0; i < fs->fs_ncg; i++)
700 *lp++ = fs->fs_contigsumsize;
701 }
702 mp->mnt_data = (qaddr_t)ump;
703 mp->mnt_stat.f_fsid.val[0] = fs->fs_id[0];
704 mp->mnt_stat.f_fsid.val[1] = fs->fs_id[1];
705 if (fs->fs_id[0] == 0 || fs->fs_id[1] == 0 ||
706 vfs_getvfs(&mp->mnt_stat.f_fsid))
707 vfs_getnewfsid(mp);
708 mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
709 mp->mnt_flag |= MNT_LOCAL;
710 ump->um_mountp = mp;
711 ump->um_dev = dev;
712 ump->um_devvp = devvp;
713 ump->um_nindir = fs->fs_nindir;
714 ump->um_bptrtodb = fs->fs_fsbtodb;
715 ump->um_seqinc = fs->fs_frag;
716 for (i = 0; i < MAXQUOTAS; i++)
717 ump->um_quotas[i] = NULLVP;
718#ifdef FFS_EXTATTR
719 ufs_extattr_uepm_init(&ump->um_extattr);
720#endif
721 devvp->v_specmountpoint = mp;
722 ffs_oldfscompat(fs);
723
724 /*
725 * Set FS local "last mounted on" information (NULL pad)
726 */
727 copystr( mp->mnt_stat.f_mntonname, /* mount point*/
728 fs->fs_fsmnt, /* copy area*/
729 sizeof(fs->fs_fsmnt) - 1, /* max size*/
730 &strsize); /* real size*/
731 bzero( fs->fs_fsmnt + strsize, sizeof(fs->fs_fsmnt) - strsize);
732
733 if( mp->mnt_flag & MNT_ROOTFS) {
734 /*
735 * Root mount; update timestamp in mount structure.
736 * this will be used by the common root mount code
737 * to update the system clock.
738 */
739 mp->mnt_time = fs->fs_time;
740 }
741
742 ump->um_savedmaxfilesize = fs->fs_maxfilesize; /* XXX */
743 maxfilesize = (u_int64_t)0x40000000 * fs->fs_bsize - 1; /* XXX */
744 if (fs->fs_maxfilesize > maxfilesize) /* XXX */
745 fs->fs_maxfilesize = maxfilesize; /* XXX */
746 if (ronly == 0) {
747 if ((fs->fs_flags & FS_DOSOFTDEP) &&
748 (error = softdep_mount(devvp, mp, fs, cred)) != 0) {
749 free(base, M_UFSMNT);
750 goto out;
751 }
752 fs->fs_fmod = 1;
753 fs->fs_clean = 0;
754 (void) ffs_sbupdate(ump, MNT_WAIT);
755 }
756 return (0);
757out:
758 devvp->v_specmountpoint = NULL;
759 if (bp)
760 brelse(bp);
761 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
762 if (ump) {
763 free(ump->um_fs, M_UFSMNT);
764 free(ump, M_UFSMNT);
765 mp->mnt_data = (qaddr_t)0;
766 }
767 return (error);
768}
769
770/*
771 * Sanity checks for old file systems.
772 *
773 * XXX - goes away some day.
774 */
775static int
776ffs_oldfscompat(fs)
777 struct fs *fs;
778{
779
780 fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */
781 fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */
782 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
783 fs->fs_nrpos = 8; /* XXX */
784 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
785#if 0
786 int i; /* XXX */
787 u_int64_t sizepb = fs->fs_bsize; /* XXX */
788 /* XXX */
789 fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
790 for (i = 0; i < NIADDR; i++) { /* XXX */
791 sizepb *= NINDIR(fs); /* XXX */
792 fs->fs_maxfilesize += sizepb; /* XXX */
793 } /* XXX */
794#endif
795 fs->fs_maxfilesize = (u_quad_t) 1LL << 39;
796 fs->fs_qbmask = ~fs->fs_bmask; /* XXX */
797 fs->fs_qfmask = ~fs->fs_fmask; /* XXX */
798 } /* XXX */
799 return (0);
800}
801
802/*
803 * unmount system call
804 */
805int
806ffs_unmount(mp, mntflags, p)
807 struct mount *mp;
808 int mntflags;
809 struct proc *p;
810{
811 register struct ufsmount *ump;
812 register struct fs *fs;
813 int error, flags;
814
815 flags = 0;
816 if (mntflags & MNT_FORCE) {
817 flags |= FORCECLOSE;
818 }
819#ifdef FFS_EXTATTR
820 if ((error = ufs_extattr_stop(mp, p))) {
821 printf("ffs_unmonut: ufs_extattr_stop returned %d\n", error);
822 }
823#endif
824 if (mp->mnt_flag & MNT_SOFTDEP) {
825 if ((error = softdep_flushfiles(mp, flags, p)) != 0)
826 return (error);
827 } else {
828 if ((error = ffs_flushfiles(mp, flags, p)) != 0)
829 return (error);
830 }
831 ump = VFSTOUFS(mp);
832 fs = ump->um_fs;
833 if (fs->fs_ronly == 0) {
834 fs->fs_clean = fs->fs_flags & FS_UNCLEAN ? 0 : 1;
835 error = ffs_sbupdate(ump, MNT_WAIT);
836 if (error) {
837 fs->fs_clean = 0;
838 return (error);
839 }
840 }
841 ump->um_devvp->v_specmountpoint = NULL;
842
843 vinvalbuf(ump->um_devvp, V_SAVE, NOCRED, p, 0, 0);
844 error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
845 NOCRED, p);
846
847 vrele(ump->um_devvp);
848
849 free(fs->fs_csp[0], M_UFSMNT);
850 free(fs, M_UFSMNT);
851 free(ump, M_UFSMNT);
852 mp->mnt_data = (qaddr_t)0;
853 mp->mnt_flag &= ~MNT_LOCAL;
854 return (error);
855}
856
857/*
858 * Flush out all the files in a filesystem.
859 */
860int
861ffs_flushfiles(mp, flags, p)
862 register struct mount *mp;
863 int flags;
864 struct proc *p;
865{
866 register struct ufsmount *ump;
867 int error;
868
869 ump = VFSTOUFS(mp);
870#ifdef QUOTA
871 if (mp->mnt_flag & MNT_QUOTA) {
872 int i;
873 error = vflush(mp, NULLVP, SKIPSYSTEM|flags);
874 if (error)
875 return (error);
876 for (i = 0; i < MAXQUOTAS; i++) {
877 if (ump->um_quotas[i] == NULLVP)
878 continue;
879 quotaoff(p, mp, i);
880 }
881 /*
882 * Here we fall through to vflush again to ensure
883 * that we have gotten rid of all the system vnodes.
884 */
885 }
886#endif
887 /*
888 * Flush all the files.
889 */
890 if ((error = vflush(mp, NULL, flags)) != 0)
891 return (error);
892 /*
893 * Flush filesystem metadata.
894 */
895 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
896 error = VOP_FSYNC(ump->um_devvp, p->p_ucred, MNT_WAIT, p);
897 VOP_UNLOCK(ump->um_devvp, 0, p);
898 return (error);
899}
900
901/*
902 * Get file system statistics.
903 */
904int
905ffs_statfs(mp, sbp, p)
906 struct mount *mp;
907 register struct statfs *sbp;
908 struct proc *p;
909{
910 register struct ufsmount *ump;
911 register struct fs *fs;
912
913 ump = VFSTOUFS(mp);
914 fs = ump->um_fs;
915 if (fs->fs_magic != FS_MAGIC)
916 panic("ffs_statfs");
917 sbp->f_bsize = fs->fs_fsize;
918 sbp->f_iosize = fs->fs_bsize;
919 sbp->f_blocks = fs->fs_dsize;
920 sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
921 fs->fs_cstotal.cs_nffree;
922 sbp->f_bavail = freespace(fs, fs->fs_minfree);
923 sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
924 sbp->f_ffree = fs->fs_cstotal.cs_nifree;
925 if (sbp != &mp->mnt_stat) {
926 sbp->f_type = mp->mnt_vfc->vfc_typenum;
927 bcopy((caddr_t)mp->mnt_stat.f_mntonname,
928 (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
929 bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
930 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
931 }
932 return (0);
933}
934
935/*
936 * Go through the disk queues to initiate sandbagged IO;
937 * go through the inodes to write those that have been modified;
938 * initiate the writing of the super block if it has been modified.
939 *
940 * Note: we are always called with the filesystem marked `MPBUSY'.
941 */
942int
943ffs_sync(mp, waitfor, cred, p)
944 struct mount *mp;
945 int waitfor;
946 struct ucred *cred;
947 struct proc *p;
948{
949 struct vnode *nvp, *vp;
950 struct inode *ip;
951 struct ufsmount *ump = VFSTOUFS(mp);
952 struct fs *fs;
953 int error, allerror = 0;
954
955 fs = ump->um_fs;
956 if (fs->fs_fmod != 0 && fs->fs_ronly != 0) { /* XXX */
957 printf("fs = %s\n", fs->fs_fsmnt);
958 panic("ffs_sync: rofs mod");
959 }
960 /*
961 * Write back each (modified) inode.
962 */
963 simple_lock(&mntvnode_slock);
964loop:
965 for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
966 /*
967 * If the vnode that we are about to sync is no longer
968 * associated with this mount point, start over.
969 */
970 if (vp->v_mount != mp)
971 goto loop;
972 simple_lock(&vp->v_interlock);
973 nvp = vp->v_mntvnodes.le_next;
974 ip = VTOI(vp);
975 if (vp->v_type == VNON || ((ip->i_flag &
976 (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
977 TAILQ_EMPTY(&vp->v_dirtyblkhd))) {
978 simple_unlock(&vp->v_interlock);
979 continue;
980 }
981 if (vp->v_type != VCHR) {
982 simple_unlock(&mntvnode_slock);
983 error =
984 vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p);
985 if (error) {
986 simple_lock(&mntvnode_slock);
987 if (error == ENOENT)
988 goto loop;
989 continue;
990 }
991 if ((error = VOP_FSYNC(vp, cred, waitfor, p)) != 0)
992 allerror = error;
993 VOP_UNLOCK(vp, 0, p);
994 vrele(vp);
995 simple_lock(&mntvnode_slock);
996 } else {
997 simple_unlock(&mntvnode_slock);
998 simple_unlock(&vp->v_interlock);
999 /* UFS_UPDATE(vp, waitfor == MNT_WAIT); */
1000 UFS_UPDATE(vp, 0);
1001 simple_lock(&mntvnode_slock);
1002 }
1003 }
1004 simple_unlock(&mntvnode_slock);
1005 /*
1006 * Force stale file system control information to be flushed.
1007 */
1008 if (waitfor != MNT_LAZY) {
1009 if (ump->um_mountp->mnt_flag & MNT_SOFTDEP)
1010 waitfor = MNT_NOWAIT;
1011 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
1012 if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0)
1013 allerror = error;
1014 VOP_UNLOCK(ump->um_devvp, 0, p);
1015 }
1016#ifdef QUOTA
1017 qsync(mp);
1018#endif
1019 /*
1020 * Write back modified superblock.
1021 */
1022 if (fs->fs_fmod != 0 && (error = ffs_sbupdate(ump, waitfor)) != 0)
1023 allerror = error;
1024 return (allerror);
1025}
1026
1027/*
1028 * Look up a FFS dinode number to find its incore vnode, otherwise read it
1029 * in from disk. If it is in core, wait for the lock bit to clear, then
1030 * return the inode locked. Detection and handling of mount points must be
1031 * done by the calling routine.
1032 */
1033static int ffs_inode_hash_lock;
1034
1035int
1036ffs_vget(mp, ino, vpp)
1037 struct mount *mp;
1038 ino_t ino;
1039 struct vnode **vpp;
1040{
1041 struct fs *fs;
1042 struct inode *ip;
1043 struct ufsmount *ump;
1044 struct buf *bp;
1045 struct vnode *vp;
1046 dev_t dev;
1047 int error;
1048
1049 ump = VFSTOUFS(mp);
1050 dev = ump->um_dev;
1051restart:
1052 if ((*vpp = ufs_ihashget(dev, ino)) != NULL) {
1053 return (0);
1054 }
1055
1056 /*
1057 * Lock out the creation of new entries in the FFS hash table in
1058 * case getnewvnode() or MALLOC() blocks, otherwise a duplicate
1059 * may occur!
1060 */
1061 if (ffs_inode_hash_lock) {
1062 while (ffs_inode_hash_lock) {
1063 ffs_inode_hash_lock = -1;
1064 tsleep(&ffs_inode_hash_lock, PVM, "ffsvgt", 0);
1065 }
1066 goto restart;
1067 }
1068 ffs_inode_hash_lock = 1;
1069
1070 /*
1071 * If this MALLOC() is performed after the getnewvnode()
1072 * it might block, leaving a vnode with a NULL v_data to be
1073 * found by ffs_sync() if a sync happens to fire right then,
1074 * which will cause a panic because ffs_sync() blindly
1075 * dereferences vp->v_data (as well it should).
1076 */
1077 MALLOC(ip, struct inode *, sizeof(struct inode),
1078 ump->um_malloctype, M_WAITOK);
1079
1080 /* Allocate a new vnode/inode. */
1081 error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp);
1082 if (error) {
1083 if (ffs_inode_hash_lock < 0)
1084 wakeup(&ffs_inode_hash_lock);
1085 ffs_inode_hash_lock = 0;
1086 *vpp = NULL;
1087 FREE(ip, ump->um_malloctype);
1088 return (error);
1089 }
1090 bzero((caddr_t)ip, sizeof(struct inode));
1091 lockinit(&ip->i_lock, PINOD, "inode", 0, LK_CANRECURSE);
1092 vp->v_data = ip;
1093 ip->i_vnode = vp;
1094 ip->i_fs = fs = ump->um_fs;
1095 ip->i_dev = dev;
1096 ip->i_number = ino;
1097#ifdef QUOTA
1098 {
1099 int i;
1100 for (i = 0; i < MAXQUOTAS; i++)
1101 ip->i_dquot[i] = NODQUOT;
1102 }
1103#endif
1104 /*
1105 * Put it onto its hash chain and lock it so that other requests for
1106 * this inode will block if they arrive while we are sleeping waiting
1107 * for old data structures to be purged or for the contents of the
1108 * disk portion of this inode to be read.
1109 */
1110 ufs_ihashins(ip);
1111
1112 if (ffs_inode_hash_lock < 0)
1113 wakeup(&ffs_inode_hash_lock);
1114 ffs_inode_hash_lock = 0;
1115
1116 /* Read in the disk contents for the inode, copy into the inode. */
1117 error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
1118 (int)fs->fs_bsize, NOCRED, &bp);
1119 if (error) {
1120 /*
1121 * The inode does not contain anything useful, so it would
1122 * be misleading to leave it on its hash chain. With mode
1123 * still zero, it will be unlinked and returned to the free
1124 * list by vput().
1125 */
1126 brelse(bp);
1127 vput(vp);
1128 *vpp = NULL;
1129 return (error);
1130 }
1131 ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino));
1132 if (DOINGSOFTDEP(vp))
1133 softdep_load_inodeblock(ip);
1134 else
1135 ip->i_effnlink = ip->i_nlink;
1136 bqrelse(bp);
1137
1138 /*
1139 * Initialize the vnode from the inode, check for aliases.
1140 * Note that the underlying vnode may have changed.
1141 */
1142 error = ufs_vinit(mp, ffs_specop_p, ffs_fifoop_p, &vp);
1143 if (error) {
1144 vput(vp);
1145 *vpp = NULL;
1146 return (error);
1147 }
1148 /*
1149 * Finish inode initialization now that aliasing has been resolved.
1150 */
1151 ip->i_devvp = ump->um_devvp;
1152 VREF(ip->i_devvp);
1153 /*
1154 * Set up a generation number for this inode if it does not
1155 * already have one. This should only happen on old filesystems.
1156 */
1157 if (ip->i_gen == 0) {
1158 ip->i_gen = random() / 2 + 1;
1159 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
1160 ip->i_flag |= IN_MODIFIED;
1161 }
1162 /*
1163 * Ensure that uid and gid are correct. This is a temporary
1164 * fix until fsck has been changed to do the update.
1165 */
1166 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
1167 ip->i_uid = ip->i_din.di_ouid; /* XXX */
1168 ip->i_gid = ip->i_din.di_ogid; /* XXX */
1169 } /* XXX */
1170
1171 *vpp = vp;
1172 return (0);
1173}
1174
1175/*
1176 * File handle to vnode
1177 *
1178 * Have to be really careful about stale file handles:
1179 * - check that the inode number is valid
1180 * - call ffs_vget() to get the locked inode
1181 * - check for an unallocated inode (i_mode == 0)
1182 * - check that the given client host has export rights and return
1183 * those rights via. exflagsp and credanonp
1184 */
1185int
1186ffs_fhtovp(mp, fhp, vpp)
1187 register struct mount *mp;
1188 struct fid *fhp;
1189 struct vnode **vpp;
1190{
1191 register struct ufid *ufhp;
1192 struct fs *fs;
1193
1194 ufhp = (struct ufid *)fhp;
1195 fs = VFSTOUFS(mp)->um_fs;
1196 if (ufhp->ufid_ino < ROOTINO ||
1197 ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg)
1198 return (ESTALE);
1199 return (ufs_fhtovp(mp, ufhp, vpp));
1200}
1201
1202/*
1203 * Vnode pointer to File handle
1204 */
1205/* ARGSUSED */
1206int
1207ffs_vptofh(vp, fhp)
1208 struct vnode *vp;
1209 struct fid *fhp;
1210{
1211 register struct inode *ip;
1212 register struct ufid *ufhp;
1213
1214 ip = VTOI(vp);
1215 ufhp = (struct ufid *)fhp;
1216 ufhp->ufid_len = sizeof(struct ufid);
1217 ufhp->ufid_ino = ip->i_number;
1218 ufhp->ufid_gen = ip->i_gen;
1219 return (0);
1220}
1221
1222/*
1223 * Initialize the filesystem; just use ufs_init.
1224 */
1225static int
1226ffs_init(vfsp)
1227 struct vfsconf *vfsp;
1228{
1229
1230 softdep_initialize();
1231 return (ufs_init(vfsp));
1232}
1233
1234/*
1235 * Write a superblock and associated information back to disk.
1236 */
1237static int
1238ffs_sbupdate(mp, waitfor)
1239 struct ufsmount *mp;
1240 int waitfor;
1241{
1242 register struct fs *dfs, *fs = mp->um_fs;
1243 register struct buf *bp;
1244 int blks;
1245 caddr_t space;
1246 int i, size, error, allerror = 0;
1247
1248 /*
1249 * First write back the summary information.
1250 */
1251 blks = howmany(fs->fs_cssize, fs->fs_fsize);
1252 space = (caddr_t)fs->fs_csp[0];
1253 for (i = 0; i < blks; i += fs->fs_frag) {
1254 size = fs->fs_bsize;
1255 if (i + fs->fs_frag > blks)
1256 size = (blks - i) * fs->fs_fsize;
1257 bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
1258 size, 0, 0);
1259 bcopy(space, bp->b_data, (u_int)size);
1260 space += size;
1261 if (waitfor != MNT_WAIT)
1262 bawrite(bp);
1263 else if ((error = bwrite(bp)) != 0)
1264 allerror = error;
1265 }
1266 /*
1267 * Now write back the superblock itself. If any errors occurred
1268 * up to this point, then fail so that the superblock avoids
1269 * being written out as clean.
1270 */
1271 if (allerror)
1272 return (allerror);
1273 bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0);
1274 fs->fs_fmod = 0;
1275 fs->fs_time = time_second;
1276 bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
1277 /* Restore compatibility to old file systems. XXX */
1278 dfs = (struct fs *)bp->b_data; /* XXX */
1279 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
1280 dfs->fs_nrpos = -1; /* XXX */
1281 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
1282 int32_t *lp, tmp; /* XXX */
1283 /* XXX */
1284 lp = (int32_t *)&dfs->fs_qbmask; /* XXX */
1285 tmp = lp[4]; /* XXX */
1286 for (i = 4; i > 0; i--) /* XXX */
1287 lp[i] = lp[i-1]; /* XXX */
1288 lp[0] = tmp; /* XXX */
1289 } /* XXX */
1290 dfs->fs_maxfilesize = mp->um_savedmaxfilesize; /* XXX */
1291 if (waitfor != MNT_WAIT)
1292 bawrite(bp);
1293 else if ((error = bwrite(bp)) != 0)
1294 allerror = error;
1295 return (allerror);
1296}
48#include <sys/buf.h>
49#include <sys/conf.h>
50#include <sys/fcntl.h>
51#include <sys/disklabel.h>
52#include <sys/malloc.h>
53
54#include <ufs/ufs/extattr.h>
55#include <ufs/ufs/quota.h>
56#include <ufs/ufs/ufsmount.h>
57#include <ufs/ufs/inode.h>
58#include <ufs/ufs/ufs_extern.h>
59
60#include <ufs/ffs/fs.h>
61#include <ufs/ffs/ffs_extern.h>
62
63#include <vm/vm.h>
64#include <vm/vm_page.h>
65
66static MALLOC_DEFINE(M_FFSNODE, "FFS node", "FFS vnode private part");
67
68static int ffs_sbupdate __P((struct ufsmount *, int));
69static int ffs_reload __P((struct mount *,struct ucred *,struct proc *));
70static int ffs_oldfscompat __P((struct fs *));
71static int ffs_mount __P((struct mount *, char *, caddr_t,
72 struct nameidata *, struct proc *));
73static int ffs_init __P((struct vfsconf *));
74
75static struct vfsops ufs_vfsops = {
76 ffs_mount,
77 ufs_start,
78 ffs_unmount,
79 ufs_root,
80 ufs_quotactl,
81 ffs_statfs,
82 ffs_sync,
83 ffs_vget,
84 ffs_fhtovp,
85 ufs_check_export,
86 ffs_vptofh,
87 ffs_init,
88 vfs_stduninit,
89#ifdef FFS_EXTATTR
90 ufs_extattrctl,
91#else
92 vfs_stdextattrctl,
93#endif
94};
95
96VFS_SET(ufs_vfsops, ufs, 0);
97
98/*
99 * ffs_mount
100 *
101 * Called when mounting local physical media
102 *
103 * PARAMETERS:
104 * mountroot
105 * mp mount point structure
106 * path NULL (flag for root mount!!!)
107 * data <unused>
108 * ndp <unused>
109 * p process (user credentials check [statfs])
110 *
111 * mount
112 * mp mount point structure
113 * path path to mount point
114 * data pointer to argument struct in user space
115 * ndp mount point namei() return (used for
116 * credentials on reload), reused to look
117 * up block device.
118 * p process (user credentials check)
119 *
120 * RETURNS: 0 Success
121 * !0 error number (errno.h)
122 *
123 * LOCK STATE:
124 *
125 * ENTRY
126 * mount point is locked
127 * EXIT
128 * mount point is locked
129 *
130 * NOTES:
131 * A NULL path can be used for a flag since the mount
132 * system call will fail with EFAULT in copyinstr in
133 * namei() if it is a genuine NULL from the user.
134 */
135static int
136ffs_mount( mp, path, data, ndp, p)
137 struct mount *mp; /* mount struct pointer*/
138 char *path; /* path to mount point*/
139 caddr_t data; /* arguments to FS specific mount*/
140 struct nameidata *ndp; /* mount point credentials*/
141 struct proc *p; /* process requesting mount*/
142{
143 size_t size;
144 int err = 0;
145 struct vnode *devvp;
146
147 struct ufs_args args;
148 struct ufsmount *ump = 0;
149 register struct fs *fs;
150 int error, flags, ronly = 0;
151 mode_t accessmode;
152
153 /*
154 * Use NULL path to flag a root mount
155 */
156 if( path == NULL) {
157 /*
158 ***
159 * Mounting root file system
160 ***
161 */
162
163 if ((err = bdevvp(rootdev, &rootvp))) {
164 printf("ffs_mountroot: can't find rootvp\n");
165 return (err);
166 }
167
168 if( ( err = ffs_mountfs(rootvp, mp, p, M_FFSNODE)) != 0) {
169 /* fs specific cleanup (if any)*/
170 goto error_1;
171 }
172
173 goto dostatfs; /* success*/
174
175 }
176
177 /*
178 ***
179 * Mounting non-root file system or updating a file system
180 ***
181 */
182
183 /* copy in user arguments*/
184 err = copyin(data, (caddr_t)&args, sizeof (struct ufs_args));
185 if (err)
186 goto error_1; /* can't get arguments*/
187
188 /*
189 * If updating, check whether changing from read-only to
190 * read/write; if there is no device name, that's all we do.
191 */
192 if (mp->mnt_flag & MNT_UPDATE) {
193 ump = VFSTOUFS(mp);
194 fs = ump->um_fs;
195 devvp = ump->um_devvp;
196 err = 0;
197 ronly = fs->fs_ronly; /* MNT_RELOAD might change this */
198 if (ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
199 flags = WRITECLOSE;
200 if (mp->mnt_flag & MNT_FORCE)
201 flags |= FORCECLOSE;
202 if (mp->mnt_flag & MNT_SOFTDEP) {
203 err = softdep_flushfiles(mp, flags, p);
204 } else {
205 err = ffs_flushfiles(mp, flags, p);
206 }
207 ronly = 1;
208 }
209 if (!err && (mp->mnt_flag & MNT_RELOAD))
210 err = ffs_reload(mp, ndp->ni_cnd.cn_cred, p);
211 if (err) {
212 goto error_1;
213 }
214 if (ronly && (mp->mnt_kern_flag & MNTK_WANTRDWR)) {
215 /*
216 * If upgrade to read-write by non-root, then verify
217 * that user has necessary permissions on the device.
218 */
219 if (p->p_ucred->cr_uid != 0) {
220 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
221 if ((error = VOP_ACCESS(devvp, VREAD | VWRITE,
222 p->p_ucred, p)) != 0) {
223 VOP_UNLOCK(devvp, 0, p);
224 return (error);
225 }
226 VOP_UNLOCK(devvp, 0, p);
227 }
228
229 fs->fs_flags &= ~FS_UNCLEAN;
230 if (fs->fs_clean == 0) {
231 fs->fs_flags |= FS_UNCLEAN;
232 if (mp->mnt_flag & MNT_FORCE) {
233 printf(
234"WARNING: %s was not properly dismounted\n",
235 fs->fs_fsmnt);
236 } else {
237 printf(
238"WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n",
239 fs->fs_fsmnt);
240 err = EPERM;
241 goto error_1;
242 }
243 }
244
245 /* check to see if we need to start softdep */
246 if (fs->fs_flags & FS_DOSOFTDEP) {
247 err = softdep_mount(devvp, mp, fs, p->p_ucred);
248 if (err)
249 goto error_1;
250 }
251
252 ronly = 0;
253 }
254 /*
255 * Soft updates is incompatible with "async",
256 * so if we are doing softupdates stop the user
257 * from setting the async flag in an update.
258 * Softdep_mount() clears it in an initial mount
259 * or ro->rw remount.
260 */
261 if (mp->mnt_flag & MNT_SOFTDEP) {
262 mp->mnt_flag &= ~MNT_ASYNC;
263 }
264 /* if not updating name...*/
265 if (args.fspec == 0) {
266 /*
267 * Process export requests. Jumping to "success"
268 * will return the vfs_export() error code.
269 */
270 err = vfs_export(mp, &ump->um_export, &args.export);
271 goto success;
272 }
273 }
274
275 /*
276 * Not an update, or updating the name: look up the name
277 * and verify that it refers to a sensible block device.
278 */
279 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
280 err = namei(ndp);
281 if (err) {
282 /* can't get devvp!*/
283 goto error_1;
284 }
285
286 NDFREE(ndp, NDF_ONLY_PNBUF);
287 devvp = ndp->ni_vp;
288
289 if (!vn_isdisk(devvp, &err))
290 goto error_2;
291
292 /*
293 * If mount by non-root, then verify that user has necessary
294 * permissions on the device.
295 */
296 if (p->p_ucred->cr_uid != 0) {
297 accessmode = VREAD;
298 if ((mp->mnt_flag & MNT_RDONLY) == 0)
299 accessmode |= VWRITE;
300 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
301 if ((error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) != 0) {
302 vput(devvp);
303 return (error);
304 }
305 VOP_UNLOCK(devvp, 0, p);
306 }
307
308 if (mp->mnt_flag & MNT_UPDATE) {
309 /*
310 ********************
311 * UPDATE
312 * If it's not the same vnode, or at least the same device
313 * then it's not correct.
314 ********************
315 */
316
317 if (devvp != ump->um_devvp) {
318 if ( devvp->v_rdev == ump->um_devvp->v_rdev) {
319 vrele(devvp);
320 } else {
321 err = EINVAL; /* needs translation */
322 }
323 } else
324 vrele(devvp);
325 /*
326 * Update device name only on success
327 */
328 if( !err) {
329 /* Save "mounted from" info for mount point (NULL pad)*/
330 copyinstr( args.fspec,
331 mp->mnt_stat.f_mntfromname,
332 MNAMELEN - 1,
333 &size);
334 bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
335 }
336 } else {
337 /*
338 ********************
339 * NEW MOUNT
340 ********************
341 */
342
343 /*
344 * Since this is a new mount, we want the names for
345 * the device and the mount point copied in. If an
346 * error occurs, the mountpoint is discarded by the
347 * upper level code.
348 */
349 /* Save "last mounted on" info for mount point (NULL pad)*/
350 copyinstr( path, /* mount point*/
351 mp->mnt_stat.f_mntonname, /* save area*/
352 MNAMELEN - 1, /* max size*/
353 &size); /* real size*/
354 bzero( mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
355
356 /* Save "mounted from" info for mount point (NULL pad)*/
357 copyinstr( args.fspec, /* device name*/
358 mp->mnt_stat.f_mntfromname, /* save area*/
359 MNAMELEN - 1, /* max size*/
360 &size); /* real size*/
361 bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
362
363 err = ffs_mountfs(devvp, mp, p, M_FFSNODE);
364 }
365 if (err) {
366 goto error_2;
367 }
368
369dostatfs:
370 /*
371 * Initialize FS stat information in mount struct; uses both
372 * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname
373 *
374 * This code is common to root and non-root mounts
375 */
376 (void)VFS_STATFS(mp, &mp->mnt_stat, p);
377
378 goto success;
379
380
381error_2: /* error with devvp held*/
382
383 /* release devvp before failing*/
384 vrele(devvp);
385
386error_1: /* no state to back out*/
387
388success:
389 if (!err && path && (mp->mnt_flag & MNT_UPDATE)) {
390 /* Update clean flag after changing read-onlyness. */
391 fs = ump->um_fs;
392 if (ronly != fs->fs_ronly) {
393 fs->fs_ronly = ronly;
394 fs->fs_clean = ronly &&
395 (fs->fs_flags & FS_UNCLEAN) == 0 ? 1 : 0;
396 ffs_sbupdate(ump, MNT_WAIT);
397 }
398 }
399 return (err);
400}
401
402/*
403 * Reload all incore data for a filesystem (used after running fsck on
404 * the root filesystem and finding things to fix). The filesystem must
405 * be mounted read-only.
406 *
407 * Things to do to update the mount:
408 * 1) invalidate all cached meta-data.
409 * 2) re-read superblock from disk.
410 * 3) re-read summary information from disk.
411 * 4) invalidate all inactive vnodes.
412 * 5) invalidate all cached file data.
413 * 6) re-read inode data for all active vnodes.
414 */
415static int
416ffs_reload(mp, cred, p)
417 register struct mount *mp;
418 struct ucred *cred;
419 struct proc *p;
420{
421 register struct vnode *vp, *nvp, *devvp;
422 struct inode *ip;
423 struct csum *space;
424 struct buf *bp;
425 struct fs *fs, *newfs;
426 struct partinfo dpart;
427 dev_t dev;
428 int i, blks, size, error;
429 int32_t *lp;
430
431 if ((mp->mnt_flag & MNT_RDONLY) == 0)
432 return (EINVAL);
433 /*
434 * Step 1: invalidate all cached meta-data.
435 */
436 devvp = VFSTOUFS(mp)->um_devvp;
437 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
438 error = vinvalbuf(devvp, 0, cred, p, 0, 0);
439 VOP_UNLOCK(devvp, 0, p);
440 if (error)
441 panic("ffs_reload: dirty1");
442
443 dev = devvp->v_rdev;
444
445 /*
446 * Only VMIO the backing device if the backing device is a real
447 * block device. See ffs_mountmfs() for more details.
448 */
449 if (devvp->v_tag != VT_MFS && vn_isdisk(devvp, NULL)) {
450 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
451 vfs_object_create(devvp, p, p->p_ucred);
452 simple_lock(&devvp->v_interlock);
453 VOP_UNLOCK(devvp, LK_INTERLOCK, p);
454 }
455
456 /*
457 * Step 2: re-read superblock from disk.
458 */
459 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
460 size = DEV_BSIZE;
461 else
462 size = dpart.disklab->d_secsize;
463 if ((error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, NOCRED,&bp)) != 0)
464 return (error);
465 newfs = (struct fs *)bp->b_data;
466 if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE ||
467 newfs->fs_bsize < sizeof(struct fs)) {
468 brelse(bp);
469 return (EIO); /* XXX needs translation */
470 }
471 fs = VFSTOUFS(mp)->um_fs;
472 /*
473 * Copy pointer fields back into superblock before copying in XXX
474 * new superblock. These should really be in the ufsmount. XXX
475 * Note that important parameters (eg fs_ncg) are unchanged.
476 */
477 bcopy(&fs->fs_csp[0], &newfs->fs_csp[0], sizeof(fs->fs_csp));
478 newfs->fs_maxcluster = fs->fs_maxcluster;
479 bcopy(newfs, fs, (u_int)fs->fs_sbsize);
480 if (fs->fs_sbsize < SBSIZE)
481 bp->b_flags |= B_INVAL;
482 brelse(bp);
483 mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
484 ffs_oldfscompat(fs);
485
486 /*
487 * Step 3: re-read summary information from disk.
488 */
489 blks = howmany(fs->fs_cssize, fs->fs_fsize);
490 space = fs->fs_csp[0];
491 for (i = 0; i < blks; i += fs->fs_frag) {
492 size = fs->fs_bsize;
493 if (i + fs->fs_frag > blks)
494 size = (blks - i) * fs->fs_fsize;
495 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
496 NOCRED, &bp);
497 if (error)
498 return (error);
499 bcopy(bp->b_data, fs->fs_csp[fragstoblks(fs, i)], (u_int)size);
500 brelse(bp);
501 }
502 /*
503 * We no longer know anything about clusters per cylinder group.
504 */
505 if (fs->fs_contigsumsize > 0) {
506 lp = fs->fs_maxcluster;
507 for (i = 0; i < fs->fs_ncg; i++)
508 *lp++ = fs->fs_contigsumsize;
509 }
510
511loop:
512 simple_lock(&mntvnode_slock);
513 for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
514 if (vp->v_mount != mp) {
515 simple_unlock(&mntvnode_slock);
516 goto loop;
517 }
518 nvp = vp->v_mntvnodes.le_next;
519 /*
520 * Step 4: invalidate all inactive vnodes.
521 */
522 if (vrecycle(vp, &mntvnode_slock, p))
523 goto loop;
524 /*
525 * Step 5: invalidate all cached file data.
526 */
527 simple_lock(&vp->v_interlock);
528 simple_unlock(&mntvnode_slock);
529 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) {
530 goto loop;
531 }
532 if (vinvalbuf(vp, 0, cred, p, 0, 0))
533 panic("ffs_reload: dirty2");
534 /*
535 * Step 6: re-read inode data for all active vnodes.
536 */
537 ip = VTOI(vp);
538 error =
539 bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
540 (int)fs->fs_bsize, NOCRED, &bp);
541 if (error) {
542 vput(vp);
543 return (error);
544 }
545 ip->i_din = *((struct dinode *)bp->b_data +
546 ino_to_fsbo(fs, ip->i_number));
547 ip->i_effnlink = ip->i_nlink;
548 brelse(bp);
549 vput(vp);
550 simple_lock(&mntvnode_slock);
551 }
552 simple_unlock(&mntvnode_slock);
553 return (0);
554}
555
556/*
557 * Common code for mount and mountroot
558 */
559int
560ffs_mountfs(devvp, mp, p, malloctype)
561 register struct vnode *devvp;
562 struct mount *mp;
563 struct proc *p;
564 struct malloc_type *malloctype;
565{
566 register struct ufsmount *ump;
567 struct buf *bp;
568 register struct fs *fs;
569 dev_t dev;
570 struct partinfo dpart;
571 caddr_t base, space;
572 int error, i, blks, size, ronly;
573 int32_t *lp;
574 struct ucred *cred;
575 u_int64_t maxfilesize; /* XXX */
576 size_t strsize;
577 int ncount;
578
579 dev = devvp->v_rdev;
580 cred = p ? p->p_ucred : NOCRED;
581 /*
582 * Disallow multiple mounts of the same device.
583 * Disallow mounting of a device that is currently in use
584 * (except for root, which might share swap device for miniroot).
585 * Flush out any old buffers remaining from a previous use.
586 */
587 error = vfs_mountedon(devvp);
588 if (error)
589 return (error);
590 ncount = vcount(devvp);
591
592 if (ncount > 1 && devvp != rootvp)
593 return (EBUSY);
594 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
595 error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0);
596 VOP_UNLOCK(devvp, 0, p);
597 if (error)
598 return (error);
599
600 /*
601 * Only VMIO the backing device if the backing device is a real
602 * block device. This excludes the original MFS implementation.
603 * Note that it is optional that the backing device be VMIOed. This
604 * increases the opportunity for metadata caching.
605 */
606 if (devvp->v_tag != VT_MFS && vn_isdisk(devvp, NULL)) {
607 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
608 vfs_object_create(devvp, p, p->p_ucred);
609 simple_lock(&devvp->v_interlock);
610 VOP_UNLOCK(devvp, LK_INTERLOCK, p);
611 }
612
613 ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
614 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
615 error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
616 VOP_UNLOCK(devvp, 0, p);
617 if (error)
618 return (error);
619 if (devvp->v_rdev->si_iosize_max > mp->mnt_iosize_max)
620 mp->mnt_iosize_max = devvp->v_rdev->si_iosize_max;
621 if (mp->mnt_iosize_max > MAXPHYS)
622 mp->mnt_iosize_max = MAXPHYS;
623
624 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0)
625 size = DEV_BSIZE;
626 else
627 size = dpart.disklab->d_secsize;
628
629 bp = NULL;
630 ump = NULL;
631 if ((error = bread(devvp, SBLOCK, SBSIZE, cred, &bp)) != 0)
632 goto out;
633 fs = (struct fs *)bp->b_data;
634 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
635 fs->fs_bsize < sizeof(struct fs)) {
636 error = EINVAL; /* XXX needs translation */
637 goto out;
638 }
639 fs->fs_fmod = 0;
640 fs->fs_flags &= ~FS_UNCLEAN;
641 if (fs->fs_clean == 0) {
642 fs->fs_flags |= FS_UNCLEAN;
643 if (ronly || (mp->mnt_flag & MNT_FORCE)) {
644 printf(
645"WARNING: %s was not properly dismounted\n",
646 fs->fs_fsmnt);
647 } else {
648 printf(
649"WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n",
650 fs->fs_fsmnt);
651 error = EPERM;
652 goto out;
653 }
654 }
655 /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */
656 if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) {
657 error = EROFS; /* needs translation */
658 goto out;
659 }
660 ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
661 bzero((caddr_t)ump, sizeof *ump);
662 ump->um_malloctype = malloctype;
663 ump->um_i_effnlink_valid = 1;
664 ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT,
665 M_WAITOK);
666 ump->um_blkatoff = ffs_blkatoff;
667 ump->um_truncate = ffs_truncate;
668 ump->um_update = ffs_update;
669 ump->um_valloc = ffs_valloc;
670 ump->um_vfree = ffs_vfree;
671 bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize);
672 if (fs->fs_sbsize < SBSIZE)
673 bp->b_flags |= B_INVAL;
674 brelse(bp);
675 bp = NULL;
676 fs = ump->um_fs;
677 fs->fs_ronly = ronly;
678 size = fs->fs_cssize;
679 blks = howmany(size, fs->fs_fsize);
680 if (fs->fs_contigsumsize > 0)
681 size += fs->fs_ncg * sizeof(int32_t);
682 base = space = malloc((u_long)size, M_UFSMNT, M_WAITOK);
683 for (i = 0; i < blks; i += fs->fs_frag) {
684 size = fs->fs_bsize;
685 if (i + fs->fs_frag > blks)
686 size = (blks - i) * fs->fs_fsize;
687 if ((error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
688 cred, &bp)) != 0) {
689 free(base, M_UFSMNT);
690 goto out;
691 }
692 bcopy(bp->b_data, space, (u_int)size);
693 fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space;
694 space += size;
695 brelse(bp);
696 bp = NULL;
697 }
698 if (fs->fs_contigsumsize > 0) {
699 fs->fs_maxcluster = lp = (int32_t *)space;
700 for (i = 0; i < fs->fs_ncg; i++)
701 *lp++ = fs->fs_contigsumsize;
702 }
703 mp->mnt_data = (qaddr_t)ump;
704 mp->mnt_stat.f_fsid.val[0] = fs->fs_id[0];
705 mp->mnt_stat.f_fsid.val[1] = fs->fs_id[1];
706 if (fs->fs_id[0] == 0 || fs->fs_id[1] == 0 ||
707 vfs_getvfs(&mp->mnt_stat.f_fsid))
708 vfs_getnewfsid(mp);
709 mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
710 mp->mnt_flag |= MNT_LOCAL;
711 ump->um_mountp = mp;
712 ump->um_dev = dev;
713 ump->um_devvp = devvp;
714 ump->um_nindir = fs->fs_nindir;
715 ump->um_bptrtodb = fs->fs_fsbtodb;
716 ump->um_seqinc = fs->fs_frag;
717 for (i = 0; i < MAXQUOTAS; i++)
718 ump->um_quotas[i] = NULLVP;
719#ifdef FFS_EXTATTR
720 ufs_extattr_uepm_init(&ump->um_extattr);
721#endif
722 devvp->v_specmountpoint = mp;
723 ffs_oldfscompat(fs);
724
725 /*
726 * Set FS local "last mounted on" information (NULL pad)
727 */
728 copystr( mp->mnt_stat.f_mntonname, /* mount point*/
729 fs->fs_fsmnt, /* copy area*/
730 sizeof(fs->fs_fsmnt) - 1, /* max size*/
731 &strsize); /* real size*/
732 bzero( fs->fs_fsmnt + strsize, sizeof(fs->fs_fsmnt) - strsize);
733
734 if( mp->mnt_flag & MNT_ROOTFS) {
735 /*
736 * Root mount; update timestamp in mount structure.
737 * this will be used by the common root mount code
738 * to update the system clock.
739 */
740 mp->mnt_time = fs->fs_time;
741 }
742
743 ump->um_savedmaxfilesize = fs->fs_maxfilesize; /* XXX */
744 maxfilesize = (u_int64_t)0x40000000 * fs->fs_bsize - 1; /* XXX */
745 if (fs->fs_maxfilesize > maxfilesize) /* XXX */
746 fs->fs_maxfilesize = maxfilesize; /* XXX */
747 if (ronly == 0) {
748 if ((fs->fs_flags & FS_DOSOFTDEP) &&
749 (error = softdep_mount(devvp, mp, fs, cred)) != 0) {
750 free(base, M_UFSMNT);
751 goto out;
752 }
753 fs->fs_fmod = 1;
754 fs->fs_clean = 0;
755 (void) ffs_sbupdate(ump, MNT_WAIT);
756 }
757 return (0);
758out:
759 devvp->v_specmountpoint = NULL;
760 if (bp)
761 brelse(bp);
762 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
763 if (ump) {
764 free(ump->um_fs, M_UFSMNT);
765 free(ump, M_UFSMNT);
766 mp->mnt_data = (qaddr_t)0;
767 }
768 return (error);
769}
770
771/*
772 * Sanity checks for old file systems.
773 *
774 * XXX - goes away some day.
775 */
776static int
777ffs_oldfscompat(fs)
778 struct fs *fs;
779{
780
781 fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */
782 fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */
783 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
784 fs->fs_nrpos = 8; /* XXX */
785 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
786#if 0
787 int i; /* XXX */
788 u_int64_t sizepb = fs->fs_bsize; /* XXX */
789 /* XXX */
790 fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
791 for (i = 0; i < NIADDR; i++) { /* XXX */
792 sizepb *= NINDIR(fs); /* XXX */
793 fs->fs_maxfilesize += sizepb; /* XXX */
794 } /* XXX */
795#endif
796 fs->fs_maxfilesize = (u_quad_t) 1LL << 39;
797 fs->fs_qbmask = ~fs->fs_bmask; /* XXX */
798 fs->fs_qfmask = ~fs->fs_fmask; /* XXX */
799 } /* XXX */
800 return (0);
801}
802
803/*
804 * unmount system call
805 */
806int
807ffs_unmount(mp, mntflags, p)
808 struct mount *mp;
809 int mntflags;
810 struct proc *p;
811{
812 register struct ufsmount *ump;
813 register struct fs *fs;
814 int error, flags;
815
816 flags = 0;
817 if (mntflags & MNT_FORCE) {
818 flags |= FORCECLOSE;
819 }
820#ifdef FFS_EXTATTR
821 if ((error = ufs_extattr_stop(mp, p))) {
822 printf("ffs_unmonut: ufs_extattr_stop returned %d\n", error);
823 }
824#endif
825 if (mp->mnt_flag & MNT_SOFTDEP) {
826 if ((error = softdep_flushfiles(mp, flags, p)) != 0)
827 return (error);
828 } else {
829 if ((error = ffs_flushfiles(mp, flags, p)) != 0)
830 return (error);
831 }
832 ump = VFSTOUFS(mp);
833 fs = ump->um_fs;
834 if (fs->fs_ronly == 0) {
835 fs->fs_clean = fs->fs_flags & FS_UNCLEAN ? 0 : 1;
836 error = ffs_sbupdate(ump, MNT_WAIT);
837 if (error) {
838 fs->fs_clean = 0;
839 return (error);
840 }
841 }
842 ump->um_devvp->v_specmountpoint = NULL;
843
844 vinvalbuf(ump->um_devvp, V_SAVE, NOCRED, p, 0, 0);
845 error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
846 NOCRED, p);
847
848 vrele(ump->um_devvp);
849
850 free(fs->fs_csp[0], M_UFSMNT);
851 free(fs, M_UFSMNT);
852 free(ump, M_UFSMNT);
853 mp->mnt_data = (qaddr_t)0;
854 mp->mnt_flag &= ~MNT_LOCAL;
855 return (error);
856}
857
858/*
859 * Flush out all the files in a filesystem.
860 */
861int
862ffs_flushfiles(mp, flags, p)
863 register struct mount *mp;
864 int flags;
865 struct proc *p;
866{
867 register struct ufsmount *ump;
868 int error;
869
870 ump = VFSTOUFS(mp);
871#ifdef QUOTA
872 if (mp->mnt_flag & MNT_QUOTA) {
873 int i;
874 error = vflush(mp, NULLVP, SKIPSYSTEM|flags);
875 if (error)
876 return (error);
877 for (i = 0; i < MAXQUOTAS; i++) {
878 if (ump->um_quotas[i] == NULLVP)
879 continue;
880 quotaoff(p, mp, i);
881 }
882 /*
883 * Here we fall through to vflush again to ensure
884 * that we have gotten rid of all the system vnodes.
885 */
886 }
887#endif
888 /*
889 * Flush all the files.
890 */
891 if ((error = vflush(mp, NULL, flags)) != 0)
892 return (error);
893 /*
894 * Flush filesystem metadata.
895 */
896 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
897 error = VOP_FSYNC(ump->um_devvp, p->p_ucred, MNT_WAIT, p);
898 VOP_UNLOCK(ump->um_devvp, 0, p);
899 return (error);
900}
901
902/*
903 * Get file system statistics.
904 */
905int
906ffs_statfs(mp, sbp, p)
907 struct mount *mp;
908 register struct statfs *sbp;
909 struct proc *p;
910{
911 register struct ufsmount *ump;
912 register struct fs *fs;
913
914 ump = VFSTOUFS(mp);
915 fs = ump->um_fs;
916 if (fs->fs_magic != FS_MAGIC)
917 panic("ffs_statfs");
918 sbp->f_bsize = fs->fs_fsize;
919 sbp->f_iosize = fs->fs_bsize;
920 sbp->f_blocks = fs->fs_dsize;
921 sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
922 fs->fs_cstotal.cs_nffree;
923 sbp->f_bavail = freespace(fs, fs->fs_minfree);
924 sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
925 sbp->f_ffree = fs->fs_cstotal.cs_nifree;
926 if (sbp != &mp->mnt_stat) {
927 sbp->f_type = mp->mnt_vfc->vfc_typenum;
928 bcopy((caddr_t)mp->mnt_stat.f_mntonname,
929 (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
930 bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
931 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
932 }
933 return (0);
934}
935
936/*
937 * Go through the disk queues to initiate sandbagged IO;
938 * go through the inodes to write those that have been modified;
939 * initiate the writing of the super block if it has been modified.
940 *
941 * Note: we are always called with the filesystem marked `MPBUSY'.
942 */
943int
944ffs_sync(mp, waitfor, cred, p)
945 struct mount *mp;
946 int waitfor;
947 struct ucred *cred;
948 struct proc *p;
949{
950 struct vnode *nvp, *vp;
951 struct inode *ip;
952 struct ufsmount *ump = VFSTOUFS(mp);
953 struct fs *fs;
954 int error, allerror = 0;
955
956 fs = ump->um_fs;
957 if (fs->fs_fmod != 0 && fs->fs_ronly != 0) { /* XXX */
958 printf("fs = %s\n", fs->fs_fsmnt);
959 panic("ffs_sync: rofs mod");
960 }
961 /*
962 * Write back each (modified) inode.
963 */
964 simple_lock(&mntvnode_slock);
965loop:
966 for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
967 /*
968 * If the vnode that we are about to sync is no longer
969 * associated with this mount point, start over.
970 */
971 if (vp->v_mount != mp)
972 goto loop;
973 simple_lock(&vp->v_interlock);
974 nvp = vp->v_mntvnodes.le_next;
975 ip = VTOI(vp);
976 if (vp->v_type == VNON || ((ip->i_flag &
977 (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
978 TAILQ_EMPTY(&vp->v_dirtyblkhd))) {
979 simple_unlock(&vp->v_interlock);
980 continue;
981 }
982 if (vp->v_type != VCHR) {
983 simple_unlock(&mntvnode_slock);
984 error =
985 vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p);
986 if (error) {
987 simple_lock(&mntvnode_slock);
988 if (error == ENOENT)
989 goto loop;
990 continue;
991 }
992 if ((error = VOP_FSYNC(vp, cred, waitfor, p)) != 0)
993 allerror = error;
994 VOP_UNLOCK(vp, 0, p);
995 vrele(vp);
996 simple_lock(&mntvnode_slock);
997 } else {
998 simple_unlock(&mntvnode_slock);
999 simple_unlock(&vp->v_interlock);
1000 /* UFS_UPDATE(vp, waitfor == MNT_WAIT); */
1001 UFS_UPDATE(vp, 0);
1002 simple_lock(&mntvnode_slock);
1003 }
1004 }
1005 simple_unlock(&mntvnode_slock);
1006 /*
1007 * Force stale file system control information to be flushed.
1008 */
1009 if (waitfor != MNT_LAZY) {
1010 if (ump->um_mountp->mnt_flag & MNT_SOFTDEP)
1011 waitfor = MNT_NOWAIT;
1012 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
1013 if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0)
1014 allerror = error;
1015 VOP_UNLOCK(ump->um_devvp, 0, p);
1016 }
1017#ifdef QUOTA
1018 qsync(mp);
1019#endif
1020 /*
1021 * Write back modified superblock.
1022 */
1023 if (fs->fs_fmod != 0 && (error = ffs_sbupdate(ump, waitfor)) != 0)
1024 allerror = error;
1025 return (allerror);
1026}
1027
1028/*
1029 * Look up a FFS dinode number to find its incore vnode, otherwise read it
1030 * in from disk. If it is in core, wait for the lock bit to clear, then
1031 * return the inode locked. Detection and handling of mount points must be
1032 * done by the calling routine.
1033 */
1034static int ffs_inode_hash_lock;
1035
1036int
1037ffs_vget(mp, ino, vpp)
1038 struct mount *mp;
1039 ino_t ino;
1040 struct vnode **vpp;
1041{
1042 struct fs *fs;
1043 struct inode *ip;
1044 struct ufsmount *ump;
1045 struct buf *bp;
1046 struct vnode *vp;
1047 dev_t dev;
1048 int error;
1049
1050 ump = VFSTOUFS(mp);
1051 dev = ump->um_dev;
1052restart:
1053 if ((*vpp = ufs_ihashget(dev, ino)) != NULL) {
1054 return (0);
1055 }
1056
1057 /*
1058 * Lock out the creation of new entries in the FFS hash table in
1059 * case getnewvnode() or MALLOC() blocks, otherwise a duplicate
1060 * may occur!
1061 */
1062 if (ffs_inode_hash_lock) {
1063 while (ffs_inode_hash_lock) {
1064 ffs_inode_hash_lock = -1;
1065 tsleep(&ffs_inode_hash_lock, PVM, "ffsvgt", 0);
1066 }
1067 goto restart;
1068 }
1069 ffs_inode_hash_lock = 1;
1070
1071 /*
1072 * If this MALLOC() is performed after the getnewvnode()
1073 * it might block, leaving a vnode with a NULL v_data to be
1074 * found by ffs_sync() if a sync happens to fire right then,
1075 * which will cause a panic because ffs_sync() blindly
1076 * dereferences vp->v_data (as well it should).
1077 */
1078 MALLOC(ip, struct inode *, sizeof(struct inode),
1079 ump->um_malloctype, M_WAITOK);
1080
1081 /* Allocate a new vnode/inode. */
1082 error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp);
1083 if (error) {
1084 if (ffs_inode_hash_lock < 0)
1085 wakeup(&ffs_inode_hash_lock);
1086 ffs_inode_hash_lock = 0;
1087 *vpp = NULL;
1088 FREE(ip, ump->um_malloctype);
1089 return (error);
1090 }
1091 bzero((caddr_t)ip, sizeof(struct inode));
1092 lockinit(&ip->i_lock, PINOD, "inode", 0, LK_CANRECURSE);
1093 vp->v_data = ip;
1094 ip->i_vnode = vp;
1095 ip->i_fs = fs = ump->um_fs;
1096 ip->i_dev = dev;
1097 ip->i_number = ino;
1098#ifdef QUOTA
1099 {
1100 int i;
1101 for (i = 0; i < MAXQUOTAS; i++)
1102 ip->i_dquot[i] = NODQUOT;
1103 }
1104#endif
1105 /*
1106 * Put it onto its hash chain and lock it so that other requests for
1107 * this inode will block if they arrive while we are sleeping waiting
1108 * for old data structures to be purged or for the contents of the
1109 * disk portion of this inode to be read.
1110 */
1111 ufs_ihashins(ip);
1112
1113 if (ffs_inode_hash_lock < 0)
1114 wakeup(&ffs_inode_hash_lock);
1115 ffs_inode_hash_lock = 0;
1116
1117 /* Read in the disk contents for the inode, copy into the inode. */
1118 error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
1119 (int)fs->fs_bsize, NOCRED, &bp);
1120 if (error) {
1121 /*
1122 * The inode does not contain anything useful, so it would
1123 * be misleading to leave it on its hash chain. With mode
1124 * still zero, it will be unlinked and returned to the free
1125 * list by vput().
1126 */
1127 brelse(bp);
1128 vput(vp);
1129 *vpp = NULL;
1130 return (error);
1131 }
1132 ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino));
1133 if (DOINGSOFTDEP(vp))
1134 softdep_load_inodeblock(ip);
1135 else
1136 ip->i_effnlink = ip->i_nlink;
1137 bqrelse(bp);
1138
1139 /*
1140 * Initialize the vnode from the inode, check for aliases.
1141 * Note that the underlying vnode may have changed.
1142 */
1143 error = ufs_vinit(mp, ffs_specop_p, ffs_fifoop_p, &vp);
1144 if (error) {
1145 vput(vp);
1146 *vpp = NULL;
1147 return (error);
1148 }
1149 /*
1150 * Finish inode initialization now that aliasing has been resolved.
1151 */
1152 ip->i_devvp = ump->um_devvp;
1153 VREF(ip->i_devvp);
1154 /*
1155 * Set up a generation number for this inode if it does not
1156 * already have one. This should only happen on old filesystems.
1157 */
1158 if (ip->i_gen == 0) {
1159 ip->i_gen = random() / 2 + 1;
1160 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
1161 ip->i_flag |= IN_MODIFIED;
1162 }
1163 /*
1164 * Ensure that uid and gid are correct. This is a temporary
1165 * fix until fsck has been changed to do the update.
1166 */
1167 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
1168 ip->i_uid = ip->i_din.di_ouid; /* XXX */
1169 ip->i_gid = ip->i_din.di_ogid; /* XXX */
1170 } /* XXX */
1171
1172 *vpp = vp;
1173 return (0);
1174}
1175
1176/*
1177 * File handle to vnode
1178 *
1179 * Have to be really careful about stale file handles:
1180 * - check that the inode number is valid
1181 * - call ffs_vget() to get the locked inode
1182 * - check for an unallocated inode (i_mode == 0)
1183 * - check that the given client host has export rights and return
1184 * those rights via. exflagsp and credanonp
1185 */
1186int
1187ffs_fhtovp(mp, fhp, vpp)
1188 register struct mount *mp;
1189 struct fid *fhp;
1190 struct vnode **vpp;
1191{
1192 register struct ufid *ufhp;
1193 struct fs *fs;
1194
1195 ufhp = (struct ufid *)fhp;
1196 fs = VFSTOUFS(mp)->um_fs;
1197 if (ufhp->ufid_ino < ROOTINO ||
1198 ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg)
1199 return (ESTALE);
1200 return (ufs_fhtovp(mp, ufhp, vpp));
1201}
1202
1203/*
1204 * Vnode pointer to File handle
1205 */
1206/* ARGSUSED */
1207int
1208ffs_vptofh(vp, fhp)
1209 struct vnode *vp;
1210 struct fid *fhp;
1211{
1212 register struct inode *ip;
1213 register struct ufid *ufhp;
1214
1215 ip = VTOI(vp);
1216 ufhp = (struct ufid *)fhp;
1217 ufhp->ufid_len = sizeof(struct ufid);
1218 ufhp->ufid_ino = ip->i_number;
1219 ufhp->ufid_gen = ip->i_gen;
1220 return (0);
1221}
1222
1223/*
1224 * Initialize the filesystem; just use ufs_init.
1225 */
1226static int
1227ffs_init(vfsp)
1228 struct vfsconf *vfsp;
1229{
1230
1231 softdep_initialize();
1232 return (ufs_init(vfsp));
1233}
1234
1235/*
1236 * Write a superblock and associated information back to disk.
1237 */
1238static int
1239ffs_sbupdate(mp, waitfor)
1240 struct ufsmount *mp;
1241 int waitfor;
1242{
1243 register struct fs *dfs, *fs = mp->um_fs;
1244 register struct buf *bp;
1245 int blks;
1246 caddr_t space;
1247 int i, size, error, allerror = 0;
1248
1249 /*
1250 * First write back the summary information.
1251 */
1252 blks = howmany(fs->fs_cssize, fs->fs_fsize);
1253 space = (caddr_t)fs->fs_csp[0];
1254 for (i = 0; i < blks; i += fs->fs_frag) {
1255 size = fs->fs_bsize;
1256 if (i + fs->fs_frag > blks)
1257 size = (blks - i) * fs->fs_fsize;
1258 bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
1259 size, 0, 0);
1260 bcopy(space, bp->b_data, (u_int)size);
1261 space += size;
1262 if (waitfor != MNT_WAIT)
1263 bawrite(bp);
1264 else if ((error = bwrite(bp)) != 0)
1265 allerror = error;
1266 }
1267 /*
1268 * Now write back the superblock itself. If any errors occurred
1269 * up to this point, then fail so that the superblock avoids
1270 * being written out as clean.
1271 */
1272 if (allerror)
1273 return (allerror);
1274 bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0);
1275 fs->fs_fmod = 0;
1276 fs->fs_time = time_second;
1277 bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
1278 /* Restore compatibility to old file systems. XXX */
1279 dfs = (struct fs *)bp->b_data; /* XXX */
1280 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
1281 dfs->fs_nrpos = -1; /* XXX */
1282 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
1283 int32_t *lp, tmp; /* XXX */
1284 /* XXX */
1285 lp = (int32_t *)&dfs->fs_qbmask; /* XXX */
1286 tmp = lp[4]; /* XXX */
1287 for (i = 4; i > 0; i--) /* XXX */
1288 lp[i] = lp[i-1]; /* XXX */
1289 lp[0] = tmp; /* XXX */
1290 } /* XXX */
1291 dfs->fs_maxfilesize = mp->um_savedmaxfilesize; /* XXX */
1292 if (waitfor != MNT_WAIT)
1293 bawrite(bp);
1294 else if ((error = bwrite(bp)) != 0)
1295 allerror = error;
1296 return (allerror);
1297}