2 * modified for EXT2FS support in Lites 1.1
4 * Aug 1995, Godmar Back (gback@cs.utah.edu)
5 * University of Utah, Department of Computer Science
8 * Copyright (c) 1989, 1991, 1993, 1994
9 * The Regents of the University of California. All rights reserved.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * @(#)ffs_vfsops.c 8.8 (Berkeley) 4/18/94
40 * $FreeBSD: src/sys/gnu/ext2fs/ext2_vfsops.c,v 1.63.2.7 2002/07/01 00:18:51 iedowse Exp $
41 * $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_vfsops.c,v 1.57 2008/09/17 21:44:21 dillon Exp $
44 #include "opt_quota.h"
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/nlookup.h>
51 #include <sys/kernel.h>
52 #include <sys/vnode.h>
53 #include <sys/mount.h>
56 #include <sys/fcntl.h>
57 #include <sys/diskslice.h>
58 #include <sys/malloc.h>
60 #include <vm/vm_zone.h>
63 #include <sys/thread2.h>
68 #include "ext2mount.h"
69 #include "ext2_extern.h"
73 #include "ext2_fs_sb.h"
75 extern struct vop_ops ext2_vnode_vops
;
76 extern struct vop_ops ext2_spec_vops
;
77 extern struct vop_ops ext2_fifo_vops
;
79 static int ext2_fhtovp (struct mount
*, struct vnode
*,
80 struct fid
*, struct vnode
**);
81 static int ext2_flushfiles (struct mount
*mp
, int flags
);
82 static int ext2_mount (struct mount
*, char *, caddr_t
, struct ucred
*);
83 static int ext2_mountfs (struct vnode
*, struct mount
*, struct ucred
*);
84 static int ext2_root(struct mount
*, struct vnode
**);
85 static int ext2_reload (struct mount
*mountp
, struct ucred
*cred
);
86 static int ext2_sbupdate (struct ext2mount
*, int);
87 static int ext2_statfs (struct mount
*, struct statfs
*, struct ucred
*);
88 static int ext2_sync (struct mount
*, int);
89 static int ext2_unmount (struct mount
*, int);
90 static int ext2_vget (struct mount
*, struct vnode
*, ino_t
, struct vnode
**);
91 static int ext2_init(struct vfsconf
*);
92 static int ext2_vptofh (struct vnode
*, struct fid
*);
94 static MALLOC_DEFINE(M_EXT2NODE
, "EXT2 node", "EXT2 vnode private part");
95 MALLOC_DEFINE(M_EXT2MNT
, "EXT2 mount", "EXT2 mount structure");
97 static struct vfsops ext2fs_vfsops
= {
98 .vfs_mount
= ext2_mount
,
99 .vfs_unmount
= ext2_unmount
,
100 .vfs_root
= ext2_root
, /* root inode via vget */
101 .vfs_quotactl
= ext2_quotactl
, /* quota operations */
102 .vfs_statfs
= ext2_statfs
,
103 .vfs_sync
= ext2_sync
,
104 .vfs_vget
= ext2_vget
,
105 .vfs_fhtovp
= ext2_fhtovp
,
106 .vfs_checkexp
= ext2_check_export
,
107 .vfs_vptofh
= ext2_vptofh
,
108 .vfs_init
= ext2_init
,
109 .vfs_uninit
= ext2_uninit
112 VFS_SET(ext2fs_vfsops
, ext2fs
, 0);
113 #define bsd_malloc kmalloc
114 #define bsd_free kfree
116 static int ext2fs_inode_hash_lock
;
118 static int ext2_check_sb_compat (struct ext2_super_block
*es
,
119 cdev_t dev
, int ronly
);
120 static int compute_sb_data (struct vnode
* devvp
,
121 struct ext2_super_block
* es
,
122 struct ext2_sb_info
* fs
);
125 ext2_root(struct mount
*mp
, struct vnode
**vpp
)
130 error
= VFS_VGET(mp
, NULL
, (ino_t
)ROOTINO
, &nvp
);
138 * Do operations associated with quotas
141 ext2_quotactl(struct mount
*mp
, int cmds
, uid_t uid
, caddr_t arg
,
147 int cmd
, type
, error
;
149 type
= cmds
& SUBCMDMASK
;
150 cmd
= cmds
>> SUBCMDSHIFT
;
171 error
= priv_check_cred(cred
, PRIV_UFS_QUOTAON
, 0);
175 error
= priv_check_cred(cred
, PRIV_UFS_QUOTAOFF
, 0);
179 error
= priv_check_cred(cred
, PRIV_VFS_SETQUOTA
, 0);
183 error
= priv_check_cred(cred
, PRIV_UFS_SETUSE
, 0);
187 if (uid
== cred
->cr_ruid
)
190 error
= priv_check_cred(cred
, PRIV_VFS_GETQUOTA
, 0);
206 if ((uint
)type
>= MAXQUOTAS
)
208 if (vfs_busy(mp
, LK_NOWAIT
))
214 error
= ext2_quotaon(cred
, mp
, type
, arg
);
218 error
= ext2_quotaoff(mp
, type
);
222 error
= ext2_setquota(mp
, uid
, type
, arg
);
226 error
= ext2_setuse(mp
, uid
, type
, arg
);
230 error
= ext2_getquota(mp
, uid
, type
, arg
);
234 error
= ext2_qsync(mp
);
247 * Initial UFS filesystems, done only once.
250 ext2_init(struct vfsconf
*vfsp
)
270 * data: this is actually a (struct ext2_args *)
273 ext2_mount(struct mount
*mp
, char *path
, caddr_t data
, struct ucred
*cred
)
276 struct ext2_args args
;
277 struct ext2mount
*ump
= 0;
278 struct ext2_sb_info
*fs
;
282 struct nlookupdata nd
;
284 if ((error
= copyin(data
, (caddr_t
)&args
, sizeof (struct ext2_args
))) != 0)
288 * If updating, check whether changing from read-only to
289 * read/write; if there is no device name, that's all we do.
291 if (mp
->mnt_flag
& MNT_UPDATE
) {
294 devvp
= ump
->um_devvp
;
296 if (fs
->s_rd_only
== 0 && (mp
->mnt_flag
& MNT_RDONLY
)) {
298 if (mp
->mnt_flag
& MNT_FORCE
)
300 if (vfs_busy(mp
, LK_NOWAIT
))
302 error
= ext2_flushfiles(mp
, flags
);
304 if (!error
&& fs
->s_wasvalid
) {
305 fs
->s_es
->s_state
|= EXT2_VALID_FS
;
306 ext2_sbupdate(ump
, MNT_WAIT
);
309 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
310 VOP_OPEN(devvp
, FREAD
, FSCRED
, NULL
);
311 VOP_CLOSE(devvp
, FREAD
|FWRITE
);
314 if (!error
&& (mp
->mnt_flag
& MNT_RELOAD
))
315 error
= ext2_reload(mp
, cred
);
318 if (ext2_check_sb_compat(fs
->s_es
, devvp
->v_rdev
,
319 (mp
->mnt_kern_flag
& MNTK_WANTRDWR
) == 0) != 0)
321 if (fs
->s_rd_only
&& (mp
->mnt_kern_flag
& MNTK_WANTRDWR
)) {
323 * If upgrade to read-write by non-root, then verify
324 * that user has necessary permissions on the device.
326 if (cred
->cr_uid
!= 0) {
327 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
328 error
= VOP_EACCESS(devvp
, VREAD
| VWRITE
, cred
);
336 if ((fs
->s_es
->s_state
& EXT2_VALID_FS
) == 0 ||
337 (fs
->s_es
->s_state
& EXT2_ERROR_FS
)) {
338 if (mp
->mnt_flag
& MNT_FORCE
) {
340 "WARNING: %s was not properly dismounted\n",
344 "WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n",
349 fs
->s_es
->s_state
&= ~EXT2_VALID_FS
;
350 ext2_sbupdate(ump
, MNT_WAIT
);
352 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
353 VOP_OPEN(devvp
, FREAD
|FWRITE
, FSCRED
, NULL
);
354 VOP_CLOSE(devvp
, FREAD
);
357 if (args
.fspec
== 0) {
359 * Process export requests.
361 return (vfs_export(mp
, &ump
->um_export
, &args
.export
));
365 * Not an update, or updating the name: look up the name
366 * and verify that it refers to a sensible block device.
369 error
= nlookup_init(&nd
, args
.fspec
, UIO_USERSPACE
, NLC_FOLLOW
);
371 error
= nlookup(&nd
);
373 error
= cache_vref(&nd
.nl_nch
, nd
.nl_cred
, &devvp
);
378 if (!vn_isdisk(devvp
, &error
)) {
384 * If mount by non-root, then verify that user has necessary
385 * permissions on the device.
387 if (cred
->cr_uid
!= 0) {
389 if ((mp
->mnt_flag
& MNT_RDONLY
) == 0)
390 accessmode
|= VWRITE
;
391 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
392 if ((error
= VOP_EACCESS(devvp
, accessmode
, cred
)) != 0) {
399 if ((mp
->mnt_flag
& MNT_UPDATE
) == 0) {
400 error
= ext2_mountfs(devvp
, mp
, cred
);
402 if (devvp
!= ump
->um_devvp
)
403 error
= EINVAL
; /* needs translation */
413 copyinstr(path
, fs
->fs_fsmnt
, sizeof(fs
->fs_fsmnt
) - 1, &size
);
414 bzero(fs
->fs_fsmnt
+ size
, sizeof(fs
->fs_fsmnt
) - size
);
415 copyinstr(args
.fspec
, mp
->mnt_stat
.f_mntfromname
, MNAMELEN
- 1, &size
);
416 bzero(mp
->mnt_stat
.f_mntfromname
+ size
, MNAMELEN
- size
);
417 ext2_statfs(mp
, &mp
->mnt_stat
, cred
);
422 * checks that the data in the descriptor blocks make sense
423 * this is taken from ext2/super.c
426 ext2_check_descriptors(struct ext2_sb_info
*sb
)
430 unsigned long block
= sb
->s_es
->s_first_data_block
;
431 struct ext2_group_desc
* gdp
= NULL
;
433 /* ext2_debug ("Checking group descriptors"); */
435 for (i
= 0; i
< sb
->s_groups_count
; i
++)
437 /* examine next descriptor block */
438 if ((i
% EXT2_DESC_PER_BLOCK(sb
)) == 0)
439 gdp
= (struct ext2_group_desc
*)
440 sb
->s_group_desc
[desc_block
++]->b_data
;
441 if (gdp
->bg_block_bitmap
< block
||
442 gdp
->bg_block_bitmap
>= block
+ EXT2_BLOCKS_PER_GROUP(sb
))
444 kprintf ("ext2_check_descriptors: "
445 "Block bitmap for group %d"
446 " not in group (block %lu)!\n",
447 i
, (unsigned long) gdp
->bg_block_bitmap
);
450 if (gdp
->bg_inode_bitmap
< block
||
451 gdp
->bg_inode_bitmap
>= block
+ EXT2_BLOCKS_PER_GROUP(sb
))
453 kprintf ("ext2_check_descriptors: "
454 "Inode bitmap for group %d"
455 " not in group (block %lu)!\n",
456 i
, (unsigned long) gdp
->bg_inode_bitmap
);
459 if (gdp
->bg_inode_table
< block
||
460 gdp
->bg_inode_table
+ sb
->s_itb_per_group
>=
461 block
+ EXT2_BLOCKS_PER_GROUP(sb
))
463 kprintf ("ext2_check_descriptors: "
464 "Inode table for group %d"
465 " not in group (block %lu)!\n",
466 i
, (unsigned long) gdp
->bg_inode_table
);
469 block
+= EXT2_BLOCKS_PER_GROUP(sb
);
476 ext2_check_sb_compat(struct ext2_super_block
*es
, cdev_t dev
, int ronly
)
478 if (es
->s_magic
!= EXT2_SUPER_MAGIC
) {
479 kprintf("ext2fs: %s: wrong magic number %#x (expected %#x)\n",
480 devtoname(dev
), es
->s_magic
, EXT2_SUPER_MAGIC
);
483 if (es
->s_rev_level
> EXT2_GOOD_OLD_REV
) {
484 if (es
->s_feature_incompat
& ~EXT2_FEATURE_INCOMPAT_SUPP
) {
486 "WARNING: mount of %s denied due to unsupported optional features\n",
491 (es
->s_feature_ro_compat
& ~EXT2_FEATURE_RO_COMPAT_SUPP
)) {
493 "WARNING: R/W mount of %s denied due to unsupported optional features\n",
502 * this computes the fields of the ext2_sb_info structure from the
503 * data in the ext2_super_block structure read in
506 compute_sb_data(struct vnode
*devvp
, struct ext2_super_block
*es
,
507 struct ext2_sb_info
*fs
)
511 int logic_sb_block
= 1; /* XXX for now */
516 #define V(v) kprintf(#v"= %d\n", fs->v);
519 fs
->s_blocksize
= EXT2_MIN_BLOCK_SIZE
<< es
->s_log_block_size
;
521 fs
->s_bshift
= EXT2_MIN_BLOCK_LOG_SIZE
+ es
->s_log_block_size
;
523 fs
->s_fsbtodb
= es
->s_log_block_size
+ 1;
525 fs
->s_qbmask
= fs
->s_blocksize
- 1;
527 fs
->s_blocksize_bits
= EXT2_BLOCK_SIZE_BITS(es
);
529 fs
->s_frag_size
= EXT2_MIN_FRAG_SIZE
<< es
->s_log_frag_size
;
532 fs
->s_frags_per_block
= fs
->s_blocksize
/ fs
->s_frag_size
;
534 fs
->s_blocks_per_group
= es
->s_blocks_per_group
;
535 V(s_blocks_per_group
)
536 fs
->s_frags_per_group
= es
->s_frags_per_group
;
538 fs
->s_inodes_per_group
= es
->s_inodes_per_group
;
539 V(s_inodes_per_group
)
540 if (es
->s_rev_level
== EXT2_GOOD_OLD_REV
) {
541 fs
->s_first_ino
= EXT2_GOOD_OLD_FIRST_INO
;
542 fs
->s_inode_size
= EXT2_GOOD_OLD_INODE_SIZE
;
544 fs
->s_first_ino
= es
->s_first_ino
;
545 fs
->s_inode_size
= es
->s_inode_size
;
547 * Simple sanity check for superblock inode size value.
549 if (fs
->s_inode_size
< EXT2_GOOD_OLD_INODE_SIZE
||
550 fs
->s_inode_size
> fs
->s_blocksize
||
551 (fs
->s_inode_size
& (fs
->s_inode_size
- 1)) != 0) {
552 kprintf("EXT2-fs: invalid inode size %d\n",
559 fs
->s_inodes_per_block
= fs
->s_blocksize
/ EXT2_INODE_SIZE(fs
);
560 V(s_inodes_per_block
)
561 fs
->s_itb_per_group
= fs
->s_inodes_per_group
/fs
->s_inodes_per_block
;
563 fs
->s_desc_per_block
= fs
->s_blocksize
/ sizeof (struct ext2_group_desc
);
565 /* s_resuid / s_resgid ? */
566 fs
->s_groups_count
= (es
->s_blocks_count
-
567 es
->s_first_data_block
+
568 EXT2_BLOCKS_PER_GROUP(fs
) - 1) /
569 EXT2_BLOCKS_PER_GROUP(fs
);
571 db_count
= (fs
->s_groups_count
+ EXT2_DESC_PER_BLOCK(fs
) - 1) /
572 EXT2_DESC_PER_BLOCK(fs
);
573 fs
->s_db_per_group
= db_count
;
576 fs
->s_group_desc
= bsd_malloc(db_count
* sizeof (struct buf
*),
577 M_EXT2MNT
, M_WAITOK
);
579 /* adjust logic_sb_block */
580 if(fs
->s_blocksize
> SBSIZE
)
581 /* Godmar thinks: if the blocksize is greater than 1024, then
582 the superblock is logically part of block zero.
586 for (i
= 0; i
< db_count
; i
++) {
587 error
= bread(devvp
, fsbtodoff(fs
, logic_sb_block
+ i
+ 1),
588 fs
->s_blocksize
, &fs
->s_group_desc
[i
]);
590 for (j
= 0; j
< i
; j
++)
591 brelse(fs
->s_group_desc
[j
]);
592 bsd_free(fs
->s_group_desc
, M_EXT2MNT
);
593 kprintf("EXT2-fs: unable to read group descriptors (%d)\n", error
);
596 /* Set the B_LOCKED flag on the buffer, then brelse() it */
597 LCK_BUF(fs
->s_group_desc
[i
])
599 if(!ext2_check_descriptors(fs
)) {
600 for (j
= 0; j
< db_count
; j
++)
601 ULCK_BUF(fs
->s_group_desc
[j
])
602 bsd_free(fs
->s_group_desc
, M_EXT2MNT
);
603 kprintf("EXT2-fs: (ext2_check_descriptors failure) "
604 "unable to read group descriptors\n");
608 for (i
= 0; i
< EXT2_MAX_GROUP_LOADED
; i
++) {
609 fs
->s_inode_bitmap_number
[i
] = 0;
610 fs
->s_inode_bitmap
[i
] = NULL
;
611 fs
->s_block_bitmap_number
[i
] = 0;
612 fs
->s_block_bitmap
[i
] = NULL
;
614 fs
->s_loaded_inode_bitmaps
= 0;
615 fs
->s_loaded_block_bitmaps
= 0;
620 * Reload all incore data for a filesystem (used after running fsck on
621 * the root filesystem and finding things to fix). The filesystem must
622 * be mounted read-only.
624 * Things to do to update the mount:
625 * 1) invalidate all cached meta-data.
626 * 2) re-read superblock from disk.
627 * 3) re-read summary information from disk.
628 * 4) invalidate all inactive vnodes.
629 * 5) invalidate all cached file data.
630 * 6) re-read inode data for all active vnodes.
632 static int ext2_reload_scan1(struct mount
*mp
, struct vnode
*vp
, void *rescan
);
633 static int ext2_reload_scan2(struct mount
*mp
, struct vnode
*vp
, void *rescan
);
640 struct ext2_sb_info
*fs
;
644 ext2_reload(struct mount
*mountp
, struct ucred
*cred
)
648 struct ext2_super_block
* es
;
649 struct ext2_sb_info
*fs
;
651 struct scaninfo scaninfo
;
653 if ((mountp
->mnt_flag
& MNT_RDONLY
) == 0)
656 * Step 1: invalidate all cached meta-data.
658 devvp
= VFSTOEXT2(mountp
)->um_devvp
;
659 if (vinvalbuf(devvp
, 0, 0, 0))
660 panic("ext2_reload: dirty1");
662 * Step 2: re-read superblock from disk.
663 * constants have been adjusted for ext2
665 if ((error
= bread(devvp
, SBOFF
, SBSIZE
, &bp
)) != 0)
667 es
= (struct ext2_super_block
*)bp
->b_data
;
668 if (ext2_check_sb_compat(es
, devvp
->v_rdev
, 0) != 0) {
670 return (EIO
); /* XXX needs translation */
672 fs
= VFSTOEXT2(mountp
)->um_e2fs
;
673 bcopy(bp
->b_data
, fs
->s_es
, sizeof(struct ext2_super_block
));
675 if((error
= compute_sb_data(devvp
, es
, fs
)) != 0) {
680 if (fs
->fs_sbsize
< SBSIZE
)
681 bp
->b_flags
|= B_INVAL
;
686 scaninfo
.devvp
= devvp
;
688 while (error
== 0 && scaninfo
.rescan
) {
690 error
= vmntvnodescan(mountp
, VMSC_GETVX
, ext2_reload_scan1
,
691 ext2_reload_scan2
, &scaninfo
);
697 ext2_reload_scan1(struct mount
*mp
, struct vnode
*vp
, void *data
)
699 /*struct scaninfo *info = data;*/
705 ext2_reload_scan2(struct mount
*mp
, struct vnode
*vp
, void *data
)
707 struct scaninfo
*info
= data
;
719 * Step 5: invalidate all cached file data.
721 if (vinvalbuf(vp
, 0, 0, 0))
722 panic("ext2_reload: dirty2");
724 * Step 6: re-read inode data for all active vnodes.
727 error
= bread(info
->devvp
,
728 fsbtodoff(info
->fs
, ino_to_fsba(info
->fs
, ip
->i_number
)),
729 (int)info
->fs
->s_blocksize
, &bp
);
732 ext2_ei2di((struct ext2_inode
*) ((char *)bp
->b_data
+
733 EXT2_INODE_SIZE(info
->fs
) * ino_to_fsbo(info
->fs
, ip
->i_number
)),
740 * Common code for mount and mountroot
743 ext2_mountfs(struct vnode
*devvp
, struct mount
*mp
, struct ucred
*cred
)
745 struct ext2mount
*ump
;
747 struct ext2_sb_info
*fs
;
748 struct ext2_super_block
* es
;
750 struct partinfo dpart
;
755 * Disallow multiple mounts of the same device.
756 * Disallow mounting of a device that is currently in use
757 * (except for root, which might share swap device for miniroot).
758 * Flush out any old buffers remaining from a previous use.
760 if ((error
= vfs_mountedon(devvp
)) != 0)
762 if (vcount(devvp
) > 0)
764 if ((error
= vinvalbuf(devvp
, V_SAVE
, 0, 0)) != 0)
767 /* turn on this to force it to be read-only */
768 mp
->mnt_flag
|= MNT_RDONLY
;
771 ronly
= (mp
->mnt_flag
& MNT_RDONLY
) != 0;
772 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
773 error
= VOP_OPEN(devvp
, ronly
? FREAD
: FREAD
|FWRITE
, FSCRED
, NULL
);
778 if (dev
->si_iosize_max
!= 0)
779 mp
->mnt_iosize_max
= dev
->si_iosize_max
;
780 if (mp
->mnt_iosize_max
> MAXPHYS
)
781 mp
->mnt_iosize_max
= MAXPHYS
;
782 VOP_IOCTL(devvp
, DIOCGPART
, (caddr_t
)&dpart
, FREAD
, cred
, NULL
);
786 if ((error
= bread(devvp
, SBOFF
, SBSIZE
, &bp
)) != 0)
788 es
= (struct ext2_super_block
*)bp
->b_data
;
789 if (ext2_check_sb_compat(es
, dev
, ronly
) != 0) {
790 error
= EINVAL
; /* XXX needs translation */
793 if ((es
->s_state
& EXT2_VALID_FS
) == 0 ||
794 (es
->s_state
& EXT2_ERROR_FS
)) {
795 if (ronly
|| (mp
->mnt_flag
& MNT_FORCE
)) {
797 "WARNING: Filesystem was not properly dismounted\n");
800 "WARNING: R/W mount denied. Filesystem is not clean - run fsck\n");
805 ump
= bsd_malloc(sizeof *ump
, M_EXT2MNT
, M_WAITOK
| M_ZERO
);
806 ump
->um_malloctype
= M_EXT2NODE
;
807 ump
->um_blkatoff
= ext2_blkatoff
;
808 ump
->um_truncate
= ext2_truncate
;
809 ump
->um_update
= ext2_update
;
810 ump
->um_valloc
= ext2_valloc
;
811 ump
->um_vfree
= ext2_vfree
;
812 /* I don't know whether this is the right strategy. Note that
813 we dynamically allocate both a ext2_sb_info and a ext2_super_block
814 while Linux keeps the super block in a locked buffer
816 ump
->um_e2fs
= bsd_malloc(sizeof(struct ext2_sb_info
),
817 M_EXT2MNT
, M_WAITOK
);
818 ump
->um_e2fs
->s_es
= bsd_malloc(sizeof(struct ext2_super_block
),
819 M_EXT2MNT
, M_WAITOK
);
820 bcopy(es
, ump
->um_e2fs
->s_es
, (u_int
)sizeof(struct ext2_super_block
));
821 if ((error
= compute_sb_data(devvp
, ump
->um_e2fs
->s_es
, ump
->um_e2fs
)))
824 * We don't free the group descriptors allocated by compute_sb_data()
825 * until ext2_unmount(). This is OK since the mount will succeed.
830 fs
->s_rd_only
= ronly
; /* ronly is set according to mnt_flags */
831 /* if the fs is not mounted read-only, make sure the super block is
832 always written back on a sync()
834 fs
->s_wasvalid
= fs
->s_es
->s_state
& EXT2_VALID_FS
? 1 : 0;
836 fs
->s_dirt
= 1; /* mark it modified */
837 fs
->s_es
->s_state
&= ~EXT2_VALID_FS
; /* set fs invalid */
839 mp
->mnt_data
= (qaddr_t
)ump
;
840 mp
->mnt_stat
.f_fsid
.val
[0] = dev2udev(dev
);
841 mp
->mnt_stat
.f_fsid
.val
[1] = mp
->mnt_vfc
->vfc_typenum
;
842 mp
->mnt_maxsymlinklen
= EXT2_MAXSYMLINKLEN
;
843 mp
->mnt_flag
|= MNT_LOCAL
;
846 ump
->um_devvp
= devvp
;
847 /* setting those two parameters allows us to use
848 ext2_bmap w/o changse !
850 ump
->um_nindir
= EXT2_ADDR_PER_BLOCK(fs
);
851 ump
->um_bptrtodb
= fs
->s_es
->s_log_block_size
+ 1;
852 ump
->um_seqinc
= EXT2_FRAGS_PER_BLOCK(fs
);
853 for (i
= 0; i
< MAXQUOTAS
; i
++)
854 ump
->um_quotas
[i
] = NULLVP
;
855 dev
->si_mountpoint
= mp
;
857 vfs_add_vnodeops(mp
, &ext2_vnode_vops
, &mp
->mnt_vn_norm_ops
);
858 vfs_add_vnodeops(mp
, &ext2_spec_vops
, &mp
->mnt_vn_spec_ops
);
859 vfs_add_vnodeops(mp
, &ext2_fifo_vops
, &mp
->mnt_vn_fifo_ops
);
862 ext2_sbupdate(ump
, MNT_WAIT
);
867 VOP_CLOSE(devvp
, ronly
? FREAD
: FREAD
|FWRITE
);
869 bsd_free(ump
->um_e2fs
->s_es
, M_EXT2MNT
);
870 bsd_free(ump
->um_e2fs
, M_EXT2MNT
);
871 bsd_free(ump
, M_EXT2MNT
);
872 mp
->mnt_data
= (qaddr_t
)0;
878 * unmount system call
881 ext2_unmount(struct mount
*mp
, int mntflags
)
883 struct ext2mount
*ump
;
884 struct ext2_sb_info
*fs
;
885 int error
, flags
, ronly
, i
;
888 if (mntflags
& MNT_FORCE
) {
889 if (mp
->mnt_flag
& MNT_ROOTFS
)
893 if ((error
= ext2_flushfiles(mp
, flags
)) != 0)
897 ronly
= fs
->s_rd_only
;
900 fs
->s_es
->s_state
|= EXT2_VALID_FS
;
901 ext2_sbupdate(ump
, MNT_WAIT
);
904 /* release buffers containing group descriptors */
905 for(i
= 0; i
< fs
->s_db_per_group
; i
++)
906 ULCK_BUF(fs
->s_group_desc
[i
])
907 bsd_free(fs
->s_group_desc
, M_EXT2MNT
);
909 /* release cached inode/block bitmaps */
910 for (i
= 0; i
< EXT2_MAX_GROUP_LOADED
; i
++)
911 if (fs
->s_inode_bitmap
[i
])
912 ULCK_BUF(fs
->s_inode_bitmap
[i
])
914 for (i
= 0; i
< EXT2_MAX_GROUP_LOADED
; i
++)
915 if (fs
->s_block_bitmap
[i
])
916 ULCK_BUF(fs
->s_block_bitmap
[i
])
918 ump
->um_devvp
->v_rdev
->si_mountpoint
= NULL
;
919 error
= VOP_CLOSE(ump
->um_devvp
, ronly
? FREAD
: FREAD
|FWRITE
);
920 vrele(ump
->um_devvp
);
921 bsd_free(fs
->s_es
, M_EXT2MNT
);
922 bsd_free(fs
, M_EXT2MNT
);
923 bsd_free(ump
, M_EXT2MNT
);
924 mp
->mnt_data
= (qaddr_t
)0;
925 mp
->mnt_flag
&= ~MNT_LOCAL
;
930 * Flush out all the files in a filesystem.
933 ext2_flushfiles(struct mount
*mp
, int flags
)
935 struct ext2mount
*ump
;
943 if (mp
->mnt_flag
& MNT_QUOTA
) {
944 if ((error
= vflush(mp
, 0, SKIPSYSTEM
|flags
)) != 0)
946 for (i
= 0; i
< MAXQUOTAS
; i
++) {
947 if (ump
->um_quotas
[i
] == NULLVP
)
949 ext2_quotaoff(mp
, i
);
952 * Here we fall through to vflush again to ensure
953 * that we have gotten rid of all the system vnodes.
957 error
= vflush(mp
, 0, flags
);
962 * Get file system statistics.
963 * taken from ext2/super.c ext2_statfs
966 ext2_statfs(struct mount
*mp
, struct statfs
*sbp
, struct ucred
*cred
)
968 unsigned long overhead
;
969 struct ext2mount
*ump
;
970 struct ext2_sb_info
*fs
;
971 struct ext2_super_block
*es
;
978 if (es
->s_magic
!= EXT2_SUPER_MAGIC
)
979 panic("ext2_statfs - magic number spoiled");
982 * Compute the overhead (FS structures)
984 if (es
->s_feature_ro_compat
& EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
) {
986 for (i
= 0 ; i
< fs
->s_groups_count
; i
++)
987 if (ext2_group_sparse(i
))
990 nsb
= fs
->s_groups_count
;
991 overhead
= es
->s_first_data_block
+
992 /* Superblocks and block group descriptors: */
993 nsb
* (1 + fs
->s_db_per_group
) +
994 /* Inode bitmap, block bitmap, and inode table: */
995 fs
->s_groups_count
* (1 + 1 + fs
->s_itb_per_group
);
997 sbp
->f_bsize
= EXT2_FRAG_SIZE(fs
);
998 sbp
->f_iosize
= EXT2_BLOCK_SIZE(fs
);
999 sbp
->f_blocks
= es
->s_blocks_count
- overhead
;
1000 sbp
->f_bfree
= es
->s_free_blocks_count
;
1001 sbp
->f_bavail
= sbp
->f_bfree
- es
->s_r_blocks_count
;
1002 sbp
->f_files
= es
->s_inodes_count
;
1003 sbp
->f_ffree
= es
->s_free_inodes_count
;
1004 if (sbp
!= &mp
->mnt_stat
) {
1005 sbp
->f_type
= mp
->mnt_vfc
->vfc_typenum
;
1006 bcopy((caddr_t
)mp
->mnt_stat
.f_mntfromname
,
1007 (caddr_t
)&sbp
->f_mntfromname
[0], MNAMELEN
);
1013 * Go through the disk queues to initiate sandbagged IO;
1014 * go through the inodes to write those that have been modified;
1015 * initiate the writing of the super block if it has been modified.
1017 * Note: we are always called with the filesystem marked `MPBUSY'.
1020 static int ext2_sync_scan(struct mount
*mp
, struct vnode
*vp
, void *data
);
1023 ext2_sync(struct mount
*mp
, int waitfor
)
1025 struct ext2mount
*ump
= VFSTOEXT2(mp
);
1026 struct ext2_sb_info
*fs
;
1027 struct scaninfo scaninfo
;
1031 if (fs
->s_dirt
!= 0 && fs
->s_rd_only
!= 0) { /* XXX */
1032 kprintf("fs = %s\n", fs
->fs_fsmnt
);
1033 panic("ext2_sync: rofs mod");
1037 * Write back each (modified) inode.
1039 scaninfo
.allerror
= 0;
1040 scaninfo
.rescan
= 1;
1041 scaninfo
.waitfor
= waitfor
;
1042 while (scaninfo
.rescan
) {
1043 scaninfo
.rescan
= 0;
1044 vmntvnodescan(mp
, VMSC_GETVP
|VMSC_NOWAIT
,
1045 NULL
, ext2_sync_scan
, &scaninfo
);
1049 * Force stale file system control information to be flushed.
1051 if ((waitfor
& MNT_LAZY
) == 0) {
1052 vn_lock(ump
->um_devvp
, LK_EXCLUSIVE
| LK_RETRY
);
1053 if ((error
= VOP_FSYNC(ump
->um_devvp
, waitfor
, 0)) != 0)
1054 scaninfo
.allerror
= error
;
1055 vn_unlock(ump
->um_devvp
);
1061 * Write back modified superblock.
1063 if (fs
->s_dirt
!= 0) {
1065 fs
->s_es
->s_wtime
= time_second
;
1066 if ((error
= ext2_sbupdate(ump
, waitfor
)) != 0)
1067 scaninfo
.allerror
= error
;
1069 return (scaninfo
.allerror
);
1073 ext2_sync_scan(struct mount
*mp
, struct vnode
*vp
, void *data
)
1075 struct scaninfo
*info
= data
;
1080 if (vp
->v_type
== VNON
||
1082 (IN_ACCESS
| IN_CHANGE
| IN_MODIFIED
| IN_UPDATE
)) == 0 &&
1083 (RB_EMPTY(&vp
->v_rbdirty_tree
) || (info
->waitfor
& MNT_LAZY
)))) {
1086 if ((error
= VOP_FSYNC(vp
, info
->waitfor
, 0)) != 0)
1087 info
->allerror
= error
;
1092 * Look up a EXT2FS dinode number to find its incore vnode, otherwise read it
1093 * in from disk. If it is in core, wait for the lock bit to clear, then
1094 * return the inode locked. Detection and handling of mount points must be
1095 * done by the calling routine.
1098 ext2_vget(struct mount
*mp
, struct vnode
*dvp
, ino_t ino
, struct vnode
**vpp
)
1100 struct ext2_sb_info
*fs
;
1102 struct ext2mount
*ump
;
1109 ump
= VFSTOEXT2(mp
);
1112 if ((*vpp
= ext2_ihashget(dev
, ino
)) != NULL
)
1116 * Lock out the creation of new entries in the FFS hash table in
1117 * case getnewvnode() or MALLOC() blocks, otherwise a duplicate
1120 if (ext2fs_inode_hash_lock
) {
1121 while (ext2fs_inode_hash_lock
) {
1122 ext2fs_inode_hash_lock
= -1;
1123 tsleep(&ext2fs_inode_hash_lock
, 0, "e2vget", 0);
1127 ext2fs_inode_hash_lock
= 1;
1130 * If this MALLOC() is performed after the getnewvnode()
1131 * it might block, leaving a vnode with a NULL v_data to be
1132 * found by ext2_sync() if a sync happens to fire right then,
1133 * which will cause a panic because ext2_sync() blindly
1134 * dereferences vp->v_data (as well it should).
1136 MALLOC(ip
, struct inode
*, sizeof(struct inode
), M_EXT2NODE
, M_WAITOK
);
1138 /* Allocate a new vnode/inode. */
1139 if ((error
= getnewvnode(VT_EXT2FS
, mp
, &vp
, 0, LK_CANRECURSE
)) != 0) {
1140 if (ext2fs_inode_hash_lock
< 0)
1141 wakeup(&ext2fs_inode_hash_lock
);
1142 ext2fs_inode_hash_lock
= 0;
1144 FREE(ip
, M_EXT2NODE
);
1147 bzero((caddr_t
)ip
, sizeof(struct inode
));
1150 ip
->i_e2fs
= fs
= ump
->um_e2fs
;
1154 for (i
= 0; i
< MAXQUOTAS
; i
++)
1155 ip
->i_dquot
[i
] = NODQUOT
;
1158 * Put it onto its hash chain. Since our vnode is locked, other
1159 * requests for this inode will block if they arrive while we are
1160 * sleeping waiting for old data structures to be purged or for the
1161 * contents of the disk portion of this inode to be read.
1165 if (ext2fs_inode_hash_lock
< 0)
1166 wakeup(&ext2fs_inode_hash_lock
);
1167 ext2fs_inode_hash_lock
= 0;
1169 /* Read in the disk contents for the inode, copy into the inode. */
1171 kprintf("ext2_vget(%d) dbn= %d ", ino
, fsbtodb(fs
, ino_to_fsba(fs
, ino
)));
1173 error
= bread(ump
->um_devvp
, fsbtodoff(fs
, ino_to_fsba(fs
, ino
)),
1174 (int)fs
->s_blocksize
, &bp
);
1177 * The inode does not contain anything useful, so it would
1178 * be misleading to leave it on its hash chain. With mode
1179 * still zero, it will be unlinked and returned to the free
1187 /* convert ext2 inode to dinode */
1188 ext2_ei2di((struct ext2_inode
*) ((char *)bp
->b_data
+ EXT2_INODE_SIZE(fs
) *
1189 ino_to_fsbo(fs
, ino
)), &ip
->i_din
);
1190 ip
->i_block_group
= ino_to_cg(fs
, ino
);
1191 ip
->i_next_alloc_block
= 0;
1192 ip
->i_next_alloc_goal
= 0;
1193 ip
->i_prealloc_count
= 0;
1194 ip
->i_prealloc_block
= 0;
1195 /* now we want to make sure that block pointers for unused
1196 blocks are zeroed out - ext2_balloc depends on this
1197 although for regular files and directories only
1199 if(S_ISDIR(ip
->i_mode
) || S_ISREG(ip
->i_mode
)) {
1200 used_blocks
= (ip
->i_size
+fs
->s_blocksize
-1) / fs
->s_blocksize
;
1201 for(i
= used_blocks
; i
< EXT2_NDIR_BLOCKS
; i
++)
1205 ext2_print_inode(ip
);
1210 * Initialize the vnode from the inode, check for aliases.
1211 * Note that the underlying vnode may have changed.
1213 if ((error
= ext2_vinit(mp
, &vp
)) != 0) {
1220 * Finish inode initialization now that aliasing has been resolved.
1222 ip
->i_devvp
= ump
->um_devvp
;
1225 * Set up a generation number for this inode if it does not
1226 * already have one. This should only happen on old filesystems.
1228 if (ip
->i_gen
== 0) {
1229 ip
->i_gen
= krandom() / 2 + 1;
1230 if ((vp
->v_mount
->mnt_flag
& MNT_RDONLY
) == 0)
1231 ip
->i_flag
|= IN_MODIFIED
;
1234 * Return the locked and refd vnode.
1241 * File handle to vnode
1243 * Have to be really careful about stale file handles:
1244 * - check that the inode number is valid
1245 * - call ext2_vget() to get the locked inode
1246 * - check for an unallocated inode (i_mode == 0)
1247 * - check that the given client host has export rights and return
1248 * those rights via. exflagsp and credanonp
1251 ext2_fhtovp(struct mount
*mp
, struct vnode
*rootvp
,
1252 struct fid
*fhp
, struct vnode
**vpp
)
1255 struct ext2_sb_info
*fs
;
1260 ufhp
= (struct ufid
*)fhp
;
1261 fs
= VFSTOEXT2(mp
)->um_e2fs
;
1262 if (ufhp
->ufid_ino
< ROOTINO
||
1263 ufhp
->ufid_ino
> fs
->s_groups_count
* fs
->s_es
->s_inodes_per_group
)
1266 error
= VFS_VGET(mp
, rootvp
, ufhp
->ufid_ino
, &nvp
);
1272 if (ip
->i_mode
== 0 ||
1273 ip
->i_gen
!= ufhp
->ufid_gen
||
1274 (VFSTOEXT2(mp
)->um_i_effnlink_valid
? ip
->i_effnlink
:
1275 ip
->i_nlink
) <= 0) {
1285 * Vnode pointer to File handle
1289 ext2_vptofh(struct vnode
*vp
, struct fid
*fhp
)
1295 ufhp
= (struct ufid
*)fhp
;
1296 ufhp
->ufid_len
= sizeof(struct ufid
);
1297 ufhp
->ufid_ino
= ip
->i_number
;
1298 ufhp
->ufid_gen
= ip
->i_gen
;
1303 * This is the generic part of fhtovp called after the underlying
1304 * filesystem has validated the file handle.
1306 * Verify that a host should have access to a filesystem.
1309 ext2_check_export(struct mount
*mp
, struct sockaddr
*nam
, int *exflagsp
,
1310 struct ucred
**credanonp
)
1313 struct ext2mount
*ump
;
1315 ump
= VFSTOEXT2(mp
);
1317 * Get the export permission structure for this <mp, client> tuple.
1319 np
= vfs_export_lookup(mp
, &ump
->um_export
, nam
);
1323 *exflagsp
= np
->netc_exflags
;
1324 *credanonp
= &np
->netc_anon
;
1329 * Write a superblock and associated information back to disk.
1332 ext2_sbupdate(struct ext2mount
*mp
, int waitfor
)
1334 struct ext2_sb_info
*fs
= mp
->um_e2fs
;
1335 struct ext2_super_block
*es
= fs
->s_es
;
1339 kprintf("\nupdating superblock, waitfor=%s\n", waitfor == MNT_WAIT ? "yes":"no");
1341 bp
= getblk(mp
->um_devvp
, SBOFF
, SBSIZE
, 0, 0);
1342 bcopy((caddr_t
)es
, bp
->b_data
, (u_int
)sizeof(struct ext2_super_block
));
1343 if (waitfor
== MNT_WAIT
)
1349 * The buffers for group descriptors, inode bitmaps and block bitmaps
1350 * are not busy at this point and are (hopefully) written by the
1351 * usual sync mechanism. No need to write them here