]>
git.saurik.com Git - apple/xnu.git/blob - bsd/ufs/ffs/ffs_vfsops.c
e16aae89a8de7af3720c2212e4d257f99d69a690
2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
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
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
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
23 * @APPLE_LICENSE_HEADER_END@
25 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
27 * Copyright (c) 1989, 1991, 1993, 1994
28 * The Regents of the University of California. All rights reserved.
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
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.
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
58 * @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95
61 #include <rev_endian_fs.h>
62 #include <sys/param.h>
63 #include <sys/systm.h>
64 #include <sys/namei.h>
66 #include <sys/kernel.h>
67 #include <sys/vnode.h>
68 #include <sys/socket.h>
69 #include <sys/mount.h>
74 #include <sys/ioctl.h>
75 #include <sys/errno.h>
76 #include <sys/malloc.h>
78 #include <sys/quota.h>
80 #include <miscfs/specfs/specdev.h>
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>
87 #include <ufs/ffs/fs.h>
88 #include <ufs/ffs/ffs_extern.h>
90 #include <ufs/ufs/ufs_byte_order.h>
91 #include <architecture/byte_order.h>
92 #endif /* REV_ENDIAN_FS */
94 int ffs_sbupdate
__P((struct ufsmount
*, int));
96 struct vfsops ufs_vfsops
= {
111 extern u_long nextgennumber
;
114 * Called by main() when ufs is going to be mounted as root.
118 extern struct vnode
*rootvp
;
121 struct proc
*p
= current_proc(); /* XXX */
122 struct ufsmount
*ump
;
127 * Get vnode for rootdev.
129 if (error
= bdevvp(rootdev
, &rootvp
)) {
130 printf("ffs_mountroot: can't setup bdevvp");
133 if (error
= vfs_rootmountalloc("ufs", "root_device", &mp
)) {
134 vrele(rootvp
); /* release the reference from bdevvp() */
138 /* Must set the MNT_ROOTFS flag before doing the actual mount */
139 mp
->mnt_flag
|= MNT_ROOTFS
;
141 /* Set asynchronous flag by default */
142 mp
->mnt_flag
|= MNT_ASYNC
;
144 if (error
= ffs_mountfs(rootvp
, mp
, p
)) {
145 mp
->mnt_vfc
->vfc_refcount
--;
147 if (mp
->mnt_kern_flag
& MNTK_IO_XINFO
)
148 FREE(mp
->mnt_xinfo_ptr
, M_TEMP
);
151 vrele(rootvp
); /* release the reference from bdevvp() */
152 FREE_ZONE(mp
, sizeof (struct mount
), M_MOUNT
);
155 simple_lock(&mountlist_slock
);
156 CIRCLEQ_INSERT_TAIL(&mountlist
, mp
, mnt_list
);
157 simple_unlock(&mountlist_slock
);
160 (void) copystr(mp
->mnt_stat
.f_mntonname
, fs
->fs_fsmnt
, MNAMELEN
- 1, 0);
161 (void)ffs_statfs(mp
, &mp
->mnt_stat
, p
);
163 inittodr(fs
->fs_time
);
173 ffs_mount(mp
, path
, data
, ndp
, p
)
174 register struct mount
*mp
;
177 struct nameidata
*ndp
;
181 struct ufs_args args
;
182 struct ufsmount
*ump
;
183 register struct fs
*fs
;
190 if (error
= copyin(data
, (caddr_t
)&args
, sizeof (struct ufs_args
)))
193 * If updating, check whether changing from read-only to
194 * read/write; if there is no device name, that's all we do.
196 if (mp
->mnt_flag
& MNT_UPDATE
) {
199 if (fs
->fs_ronly
== 0 && (mp
->mnt_flag
& MNT_RDONLY
)) {
201 if (mp
->mnt_flag
& MNT_FORCE
)
203 if (error
= ffs_flushfiles(mp
, flags
, p
))
207 if (error
= ffs_sbupdate(ump
, MNT_WAIT
)) {
213 /* save fs_ronly to later use */
214 ronly
= fs
->fs_ronly
;
215 if ((mp
->mnt_flag
& MNT_RELOAD
) || ronly
)
218 (error
= ffs_reload(mp
, ndp
->ni_cnd
.cn_cred
, p
)))
220 /* replace the ronly after load */
221 fs
->fs_ronly
= ronly
;
223 * Do not update the file system if the user was in singleuser
224 * and then tries to mount -uw without fscking
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
);
231 * Reset the readonly bit as reload might have
239 if (ronly
&& (mp
->mnt_kern_flag
& MNTK_WANTRDWR
)) {
241 * If upgrade to read-write by non-root, then verify
242 * that user has necessary permissions on the device.
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
,
249 VOP_UNLOCK(devvp
, 0, p
);
252 VOP_UNLOCK(devvp
, 0, p
);
256 (void) ffs_sbupdate(ump
, MNT_WAIT
);
258 if (args
.fspec
== 0) {
260 * Process export requests.
262 return (vfs_export(mp
, &ump
->um_export
, &args
.export
));
266 * Not an update, or updating the name: look up the name
267 * and verify that it refers to a sensible block device.
269 NDINIT(ndp
, LOOKUP
, FOLLOW
, UIO_USERSPACE
, args
.fspec
, p
);
270 if (error
= namei(ndp
))
274 if (devvp
->v_type
!= VBLK
) {
278 if (major(devvp
->v_rdev
) >= nblkdev
) {
283 * If mount by non-root, then verify that user has necessary
284 * permissions on the device.
286 if (p
->p_ucred
->cr_uid
!= 0) {
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
)) {
295 VOP_UNLOCK(devvp
, 0, p
);
297 if ((mp
->mnt_flag
& MNT_UPDATE
) == 0)
298 error
= ffs_mountfs(devvp
, mp
, p
);
300 if (devvp
!= ump
->um_devvp
)
301 error
= EINVAL
; /* needs translation */
311 (void) copyinstr(path
, fs
->fs_fsmnt
, sizeof(fs
->fs_fsmnt
) - 1,
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
,
316 (void) copyinstr(args
.fspec
, mp
->mnt_stat
.f_mntfromname
, MNAMELEN
- 1,
318 bzero(mp
->mnt_stat
.f_mntfromname
+ size
, MNAMELEN
- size
);
319 (void)ffs_statfs(mp
, &mp
->mnt_stat
, p
);
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.
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.
336 ffs_reload(mountp
, cred
, p
)
337 register struct mount
*mountp
;
341 register struct vnode
*vp
, *nvp
, *devvp
;
345 struct fs
*fs
, *newfs
;
346 int i
, blks
, size
, error
;
347 u_int64_t maxfilesize
; /* XXX */
350 int rev_endian
= (mountp
->mnt_flag
& MNT_REVEND
);
351 #endif /* REV_ENDIAN_FS */
353 if ((mountp
->mnt_flag
& MNT_RDONLY
) == 0)
356 * Step 1: invalidate all cached meta-data.
358 devvp
= VFSTOUFS(mountp
)->um_devvp
;
359 if (vinvalbuf(devvp
, 0, cred
, p
, 0, 0))
360 panic("ffs_reload: dirty1");
362 * Step 2: re-read superblock from disk.
364 VOP_DEVBLOCKSIZE(devvp
,&size
);
366 if (error
= bread(devvp
, (ufs_daddr_t
)(SBOFF
/size
), SBSIZE
, NOCRED
,&bp
)) {
370 newfs
= (struct fs
*)bp
->b_data
;
373 byte_swap_sbin(newfs
);
375 #endif /* REV_ENDIAN_FS */
376 if (newfs
->fs_magic
!= FS_MAGIC
|| newfs
->fs_bsize
> MAXBSIZE
||
377 newfs
->fs_bsize
< sizeof(struct fs
)) {
380 byte_swap_sbout(newfs
);
381 #endif /* REV_ENDIAN_FS */
384 return (EIO
); /* XXX needs translation */
386 fs
= VFSTOUFS(mountp
)->um_fs
;
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.
392 newfs
->fs_csp
= fs
->fs_csp
;
393 newfs
->fs_maxcluster
= fs
->fs_maxcluster
;
394 newfs
->fs_contigdirs
= fs
->fs_contigdirs
;
395 bcopy(newfs
, fs
, (u_int
)fs
->fs_sbsize
);
396 if (fs
->fs_sbsize
< SBSIZE
)
397 bp
->b_flags
|= B_INVAL
;
400 byte_swap_sbout(newfs
);
401 #endif /* REV_ENDIAN_FS */
403 mountp
->mnt_maxsymlinklen
= fs
->fs_maxsymlinklen
;
405 maxfilesize
= 0x100000000ULL
; /* 4GB */
406 if (fs
->fs_maxfilesize
> maxfilesize
) /* XXX */
407 fs
->fs_maxfilesize
= maxfilesize
; /* XXX */
409 * Step 3: re-read summary information from disk.
411 blks
= howmany(fs
->fs_cssize
, fs
->fs_fsize
);
413 for (i
= 0; i
< blks
; i
+= fs
->fs_frag
) {
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
,
425 byte_swap_ints((int *)bp
->b_data
, size
/ sizeof(int));
427 #endif /* REV_ENDIAN_FS */
428 bcopy(bp
->b_data
, space
, (u_int
)size
);
432 byte_swap_ints((int *)bp
->b_data
, size
/ sizeof(int));
434 #endif /* REV_ENDIAN_FS */
435 space
= (char *) space
+ size
;
439 * We no longer know anything about clusters per cylinder group.
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
;
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
);
454 nvp
= vp
->v_mntvnodes
.le_next
;
456 * Step 4: invalidate all inactive vnodes.
458 if (vrecycle(vp
, &mntvnode_slock
, p
))
461 * Step 5: invalidate all cached file data.
463 simple_lock(&vp
->v_interlock
);
464 simple_unlock(&mntvnode_slock
);
465 if (vget(vp
, LK_EXCLUSIVE
| LK_INTERLOCK
, p
)) {
468 if (vinvalbuf(vp
, 0, cred
, p
, 0, 0))
469 panic("ffs_reload: dirty2");
471 * Step 6: re-read inode data for all active vnodes.
475 bread(devvp
, fsbtodb(fs
, ino_to_fsba(fs
, ip
->i_number
)),
476 (int)fs
->fs_bsize
, NOCRED
, &bp
)) {
483 byte_swap_inode_in(((struct dinode
*)bp
->b_data
+
484 ino_to_fsbo(fs
, ip
->i_number
)), ip
);
486 #endif /* REV_ENDIAN_FS */
487 ip
->i_din
= *((struct dinode
*)bp
->b_data
+
488 ino_to_fsbo(fs
, ip
->i_number
));
491 #endif /* REV_ENDIAN_FS */
494 simple_lock(&mntvnode_slock
);
496 simple_unlock(&mntvnode_slock
);
501 * Common code for mount and mountroot
504 ffs_mountfs(devvp
, mp
, p
)
505 register struct vnode
*devvp
;
509 register struct ufsmount
*ump
;
511 register struct fs
*fs
;
515 int32_t clustersumoff
;
517 int error
, i
, blks
, size
, ronly
;
520 extern struct vnode
*rootvp
;
521 u_int64_t maxfilesize
; /* XXX */
522 u_int dbsize
= DEV_BSIZE
;
525 #endif /* REV_ENDIAN_FS */
527 cred
= p
? p
->p_ucred
: NOCRED
;
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.
534 if (error
= vfs_mountedon(devvp
))
536 if (vcount(devvp
) > 1 && devvp
!= rootvp
)
538 if (error
= vinvalbuf(devvp
, V_SAVE
, cred
, p
, 0, 0))
541 ronly
= (mp
->mnt_flag
& MNT_RDONLY
) != 0;
542 if (error
= VOP_OPEN(devvp
, ronly
? FREAD
: FREAD
|FWRITE
, FSCRED
, p
))
545 VOP_DEVBLOCKSIZE(devvp
,&size
);
549 if (error
= bread(devvp
, (ufs_daddr_t
)(SBOFF
/size
), SBSIZE
, cred
, &bp
))
551 fs
= (struct fs
*)bp
->b_data
;
553 if (fs
->fs_magic
!= FS_MAGIC
|| fs
->fs_bsize
> MAXBSIZE
||
554 fs
->fs_bsize
< sizeof(struct fs
)) {
555 int magic
= fs
->fs_magic
;
557 byte_swap_ints(&magic
, 1);
558 if (magic
!= FS_MAGIC
) {
563 if (fs
->fs_magic
!= FS_MAGIC
|| fs
->fs_bsize
> MAXBSIZE
||
564 fs
->fs_bsize
< sizeof(struct fs
)) {
566 error
= EINVAL
; /* XXX needs translation */
571 #endif /* REV_ENDIAN_FS */
572 if (fs
->fs_magic
!= FS_MAGIC
|| fs
->fs_bsize
> MAXBSIZE
||
573 fs
->fs_bsize
< sizeof(struct fs
)) {
577 #endif /* REV_ENDIAN_FS */
578 error
= EINVAL
; /* XXX needs translation */
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.
594 * Can't mount filesystems with a fragment size less than DIRBLKSIZ
597 * Don't mount dirty filesystems, except for the root filesystem
599 if ((fs
->fs_bsize
> PAGE_SIZE
) || (fs
->fs_fsize
< DIRBLKSIZ
) ||
600 ((!(mp
->mnt_flag
& MNT_ROOTFS
)) && (!fs
->fs_clean
))) {
604 #endif /* REV_ENDIAN_FS */
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 */
612 dbsize
= fs
->fs_fsize
/ NSPF(fs
);
614 kprintf("device blocksize computaion failed\n");
616 if (VOP_IOCTL(devvp
, DKIOCSETBLOCKSIZE
, (caddr_t
)&dbsize
,
617 FWRITE
, NOCRED
, p
) != 0) {
618 kprintf("failed to set device blocksize\n");
620 /* force the specfs to reread blocksize from size() */
621 set_fsblocksize(devvp
);
624 /* cache the IO attributes */
625 error
= vfs_init_io_attributes(devvp
, mp
);
627 printf("ffs_mountfs: vfs_init_io_attributes returned %d\n",
632 /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */
633 if (fs
->fs_postblformat
== FS_42POSTBLFMT
&& !ronly
) {
637 #endif /* REV_ENDIAN_FS */
638 error
= EROFS
; /* needs translation */
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
648 if (error
= bread (devvp
, fsbtodb(fs
, cgtod(fs
, 0)),
649 (int)fs
->fs_cgsize
, NOCRED
, &cgbp
)) {
653 cgp
= (struct cg
*)cgbp
->b_data
;
656 byte_swap_cgin(cgp
,fs
);
657 #endif /* REV_ENDIAN_FS */
658 if (!cg_chkmagic(cgp
)){
661 byte_swap_cgout(cgp
,fs
);
662 #endif /* REV_ENDIAN_FS */
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
) {
673 mp
->mnt_flag
|= MNT_RDONLY
;
679 byte_swap_cgout(cgp
,fs
);
680 #endif /* REV_ENDIAN_FS */
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
,
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
;
694 #endif /* REV_ENDIAN_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);
703 size
+= fs
->fs_ncg
* sizeof(u_int8_t
);
704 space
= _MALLOC((u_long
)size
, M_UFSMNT
, M_WAITOK
);
706 for (i
= 0; i
< blks
; i
+= fs
->fs_frag
) {
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
,
712 _FREE(fs
->fs_csp
, M_UFSMNT
);
715 bcopy(bp
->b_data
, space
, (u_int
)size
);
718 byte_swap_ints((int *) space
, size
/ sizeof(int));
719 #endif /* REV_ENDIAN_FS */
720 space
= (char *)space
+ size
;
724 if (fs
->fs_contigsumsize
> 0) {
725 fs
->fs_maxcluster
= lp
= space
;
726 for (i
= 0; i
< fs
->fs_ncg
; i
++)
727 *lp
++ = fs
->fs_contigsumsize
;
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 */
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
;
743 /* XXX warning hardcoded max symlen and not "mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;" */
744 mp
->mnt_maxsymlinklen
= 60;
747 mp
->mnt_flag
|= MNT_REVEND
;
748 #endif /* REV_ENDIAN_FS */
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
++)
756 ump
->um_qfiles
[i
].qf_vp
= NULLVP
;
757 devvp
->v_specflags
|= SI_MOUNTEDON
;
759 ump
->um_savedmaxfilesize
= fs
->fs_maxfilesize
; /* XXX */
760 maxfilesize
= 0x100000000ULL
; /* 4GB */
762 maxfilesize
= (u_int64_t
)0x40000000 * fs
->fs_bsize
- 1; /* XXX */
764 if (fs
->fs_maxfilesize
> maxfilesize
) /* XXX */
765 fs
->fs_maxfilesize
= maxfilesize
; /* XXX */
768 (void) ffs_sbupdate(ump
, MNT_WAIT
);
774 (void)VOP_CLOSE(devvp
, ronly
? FREAD
: FREAD
|FWRITE
, cred
, p
);
776 _FREE(ump
->um_fs
, M_UFSMNT
);
777 _FREE(ump
, M_UFSMNT
);
778 mp
->mnt_data
= (qaddr_t
)0;
784 * Sanity checks for old file systems.
786 * XXX - goes away some day.
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 */
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 */
805 fs
->fs_qbmask
= ~fs
->fs_bmask
; /* XXX */
806 fs
->fs_qfmask
= ~fs
->fs_fmask
; /* XXX */
812 * unmount system call
815 ffs_unmount(mp
, mntflags
, p
)
820 register struct ufsmount
*ump
;
821 register struct fs
*fs
;
827 if (mntflags
& MNT_FORCE
) {
831 if ( (error
= ffs_flushfiles(mp
, flags
, p
)) && !force
)
835 if (fs
->fs_ronly
== 0) {
837 if (error
= ffs_sbupdate(ump
, MNT_WAIT
)) {
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 */
849 ump
->um_devvp
->v_specflags
&= ~SI_MOUNTEDON
;
850 error
= VOP_CLOSE(ump
->um_devvp
, fs
->fs_ronly
? FREAD
: FREAD
|FWRITE
,
854 vrele(ump
->um_devvp
);
856 _FREE(fs
->fs_csp
, M_UFSMNT
);
858 _FREE(ump
, M_UFSMNT
);
859 mp
->mnt_data
= (qaddr_t
)0;
861 mp
->mnt_flag
&= ~MNT_REVEND
;
862 #endif /* REV_ENDIAN_FS */
867 * Flush out all the files in a filesystem.
869 ffs_flushfiles(mp
, flags
, p
)
870 register struct mount
*mp
;
874 register struct ufsmount
*ump
;
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.
885 if (mp
->mnt_flag
& MNT_QUOTA
) {
886 struct vnode
*rootvp
= NULLVP
;
887 int quotafilecnt
= 0;
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
)
896 * Check if the root vnode is in our inode hash
897 * (so we can skip over it).
899 rootvp
= ufs_ihashget(ump
->um_dev
, ROOTINO
);
901 error
= vflush(mp
, rootvp
, SKIPSYSTEM
|flags
);
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.
910 (rootvp
->v_usecount
> (1 + quotafilecnt
))) {
911 error
= EBUSY
; /* root dir is still open */
915 if (error
&& (flags
& FORCECLOSE
) == 0)
918 for (i
= 0; i
< MAXQUOTAS
; i
++) {
919 if (ump
->um_qfiles
[i
].qf_vp
== NULLVP
)
924 * Here we fall through to vflush again to ensure
925 * that we have gotten rid of all the system vnodes.
929 error
= vflush(mp
, NULLVP
, SKIPSWAP
|flags
);
930 error
= vflush(mp
, NULLVP
, flags
);
935 * Get file system statistics.
938 ffs_statfs(mp
, sbp
, p
)
940 register struct statfs
*sbp
;
943 register struct ufsmount
*ump
;
944 register struct fs
*fs
;
948 if (fs
->fs_magic
!= FS_MAGIC
)
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
);
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.
973 * Note: we are always called with the filesystem marked `MPBUSY'.
976 ffs_sync(mp
, waitfor
, cred
, p
)
982 struct vnode
*nvp
, *vp
;
984 struct ufsmount
*ump
= VFSTOUFS(mp
);
986 int error
, allerror
= 0;
989 if (fs
->fs_fmod
!= 0 && fs
->fs_ronly
!= 0) { /* XXX */
990 printf("fs = %s\n", fs
->fs_fsmnt
);
991 panic("update: rofs mod");
994 * Write back each (modified) inode.
996 simple_lock(&mntvnode_slock
);
998 for (vp
= mp
->mnt_vnodelist
.lh_first
;
1004 * If the vnode that we are about to sync is no longer
1005 * associated with this mount point, start over.
1007 if (vp
->v_mount
!= mp
)
1009 simple_lock(&vp
->v_interlock
);
1010 nvp
= vp
->v_mntvnodes
.le_next
;
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
);
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
);
1026 simple_unlock(&mntvnode_slock
);
1027 error
= vget(vp
, LK_EXCLUSIVE
| LK_NOWAIT
| LK_INTERLOCK
, p
);
1029 simple_lock(&mntvnode_slock
);
1030 if (error
== ENOENT
)
1034 didhold
= ubc_hold(vp
);
1035 if (error
= VOP_FSYNC(vp
, cred
, waitfor
, p
))
1037 VOP_UNLOCK(vp
, 0, p
);
1041 simple_lock(&mntvnode_slock
);
1043 simple_unlock(&mntvnode_slock
);
1045 * Force stale file system control information to be flushed.
1047 if (error
= VOP_FSYNC(ump
->um_devvp
, cred
, waitfor
, p
))
1053 * Write back modified superblock.
1055 if (fs
->fs_fmod
!= 0) {
1057 fs
->fs_time
= time
.tv_sec
;
1058 if (error
= ffs_sbupdate(ump
, waitfor
))
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.
1071 ffs_vget(mp
, inop
, vpp
)
1076 struct proc
*p
= current_proc(); /* XXX */
1079 struct ufsmount
*ump
;
1084 int i
, type
, error
= 0;
1090 /* Check for unmount in progress */
1091 if (mp
->mnt_kern_flag
& MNTK_UNMOUNT
) {
1096 /* check in the inode hash */
1097 if ((*vpp
= ufs_ihashget(dev
, ino
)) != NULL
) {
1099 UBCINFOCHECK("ffs_vget", vp
);
1104 * Not in inode hash.
1105 * Allocate a new vnode/inode.
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
);
1109 bzero((caddr_t
)ip
, sizeof(struct inode
));
1110 lockinit(&ip
->i_lock
, PINOD
, "inode", 0, 0);
1111 /* lock the inode */
1112 lockmgr(&ip
->i_lock
, LK_EXCLUSIVE
, (struct slock
*)0, p
);
1114 ip
->i_fs
= fs
= ump
->um_fs
;
1117 SET(ip
->i_flag
, IN_ALLOC
);
1119 for (i
= 0; i
< MAXQUOTAS
; i
++)
1120 ip
->i_dquot
[i
] = NODQUOT
;
1124 * We could have blocked in MALLOC_ZONE. Check for the race.
1126 if ((*vpp
= ufs_ihashget(dev
, ino
)) != NULL
) {
1127 /* lost the race, clean up */
1128 FREE_ZONE(ip
, sizeof(struct inode
), type
);
1130 UBCINFOCHECK("ffs_vget", vp
);
1135 * Put it onto its hash chain locked so that other requests for
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.
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
)) {
1149 if (mp
->mnt_flag
& MNT_REVEND
) {
1150 byte_swap_inode_in(((struct dinode
*)bp
->b_data
+ ino_to_fsbo(fs
, ino
)),ip
);
1152 ip
->i_din
= *((struct dinode
*)bp
->b_data
+ ino_to_fsbo(fs
, ino
));
1155 ip
->i_din
= *((struct dinode
*)bp
->b_data
+ ino_to_fsbo(fs
, ino
));
1156 #endif /* REV_ENDIAN_FS */
1159 if (error
= getnewvnode(VT_UFS
, mp
, ffs_vnodeop_p
, &vp
))
1166 * Initialize the vnode from the inode, check for aliases.
1167 * Note that the underlying vnode may have changed.
1169 if (error
= ufs_vinit(mp
, ffs_specop_p
, FFS_FIFOOPS
, &vp
)) {
1175 * Finish inode initialization now that aliasing has been resolved.
1177 ip
->i_devvp
= ump
->um_devvp
;
1180 * Set up a generation number for this inode if it does not
1181 * already have one. This should only happen on old filesystems.
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
;
1191 * Ensure that uid and gid are correct. This is a temporary
1192 * fix until fsck has been changed to do the update.
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 */
1199 if (UBCINFOMISSING(vp
) || UBCINFORECLAIMED(vp
))
1204 CLR(ip
->i_flag
, IN_ALLOC
);
1205 if (ISSET(ip
->i_flag
, IN_WALLOC
))
1211 CLR(ip
->i_flag
, IN_ALLOC
);
1212 if (ISSET(ip
->i_flag
, IN_WALLOC
))
1214 FREE_ZONE(ip
, sizeof(struct inode
), type
);
1220 * File handle to vnode
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
1230 ffs_fhtovp(mp
, fhp
, nam
, vpp
, exflagsp
, credanonp
)
1231 register struct mount
*mp
;
1236 struct ucred
**credanonp
;
1238 register struct ufid
*ufhp
;
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
)
1246 return (ufs_check_export(mp
, ufhp
, nam
, vpp
, exflagsp
, credanonp
));
1250 * Vnode pointer to File handle
1257 register struct inode
*ip
;
1258 register struct ufid
*ufhp
;
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
;
1269 * Initialize the filesystem; just use ufs_init.
1273 struct vfsconf
*vfsp
;
1276 return (ufs_init(vfsp
));
1280 * fast filesystem related variables.
1282 ffs_sysctl(name
, namelen
, oldp
, oldlenp
, newp
, newlen
, p
)
1291 extern int doclusterread
, doclusterwrite
, doreallocblks
, doasyncfree
;
1293 /* all sysctl names at this level are terminal */
1295 return (ENOTDIR
); /* overloaded */
1298 case FFS_CLUSTERREAD
:
1299 return (sysctl_int(oldp
, oldlenp
, newp
, newlen
,
1301 case FFS_CLUSTERWRITE
:
1302 return (sysctl_int(oldp
, oldlenp
, newp
, newlen
,
1304 case FFS_REALLOCBLKS
:
1305 return (sysctl_int(oldp
, oldlenp
, newp
, newlen
,
1308 return (sysctl_int(oldp
, oldlenp
, newp
, newlen
, &doasyncfree
));
1310 return (EOPNOTSUPP
);
1316 * Write a superblock and associated information back to disk.
1319 ffs_sbupdate(mp
, waitfor
)
1320 struct ufsmount
*mp
;
1323 register struct fs
*dfs
, *fs
= mp
->um_fs
;
1324 register struct buf
*bp
;
1327 int i
, size
, error
, allerror
= 0;
1330 int rev_endian
=(mp
->um_mountp
->mnt_flag
& MNT_REVEND
);
1331 #endif /* REV_ENDIAN_FS */
1334 * First write back the summary information.
1336 blks
= howmany(fs
->fs_cssize
, fs
->fs_fsize
);
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
);
1347 byte_swap_ints((int *)bp
->b_data
, size
/ sizeof(int));
1349 #endif /* REV_ENDIAN_FS */
1350 space
= (char *)space
+ size
;
1351 if (waitfor
!= MNT_WAIT
)
1353 else if (error
= bwrite(bp
))
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.
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 */
1372 * Swapping bytes here ; so that in case
1373 * of inode format < FS_44INODEFMT appropriate
1377 byte_swap_sbout((struct fs
*)bp
->b_data
);
1379 #endif /* REV_ENDIAN_FS */
1380 if (fs
->fs_inodefmt
< FS_44INODEFMT
) { /* XXX */
1381 int32_t *lp
, tmp
; /* 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 */
1390 /* Note that dfs is already swapped so swap the filesize
1394 dfs
->fs_maxfilesize
= NXSwapLongLong(mp
->um_savedmaxfilesize
); /* XXX */
1396 #endif /* REV_ENDIAN_FS */
1397 dfs
->fs_maxfilesize
= mp
->um_savedmaxfilesize
; /* XXX */
1400 #endif /* REV_ENDIAN_FS */
1401 if (waitfor
!= MNT_WAIT
)
1403 else if (error
= bwrite(bp
))