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