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 if (VOP_IOCTL(devvp
, DIOCGPART
, (caddr_t
)&dpart
, FREAD
,
786 size
= dpart
.media_blksize
;
791 if ((error
= bread(devvp
, SBOFF
, SBSIZE
, &bp
)) != 0)
793 es
= (struct ext2_super_block
*)bp
->b_data
;
794 if (ext2_check_sb_compat(es
, dev
, ronly
) != 0) {
795 error
= EINVAL
; /* XXX needs translation */
798 if ((es
->s_state
& EXT2_VALID_FS
) == 0 ||
799 (es
->s_state
& EXT2_ERROR_FS
)) {
800 if (ronly
|| (mp
->mnt_flag
& MNT_FORCE
)) {
802 "WARNING: Filesystem was not properly dismounted\n");
805 "WARNING: R/W mount denied. Filesystem is not clean - run fsck\n");
810 ump
= bsd_malloc(sizeof *ump
, M_EXT2MNT
, M_WAITOK
| M_ZERO
);
811 ump
->um_malloctype
= M_EXT2NODE
;
812 ump
->um_blkatoff
= ext2_blkatoff
;
813 ump
->um_truncate
= ext2_truncate
;
814 ump
->um_update
= ext2_update
;
815 ump
->um_valloc
= ext2_valloc
;
816 ump
->um_vfree
= ext2_vfree
;
817 /* I don't know whether this is the right strategy. Note that
818 we dynamically allocate both a ext2_sb_info and a ext2_super_block
819 while Linux keeps the super block in a locked buffer
821 ump
->um_e2fs
= bsd_malloc(sizeof(struct ext2_sb_info
),
822 M_EXT2MNT
, M_WAITOK
);
823 ump
->um_e2fs
->s_es
= bsd_malloc(sizeof(struct ext2_super_block
),
824 M_EXT2MNT
, M_WAITOK
);
825 bcopy(es
, ump
->um_e2fs
->s_es
, (u_int
)sizeof(struct ext2_super_block
));
826 if ((error
= compute_sb_data(devvp
, ump
->um_e2fs
->s_es
, ump
->um_e2fs
)))
829 * We don't free the group descriptors allocated by compute_sb_data()
830 * until ext2_unmount(). This is OK since the mount will succeed.
835 fs
->s_rd_only
= ronly
; /* ronly is set according to mnt_flags */
836 /* if the fs is not mounted read-only, make sure the super block is
837 always written back on a sync()
839 fs
->s_wasvalid
= fs
->s_es
->s_state
& EXT2_VALID_FS
? 1 : 0;
841 fs
->s_dirt
= 1; /* mark it modified */
842 fs
->s_es
->s_state
&= ~EXT2_VALID_FS
; /* set fs invalid */
844 mp
->mnt_data
= (qaddr_t
)ump
;
845 mp
->mnt_stat
.f_fsid
.val
[0] = dev2udev(dev
);
846 mp
->mnt_stat
.f_fsid
.val
[1] = mp
->mnt_vfc
->vfc_typenum
;
847 mp
->mnt_maxsymlinklen
= EXT2_MAXSYMLINKLEN
;
848 mp
->mnt_flag
|= MNT_LOCAL
;
851 ump
->um_devvp
= devvp
;
852 /* setting those two parameters allows us to use
853 ext2_bmap w/o changse !
855 ump
->um_nindir
= EXT2_ADDR_PER_BLOCK(fs
);
856 ump
->um_bptrtodb
= fs
->s_es
->s_log_block_size
+ 1;
857 ump
->um_seqinc
= EXT2_FRAGS_PER_BLOCK(fs
);
858 for (i
= 0; i
< MAXQUOTAS
; i
++)
859 ump
->um_quotas
[i
] = NULLVP
;
860 dev
->si_mountpoint
= mp
;
862 vfs_add_vnodeops(mp
, &ext2_vnode_vops
, &mp
->mnt_vn_norm_ops
);
863 vfs_add_vnodeops(mp
, &ext2_spec_vops
, &mp
->mnt_vn_spec_ops
);
864 vfs_add_vnodeops(mp
, &ext2_fifo_vops
, &mp
->mnt_vn_fifo_ops
);
867 ext2_sbupdate(ump
, MNT_WAIT
);
872 VOP_CLOSE(devvp
, ronly
? FREAD
: FREAD
|FWRITE
);
874 bsd_free(ump
->um_e2fs
->s_es
, M_EXT2MNT
);
875 bsd_free(ump
->um_e2fs
, M_EXT2MNT
);
876 bsd_free(ump
, M_EXT2MNT
);
877 mp
->mnt_data
= (qaddr_t
)0;
883 * unmount system call
886 ext2_unmount(struct mount
*mp
, int mntflags
)
888 struct ext2mount
*ump
;
889 struct ext2_sb_info
*fs
;
890 int error
, flags
, ronly
, i
;
893 if (mntflags
& MNT_FORCE
) {
894 if (mp
->mnt_flag
& MNT_ROOTFS
)
898 if ((error
= ext2_flushfiles(mp
, flags
)) != 0)
902 ronly
= fs
->s_rd_only
;
905 fs
->s_es
->s_state
|= EXT2_VALID_FS
;
906 ext2_sbupdate(ump
, MNT_WAIT
);
909 /* release buffers containing group descriptors */
910 for(i
= 0; i
< fs
->s_db_per_group
; i
++)
911 ULCK_BUF(fs
->s_group_desc
[i
])
912 bsd_free(fs
->s_group_desc
, M_EXT2MNT
);
914 /* release cached inode/block bitmaps */
915 for (i
= 0; i
< EXT2_MAX_GROUP_LOADED
; i
++)
916 if (fs
->s_inode_bitmap
[i
])
917 ULCK_BUF(fs
->s_inode_bitmap
[i
])
919 for (i
= 0; i
< EXT2_MAX_GROUP_LOADED
; i
++)
920 if (fs
->s_block_bitmap
[i
])
921 ULCK_BUF(fs
->s_block_bitmap
[i
])
923 ump
->um_devvp
->v_rdev
->si_mountpoint
= NULL
;
924 error
= VOP_CLOSE(ump
->um_devvp
, ronly
? FREAD
: FREAD
|FWRITE
);
925 vrele(ump
->um_devvp
);
926 bsd_free(fs
->s_es
, M_EXT2MNT
);
927 bsd_free(fs
, M_EXT2MNT
);
928 bsd_free(ump
, M_EXT2MNT
);
929 mp
->mnt_data
= (qaddr_t
)0;
930 mp
->mnt_flag
&= ~MNT_LOCAL
;
935 * Flush out all the files in a filesystem.
938 ext2_flushfiles(struct mount
*mp
, int flags
)
940 struct ext2mount
*ump
;
948 if (mp
->mnt_flag
& MNT_QUOTA
) {
949 if ((error
= vflush(mp
, 0, SKIPSYSTEM
|flags
)) != 0)
951 for (i
= 0; i
< MAXQUOTAS
; i
++) {
952 if (ump
->um_quotas
[i
] == NULLVP
)
954 ext2_quotaoff(mp
, i
);
957 * Here we fall through to vflush again to ensure
958 * that we have gotten rid of all the system vnodes.
962 error
= vflush(mp
, 0, flags
);
967 * Get file system statistics.
968 * taken from ext2/super.c ext2_statfs
971 ext2_statfs(struct mount
*mp
, struct statfs
*sbp
, struct ucred
*cred
)
973 unsigned long overhead
;
974 struct ext2mount
*ump
;
975 struct ext2_sb_info
*fs
;
976 struct ext2_super_block
*es
;
983 if (es
->s_magic
!= EXT2_SUPER_MAGIC
)
984 panic("ext2_statfs - magic number spoiled");
987 * Compute the overhead (FS structures)
989 if (es
->s_feature_ro_compat
& EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
) {
991 for (i
= 0 ; i
< fs
->s_groups_count
; i
++)
992 if (ext2_group_sparse(i
))
995 nsb
= fs
->s_groups_count
;
996 overhead
= es
->s_first_data_block
+
997 /* Superblocks and block group descriptors: */
998 nsb
* (1 + fs
->s_db_per_group
) +
999 /* Inode bitmap, block bitmap, and inode table: */
1000 fs
->s_groups_count
* (1 + 1 + fs
->s_itb_per_group
);
1002 sbp
->f_bsize
= EXT2_FRAG_SIZE(fs
);
1003 sbp
->f_iosize
= EXT2_BLOCK_SIZE(fs
);
1004 sbp
->f_blocks
= es
->s_blocks_count
- overhead
;
1005 sbp
->f_bfree
= es
->s_free_blocks_count
;
1006 sbp
->f_bavail
= sbp
->f_bfree
- es
->s_r_blocks_count
;
1007 sbp
->f_files
= es
->s_inodes_count
;
1008 sbp
->f_ffree
= es
->s_free_inodes_count
;
1009 if (sbp
!= &mp
->mnt_stat
) {
1010 sbp
->f_type
= mp
->mnt_vfc
->vfc_typenum
;
1011 bcopy((caddr_t
)mp
->mnt_stat
.f_mntfromname
,
1012 (caddr_t
)&sbp
->f_mntfromname
[0], MNAMELEN
);
1018 * Go through the disk queues to initiate sandbagged IO;
1019 * go through the inodes to write those that have been modified;
1020 * initiate the writing of the super block if it has been modified.
1022 * Note: we are always called with the filesystem marked `MPBUSY'.
1025 static int ext2_sync_scan(struct mount
*mp
, struct vnode
*vp
, void *data
);
1028 ext2_sync(struct mount
*mp
, int waitfor
)
1030 struct ext2mount
*ump
= VFSTOEXT2(mp
);
1031 struct ext2_sb_info
*fs
;
1032 struct scaninfo scaninfo
;
1036 if (fs
->s_dirt
!= 0 && fs
->s_rd_only
!= 0) { /* XXX */
1037 kprintf("fs = %s\n", fs
->fs_fsmnt
);
1038 panic("ext2_sync: rofs mod");
1042 * Write back each (modified) inode.
1044 scaninfo
.allerror
= 0;
1045 scaninfo
.rescan
= 1;
1046 scaninfo
.waitfor
= waitfor
;
1047 while (scaninfo
.rescan
) {
1048 scaninfo
.rescan
= 0;
1049 vmntvnodescan(mp
, VMSC_GETVP
|VMSC_NOWAIT
,
1050 NULL
, ext2_sync_scan
, &scaninfo
);
1054 * Force stale file system control information to be flushed.
1056 if (waitfor
!= MNT_LAZY
) {
1057 vn_lock(ump
->um_devvp
, LK_EXCLUSIVE
| LK_RETRY
);
1058 if ((error
= VOP_FSYNC(ump
->um_devvp
, waitfor
, 0)) != 0)
1059 scaninfo
.allerror
= error
;
1060 vn_unlock(ump
->um_devvp
);
1066 * Write back modified superblock.
1068 if (fs
->s_dirt
!= 0) {
1070 fs
->s_es
->s_wtime
= time_second
;
1071 if ((error
= ext2_sbupdate(ump
, waitfor
)) != 0)
1072 scaninfo
.allerror
= error
;
1074 return (scaninfo
.allerror
);
1078 ext2_sync_scan(struct mount
*mp
, struct vnode
*vp
, void *data
)
1080 struct scaninfo
*info
= data
;
1085 if (vp
->v_type
== VNON
||
1087 (IN_ACCESS
| IN_CHANGE
| IN_MODIFIED
| IN_UPDATE
)) == 0 &&
1088 (RB_EMPTY(&vp
->v_rbdirty_tree
) || info
->waitfor
== MNT_LAZY
))) {
1091 if ((error
= VOP_FSYNC(vp
, info
->waitfor
, 0)) != 0)
1092 info
->allerror
= error
;
1097 * Look up a EXT2FS dinode number to find its incore vnode, otherwise read it
1098 * in from disk. If it is in core, wait for the lock bit to clear, then
1099 * return the inode locked. Detection and handling of mount points must be
1100 * done by the calling routine.
1103 ext2_vget(struct mount
*mp
, struct vnode
*dvp
, ino_t ino
, struct vnode
**vpp
)
1105 struct ext2_sb_info
*fs
;
1107 struct ext2mount
*ump
;
1114 ump
= VFSTOEXT2(mp
);
1117 if ((*vpp
= ext2_ihashget(dev
, ino
)) != NULL
)
1121 * Lock out the creation of new entries in the FFS hash table in
1122 * case getnewvnode() or MALLOC() blocks, otherwise a duplicate
1125 if (ext2fs_inode_hash_lock
) {
1126 while (ext2fs_inode_hash_lock
) {
1127 ext2fs_inode_hash_lock
= -1;
1128 tsleep(&ext2fs_inode_hash_lock
, 0, "e2vget", 0);
1132 ext2fs_inode_hash_lock
= 1;
1135 * If this MALLOC() is performed after the getnewvnode()
1136 * it might block, leaving a vnode with a NULL v_data to be
1137 * found by ext2_sync() if a sync happens to fire right then,
1138 * which will cause a panic because ext2_sync() blindly
1139 * dereferences vp->v_data (as well it should).
1141 MALLOC(ip
, struct inode
*, sizeof(struct inode
), M_EXT2NODE
, M_WAITOK
);
1143 /* Allocate a new vnode/inode. */
1144 if ((error
= getnewvnode(VT_EXT2FS
, mp
, &vp
, 0, LK_CANRECURSE
)) != 0) {
1145 if (ext2fs_inode_hash_lock
< 0)
1146 wakeup(&ext2fs_inode_hash_lock
);
1147 ext2fs_inode_hash_lock
= 0;
1149 FREE(ip
, M_EXT2NODE
);
1152 bzero((caddr_t
)ip
, sizeof(struct inode
));
1155 ip
->i_e2fs
= fs
= ump
->um_e2fs
;
1159 for (i
= 0; i
< MAXQUOTAS
; i
++)
1160 ip
->i_dquot
[i
] = NODQUOT
;
1163 * Put it onto its hash chain. Since our vnode is locked, other
1164 * requests for this inode will block if they arrive while we are
1165 * sleeping waiting for old data structures to be purged or for the
1166 * contents of the disk portion of this inode to be read.
1170 if (ext2fs_inode_hash_lock
< 0)
1171 wakeup(&ext2fs_inode_hash_lock
);
1172 ext2fs_inode_hash_lock
= 0;
1174 /* Read in the disk contents for the inode, copy into the inode. */
1176 kprintf("ext2_vget(%d) dbn= %d ", ino
, fsbtodb(fs
, ino_to_fsba(fs
, ino
)));
1178 error
= bread(ump
->um_devvp
, fsbtodoff(fs
, ino_to_fsba(fs
, ino
)),
1179 (int)fs
->s_blocksize
, &bp
);
1182 * The inode does not contain anything useful, so it would
1183 * be misleading to leave it on its hash chain. With mode
1184 * still zero, it will be unlinked and returned to the free
1192 /* convert ext2 inode to dinode */
1193 ext2_ei2di((struct ext2_inode
*) ((char *)bp
->b_data
+ EXT2_INODE_SIZE(fs
) *
1194 ino_to_fsbo(fs
, ino
)), &ip
->i_din
);
1195 ip
->i_block_group
= ino_to_cg(fs
, ino
);
1196 ip
->i_next_alloc_block
= 0;
1197 ip
->i_next_alloc_goal
= 0;
1198 ip
->i_prealloc_count
= 0;
1199 ip
->i_prealloc_block
= 0;
1200 /* now we want to make sure that block pointers for unused
1201 blocks are zeroed out - ext2_balloc depends on this
1202 although for regular files and directories only
1204 if(S_ISDIR(ip
->i_mode
) || S_ISREG(ip
->i_mode
)) {
1205 used_blocks
= (ip
->i_size
+fs
->s_blocksize
-1) / fs
->s_blocksize
;
1206 for(i
= used_blocks
; i
< EXT2_NDIR_BLOCKS
; i
++)
1210 ext2_print_inode(ip
);
1215 * Initialize the vnode from the inode, check for aliases.
1216 * Note that the underlying vnode may have changed.
1218 if ((error
= ext2_vinit(mp
, &vp
)) != 0) {
1225 * Finish inode initialization now that aliasing has been resolved.
1227 ip
->i_devvp
= ump
->um_devvp
;
1230 * Set up a generation number for this inode if it does not
1231 * already have one. This should only happen on old filesystems.
1233 if (ip
->i_gen
== 0) {
1234 ip
->i_gen
= krandom() / 2 + 1;
1235 if ((vp
->v_mount
->mnt_flag
& MNT_RDONLY
) == 0)
1236 ip
->i_flag
|= IN_MODIFIED
;
1239 * Return the locked and refd vnode.
1246 * File handle to vnode
1248 * Have to be really careful about stale file handles:
1249 * - check that the inode number is valid
1250 * - call ext2_vget() to get the locked inode
1251 * - check for an unallocated inode (i_mode == 0)
1252 * - check that the given client host has export rights and return
1253 * those rights via. exflagsp and credanonp
1256 ext2_fhtovp(struct mount
*mp
, struct vnode
*rootvp
,
1257 struct fid
*fhp
, struct vnode
**vpp
)
1260 struct ext2_sb_info
*fs
;
1265 ufhp
= (struct ufid
*)fhp
;
1266 fs
= VFSTOEXT2(mp
)->um_e2fs
;
1267 if (ufhp
->ufid_ino
< ROOTINO
||
1268 ufhp
->ufid_ino
> fs
->s_groups_count
* fs
->s_es
->s_inodes_per_group
)
1271 error
= VFS_VGET(mp
, rootvp
, ufhp
->ufid_ino
, &nvp
);
1277 if (ip
->i_mode
== 0 ||
1278 ip
->i_gen
!= ufhp
->ufid_gen
||
1279 (VFSTOEXT2(mp
)->um_i_effnlink_valid
? ip
->i_effnlink
:
1280 ip
->i_nlink
) <= 0) {
1290 * Vnode pointer to File handle
1294 ext2_vptofh(struct vnode
*vp
, struct fid
*fhp
)
1300 ufhp
= (struct ufid
*)fhp
;
1301 ufhp
->ufid_len
= sizeof(struct ufid
);
1302 ufhp
->ufid_ino
= ip
->i_number
;
1303 ufhp
->ufid_gen
= ip
->i_gen
;
1308 * This is the generic part of fhtovp called after the underlying
1309 * filesystem has validated the file handle.
1311 * Verify that a host should have access to a filesystem.
1314 ext2_check_export(struct mount
*mp
, struct sockaddr
*nam
, int *exflagsp
,
1315 struct ucred
**credanonp
)
1318 struct ext2mount
*ump
;
1320 ump
= VFSTOEXT2(mp
);
1322 * Get the export permission structure for this <mp, client> tuple.
1324 np
= vfs_export_lookup(mp
, &ump
->um_export
, nam
);
1328 *exflagsp
= np
->netc_exflags
;
1329 *credanonp
= &np
->netc_anon
;
1334 * Write a superblock and associated information back to disk.
1337 ext2_sbupdate(struct ext2mount
*mp
, int waitfor
)
1339 struct ext2_sb_info
*fs
= mp
->um_e2fs
;
1340 struct ext2_super_block
*es
= fs
->s_es
;
1344 kprintf("\nupdating superblock, waitfor=%s\n", waitfor == MNT_WAIT ? "yes":"no");
1346 bp
= getblk(mp
->um_devvp
, SBOFF
, SBSIZE
, 0, 0);
1347 bcopy((caddr_t
)es
, bp
->b_data
, (u_int
)sizeof(struct ext2_super_block
));
1348 if (waitfor
== MNT_WAIT
)
1354 * The buffers for group descriptors, inode bitmaps and block bitmaps
1355 * are not busy at this point and are (hopefully) written by the
1356 * usual sync mechanism. No need to write them here