]> git.saurik.com Git - apple/xnu.git/blame - bsd/ufs/ffs/ffs_vfsops.c
xnu-517.tar.gz
[apple/xnu.git] / bsd / ufs / ffs / ffs_vfsops.c
CommitLineData
1c79356b 1/*
55e303ae 2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
1c79356b
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
43866e37 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
43866e37
A
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
43866e37
A
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
1c79356b
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
26/*
27 * Copyright (c) 1989, 1991, 1993, 1994
28 * The Regents of the University of California. All rights reserved.
29 *
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
32 * are met:
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed by the University of
41 * California, Berkeley and its contributors.
42 * 4. Neither the name of the University nor the names of its contributors
43 * may be used to endorse or promote products derived from this software
44 * without specific prior written permission.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * SUCH DAMAGE.
57 *
58 * @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95
59 */
60
61#include <rev_endian_fs.h>
62#include <sys/param.h>
63#include <sys/systm.h>
64#include <sys/namei.h>
65#include <sys/proc.h>
66#include <sys/kernel.h>
67#include <sys/vnode.h>
68#include <sys/socket.h>
69#include <sys/mount.h>
70#include <sys/buf.h>
71#include <sys/mbuf.h>
72#include <sys/file.h>
55e303ae 73#include <sys/disk.h>
1c79356b
A
74#include <sys/ioctl.h>
75#include <sys/errno.h>
76#include <sys/malloc.h>
77#include <sys/ubc.h>
9bccf70c 78#include <sys/quota.h>
1c79356b
A
79
80#include <miscfs/specfs/specdev.h>
81
82#include <ufs/ufs/quota.h>
83#include <ufs/ufs/ufsmount.h>
84#include <ufs/ufs/inode.h>
85#include <ufs/ufs/ufs_extern.h>
86
87#include <ufs/ffs/fs.h>
88#include <ufs/ffs/ffs_extern.h>
89#if REV_ENDIAN_FS
90#include <ufs/ufs/ufs_byte_order.h>
91#include <architecture/byte_order.h>
92#endif /* REV_ENDIAN_FS */
93
94int ffs_sbupdate __P((struct ufsmount *, int));
95
96struct vfsops ufs_vfsops = {
97 ffs_mount,
98 ufs_start,
99 ffs_unmount,
100 ufs_root,
101 ufs_quotactl,
102 ffs_statfs,
103 ffs_sync,
104 ffs_vget,
105 ffs_fhtovp,
106 ffs_vptofh,
107 ffs_init,
108 ffs_sysctl,
109};
110
111extern u_long nextgennumber;
112
113/*
114 * Called by main() when ufs is going to be mounted as root.
115 */
116ffs_mountroot()
117{
118 extern struct vnode *rootvp;
119 struct fs *fs;
120 struct mount *mp;
121 struct proc *p = current_proc(); /* XXX */
122 struct ufsmount *ump;
123 u_int size;
124 int error;
125
126 /*
127 * Get vnode for rootdev.
128 */
129 if (error = bdevvp(rootdev, &rootvp)) {
130 printf("ffs_mountroot: can't setup bdevvp");
131 return (error);
132 }
9bccf70c
A
133 if (error = vfs_rootmountalloc("ufs", "root_device", &mp)) {
134 vrele(rootvp); /* release the reference from bdevvp() */
1c79356b 135 return (error);
9bccf70c 136 }
1c79356b
A
137
138 /* Must set the MNT_ROOTFS flag before doing the actual mount */
139 mp->mnt_flag |= MNT_ROOTFS;
140
55e303ae
A
141 /* Set asynchronous flag by default */
142 mp->mnt_flag |= MNT_ASYNC;
143
1c79356b
A
144 if (error = ffs_mountfs(rootvp, mp, p)) {
145 mp->mnt_vfc->vfc_refcount--;
55e303ae
A
146
147 if (mp->mnt_kern_flag & MNTK_IO_XINFO)
148 FREE(mp->mnt_xinfo_ptr, M_TEMP);
1c79356b 149 vfs_unbusy(mp, p);
55e303ae 150
9bccf70c 151 vrele(rootvp); /* release the reference from bdevvp() */
55e303ae 152 FREE_ZONE(mp, sizeof (struct mount), M_MOUNT);
1c79356b
A
153 return (error);
154 }
155 simple_lock(&mountlist_slock);
156 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
157 simple_unlock(&mountlist_slock);
158 ump = VFSTOUFS(mp);
159 fs = ump->um_fs;
160 (void) copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0);
161 (void)ffs_statfs(mp, &mp->mnt_stat, p);
162 vfs_unbusy(mp, p);
163 inittodr(fs->fs_time);
164 return (0);
165}
166
167/*
168 * VFS Operations.
169 *
170 * mount system call
171 */
172int
173ffs_mount(mp, path, data, ndp, p)
174 register struct mount *mp;
175 char *path;
176 caddr_t data;
177 struct nameidata *ndp;
178 struct proc *p;
179{
180 struct vnode *devvp;
181 struct ufs_args args;
182 struct ufsmount *ump;
183 register struct fs *fs;
184 u_int size;
185 int error, flags;
186 mode_t accessmode;
187 int ronly;
188 int reload = 0;
189
190 if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
191 return (error);
192 /*
193 * If updating, check whether changing from read-only to
194 * read/write; if there is no device name, that's all we do.
195 */
196 if (mp->mnt_flag & MNT_UPDATE) {
197 ump = VFSTOUFS(mp);
198 fs = ump->um_fs;
199 if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
200 flags = WRITECLOSE;
201 if (mp->mnt_flag & MNT_FORCE)
202 flags |= FORCECLOSE;
203 if (error = ffs_flushfiles(mp, flags, p))
204 return (error);
205 fs->fs_clean = 1;
206 fs->fs_ronly = 1;
207 if (error = ffs_sbupdate(ump, MNT_WAIT)) {
208 fs->fs_clean = 0;
209 fs->fs_ronly = 0;
210 return (error);
211 }
212 }
213 /* save fs_ronly to later use */
214 ronly = fs->fs_ronly;
215 if ((mp->mnt_flag & MNT_RELOAD) || ronly)
216 reload = 1;
217 if ((reload) &&
218 (error = ffs_reload(mp, ndp->ni_cnd.cn_cred, p)))
219 return (error);
220 /* replace the ronly after load */
221 fs->fs_ronly = ronly;
222 /*
223 * Do not update the file system if the user was in singleuser
224 * and then tries to mount -uw without fscking
225 */
226 if (!fs->fs_clean && ronly) {
227 printf("WARNING: trying to mount a dirty file system\n");
228 if (issingleuser() && (mp->mnt_flag & MNT_ROOTFS)) {
229 printf("WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n",fs->fs_fsmnt);
230 /*
231 * Reset the readonly bit as reload might have
232 * modified this bit
233 */
234 fs->fs_ronly = 1;
235 return(EPERM);
236 }
237 }
238
239 if (ronly && (mp->mnt_kern_flag & MNTK_WANTRDWR)) {
240 /*
241 * If upgrade to read-write by non-root, then verify
242 * that user has necessary permissions on the device.
243 */
244 if (p->p_ucred->cr_uid != 0) {
245 devvp = ump->um_devvp;
246 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
247 if (error = VOP_ACCESS(devvp, VREAD | VWRITE,
248 p->p_ucred, p)) {
249 VOP_UNLOCK(devvp, 0, p);
250 return (error);
251 }
252 VOP_UNLOCK(devvp, 0, p);
253 }
254 fs->fs_ronly = 0;
255 fs->fs_clean = 0;
256 (void) ffs_sbupdate(ump, MNT_WAIT);
257 }
258 if (args.fspec == 0) {
259 /*
260 * Process export requests.
261 */
262 return (vfs_export(mp, &ump->um_export, &args.export));
263 }
264 }
265 /*
266 * Not an update, or updating the name: look up the name
267 * and verify that it refers to a sensible block device.
268 */
269 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
270 if (error = namei(ndp))
271 return (error);
272 devvp = ndp->ni_vp;
273
274 if (devvp->v_type != VBLK) {
275 vrele(devvp);
276 return (ENOTBLK);
277 }
278 if (major(devvp->v_rdev) >= nblkdev) {
279 vrele(devvp);
280 return (ENXIO);
281 }
282 /*
283 * If mount by non-root, then verify that user has necessary
284 * permissions on the device.
285 */
286 if (p->p_ucred->cr_uid != 0) {
287 accessmode = VREAD;
288 if ((mp->mnt_flag & MNT_RDONLY) == 0)
289 accessmode |= VWRITE;
290 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
291 if (error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) {
292 vput(devvp);
293 return (error);
294 }
295 VOP_UNLOCK(devvp, 0, p);
296 }
297 if ((mp->mnt_flag & MNT_UPDATE) == 0)
298 error = ffs_mountfs(devvp, mp, p);
299 else {
300 if (devvp != ump->um_devvp)
301 error = EINVAL; /* needs translation */
302 else
303 vrele(devvp);
304 }
305 if (error) {
306 vrele(devvp);
307 return (error);
308 }
309 ump = VFSTOUFS(mp);
310 fs = ump->um_fs;
55e303ae
A
311 (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1,
312 (size_t *)&size);
1c79356b
A
313 bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
314 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
315 MNAMELEN);
316 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
55e303ae 317 (size_t *)&size);
1c79356b
A
318 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
319 (void)ffs_statfs(mp, &mp->mnt_stat, p);
320 return (0);
321}
322
323/*
324 * Reload all incore data for a filesystem (used after running fsck on
325 * the root filesystem and finding things to fix). The filesystem must
326 * be mounted read-only.
327 *
328 * Things to do to update the mount:
329 * 1) invalidate all cached meta-data.
330 * 2) re-read superblock from disk.
331 * 3) re-read summary information from disk.
332 * 4) invalidate all inactive vnodes.
333 * 5) invalidate all cached file data.
334 * 6) re-read inode data for all active vnodes.
335 */
336ffs_reload(mountp, cred, p)
337 register struct mount *mountp;
338 struct ucred *cred;
339 struct proc *p;
340{
341 register struct vnode *vp, *nvp, *devvp;
342 struct inode *ip;
9bccf70c 343 void *space;
1c79356b
A
344 struct buf *bp;
345 struct fs *fs, *newfs;
346 int i, blks, size, error;
0b4e3aa0 347 u_int64_t maxfilesize; /* XXX */
1c79356b
A
348 int32_t *lp;
349#if REV_ENDIAN_FS
350 int rev_endian = (mountp->mnt_flag & MNT_REVEND);
351#endif /* REV_ENDIAN_FS */
352
353 if ((mountp->mnt_flag & MNT_RDONLY) == 0)
354 return (EINVAL);
355 /*
356 * Step 1: invalidate all cached meta-data.
357 */
358 devvp = VFSTOUFS(mountp)->um_devvp;
359 if (vinvalbuf(devvp, 0, cred, p, 0, 0))
360 panic("ffs_reload: dirty1");
361 /*
362 * Step 2: re-read superblock from disk.
363 */
364 VOP_DEVBLOCKSIZE(devvp,&size);
365
366 if (error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, NOCRED,&bp)) {
367 brelse(bp);
368 return (error);
369 }
370 newfs = (struct fs *)bp->b_data;
371#if REV_ENDIAN_FS
372 if (rev_endian) {
373 byte_swap_sbin(newfs);
374 }
375#endif /* REV_ENDIAN_FS */
376 if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE ||
377 newfs->fs_bsize < sizeof(struct fs)) {
378#if REV_ENDIAN_FS
379 if (rev_endian)
380 byte_swap_sbout(newfs);
381#endif /* REV_ENDIAN_FS */
382
383 brelse(bp);
384 return (EIO); /* XXX needs translation */
385 }
386 fs = VFSTOUFS(mountp)->um_fs;
387 /*
388 * Copy pointer fields back into superblock before copying in XXX
389 * new superblock. These should really be in the ufsmount. XXX
390 * Note that important parameters (eg fs_ncg) are unchanged.
391 */
9bccf70c 392 newfs->fs_csp = fs->fs_csp;
1c79356b 393 newfs->fs_maxcluster = fs->fs_maxcluster;
55e303ae 394 newfs->fs_contigdirs = fs->fs_contigdirs;
1c79356b
A
395 bcopy(newfs, fs, (u_int)fs->fs_sbsize);
396 if (fs->fs_sbsize < SBSIZE)
397 bp->b_flags |= B_INVAL;
398#if REV_ENDIAN_FS
399 if (rev_endian)
400 byte_swap_sbout(newfs);
401#endif /* REV_ENDIAN_FS */
402 brelse(bp);
403 mountp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
404 ffs_oldfscompat(fs);
55e303ae 405 maxfilesize = 0x100000000ULL; /* 4GB */
0b4e3aa0
A
406 if (fs->fs_maxfilesize > maxfilesize) /* XXX */
407 fs->fs_maxfilesize = maxfilesize; /* XXX */
1c79356b
A
408 /*
409 * Step 3: re-read summary information from disk.
410 */
411 blks = howmany(fs->fs_cssize, fs->fs_fsize);
9bccf70c 412 space = fs->fs_csp;
1c79356b
A
413 for (i = 0; i < blks; i += fs->fs_frag) {
414 size = fs->fs_bsize;
415 if (i + fs->fs_frag > blks)
416 size = (blks - i) * fs->fs_fsize;
417 if (error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
418 NOCRED, &bp)) {
419 brelse(bp);
420 return (error);
421 }
422#if REV_ENDIAN_FS
423 if (rev_endian) {
424 /* csum swaps */
425 byte_swap_ints((int *)bp->b_data, size / sizeof(int));
426 }
427#endif /* REV_ENDIAN_FS */
9bccf70c 428 bcopy(bp->b_data, space, (u_int)size);
1c79356b
A
429#if REV_ENDIAN_FS
430 if (rev_endian) {
431 /* csum swaps */
432 byte_swap_ints((int *)bp->b_data, size / sizeof(int));
433 }
434#endif /* REV_ENDIAN_FS */
55e303ae 435 space = (char *) space + size;
1c79356b
A
436 brelse(bp);
437 }
438 /*
439 * We no longer know anything about clusters per cylinder group.
440 */
441 if (fs->fs_contigsumsize > 0) {
442 lp = fs->fs_maxcluster;
443 for (i = 0; i < fs->fs_ncg; i++)
444 *lp++ = fs->fs_contigsumsize;
445 }
446
447loop:
448 simple_lock(&mntvnode_slock);
449 for (vp = mountp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
450 if (vp->v_mount != mountp) {
451 simple_unlock(&mntvnode_slock);
452 goto loop;
453 }
454 nvp = vp->v_mntvnodes.le_next;
455 /*
456 * Step 4: invalidate all inactive vnodes.
457 */
458 if (vrecycle(vp, &mntvnode_slock, p))
459 goto loop;
460 /*
461 * Step 5: invalidate all cached file data.
462 */
463 simple_lock(&vp->v_interlock);
464 simple_unlock(&mntvnode_slock);
465 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) {
466 goto loop;
467 }
468 if (vinvalbuf(vp, 0, cred, p, 0, 0))
469 panic("ffs_reload: dirty2");
470 /*
471 * Step 6: re-read inode data for all active vnodes.
472 */
473 ip = VTOI(vp);
474 if (error =
475 bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
476 (int)fs->fs_bsize, NOCRED, &bp)) {
477 brelse(bp);
478 vput(vp);
479 return (error);
480 }
481#if REV_ENDIAN_FS
482 if (rev_endian) {
483 byte_swap_inode_in(((struct dinode *)bp->b_data +
484 ino_to_fsbo(fs, ip->i_number)), ip);
485 } else {
486#endif /* REV_ENDIAN_FS */
487 ip->i_din = *((struct dinode *)bp->b_data +
488 ino_to_fsbo(fs, ip->i_number));
489#if REV_ENDIAN_FS
490 }
491#endif /* REV_ENDIAN_FS */
492 brelse(bp);
493 vput(vp);
494 simple_lock(&mntvnode_slock);
495 }
496 simple_unlock(&mntvnode_slock);
497 return (0);
498}
499
500/*
501 * Common code for mount and mountroot
502 */
503int
504ffs_mountfs(devvp, mp, p)
505 register struct vnode *devvp;
506 struct mount *mp;
507 struct proc *p;
508{
509 register struct ufsmount *ump;
510 struct buf *bp;
511 register struct fs *fs;
512 dev_t dev;
513 struct buf *cgbp;
514 struct cg *cgp;
515 int32_t clustersumoff;
9bccf70c 516 void *space;
1c79356b
A
517 int error, i, blks, size, ronly;
518 int32_t *lp;
519 struct ucred *cred;
520 extern struct vnode *rootvp;
521 u_int64_t maxfilesize; /* XXX */
522 u_int dbsize = DEV_BSIZE;
523#if REV_ENDIAN_FS
524 int rev_endian=0;
525#endif /* REV_ENDIAN_FS */
526 dev = devvp->v_rdev;
527 cred = p ? p->p_ucred : NOCRED;
528 /*
529 * Disallow multiple mounts of the same device.
530 * Disallow mounting of a device that is currently in use
531 * (except for root, which might share swap device for miniroot).
532 * Flush out any old buffers remaining from a previous use.
533 */
534 if (error = vfs_mountedon(devvp))
535 return (error);
536 if (vcount(devvp) > 1 && devvp != rootvp)
537 return (EBUSY);
538 if (error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0))
539 return (error);
540
541 ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
542 if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p))
543 return (error);
544
545 VOP_DEVBLOCKSIZE(devvp,&size);
546
547 bp = NULL;
548 ump = NULL;
549 if (error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, cred, &bp))
550 goto out;
551 fs = (struct fs *)bp->b_data;
552#if REV_ENDIAN_FS
553 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
554 fs->fs_bsize < sizeof(struct fs)) {
555 int magic = fs->fs_magic;
556
557 byte_swap_ints(&magic, 1);
558 if (magic != FS_MAGIC) {
559 error = EINVAL;
560 goto out;
561 }
562 byte_swap_sbin(fs);
563 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
564 fs->fs_bsize < sizeof(struct fs)) {
565 byte_swap_sbout(fs);
566 error = EINVAL; /* XXX needs translation */
567 goto out;
568 }
569 rev_endian=1;
570 }
571#endif /* REV_ENDIAN_FS */
572 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
573 fs->fs_bsize < sizeof(struct fs)) {
574#if REV_ENDIAN_FS
575 if (rev_endian)
576 byte_swap_sbout(fs);
577#endif /* REV_ENDIAN_FS */
578 error = EINVAL; /* XXX needs translation */
579 goto out;
580 }
581
582
583 /*
584 * Buffer cache does not handle multiple pages in a buf when
585 * invalidating incore buffer in pageout. There are no locks
586 * in the pageout path. So there is a danger of loosing data when
587 * block allocation happens at the same time a pageout of buddy
588 * page occurs. incore() returns buf with both
589 * pages, this leads vnode-pageout to incorrectly flush of entire.
590 * buf. Till the low level ffs code is modified to deal with these
591 * do not mount any FS more than 4K size.
592 */
593 /*
594 * Can't mount filesystems with a fragment size less than DIRBLKSIZ
595 */
596 /*
597 * Don't mount dirty filesystems, except for the root filesystem
598 */
599 if ((fs->fs_bsize > PAGE_SIZE) || (fs->fs_fsize < DIRBLKSIZ) ||
600 ((!(mp->mnt_flag & MNT_ROOTFS)) && (!fs->fs_clean))) {
601#if REV_ENDIAN_FS
602 if (rev_endian)
603 byte_swap_sbout(fs);
604#endif /* REV_ENDIAN_FS */
605 error = ENOTSUP;
606 goto out;
607 }
608
609 /* Let's figure out the devblock size the file system is with */
610 /* the device block size = fragment size / number of sectors per frag */
611
612 dbsize = fs->fs_fsize / NSPF(fs);
613 if(dbsize <= 0 ) {
614 kprintf("device blocksize computaion failed\n");
55e303ae
A
615 } else {
616 if (VOP_IOCTL(devvp, DKIOCSETBLOCKSIZE, (caddr_t)&dbsize,
617 FWRITE, NOCRED, p) != 0) {
1c79356b 618 kprintf("failed to set device blocksize\n");
55e303ae 619 }
1c79356b
A
620 /* force the specfs to reread blocksize from size() */
621 set_fsblocksize(devvp);
55e303ae 622 }
1c79356b 623
0b4e3aa0
A
624 /* cache the IO attributes */
625 error = vfs_init_io_attributes(devvp, mp);
626 if (error) {
627 printf("ffs_mountfs: vfs_init_io_attributes returned %d\n",
628 error);
629 goto out;
630 }
1c79356b
A
631
632 /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */
633 if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) {
634#if REV_ENDIAN_FS
635 if (rev_endian)
636 byte_swap_sbout(fs);
637#endif /* REV_ENDIAN_FS */
638 error = EROFS; /* needs translation */
639 goto out;
640 }
641
642 /* If we are not mounting read only, then check for overlap
643 * condition in cylinder group's free block map.
644 * If overlap exists, then force this into a read only mount
645 * to avoid further corruption. PR#2216969
646 */
647 if (ronly == 0){
648 if (error = bread (devvp, fsbtodb(fs, cgtod(fs, 0)),
649 (int)fs->fs_cgsize, NOCRED, &cgbp)) {
650 brelse(cgbp);
651 goto out;
652 }
653 cgp = (struct cg *)cgbp->b_data;
654#if REV_ENDIAN_FS
655 if (rev_endian)
656 byte_swap_cgin(cgp,fs);
657#endif /* REV_ENDIAN_FS */
658 if (!cg_chkmagic(cgp)){
659#if REV_ENDIAN_FS
660 if (rev_endian)
661 byte_swap_cgout(cgp,fs);
662#endif /* REV_ENDIAN_FS */
663 brelse(cgbp);
664 goto out;
665 }
666 if (cgp->cg_clustersumoff != 0) {
667 /* Check for overlap */
668 clustersumoff = cgp->cg_freeoff +
669 howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY);
670 clustersumoff = roundup(clustersumoff, sizeof(long));
671 if (cgp->cg_clustersumoff < clustersumoff) {
672 /* Overlap exists */
673 mp->mnt_flag |= MNT_RDONLY;
674 ronly = 1;
675 }
676 }
677#if REV_ENDIAN_FS
678 if (rev_endian)
679 byte_swap_cgout(cgp,fs);
680#endif /* REV_ENDIAN_FS */
681 brelse(cgbp);
682 }
683
684 ump = _MALLOC(sizeof *ump, M_UFSMNT, M_WAITOK);
685 bzero((caddr_t)ump, sizeof *ump);
686 ump->um_fs = _MALLOC((u_long)fs->fs_sbsize, M_UFSMNT,
687 M_WAITOK);
688 bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize);
689 if (fs->fs_sbsize < SBSIZE)
690 bp->b_flags |= B_INVAL;
691#if REV_ENDIAN_FS
692 if (rev_endian)
693 byte_swap_sbout(fs);
694#endif /* REV_ENDIAN_FS */
695 brelse(bp);
696 bp = NULL;
697 fs = ump->um_fs;
698 fs->fs_ronly = ronly;
699 size = fs->fs_cssize;
700 blks = howmany(size, fs->fs_fsize);
701 if (fs->fs_contigsumsize > 0)
702 size += fs->fs_ncg * sizeof(int32_t);
55e303ae 703 size += fs->fs_ncg * sizeof(u_int8_t);
9bccf70c
A
704 space = _MALLOC((u_long)size, M_UFSMNT, M_WAITOK);
705 fs->fs_csp = space;
1c79356b
A
706 for (i = 0; i < blks; i += fs->fs_frag) {
707 size = fs->fs_bsize;
708 if (i + fs->fs_frag > blks)
709 size = (blks - i) * fs->fs_fsize;
710 if (error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
711 cred, &bp)) {
9bccf70c 712 _FREE(fs->fs_csp, M_UFSMNT);
1c79356b
A
713 goto out;
714 }
715 bcopy(bp->b_data, space, (u_int)size);
716#if REV_ENDIAN_FS
717 if (rev_endian)
718 byte_swap_ints((int *) space, size / sizeof(int));
719#endif /* REV_ENDIAN_FS */
9bccf70c 720 space = (char *)space + size;
1c79356b
A
721 brelse(bp);
722 bp = NULL;
723 }
724 if (fs->fs_contigsumsize > 0) {
9bccf70c 725 fs->fs_maxcluster = lp = space;
1c79356b
A
726 for (i = 0; i < fs->fs_ncg; i++)
727 *lp++ = fs->fs_contigsumsize;
55e303ae 728 space = lp;
1c79356b 729 }
55e303ae
A
730 size = fs->fs_ncg * sizeof(u_int8_t);
731 fs->fs_contigdirs = (u_int8_t *)space;
732 space = (u_int8_t *)space + size;
733 bzero(fs->fs_contigdirs, size);
734 /* XXX Compatibility for old filesystems */
735 if (fs->fs_avgfilesize <= 0)
736 fs->fs_avgfilesize = AVFILESIZ;
737 if (fs->fs_avgfpdir <= 0)
738 fs->fs_avgfpdir = AFPDIR;
739 /* XXX End of compatibility */
1c79356b
A
740 mp->mnt_data = (qaddr_t)ump;
741 mp->mnt_stat.f_fsid.val[0] = (long)dev;
742 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
55e303ae 743 /* XXX warning hardcoded max symlen and not "mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;" */
1c79356b
A
744 mp->mnt_maxsymlinklen = 60;
745#if REV_ENDIAN_FS
746 if (rev_endian)
747 mp->mnt_flag |= MNT_REVEND;
748#endif /* REV_ENDIAN_FS */
749 ump->um_mountp = mp;
750 ump->um_dev = dev;
751 ump->um_devvp = devvp;
752 ump->um_nindir = fs->fs_nindir;
753 ump->um_bptrtodb = fs->fs_fsbtodb;
754 ump->um_seqinc = fs->fs_frag;
755 for (i = 0; i < MAXQUOTAS; i++)
9bccf70c 756 ump->um_qfiles[i].qf_vp = NULLVP;
1c79356b
A
757 devvp->v_specflags |= SI_MOUNTEDON;
758 ffs_oldfscompat(fs);
759 ump->um_savedmaxfilesize = fs->fs_maxfilesize; /* XXX */
55e303ae 760 maxfilesize = 0x100000000ULL; /* 4GB */
1c79356b
A
761#if 0
762 maxfilesize = (u_int64_t)0x40000000 * fs->fs_bsize - 1; /* XXX */
763#endif /* 0 */
764 if (fs->fs_maxfilesize > maxfilesize) /* XXX */
765 fs->fs_maxfilesize = maxfilesize; /* XXX */
766 if (ronly == 0) {
767 fs->fs_clean = 0;
768 (void) ffs_sbupdate(ump, MNT_WAIT);
769 }
770 return (0);
771out:
772 if (bp)
773 brelse(bp);
774 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
775 if (ump) {
776 _FREE(ump->um_fs, M_UFSMNT);
777 _FREE(ump, M_UFSMNT);
778 mp->mnt_data = (qaddr_t)0;
779 }
780 return (error);
781}
782
783/*
784 * Sanity checks for old file systems.
785 *
786 * XXX - goes away some day.
787 */
788ffs_oldfscompat(fs)
789 struct fs *fs;
790{
791 int i;
792
793 fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */
794 fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */
795 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
796 fs->fs_nrpos = 8; /* XXX */
797 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
798 u_int64_t sizepb = fs->fs_bsize; /* XXX */
799 /* XXX */
800 fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
801 for (i = 0; i < NIADDR; i++) { /* XXX */
802 sizepb *= NINDIR(fs); /* XXX */
803 fs->fs_maxfilesize += sizepb; /* XXX */
804 } /* XXX */
805 fs->fs_qbmask = ~fs->fs_bmask; /* XXX */
806 fs->fs_qfmask = ~fs->fs_fmask; /* XXX */
807 } /* XXX */
808 return (0);
809}
810
811/*
812 * unmount system call
813 */
814int
815ffs_unmount(mp, mntflags, p)
816 struct mount *mp;
817 int mntflags;
818 struct proc *p;
819{
820 register struct ufsmount *ump;
821 register struct fs *fs;
822 int error, flags;
9bccf70c
A
823 int force;
824
1c79356b 825 flags = 0;
9bccf70c
A
826 force = 0;
827 if (mntflags & MNT_FORCE) {
1c79356b 828 flags |= FORCECLOSE;
9bccf70c
A
829 force = 1;
830 }
831 if ( (error = ffs_flushfiles(mp, flags, p)) && !force )
1c79356b
A
832 return (error);
833 ump = VFSTOUFS(mp);
834 fs = ump->um_fs;
835 if (fs->fs_ronly == 0) {
836 fs->fs_clean = 1;
837 if (error = ffs_sbupdate(ump, MNT_WAIT)) {
838 fs->fs_clean = 0;
839#ifdef notyet
840 /* we can atleast cleanup ; as the media could be WP */
841 /* & during mount, we do not check for write failures */
842 /* FIXME LATER : the Correct fix would be to have */
843 /* mount detect the WP media and downgrade to readonly mount */
844 /* For now, here it is */
845 return (error);
846#endif /* notyet */
847 }
848 }
849 ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
850 error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
851 NOCRED, p);
9bccf70c
A
852 if (error && !force)
853 return (error);
1c79356b
A
854 vrele(ump->um_devvp);
855
9bccf70c 856 _FREE(fs->fs_csp, M_UFSMNT);
1c79356b
A
857 _FREE(fs, M_UFSMNT);
858 _FREE(ump, M_UFSMNT);
859 mp->mnt_data = (qaddr_t)0;
860#if REV_ENDIAN_FS
861 mp->mnt_flag &= ~MNT_REVEND;
862#endif /* REV_ENDIAN_FS */
9bccf70c 863 return (0);
1c79356b
A
864}
865
866/*
867 * Flush out all the files in a filesystem.
868 */
869ffs_flushfiles(mp, flags, p)
870 register struct mount *mp;
871 int flags;
872 struct proc *p;
873{
874 register struct ufsmount *ump;
875 int i, error;
876
877 ump = VFSTOUFS(mp);
55e303ae 878
1c79356b 879#if QUOTA
55e303ae
A
880 /*
881 * NOTE: The open quota files have an indirect reference
882 * on the root directory vnode. We must account for this
883 * extra reference when doing the intial vflush.
884 */
1c79356b 885 if (mp->mnt_flag & MNT_QUOTA) {
55e303ae
A
886 struct vnode *rootvp = NULLVP;
887 int quotafilecnt = 0;
888
889 /* Find out how many quota files we have open. */
890 for (i = 0; i < MAXQUOTAS; i++) {
891 if (ump->um_qfiles[i].qf_vp != NULLVP)
892 ++quotafilecnt;
893 }
894
895 /*
896 * Check if the root vnode is in our inode hash
897 * (so we can skip over it).
898 */
899 rootvp = ufs_ihashget(ump->um_dev, ROOTINO);
900
901 error = vflush(mp, rootvp, SKIPSYSTEM|flags);
902
903 if (rootvp) {
904 /*
905 * See if there are additional references on the
906 * root vp besides the ones obtained from the open
907 * quota files and the hfs_chashget call above.
908 */
909 if ((error == 0) &&
910 (rootvp->v_usecount > (1 + quotafilecnt))) {
911 error = EBUSY; /* root dir is still open */
912 }
913 vput(rootvp);
914 }
915 if (error && (flags & FORCECLOSE) == 0)
1c79356b 916 return (error);
55e303ae 917
1c79356b 918 for (i = 0; i < MAXQUOTAS; i++) {
9bccf70c 919 if (ump->um_qfiles[i].qf_vp == NULLVP)
1c79356b
A
920 continue;
921 quotaoff(p, mp, i);
922 }
923 /*
924 * Here we fall through to vflush again to ensure
925 * that we have gotten rid of all the system vnodes.
926 */
927 }
928#endif
929 error = vflush(mp, NULLVP, SKIPSWAP|flags);
930 error = vflush(mp, NULLVP, flags);
931 return (error);
932}
933
934/*
935 * Get file system statistics.
936 */
937int
938ffs_statfs(mp, sbp, p)
939 struct mount *mp;
940 register struct statfs *sbp;
941 struct proc *p;
942{
943 register struct ufsmount *ump;
944 register struct fs *fs;
945
946 ump = VFSTOUFS(mp);
947 fs = ump->um_fs;
948 if (fs->fs_magic != FS_MAGIC)
949 panic("ffs_statfs");
950 sbp->f_bsize = fs->fs_fsize;
951 sbp->f_iosize = fs->fs_bsize;
952 sbp->f_blocks = fs->fs_dsize;
953 sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
954 fs->fs_cstotal.cs_nffree;
955 sbp->f_bavail = freespace(fs, fs->fs_minfree);
956 sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
957 sbp->f_ffree = fs->fs_cstotal.cs_nifree;
958 if (sbp != &mp->mnt_stat) {
959 sbp->f_type = mp->mnt_vfc->vfc_typenum;
960 bcopy((caddr_t)mp->mnt_stat.f_mntonname,
961 (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
962 bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
963 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
964 }
965 return (0);
966}
967
968/*
969 * Go through the disk queues to initiate sandbagged IO;
970 * go through the inodes to write those that have been modified;
971 * initiate the writing of the super block if it has been modified.
972 *
973 * Note: we are always called with the filesystem marked `MPBUSY'.
974 */
975int
976ffs_sync(mp, waitfor, cred, p)
977 struct mount *mp;
978 int waitfor;
979 struct ucred *cred;
980 struct proc *p;
981{
982 struct vnode *nvp, *vp;
983 struct inode *ip;
984 struct ufsmount *ump = VFSTOUFS(mp);
985 struct fs *fs;
986 int error, allerror = 0;
987
988 fs = ump->um_fs;
989 if (fs->fs_fmod != 0 && fs->fs_ronly != 0) { /* XXX */
990 printf("fs = %s\n", fs->fs_fsmnt);
991 panic("update: rofs mod");
992 }
993 /*
994 * Write back each (modified) inode.
995 */
996 simple_lock(&mntvnode_slock);
997loop:
998 for (vp = mp->mnt_vnodelist.lh_first;
999 vp != NULL;
1000 vp = nvp) {
0b4e3aa0
A
1001 int didhold = 0;
1002
1c79356b
A
1003 /*
1004 * If the vnode that we are about to sync is no longer
1005 * associated with this mount point, start over.
1006 */
1007 if (vp->v_mount != mp)
1008 goto loop;
1009 simple_lock(&vp->v_interlock);
1010 nvp = vp->v_mntvnodes.le_next;
1011 ip = VTOI(vp);
55e303ae
A
1012
1013 // restart our whole search if this guy is locked
1014 // or being reclaimed.
1015 if (ip == NULL || vp->v_flag & (VXLOCK|VORECLAIM)) {
1016 simple_unlock(&vp->v_interlock);
1017 continue;
1018 }
1019
1c79356b
A
1020 if ((vp->v_type == VNON) ||
1021 ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
1022 vp->v_dirtyblkhd.lh_first == NULL && !(vp->v_flag & VHASDIRTY))) {
1023 simple_unlock(&vp->v_interlock);
1024 continue;
1025 }
1026 simple_unlock(&mntvnode_slock);
1027 error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p);
1028 if (error) {
1029 simple_lock(&mntvnode_slock);
1030 if (error == ENOENT)
1031 goto loop;
1032 continue;
1033 }
0b4e3aa0 1034 didhold = ubc_hold(vp);
1c79356b
A
1035 if (error = VOP_FSYNC(vp, cred, waitfor, p))
1036 allerror = error;
1037 VOP_UNLOCK(vp, 0, p);
0b4e3aa0
A
1038 if (didhold)
1039 ubc_rele(vp);
1c79356b
A
1040 vrele(vp);
1041 simple_lock(&mntvnode_slock);
1042 }
1043 simple_unlock(&mntvnode_slock);
1044 /*
1045 * Force stale file system control information to be flushed.
1046 */
1047 if (error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p))
1048 allerror = error;
1049#if QUOTA
1050 qsync(mp);
1051#endif
1052 /*
1053 * Write back modified superblock.
1054 */
1055 if (fs->fs_fmod != 0) {
1056 fs->fs_fmod = 0;
1057 fs->fs_time = time.tv_sec;
1058 if (error = ffs_sbupdate(ump, waitfor))
1059 allerror = error;
1060 }
1061 return (allerror);
1062}
1063
1064/*
1065 * Look up a FFS dinode number to find its incore vnode, otherwise read it
1066 * in from disk. If it is in core, wait for the lock bit to clear, then
1067 * return the inode locked. Detection and handling of mount points must be
1068 * done by the calling routine.
1069 */
1070int
55e303ae 1071ffs_vget(mp, inop, vpp)
1c79356b 1072 struct mount *mp;
55e303ae 1073 void *inop;
1c79356b
A
1074 struct vnode **vpp;
1075{
1076 struct proc *p = current_proc(); /* XXX */
1077 struct fs *fs;
1078 struct inode *ip;
1079 struct ufsmount *ump;
1080 struct buf *bp;
1081 struct vnode *vp;
55e303ae 1082 ino_t ino;
1c79356b 1083 dev_t dev;
55e303ae 1084 int i, type, error = 0;
1c79356b 1085
55e303ae 1086 ino = (ino_t) inop;
1c79356b
A
1087 ump = VFSTOUFS(mp);
1088 dev = ump->um_dev;
1089
1090 /* Check for unmount in progress */
1091 if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
1092 *vpp = NULL;
1093 return (EPERM);
1094 }
1095
55e303ae 1096 /* check in the inode hash */
1c79356b
A
1097 if ((*vpp = ufs_ihashget(dev, ino)) != NULL) {
1098 vp = *vpp;
1099 UBCINFOCHECK("ffs_vget", vp);
1100 return (0);
1101 }
55e303ae
A
1102
1103 /*
1104 * Not in inode hash.
1105 * Allocate a new vnode/inode.
1106 */
1c79356b
A
1107 type = ump->um_devvp->v_tag == VT_MFS ? M_MFSNODE : M_FFSNODE; /* XXX */
1108 MALLOC_ZONE(ip, struct inode *, sizeof(struct inode), type, M_WAITOK);
1c79356b
A
1109 bzero((caddr_t)ip, sizeof(struct inode));
1110 lockinit(&ip->i_lock, PINOD, "inode", 0, 0);
7b1edb79
A
1111 /* lock the inode */
1112 lockmgr(&ip->i_lock, LK_EXCLUSIVE, (struct slock *)0, p);
1113
1c79356b
A
1114 ip->i_fs = fs = ump->um_fs;
1115 ip->i_dev = dev;
1116 ip->i_number = ino;
55e303ae 1117 SET(ip->i_flag, IN_ALLOC);
1c79356b
A
1118#if QUOTA
1119 for (i = 0; i < MAXQUOTAS; i++)
1120 ip->i_dquot[i] = NODQUOT;
1121#endif
7b1edb79 1122
1c79356b 1123 /*
55e303ae 1124 * We could have blocked in MALLOC_ZONE. Check for the race.
7b1edb79
A
1125 */
1126 if ((*vpp = ufs_ihashget(dev, ino)) != NULL) {
55e303ae 1127 /* lost the race, clean up */
7b1edb79
A
1128 FREE_ZONE(ip, sizeof(struct inode), type);
1129 vp = *vpp;
1130 UBCINFOCHECK("ffs_vget", vp);
1131 return (0);
1132 }
1133
1134 /*
1135 * Put it onto its hash chain locked so that other requests for
1c79356b
A
1136 * this inode will block if they arrive while we are sleeping waiting
1137 * for old data structures to be purged or for the contents of the
1138 * disk portion of this inode to be read.
1139 */
1140 ufs_ihashins(ip);
1141
1142 /* Read in the disk contents for the inode, copy into the inode. */
1143 if (error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
1144 (int)fs->fs_bsize, NOCRED, &bp)) {
1c79356b 1145 brelse(bp);
55e303ae 1146 goto errout;
1c79356b
A
1147 }
1148#if REV_ENDIAN_FS
1149 if (mp->mnt_flag & MNT_REVEND) {
1150 byte_swap_inode_in(((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino)),ip);
1151 } else {
55e303ae 1152 ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino));
1c79356b 1153 }
55e303ae
A
1154#else
1155 ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino));
1c79356b
A
1156#endif /* REV_ENDIAN_FS */
1157 brelse(bp);
1158
55e303ae
A
1159 if (error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp))
1160 goto errout;
1161
1162 vp->v_data = ip;
1163 ip->i_vnode = vp;
1164
1c79356b
A
1165 /*
1166 * Initialize the vnode from the inode, check for aliases.
1167 * Note that the underlying vnode may have changed.
1168 */
1169 if (error = ufs_vinit(mp, ffs_specop_p, FFS_FIFOOPS, &vp)) {
1170 vput(vp);
1171 *vpp = NULL;
55e303ae 1172 goto out;
1c79356b
A
1173 }
1174 /*
1175 * Finish inode initialization now that aliasing has been resolved.
1176 */
1177 ip->i_devvp = ump->um_devvp;
1178 VREF(ip->i_devvp);
1179 /*
1180 * Set up a generation number for this inode if it does not
1181 * already have one. This should only happen on old filesystems.
1182 */
1183 if (ip->i_gen == 0) {
1184 if (++nextgennumber < (u_long)time.tv_sec)
1185 nextgennumber = time.tv_sec;
1186 ip->i_gen = nextgennumber;
1187 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
1188 ip->i_flag |= IN_MODIFIED;
1189 }
1190 /*
1191 * Ensure that uid and gid are correct. This is a temporary
1192 * fix until fsck has been changed to do the update.
1193 */
1194 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
1195 ip->i_uid = ip->i_din.di_ouid; /* XXX */
1196 ip->i_gid = ip->i_din.di_ogid; /* XXX */
1197 } /* XXX */
1198
1c79356b
A
1199 if (UBCINFOMISSING(vp) || UBCINFORECLAIMED(vp))
1200 ubc_info_init(vp);
55e303ae
A
1201 *vpp = vp;
1202
1203out:
1204 CLR(ip->i_flag, IN_ALLOC);
1205 if (ISSET(ip->i_flag, IN_WALLOC))
1206 wakeup(ip);
1207 return (error);
1208
1209errout:
1210 ufs_ihashrem(ip);
1211 CLR(ip->i_flag, IN_ALLOC);
1212 if (ISSET(ip->i_flag, IN_WALLOC))
1213 wakeup(ip);
1214 FREE_ZONE(ip, sizeof(struct inode), type);
1215 *vpp = NULL;
1216 return (error);
1c79356b
A
1217}
1218
1219/*
1220 * File handle to vnode
1221 *
1222 * Have to be really careful about stale file handles:
1223 * - check that the inode number is valid
1224 * - call ffs_vget() to get the locked inode
1225 * - check for an unallocated inode (i_mode == 0)
1226 * - check that the given client host has export rights and return
1227 * those rights via. exflagsp and credanonp
1228 */
1229int
1230ffs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
1231 register struct mount *mp;
1232 struct fid *fhp;
1233 struct mbuf *nam;
1234 struct vnode **vpp;
1235 int *exflagsp;
1236 struct ucred **credanonp;
1237{
1238 register struct ufid *ufhp;
1239 struct fs *fs;
1240
1241 ufhp = (struct ufid *)fhp;
1242 fs = VFSTOUFS(mp)->um_fs;
1243 if (ufhp->ufid_ino < ROOTINO ||
1244 ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg)
1245 return (ESTALE);
1246 return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp));
1247}
1248
1249/*
1250 * Vnode pointer to File handle
1251 */
1252/* ARGSUSED */
1253ffs_vptofh(vp, fhp)
1254 struct vnode *vp;
1255 struct fid *fhp;
1256{
1257 register struct inode *ip;
1258 register struct ufid *ufhp;
1259
1260 ip = VTOI(vp);
1261 ufhp = (struct ufid *)fhp;
1262 ufhp->ufid_len = sizeof(struct ufid);
1263 ufhp->ufid_ino = ip->i_number;
1264 ufhp->ufid_gen = ip->i_gen;
1265 return (0);
1266}
1267
1268/*
1269 * Initialize the filesystem; just use ufs_init.
1270 */
1271int
1272ffs_init(vfsp)
1273 struct vfsconf *vfsp;
1274{
1275
1276 return (ufs_init(vfsp));
1277}
1278
1279/*
1280 * fast filesystem related variables.
1281 */
1282ffs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
1283 int *name;
1284 u_int namelen;
1285 void *oldp;
1286 size_t *oldlenp;
1287 void *newp;
1288 size_t newlen;
1289 struct proc *p;
1290{
1291 extern int doclusterread, doclusterwrite, doreallocblks, doasyncfree;
1292
1293 /* all sysctl names at this level are terminal */
1294 if (namelen != 1)
1295 return (ENOTDIR); /* overloaded */
1296
1297 switch (name[0]) {
1298 case FFS_CLUSTERREAD:
1299 return (sysctl_int(oldp, oldlenp, newp, newlen,
1300 &doclusterread));
1301 case FFS_CLUSTERWRITE:
1302 return (sysctl_int(oldp, oldlenp, newp, newlen,
1303 &doclusterwrite));
1304 case FFS_REALLOCBLKS:
1305 return (sysctl_int(oldp, oldlenp, newp, newlen,
1306 &doreallocblks));
1307 case FFS_ASYNCFREE:
1308 return (sysctl_int(oldp, oldlenp, newp, newlen, &doasyncfree));
1309 default:
1310 return (EOPNOTSUPP);
1311 }
1312 /* NOTREACHED */
1313}
1314
1315/*
1316 * Write a superblock and associated information back to disk.
1317 */
1318int
1319ffs_sbupdate(mp, waitfor)
1320 struct ufsmount *mp;
1321 int waitfor;
1322{
1323 register struct fs *dfs, *fs = mp->um_fs;
1324 register struct buf *bp;
1325 int blks;
9bccf70c 1326 void *space;
1c79356b
A
1327 int i, size, error, allerror = 0;
1328 int devBlockSize=0;
1329#if REV_ENDIAN_FS
1330 int rev_endian=(mp->um_mountp->mnt_flag & MNT_REVEND);
1331#endif /* REV_ENDIAN_FS */
1332
1333 /*
1334 * First write back the summary information.
1335 */
1336 blks = howmany(fs->fs_cssize, fs->fs_fsize);
9bccf70c 1337 space = fs->fs_csp;
1c79356b
A
1338 for (i = 0; i < blks; i += fs->fs_frag) {
1339 size = fs->fs_bsize;
1340 if (i + fs->fs_frag > blks)
1341 size = (blks - i) * fs->fs_fsize;
1342 bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
1343 size, 0, 0, BLK_META);
1344 bcopy(space, bp->b_data, (u_int)size);
1345#if REV_ENDIAN_FS
1346 if (rev_endian) {
1347 byte_swap_ints((int *)bp->b_data, size / sizeof(int));
1348 }
1349#endif /* REV_ENDIAN_FS */
9bccf70c 1350 space = (char *)space + size;
1c79356b
A
1351 if (waitfor != MNT_WAIT)
1352 bawrite(bp);
1353 else if (error = bwrite(bp))
1354 allerror = error;
1355 }
1356 /*
1357 * Now write back the superblock itself. If any errors occurred
1358 * up to this point, then fail so that the superblock avoids
1359 * being written out as clean.
1360 */
1361 if (allerror)
1362 return (allerror);
1363 VOP_DEVBLOCKSIZE(mp->um_devvp,&devBlockSize);
1364 bp = getblk(mp->um_devvp, (SBOFF/devBlockSize), (int)fs->fs_sbsize, 0, 0, BLK_META);
1365 bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
1366 /* Restore compatibility to old file systems. XXX */
1367 dfs = (struct fs *)bp->b_data; /* XXX */
1368 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
1369 dfs->fs_nrpos = -1; /* XXX */
1370#if REV_ENDIAN_FS
1371 /*
1372 * Swapping bytes here ; so that in case
1373 * of inode format < FS_44INODEFMT appropriate
1374 * fields get moved
1375 */
1376 if (rev_endian) {
1377 byte_swap_sbout((struct fs *)bp->b_data);
1378 }
1379#endif /* REV_ENDIAN_FS */
1380 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
1381 int32_t *lp, tmp; /* XXX */
1382 /* XXX */
1383 lp = (int32_t *)&dfs->fs_qbmask; /* XXX */
1384 tmp = lp[4]; /* XXX */
1385 for (i = 4; i > 0; i--) /* XXX */
1386 lp[i] = lp[i-1]; /* XXX */
1387 lp[0] = tmp; /* XXX */
1388 } /* XXX */
1389#if REV_ENDIAN_FS
1390 /* Note that dfs is already swapped so swap the filesize
1391 * before writing
1392 */
1393 if (rev_endian) {
1394 dfs->fs_maxfilesize = NXSwapLongLong(mp->um_savedmaxfilesize); /* XXX */
1395 } else {
1396#endif /* REV_ENDIAN_FS */
1397 dfs->fs_maxfilesize = mp->um_savedmaxfilesize; /* XXX */
1398#if REV_ENDIAN_FS
1399 }
1400#endif /* REV_ENDIAN_FS */
1401 if (waitfor != MNT_WAIT)
1402 bawrite(bp);
1403 else if (error = bwrite(bp))
1404 allerror = error;
1405
1406 return (allerror);
1407}