1 /* $NetBSD: ext2fs_vfsops.c,v 1.193 2015/03/28 19:24:04 maxv Exp $ */
4 * Copyright (c) 1989, 1991, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * @(#)ffs_vfsops.c 8.14 (Berkeley) 11/28/94
32 * Modified for ext2fs by Manuel Bouyer.
36 * Copyright (c) 1997 Manuel Bouyer.
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
47 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
48 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
49 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
50 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
51 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
52 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
53 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
54 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
55 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
56 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58 * @(#)ffs_vfsops.c 8.14 (Berkeley) 11/28/94
59 * Modified for ext2fs by Manuel Bouyer.
62 #include <sys/cdefs.h>
63 __KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.193 2015/03/28 19:24:04 maxv Exp $");
65 #if defined(_KERNEL_OPT)
66 #include "opt_compat_netbsd.h"
69 #include <sys/param.h>
70 #include <sys/systm.h>
71 #include <sys/sysctl.h>
72 #include <sys/namei.h>
74 #include <sys/kernel.h>
75 #include <sys/vnode.h>
76 #include <sys/socket.h>
77 #include <sys/mount.h>
79 #include <sys/device.h>
82 #include <sys/disklabel.h>
83 #include <sys/ioctl.h>
84 #include <sys/errno.h>
88 #include <sys/kauth.h>
89 #include <sys/module.h>
91 #include <miscfs/genfs/genfs.h>
92 #include <miscfs/specfs/specdev.h>
94 #include <ufs/ufs/quota.h>
95 #include <ufs/ufs/ufsmount.h>
96 #include <ufs/ufs/inode.h>
97 #include <ufs/ufs/dir.h>
98 #include <ufs/ufs/ufs_extern.h>
100 #include <ufs/ext2fs/ext2fs.h>
101 #include <ufs/ext2fs/ext2fs_dir.h>
102 #include <ufs/ext2fs/ext2fs_extern.h>
104 MODULE(MODULE_CLASS_VFS
, ext2fs
, "ffs");
106 int ext2fs_sbupdate(struct ufsmount
*, int);
107 static int ext2fs_sbfill(struct m_ext2fs
*, int);
109 static struct sysctllog
*ext2fs_sysctl_log
;
111 extern const struct vnodeopv_desc ext2fs_vnodeop_opv_desc
;
112 extern const struct vnodeopv_desc ext2fs_specop_opv_desc
;
113 extern const struct vnodeopv_desc ext2fs_fifoop_opv_desc
;
115 const struct vnodeopv_desc
* const ext2fs_vnodeopv_descs
[] = {
116 &ext2fs_vnodeop_opv_desc
,
117 &ext2fs_specop_opv_desc
,
118 &ext2fs_fifoop_opv_desc
,
122 struct vfsops ext2fs_vfsops
= {
123 .vfs_name
= MOUNT_EXT2FS
,
124 .vfs_min_mount_data
= sizeof (struct ufs_args
),
125 .vfs_mount
= ext2fs_mount
,
126 .vfs_start
= ufs_start
,
127 .vfs_unmount
= ext2fs_unmount
,
128 .vfs_root
= ufs_root
,
129 .vfs_quotactl
= ufs_quotactl
,
130 .vfs_statvfs
= ext2fs_statvfs
,
131 .vfs_sync
= ext2fs_sync
,
132 .vfs_vget
= ufs_vget
,
133 .vfs_loadvnode
= ext2fs_loadvnode
,
134 .vfs_fhtovp
= ext2fs_fhtovp
,
135 .vfs_vptofh
= ext2fs_vptofh
,
136 .vfs_init
= ext2fs_init
,
137 .vfs_reinit
= ext2fs_reinit
,
138 .vfs_done
= ext2fs_done
,
139 .vfs_mountroot
= ext2fs_mountroot
,
140 .vfs_snapshot
= (void *)eopnotsupp
,
141 .vfs_extattrctl
= vfs_stdextattrctl
,
142 .vfs_suspendctl
= (void *)eopnotsupp
,
143 .vfs_renamelock_enter
= genfs_renamelock_enter
,
144 .vfs_renamelock_exit
= genfs_renamelock_exit
,
145 .vfs_fsync
= (void *)eopnotsupp
,
146 .vfs_opv_descs
= ext2fs_vnodeopv_descs
149 static const struct genfs_ops ext2fs_genfsops
= {
150 .gop_size
= genfs_size
,
151 .gop_alloc
= ext2fs_gop_alloc
,
152 .gop_write
= genfs_gop_write
,
153 .gop_markupdate
= ufs_gop_markupdate
,
156 static const struct ufs_ops ext2fs_ufsops
= {
157 .uo_itimes
= ext2fs_itimes
,
158 .uo_update
= ext2fs_update
,
159 .uo_bufrd
= ext2fs_bufrd
,
160 .uo_bufwr
= ext2fs_bufwr
,
163 /* Fill in the inode uid/gid from ext2 halves. */
165 ext2fs_set_inode_guid(struct inode
*ip
)
168 ip
->i_gid
= ip
->i_e2fs_gid
;
169 ip
->i_uid
= ip
->i_e2fs_uid
;
170 if (ip
->i_e2fs
->e2fs
.e2fs_rev
> E2FS_REV0
) {
171 ip
->i_gid
|= ip
->i_e2fs_gid_high
<< 16;
172 ip
->i_uid
|= ip
->i_e2fs_uid_high
<< 16;
177 ext2fs_modcmd(modcmd_t cmd
, void *arg
)
182 case MODULE_CMD_INIT
:
183 error
= vfs_attach(&ext2fs_vfsops
);
186 sysctl_createv(&ext2fs_sysctl_log
, 0, NULL
, NULL
,
188 CTLTYPE_NODE
, "ext2fs",
189 SYSCTL_DESCR("Linux EXT2FS file system"),
191 CTL_VFS
, 17, CTL_EOL
);
193 * XXX the "17" above could be dynamic, thereby eliminating
194 * one more instance of the "number to vfs" mapping problem,
195 * but "17" is the order as taken from sys/mount.h
198 case MODULE_CMD_FINI
:
199 error
= vfs_detach(&ext2fs_vfsops
);
202 sysctl_teardown(&ext2fs_sysctl_log
);
213 * XXX Same structure as FFS inodes? Should we share a common pool?
215 struct pool ext2fs_inode_pool
;
216 struct pool ext2fs_dinode_pool
;
218 extern u_long ext2gennumber
;
224 pool_init(&ext2fs_inode_pool
, sizeof(struct inode
), 0, 0, 0,
225 "ext2fsinopl", &pool_allocator_nointr
, IPL_NONE
);
226 pool_init(&ext2fs_dinode_pool
, sizeof(struct ext2fs_dinode
), 0, 0, 0,
227 "ext2dinopl", &pool_allocator_nointr
, IPL_NONE
);
242 pool_destroy(&ext2fs_inode_pool
);
243 pool_destroy(&ext2fs_dinode_pool
);
247 * Called by main() when ext2fs is going to be mounted as root.
249 * Name is updated by mount(8) after booting.
253 ext2fs_mountroot(void)
255 extern struct vnode
*rootvp
;
258 struct ufsmount
*ump
;
261 if (device_class(root_device
) != DV_DISK
)
264 if ((error
= vfs_rootmountalloc(MOUNT_EXT2FS
, "root_device", &mp
))) {
269 if ((error
= ext2fs_mountfs(rootvp
, mp
)) != 0) {
270 vfs_unbusy(mp
, false, NULL
);
274 mountlist_append(mp
);
277 memset(fs
->e2fs_fsmnt
, 0, sizeof(fs
->e2fs_fsmnt
));
278 (void) copystr(mp
->mnt_stat
.f_mntonname
, fs
->e2fs_fsmnt
,
279 sizeof(fs
->e2fs_fsmnt
) - 1, 0);
280 if (fs
->e2fs
.e2fs_rev
> E2FS_REV0
) {
281 memset(fs
->e2fs
.e2fs_fsmnt
, 0, sizeof(fs
->e2fs
.e2fs_fsmnt
));
282 (void) copystr(mp
->mnt_stat
.f_mntonname
, fs
->e2fs
.e2fs_fsmnt
,
283 sizeof(fs
->e2fs
.e2fs_fsmnt
) - 1, 0);
285 (void)ext2fs_statvfs(mp
, &mp
->mnt_stat
);
286 vfs_unbusy(mp
, false, NULL
);
287 setrootfstime((time_t)fs
->e2fs
.e2fs_wtime
);
297 ext2fs_mount(struct mount
*mp
, const char *path
, void *data
, size_t *data_len
)
299 struct lwp
*l
= curlwp
;
301 struct ufs_args
*args
= data
;
302 struct ufsmount
*ump
= NULL
;
305 int error
= 0, flags
, update
;
310 if (*data_len
< sizeof *args
)
313 if (mp
->mnt_flag
& MNT_GETARGS
) {
317 memset(args
, 0, sizeof *args
);
319 *data_len
= sizeof *args
;
323 update
= mp
->mnt_flag
& MNT_UPDATE
;
325 /* Check arguments */
326 if (args
->fspec
!= NULL
) {
328 * Look up the name and verify that it's sane.
330 error
= namei_simple_user(args
->fspec
,
331 NSM_FOLLOW_NOEMULROOT
, &devvp
);
337 * Be sure this is a valid block device
339 if (devvp
->v_type
!= VBLK
)
341 else if (bdevsw_lookup(devvp
->v_rdev
) == NULL
)
345 * Be sure we're still naming the same device
346 * used for our initial mount
349 if (devvp
!= ump
->um_devvp
) {
350 if (devvp
->v_rdev
!= ump
->um_devvp
->v_rdev
)
354 devvp
= ump
->um_devvp
;
361 /* New mounts must have a filename for the device */
365 devvp
= ump
->um_devvp
;
371 * If mount by non-root, then verify that user has necessary
372 * permissions on the device.
374 * Permission to update a mount is checked higher, so here we presume
375 * updating the mount is okay (for example, as far as securelevel goes)
376 * which leaves us with the normal check.
381 (mp
->mnt_iflag
& IMNT_WANTRDWR
) != 0 :
382 (mp
->mnt_flag
& MNT_RDONLY
) == 0)
383 accessmode
|= VWRITE
;
384 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
385 error
= kauth_authorize_system(l
->l_cred
, KAUTH_SYSTEM_MOUNT
,
386 KAUTH_REQ_SYSTEM_MOUNT_DEVICE
, mp
, devvp
,
387 KAUTH_ARG(accessmode
));
399 if (mp
->mnt_flag
& MNT_RDONLY
)
402 xflags
= FREAD
|FWRITE
;
403 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
404 error
= VOP_OPEN(devvp
, xflags
, FSCRED
);
408 error
= ext2fs_mountfs(devvp
, mp
);
410 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
411 (void)VOP_CLOSE(devvp
, xflags
, NOCRED
);
424 * The initial mount got a reference on this
425 * device, so drop the one obtained via
432 if (fs
->e2fs_ronly
== 0 && (mp
->mnt_flag
& MNT_RDONLY
)) {
434 * Changing from r/w to r/o
437 if (mp
->mnt_flag
& MNT_FORCE
)
439 error
= ext2fs_flushfiles(mp
, flags
);
441 ext2fs_cgupdate(ump
, MNT_WAIT
) == 0 &&
442 (fs
->e2fs
.e2fs_state
& E2FS_ERRORS
) == 0) {
443 fs
->e2fs
.e2fs_state
= E2FS_ISCLEAN
;
444 (void) ext2fs_sbupdate(ump
, MNT_WAIT
);
451 if (mp
->mnt_flag
& MNT_RELOAD
) {
452 error
= ext2fs_reload(mp
, l
->l_cred
, l
);
457 if (fs
->e2fs_ronly
&& (mp
->mnt_iflag
& IMNT_WANTRDWR
)) {
459 * Changing from read-only to read/write
462 if (fs
->e2fs
.e2fs_state
== E2FS_ISCLEAN
)
463 fs
->e2fs
.e2fs_state
= 0;
465 fs
->e2fs
.e2fs_state
= E2FS_ERRORS
;
468 if (args
->fspec
== NULL
)
472 error
= set_statvfs_info(path
, UIO_USERSPACE
, args
->fspec
,
473 UIO_USERSPACE
, mp
->mnt_op
->vfs_name
, mp
, l
);
474 (void) copystr(mp
->mnt_stat
.f_mntonname
, fs
->e2fs_fsmnt
,
475 sizeof(fs
->e2fs_fsmnt
) - 1, &size
);
476 memset(fs
->e2fs_fsmnt
+ size
, 0, sizeof(fs
->e2fs_fsmnt
) - size
);
477 if (fs
->e2fs
.e2fs_rev
> E2FS_REV0
) {
478 (void) copystr(mp
->mnt_stat
.f_mntonname
, fs
->e2fs
.e2fs_fsmnt
,
479 sizeof(fs
->e2fs
.e2fs_fsmnt
) - 1, &size
);
480 memset(fs
->e2fs
.e2fs_fsmnt
, 0,
481 sizeof(fs
->e2fs
.e2fs_fsmnt
) - size
);
483 if (fs
->e2fs_fmod
!= 0) { /* XXX */
485 if (fs
->e2fs
.e2fs_state
== 0)
486 fs
->e2fs
.e2fs_wtime
= time_second
;
488 printf("%s: file system not clean; please fsck(8)\n",
489 mp
->mnt_stat
.f_mntfromname
);
490 (void) ext2fs_cgupdate(ump
, MNT_WAIT
);
500 * Reload all incore data for a filesystem (used after running fsck on
501 * the root filesystem and finding things to fix). The filesystem must
502 * be mounted read-only.
504 * Things to do to update the mount:
505 * 1) invalidate all cached meta-data.
506 * 2) re-read superblock from disk.
507 * 3) re-read summary information from disk.
508 * 4) invalidate all inactive vnodes.
509 * 5) invalidate all cached file data.
510 * 6) re-read inode data for all active vnodes.
513 ext2fs_reload(struct mount
*mp
, kauth_cred_t cred
, struct lwp
*l
)
515 struct vnode
*vp
, *devvp
;
519 struct ext2fs
*newfs
;
522 struct ufsmount
*ump
;
523 struct vnode_iterator
*marker
;
525 if ((mp
->mnt_flag
& MNT_RDONLY
) == 0)
530 * Step 1: invalidate all cached meta-data.
532 devvp
= ump
->um_devvp
;
533 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
534 error
= vinvalbuf(devvp
, 0, cred
, l
, 0, 0);
537 panic("ext2fs_reload: dirty1");
541 * Step 2: re-read superblock from disk. Copy in new superblock, and compute
544 error
= bread(devvp
, SBLOCK
, SBSIZE
, 0, &bp
);
547 newfs
= (struct ext2fs
*)bp
->b_data
;
548 e2fs_sbload(newfs
, &fs
->e2fs
);
552 error
= ext2fs_sbfill(fs
, (mp
->mnt_flag
& MNT_RDONLY
) != 0);
557 * Step 3: re-read summary information from disk.
559 for (i
= 0; i
< fs
->e2fs_ngdb
; i
++) {
560 error
= bread(devvp
,
561 EXT2_FSBTODB(fs
, fs
->e2fs
.e2fs_first_dblock
+
562 1 /* superblock */ + i
),
563 fs
->e2fs_bsize
, 0, &bp
);
567 e2fs_cgload((struct ext2_gd
*)bp
->b_data
,
568 &fs
->e2fs_gd
[i
* fs
->e2fs_bsize
/ sizeof(struct ext2_gd
)],
573 vfs_vnode_iterator_init(mp
, &marker
);
574 while ((vp
= vfs_vnode_iterator_next(marker
, NULL
, NULL
))) {
576 * Step 4: invalidate all inactive vnodes.
581 * Step 5: invalidate all cached file data.
583 if (vn_lock(vp
, LK_EXCLUSIVE
)) {
587 if (vinvalbuf(vp
, 0, cred
, l
, 0, 0))
588 panic("ext2fs_reload: dirty2");
590 * Step 6: re-read inode data for all active vnodes.
593 error
= bread(devvp
, EXT2_FSBTODB(fs
, ino_to_fsba(fs
, ip
->i_number
)),
594 (int)fs
->e2fs_bsize
, 0, &bp
);
599 cp
= (char *)bp
->b_data
+
600 (ino_to_fsbo(fs
, ip
->i_number
) * EXT2_DINODE_SIZE(fs
));
601 e2fs_iload((struct ext2fs_dinode
*)cp
, ip
->i_din
.e2fs_din
);
602 ext2fs_set_inode_guid(ip
);
606 vfs_vnode_iterator_destroy(marker
);
611 * Common code for mount and mountroot
614 ext2fs_mountfs(struct vnode
*devvp
, struct mount
*mp
)
616 struct lwp
*l
= curlwp
;
617 struct ufsmount
*ump
;
620 struct m_ext2fs
*m_fs
;
628 /* Flush out any old buffers remaining from a previous use. */
629 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
630 error
= vinvalbuf(devvp
, V_SAVE
, cred
, l
, 0, 0);
635 ronly
= (mp
->mnt_flag
& MNT_RDONLY
) != 0;
640 /* Read the superblock from disk, and swap it directly. */
641 error
= bread(devvp
, SBLOCK
, SBSIZE
, 0, &bp
);
644 fs
= (struct ext2fs
*)bp
->b_data
;
645 m_fs
= kmem_zalloc(sizeof(struct m_ext2fs
), KM_SLEEP
);
646 e2fs_sbload(fs
, &m_fs
->e2fs
);
651 /* Once swapped, validate and fill in the superblock. */
652 error
= ext2fs_sbfill(m_fs
, ronly
);
654 kmem_free(m_fs
, sizeof(struct m_ext2fs
));
657 m_fs
->e2fs_ronly
= ronly
;
659 ump
= kmem_zalloc(sizeof(*ump
), KM_SLEEP
);
660 ump
->um_fstype
= UFS1
;
661 ump
->um_ops
= &ext2fs_ufsops
;
665 if (m_fs
->e2fs
.e2fs_state
== E2FS_ISCLEAN
)
666 m_fs
->e2fs
.e2fs_state
= 0;
668 m_fs
->e2fs
.e2fs_state
= E2FS_ERRORS
;
672 /* XXX: should be added in ext2fs_sbfill()? */
673 m_fs
->e2fs_gd
= kmem_alloc(m_fs
->e2fs_ngdb
* m_fs
->e2fs_bsize
, KM_SLEEP
);
674 for (i
= 0; i
< m_fs
->e2fs_ngdb
; i
++) {
676 EXT2_FSBTODB(m_fs
, m_fs
->e2fs
.e2fs_first_dblock
+
677 1 /* superblock */ + i
),
678 m_fs
->e2fs_bsize
, 0, &bp
);
680 kmem_free(m_fs
->e2fs_gd
,
681 m_fs
->e2fs_ngdb
* m_fs
->e2fs_bsize
);
684 e2fs_cgload((struct ext2_gd
*)bp
->b_data
,
686 i
* m_fs
->e2fs_bsize
/ sizeof(struct ext2_gd
)],
693 mp
->mnt_stat
.f_fsidx
.__fsid_val
[0] = (long)dev
;
694 mp
->mnt_stat
.f_fsidx
.__fsid_val
[1] = makefstype(MOUNT_EXT2FS
);
695 mp
->mnt_stat
.f_fsid
= mp
->mnt_stat
.f_fsidx
.__fsid_val
[0];
696 mp
->mnt_stat
.f_namemax
= EXT2FS_MAXNAMLEN
;
697 mp
->mnt_flag
|= MNT_LOCAL
;
698 mp
->mnt_dev_bshift
= DEV_BSHIFT
; /* XXX */
699 mp
->mnt_fs_bshift
= m_fs
->e2fs_bshift
;
700 mp
->mnt_iflag
|= IMNT_DTYPE
;
704 ump
->um_devvp
= devvp
;
705 ump
->um_nindir
= EXT2_NINDIR(m_fs
);
706 ump
->um_lognindir
= ffs(EXT2_NINDIR(m_fs
)) - 1;
707 ump
->um_bptrtodb
= m_fs
->e2fs_fsbtodb
;
708 ump
->um_seqinc
= 1; /* no frags */
709 ump
->um_maxsymlinklen
= EXT2_MAXSYMLINKLEN
;
710 ump
->um_dirblksiz
= m_fs
->e2fs_bsize
;
711 ump
->um_maxfilesize
= ((uint64_t)0x80000000 * m_fs
->e2fs_bsize
- 1);
712 spec_node_setmountedfs(devvp
, mp
);
719 kmem_free(ump
->um_e2fs
, sizeof(struct m_ext2fs
));
720 kmem_free(ump
, sizeof(*ump
));
727 * unmount system call
730 ext2fs_unmount(struct mount
*mp
, int mntflags
)
732 struct ufsmount
*ump
;
737 if (mntflags
& MNT_FORCE
)
739 if ((error
= ext2fs_flushfiles(mp
, flags
)) != 0)
743 if (fs
->e2fs_ronly
== 0 &&
744 ext2fs_cgupdate(ump
, MNT_WAIT
) == 0 &&
745 (fs
->e2fs
.e2fs_state
& E2FS_ERRORS
) == 0) {
746 fs
->e2fs
.e2fs_state
= E2FS_ISCLEAN
;
747 (void) ext2fs_sbupdate(ump
, MNT_WAIT
);
749 if (ump
->um_devvp
->v_type
!= VBAD
)
750 spec_node_setmountedfs(ump
->um_devvp
, NULL
);
751 vn_lock(ump
->um_devvp
, LK_EXCLUSIVE
| LK_RETRY
);
752 error
= VOP_CLOSE(ump
->um_devvp
, fs
->e2fs_ronly
? FREAD
: FREAD
|FWRITE
,
755 kmem_free(fs
->e2fs_gd
, fs
->e2fs_ngdb
* fs
->e2fs_bsize
);
756 kmem_free(fs
, sizeof(*fs
));
757 kmem_free(ump
, sizeof(*ump
));
759 mp
->mnt_flag
&= ~MNT_LOCAL
;
764 * Flush out all the files in a filesystem.
767 ext2fs_flushfiles(struct mount
*mp
, int flags
)
773 flags
&= ~FORCECLOSE
;
774 error
= vflush(mp
, NULLVP
, flags
);
779 * Get file system statistics.
782 ext2fs_statvfs(struct mount
*mp
, struct statvfs
*sbp
)
784 struct ufsmount
*ump
;
786 uint32_t overhead
, overhead_per_group
, ngdb
;
791 if (fs
->e2fs
.e2fs_magic
!= E2FS_MAGIC
)
792 panic("ext2fs_statvfs");
795 * Compute the overhead (FS structures)
798 1 /* block bitmap */ +
799 1 /* inode bitmap */ +
801 overhead
= fs
->e2fs
.e2fs_first_dblock
+
802 fs
->e2fs_ncg
* overhead_per_group
;
803 if (fs
->e2fs
.e2fs_rev
> E2FS_REV0
&&
804 fs
->e2fs
.e2fs_features_rocompat
& EXT2F_ROCOMPAT_SPARSESUPER
) {
805 for (i
= 0, ngroups
= 0; i
< fs
->e2fs_ncg
; i
++) {
810 ngroups
= fs
->e2fs_ncg
;
812 ngdb
= fs
->e2fs_ngdb
;
813 if (fs
->e2fs
.e2fs_rev
> E2FS_REV0
&&
814 fs
->e2fs
.e2fs_features_compat
& EXT2F_COMPAT_RESIZE
)
815 ngdb
+= fs
->e2fs
.e2fs_reserved_ngdb
;
816 overhead
+= ngroups
* (1 /* superblock */ + ngdb
);
818 sbp
->f_bsize
= fs
->e2fs_bsize
;
819 sbp
->f_frsize
= MINBSIZE
<< fs
->e2fs
.e2fs_fsize
;
820 sbp
->f_iosize
= fs
->e2fs_bsize
;
821 sbp
->f_blocks
= fs
->e2fs
.e2fs_bcount
- overhead
;
822 sbp
->f_bfree
= fs
->e2fs
.e2fs_fbcount
;
823 sbp
->f_bresvd
= fs
->e2fs
.e2fs_rbcount
;
824 if (sbp
->f_bfree
> sbp
->f_bresvd
)
825 sbp
->f_bavail
= sbp
->f_bfree
- sbp
->f_bresvd
;
828 sbp
->f_files
= fs
->e2fs
.e2fs_icount
;
829 sbp
->f_ffree
= fs
->e2fs
.e2fs_ficount
;
830 sbp
->f_favail
= fs
->e2fs
.e2fs_ficount
;
832 copy_statvfs_info(sbp
, mp
);
837 ext2fs_sync_selector(void *cl
, struct vnode
*vp
)
843 * Skip the vnode/inode if inaccessible.
845 if (ip
== NULL
|| vp
->v_type
== VNON
)
849 (IN_CHANGE
| IN_UPDATE
| IN_MODIFIED
)) == 0 &&
850 LIST_EMPTY(&vp
->v_dirtyblkhd
) &&
851 UVM_OBJ_IS_CLEAN(&vp
->v_uobj
)))
857 * Go through the disk queues to initiate sandbagged IO;
858 * go through the inodes to write those that have been modified;
859 * initiate the writing of the super block if it has been modified.
861 * Note: we are always called with the filesystem marked `MPBUSY'.
864 ext2fs_sync(struct mount
*mp
, int waitfor
, kauth_cred_t cred
)
867 struct ufsmount
*ump
= VFSTOUFS(mp
);
869 struct vnode_iterator
*marker
;
870 int error
, allerror
= 0;
873 if (fs
->e2fs_fmod
!= 0 && fs
->e2fs_ronly
!= 0) { /* XXX */
874 printf("fs = %s\n", fs
->e2fs_fsmnt
);
875 panic("update: rofs mod");
879 * Write back each (modified) inode.
881 vfs_vnode_iterator_init(mp
, &marker
);
882 while ((vp
= vfs_vnode_iterator_next(marker
, ext2fs_sync_selector
,
885 error
= vn_lock(vp
, LK_EXCLUSIVE
);
890 if (vp
->v_type
== VREG
&& waitfor
== MNT_LAZY
)
891 error
= ext2fs_update(vp
, NULL
, NULL
, 0);
893 error
= VOP_FSYNC(vp
, cred
,
894 waitfor
== MNT_WAIT
? FSYNC_WAIT
: 0, 0, 0);
899 vfs_vnode_iterator_destroy(marker
);
901 * Force stale file system control information to be flushed.
903 if (waitfor
!= MNT_LAZY
) {
904 vn_lock(ump
->um_devvp
, LK_EXCLUSIVE
| LK_RETRY
);
905 if ((error
= VOP_FSYNC(ump
->um_devvp
, cred
,
906 waitfor
== MNT_WAIT
? FSYNC_WAIT
: 0, 0, 0)) != 0)
908 VOP_UNLOCK(ump
->um_devvp
);
911 * Write back modified superblock.
913 if (fs
->e2fs_fmod
!= 0) {
915 fs
->e2fs
.e2fs_wtime
= time_second
;
916 if ((error
= ext2fs_cgupdate(ump
, waitfor
)))
923 * Read an inode from disk and initialize this vnode / inode pair.
924 * Caller assures no other thread will try to load this inode.
927 ext2fs_loadvnode(struct mount
*mp
, struct vnode
*vp
,
928 const void *key
, size_t key_len
, const void **new_key
)
933 struct ufsmount
*ump
;
939 KASSERT(key_len
== sizeof(ino
));
940 memcpy(&ino
, key
, key_len
);
945 /* Read in the disk contents for the inode, copy into the inode. */
946 error
= bread(ump
->um_devvp
, EXT2_FSBTODB(fs
, ino_to_fsba(fs
, ino
)),
947 (int)fs
->e2fs_bsize
, 0, &bp
);
951 /* Allocate and initialize inode. */
952 ip
= pool_get(&ext2fs_inode_pool
, PR_WAITOK
);
953 memset(ip
, 0, sizeof(struct inode
));
954 vp
->v_tag
= VT_EXT2FS
;
955 vp
->v_op
= ext2fs_vnodeop_p
;
956 vp
->v_vflag
|= VV_LOCKSWORK
;
963 ip
->i_e2fs_last_lblk
= 0;
964 ip
->i_e2fs_last_blk
= 0;
966 /* Initialize genfs node. */
967 genfs_node_init(vp
, &ext2fs_genfsops
);
969 cp
= (char *)bp
->b_data
+ (ino_to_fsbo(fs
, ino
) * EXT2_DINODE_SIZE(fs
));
970 ip
->i_din
.e2fs_din
= pool_get(&ext2fs_dinode_pool
, PR_WAITOK
);
971 e2fs_iload((struct ext2fs_dinode
*)cp
, ip
->i_din
.e2fs_din
);
972 ext2fs_set_inode_guid(ip
);
975 /* If the inode was deleted, reset all fields */
976 if (ip
->i_e2fs_dtime
!= 0) {
978 (void)ext2fs_setsize(ip
, 0);
979 (void)ext2fs_setnblock(ip
, 0);
980 memset(ip
->i_e2fs_blocks
, 0, sizeof(ip
->i_e2fs_blocks
));
983 /* Initialize the vnode from the inode. */
984 ext2fs_vinit(mp
, ext2fs_specop_p
, ext2fs_fifoop_p
, &vp
);
986 /* Finish inode initialization. */
987 ip
->i_devvp
= ump
->um_devvp
;
991 * Set up a generation number for this inode if it does not
992 * already have one. This should only happen on old filesystems.
995 if (ip
->i_e2fs_gen
== 0) {
996 if (++ext2gennumber
< (u_long
)time_second
)
997 ext2gennumber
= time_second
;
998 ip
->i_e2fs_gen
= ext2gennumber
;
999 if ((mp
->mnt_flag
& MNT_RDONLY
) == 0)
1000 ip
->i_flag
|= IN_MODIFIED
;
1002 uvm_vnp_setsize(vp
, ext2fs_size(ip
));
1003 *new_key
= &ip
->i_number
;
1008 * File handle to vnode
1010 * Have to be really careful about stale file handles:
1011 * - check that the inode number is valid
1012 * - call ext2fs_vget() to get the locked inode
1013 * - check for an unallocated inode (i_mode == 0)
1016 ext2fs_fhtovp(struct mount
*mp
, struct fid
*fhp
, struct vnode
**vpp
)
1022 struct m_ext2fs
*fs
;
1024 if (fhp
->fid_len
!= sizeof(struct ufid
))
1027 memcpy(&ufh
, fhp
, sizeof(struct ufid
));
1028 fs
= VFSTOUFS(mp
)->um_e2fs
;
1029 if ((ufh
.ufid_ino
< EXT2_FIRSTINO
&& ufh
.ufid_ino
!= EXT2_ROOTINO
) ||
1030 ufh
.ufid_ino
>= fs
->e2fs_ncg
* fs
->e2fs
.e2fs_ipg
)
1033 if ((error
= VFS_VGET(mp
, ufh
.ufid_ino
, &nvp
)) != 0) {
1038 if (ip
->i_e2fs_mode
== 0 || ip
->i_e2fs_dtime
!= 0 ||
1039 ip
->i_e2fs_gen
!= ufh
.ufid_gen
) {
1049 * Vnode pointer to File handle
1053 ext2fs_vptofh(struct vnode
*vp
, struct fid
*fhp
, size_t *fh_size
)
1058 if (*fh_size
< sizeof(struct ufid
)) {
1059 *fh_size
= sizeof(struct ufid
);
1062 *fh_size
= sizeof(struct ufid
);
1065 memset(&ufh
, 0, sizeof(ufh
));
1066 ufh
.ufid_len
= sizeof(struct ufid
);
1067 ufh
.ufid_ino
= ip
->i_number
;
1068 ufh
.ufid_gen
= ip
->i_e2fs_gen
;
1069 memcpy(fhp
, &ufh
, sizeof(ufh
));
1074 * Write a superblock and associated information back to disk.
1077 ext2fs_sbupdate(struct ufsmount
*mp
, int waitfor
)
1079 struct m_ext2fs
*fs
= mp
->um_e2fs
;
1083 bp
= getblk(mp
->um_devvp
, SBLOCK
, SBSIZE
, 0, 0);
1084 e2fs_sbsave(&fs
->e2fs
, (struct ext2fs
*)bp
->b_data
);
1085 if (waitfor
== MNT_WAIT
)
1093 ext2fs_cgupdate(struct ufsmount
*mp
, int waitfor
)
1095 struct m_ext2fs
*fs
= mp
->um_e2fs
;
1097 int i
, error
= 0, allerror
= 0;
1099 allerror
= ext2fs_sbupdate(mp
, waitfor
);
1100 for (i
= 0; i
< fs
->e2fs_ngdb
; i
++) {
1101 bp
= getblk(mp
->um_devvp
, EXT2_FSBTODB(fs
,
1102 fs
->e2fs
.e2fs_first_dblock
+
1103 1 /* superblock */ + i
), fs
->e2fs_bsize
, 0, 0);
1104 e2fs_cgsave(&fs
->e2fs_gd
[
1105 i
* fs
->e2fs_bsize
/ sizeof(struct ext2_gd
)],
1106 (struct ext2_gd
*)bp
->b_data
, fs
->e2fs_bsize
);
1107 if (waitfor
== MNT_WAIT
)
1113 if (!allerror
&& error
)
1119 * Fill in the m_fs structure, and validate the fields of the superblock.
1120 * NOTE: here, the superblock is already swapped.
1123 ext2fs_sbfill(struct m_ext2fs
*m_fs
, int ronly
)
1126 struct ext2fs
*fs
= &m_fs
->e2fs
;
1129 * General sanity checks
1131 if (fs
->e2fs_magic
!= E2FS_MAGIC
)
1133 if (fs
->e2fs_rev
> E2FS_REV1
) {
1134 printf("ext2fs: unsupported revision number: %x\n", fs
->e2fs_rev
);
1137 if (fs
->e2fs_log_bsize
> 2) {
1138 /* block size = 1024|2048|4096 */
1139 printf("ext2fs: bad block size: %d\n", fs
->e2fs_log_bsize
);
1142 if (fs
->e2fs_bpg
== 0) {
1143 printf("ext2fs: zero blocks per group\n");
1146 if (fs
->e2fs_ipg
== 0) {
1147 printf("ext2fs: zero inodes per group\n");
1151 if (fs
->e2fs_first_dblock
>= fs
->e2fs_bcount
) {
1152 printf("ext2fs: invalid first data block\n");
1155 if (fs
->e2fs_rbcount
> fs
->e2fs_bcount
||
1156 fs
->e2fs_fbcount
> fs
->e2fs_bcount
) {
1157 printf("ext2fs: invalid block count\n");
1162 * Revision-specific checks
1164 if (fs
->e2fs_rev
> E2FS_REV0
) {
1166 if (fs
->e2fs_first_ino
!= EXT2_FIRSTINO
) {
1167 printf("ext2fs: unsupported first inode position\n");
1170 u32
= fs
->e2fs_features_incompat
& ~EXT2F_INCOMPAT_SUPP
;
1172 snprintb(buf
, sizeof(buf
), EXT2F_INCOMPAT_BITS
, u32
);
1173 printf("ext2fs: unsupported incompat features: %s\n", buf
);
1176 u32
= fs
->e2fs_features_rocompat
& ~EXT2F_ROCOMPAT_SUPP
;
1177 if (!ronly
&& u32
) {
1178 snprintb(buf
, sizeof(buf
), EXT2F_ROCOMPAT_BITS
, u32
);
1179 printf("ext2fs: unsupported ro-incompat features: %s\n",
1183 if (fs
->e2fs_inode_size
== 0 || !powerof2(fs
->e2fs_inode_size
)) {
1184 printf("ext2fs: bad inode size\n");
1190 * Compute the fields of the superblock
1192 u32
= fs
->e2fs_bcount
- fs
->e2fs_first_dblock
; /* > 0 */
1193 m_fs
->e2fs_ncg
= howmany(u32
, fs
->e2fs_bpg
);
1194 if (m_fs
->e2fs_ncg
== 0) {
1195 printf("ext2fs: invalid number of cylinder groups\n");
1199 m_fs
->e2fs_fsbtodb
= fs
->e2fs_log_bsize
+ LOG_MINBSIZE
- DEV_BSHIFT
;
1200 m_fs
->e2fs_bsize
= MINBSIZE
<< fs
->e2fs_log_bsize
;
1201 m_fs
->e2fs_bshift
= LOG_MINBSIZE
+ fs
->e2fs_log_bsize
;
1202 m_fs
->e2fs_qbmask
= m_fs
->e2fs_bsize
- 1;
1203 m_fs
->e2fs_bmask
= ~m_fs
->e2fs_qbmask
;
1205 if ((u32
= m_fs
->e2fs_bsize
/ sizeof(struct ext2_gd
)) == 0) {
1206 /* Unlikely to happen */
1207 printf("ext2fs: invalid block size\n");
1210 m_fs
->e2fs_ngdb
= howmany(m_fs
->e2fs_ncg
, u32
);
1211 if (m_fs
->e2fs_ngdb
== 0) {
1212 printf("ext2fs: invalid number of group descriptor blocks\n");
1216 if (m_fs
->e2fs_bsize
< EXT2_DINODE_SIZE(m_fs
)) {
1217 printf("ext2fs: invalid inode size\n");
1220 m_fs
->e2fs_ipb
= m_fs
->e2fs_bsize
/ EXT2_DINODE_SIZE(m_fs
);
1222 m_fs
->e2fs_itpg
= fs
->e2fs_ipg
/ m_fs
->e2fs_ipb
;