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.56.4.1 2008/09/25 02:20:49 dillon Exp $
44 #include "opt_quota.h"
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/nlookup.h>
50 #include <sys/kernel.h>
51 #include <sys/vnode.h>
52 #include <sys/mount.h>
55 #include <sys/fcntl.h>
56 #include <sys/diskslice.h>
57 #include <sys/malloc.h>
59 #include <vm/vm_zone.h>
62 #include <sys/thread2.h>
67 #include "ext2mount.h"
68 #include "ext2_extern.h"
72 #include "ext2_fs_sb.h"
74 extern struct vop_ops ext2_vnode_vops
;
75 extern struct vop_ops ext2_spec_vops
;
76 extern struct vop_ops ext2_fifo_vops
;
78 static int ext2_fhtovp (struct mount
*, struct vnode
*,
79 struct fid
*, struct vnode
**);
80 static int ext2_flushfiles (struct mount
*mp
, int flags
);
81 static int ext2_mount (struct mount
*, char *, caddr_t
, struct ucred
*);
82 static int ext2_mountfs (struct vnode
*, struct mount
*, struct ucred
*);
83 static int ext2_root(struct mount
*, struct vnode
**);
84 static int ext2_reload (struct mount
*mountp
, struct ucred
*cred
);
85 static int ext2_sbupdate (struct ext2mount
*, int);
86 static int ext2_statfs (struct mount
*, struct statfs
*, struct ucred
*);
87 static int ext2_sync (struct mount
*, int);
88 static int ext2_unmount (struct mount
*, int);
89 static int ext2_vget (struct mount
*, ino_t
, struct vnode
**);
90 static int ext2_init(struct vfsconf
*);
91 static int ext2_vptofh (struct vnode
*, struct fid
*);
93 static MALLOC_DEFINE(M_EXT2NODE
, "EXT2 node", "EXT2 vnode private part");
94 MALLOC_DEFINE(M_EXT2MNT
, "EXT2 mount", "EXT2 mount structure");
96 static struct vfsops ext2fs_vfsops
= {
97 .vfs_mount
= ext2_mount
,
98 .vfs_unmount
= ext2_unmount
,
99 .vfs_root
= ext2_root
, /* root inode via vget */
100 .vfs_quotactl
= ext2_quotactl
, /* quota operations */
101 .vfs_statfs
= ext2_statfs
,
102 .vfs_sync
= ext2_sync
,
103 .vfs_vget
= ext2_vget
,
104 .vfs_fhtovp
= ext2_fhtovp
,
105 .vfs_checkexp
= ext2_check_export
,
106 .vfs_vptofh
= ext2_vptofh
,
107 .vfs_init
= ext2_init
,
108 .vfs_uninit
= ext2_uninit
111 VFS_SET(ext2fs_vfsops
, ext2fs
, 0);
112 #define bsd_malloc kmalloc
113 #define bsd_free kfree
115 static int ext2fs_inode_hash_lock
;
117 static int ext2_check_sb_compat (struct ext2_super_block
*es
,
118 cdev_t dev
, int ronly
);
119 static int compute_sb_data (struct vnode
* devvp
,
120 struct ext2_super_block
* es
,
121 struct ext2_sb_info
* fs
);
124 ext2_root(struct mount
*mp
, struct vnode
**vpp
)
129 error
= VFS_VGET(mp
, (ino_t
)ROOTINO
, &nvp
);
137 * Do operations associated with quotas
140 ext2_quotactl(struct mount
*mp
, int cmds
, uid_t uid
, caddr_t arg
,
146 int cmd
, type
, error
;
148 type
= cmds
& SUBCMDMASK
;
149 cmd
= cmds
>> SUBCMDSHIFT
;
168 if (uid
== cred
->cr_ruid
)
172 if ((error
= suser_cred(cred
, PRISON_ROOT
)) != 0)
176 type
= cmds
& SUBCMDMASK
;
177 if ((uint
)type
>= MAXQUOTAS
)
179 if (vfs_busy(mp
, LK_NOWAIT
))
185 error
= ext2_quotaon(cred
, mp
, type
, arg
);
189 error
= ext2_quotaoff(mp
, type
);
193 error
= ext2_setquota(mp
, uid
, type
, arg
);
197 error
= ext2_setuse(mp
, uid
, type
, arg
);
201 error
= ext2_getquota(mp
, uid
, type
, arg
);
205 error
= ext2_qsync(mp
);
218 * Initial UFS filesystems, done only once.
221 ext2_init(struct vfsconf
*vfsp
)
241 * data: this is actually a (struct ext2_args *)
244 ext2_mount(struct mount
*mp
, char *path
, caddr_t data
, struct ucred
*cred
)
247 struct ext2_args args
;
248 struct ext2mount
*ump
= 0;
249 struct ext2_sb_info
*fs
;
253 struct nlookupdata nd
;
255 if ((error
= copyin(data
, (caddr_t
)&args
, sizeof (struct ext2_args
))) != 0)
259 * If updating, check whether changing from read-only to
260 * read/write; if there is no device name, that's all we do.
262 if (mp
->mnt_flag
& MNT_UPDATE
) {
265 devvp
= ump
->um_devvp
;
267 if (fs
->s_rd_only
== 0 && (mp
->mnt_flag
& MNT_RDONLY
)) {
269 if (mp
->mnt_flag
& MNT_FORCE
)
271 if (vfs_busy(mp
, LK_NOWAIT
))
273 error
= ext2_flushfiles(mp
, flags
);
275 if (!error
&& fs
->s_wasvalid
) {
276 fs
->s_es
->s_state
|= EXT2_VALID_FS
;
277 ext2_sbupdate(ump
, MNT_WAIT
);
280 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
281 VOP_OPEN(devvp
, FREAD
, FSCRED
, NULL
);
282 VOP_CLOSE(devvp
, FREAD
|FWRITE
);
285 if (!error
&& (mp
->mnt_flag
& MNT_RELOAD
))
286 error
= ext2_reload(mp
, cred
);
289 if (ext2_check_sb_compat(fs
->s_es
, devvp
->v_rdev
,
290 (mp
->mnt_kern_flag
& MNTK_WANTRDWR
) == 0) != 0)
292 if (fs
->s_rd_only
&& (mp
->mnt_kern_flag
& MNTK_WANTRDWR
)) {
294 * If upgrade to read-write by non-root, then verify
295 * that user has necessary permissions on the device.
297 if (cred
->cr_uid
!= 0) {
298 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
299 error
= VOP_ACCESS(devvp
, VREAD
| VWRITE
, cred
);
307 if ((fs
->s_es
->s_state
& EXT2_VALID_FS
) == 0 ||
308 (fs
->s_es
->s_state
& EXT2_ERROR_FS
)) {
309 if (mp
->mnt_flag
& MNT_FORCE
) {
311 "WARNING: %s was not properly dismounted\n",
315 "WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n",
320 fs
->s_es
->s_state
&= ~EXT2_VALID_FS
;
321 ext2_sbupdate(ump
, MNT_WAIT
);
323 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
324 VOP_OPEN(devvp
, FREAD
|FWRITE
, FSCRED
, NULL
);
325 VOP_CLOSE(devvp
, FREAD
);
328 if (args
.fspec
== 0) {
330 * Process export requests.
332 return (vfs_export(mp
, &ump
->um_export
, &args
.export
));
336 * Not an update, or updating the name: look up the name
337 * and verify that it refers to a sensible block device.
340 error
= nlookup_init(&nd
, args
.fspec
, UIO_USERSPACE
, NLC_FOLLOW
);
342 error
= nlookup(&nd
);
344 error
= cache_vref(&nd
.nl_nch
, nd
.nl_cred
, &devvp
);
349 if (!vn_isdisk(devvp
, &error
)) {
355 * If mount by non-root, then verify that user has necessary
356 * permissions on the device.
358 if (cred
->cr_uid
!= 0) {
360 if ((mp
->mnt_flag
& MNT_RDONLY
) == 0)
361 accessmode
|= VWRITE
;
362 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
363 if ((error
= VOP_ACCESS(devvp
, accessmode
, cred
)) != 0) {
370 if ((mp
->mnt_flag
& MNT_UPDATE
) == 0) {
371 error
= ext2_mountfs(devvp
, mp
, cred
);
373 if (devvp
!= ump
->um_devvp
)
374 error
= EINVAL
; /* needs translation */
384 copyinstr(path
, fs
->fs_fsmnt
, sizeof(fs
->fs_fsmnt
) - 1, &size
);
385 bzero(fs
->fs_fsmnt
+ size
, sizeof(fs
->fs_fsmnt
) - size
);
386 copyinstr(args
.fspec
, mp
->mnt_stat
.f_mntfromname
, MNAMELEN
- 1, &size
);
387 bzero(mp
->mnt_stat
.f_mntfromname
+ size
, MNAMELEN
- size
);
388 ext2_statfs(mp
, &mp
->mnt_stat
, cred
);
393 * checks that the data in the descriptor blocks make sense
394 * this is taken from ext2/super.c
397 ext2_check_descriptors(struct ext2_sb_info
*sb
)
401 unsigned long block
= sb
->s_es
->s_first_data_block
;
402 struct ext2_group_desc
* gdp
= NULL
;
404 /* ext2_debug ("Checking group descriptors"); */
406 for (i
= 0; i
< sb
->s_groups_count
; i
++)
408 /* examine next descriptor block */
409 if ((i
% EXT2_DESC_PER_BLOCK(sb
)) == 0)
410 gdp
= (struct ext2_group_desc
*)
411 sb
->s_group_desc
[desc_block
++]->b_data
;
412 if (gdp
->bg_block_bitmap
< block
||
413 gdp
->bg_block_bitmap
>= block
+ EXT2_BLOCKS_PER_GROUP(sb
))
415 kprintf ("ext2_check_descriptors: "
416 "Block bitmap for group %d"
417 " not in group (block %lu)!\n",
418 i
, (unsigned long) gdp
->bg_block_bitmap
);
421 if (gdp
->bg_inode_bitmap
< block
||
422 gdp
->bg_inode_bitmap
>= block
+ EXT2_BLOCKS_PER_GROUP(sb
))
424 kprintf ("ext2_check_descriptors: "
425 "Inode bitmap for group %d"
426 " not in group (block %lu)!\n",
427 i
, (unsigned long) gdp
->bg_inode_bitmap
);
430 if (gdp
->bg_inode_table
< block
||
431 gdp
->bg_inode_table
+ sb
->s_itb_per_group
>=
432 block
+ EXT2_BLOCKS_PER_GROUP(sb
))
434 kprintf ("ext2_check_descriptors: "
435 "Inode table for group %d"
436 " not in group (block %lu)!\n",
437 i
, (unsigned long) gdp
->bg_inode_table
);
440 block
+= EXT2_BLOCKS_PER_GROUP(sb
);
447 ext2_check_sb_compat(struct ext2_super_block
*es
, cdev_t dev
, int ronly
)
449 if (es
->s_magic
!= EXT2_SUPER_MAGIC
) {
450 kprintf("ext2fs: %s: wrong magic number %#x (expected %#x)\n",
451 devtoname(dev
), es
->s_magic
, EXT2_SUPER_MAGIC
);
454 if (es
->s_rev_level
> EXT2_GOOD_OLD_REV
) {
455 if (es
->s_feature_incompat
& ~EXT2_FEATURE_INCOMPAT_SUPP
) {
457 "WARNING: mount of %s denied due to unsupported optional features\n",
462 (es
->s_feature_ro_compat
& ~EXT2_FEATURE_RO_COMPAT_SUPP
)) {
464 "WARNING: R/W mount of %s denied due to unsupported optional features\n",
473 * this computes the fields of the ext2_sb_info structure from the
474 * data in the ext2_super_block structure read in
477 compute_sb_data(struct vnode
*devvp
, struct ext2_super_block
*es
,
478 struct ext2_sb_info
*fs
)
482 int logic_sb_block
= 1; /* XXX for now */
487 #define V(v) kprintf(#v"= %d\n", fs->v);
490 fs
->s_blocksize
= EXT2_MIN_BLOCK_SIZE
<< es
->s_log_block_size
;
492 fs
->s_bshift
= EXT2_MIN_BLOCK_LOG_SIZE
+ es
->s_log_block_size
;
494 fs
->s_fsbtodb
= es
->s_log_block_size
+ 1;
496 fs
->s_qbmask
= fs
->s_blocksize
- 1;
498 fs
->s_blocksize_bits
= EXT2_BLOCK_SIZE_BITS(es
);
500 fs
->s_frag_size
= EXT2_MIN_FRAG_SIZE
<< es
->s_log_frag_size
;
503 fs
->s_frags_per_block
= fs
->s_blocksize
/ fs
->s_frag_size
;
505 fs
->s_blocks_per_group
= es
->s_blocks_per_group
;
506 V(s_blocks_per_group
)
507 fs
->s_frags_per_group
= es
->s_frags_per_group
;
509 fs
->s_inodes_per_group
= es
->s_inodes_per_group
;
510 V(s_inodes_per_group
)
511 fs
->s_inodes_per_block
= fs
->s_blocksize
/ EXT2_INODE_SIZE
;
512 V(s_inodes_per_block
)
513 fs
->s_itb_per_group
= fs
->s_inodes_per_group
/fs
->s_inodes_per_block
;
515 fs
->s_desc_per_block
= fs
->s_blocksize
/ sizeof (struct ext2_group_desc
);
517 /* s_resuid / s_resgid ? */
518 fs
->s_groups_count
= (es
->s_blocks_count
-
519 es
->s_first_data_block
+
520 EXT2_BLOCKS_PER_GROUP(fs
) - 1) /
521 EXT2_BLOCKS_PER_GROUP(fs
);
523 db_count
= (fs
->s_groups_count
+ EXT2_DESC_PER_BLOCK(fs
) - 1) /
524 EXT2_DESC_PER_BLOCK(fs
);
525 fs
->s_db_per_group
= db_count
;
528 fs
->s_group_desc
= bsd_malloc(db_count
* sizeof (struct buf
*),
529 M_EXT2MNT
, M_WAITOK
);
531 /* adjust logic_sb_block */
532 if(fs
->s_blocksize
> SBSIZE
)
533 /* Godmar thinks: if the blocksize is greater than 1024, then
534 the superblock is logically part of block zero.
538 for (i
= 0; i
< db_count
; i
++) {
539 error
= bread(devvp
, fsbtodoff(fs
, logic_sb_block
+ i
+ 1),
540 fs
->s_blocksize
, &fs
->s_group_desc
[i
]);
542 for (j
= 0; j
< i
; j
++)
543 brelse(fs
->s_group_desc
[j
]);
544 bsd_free(fs
->s_group_desc
, M_EXT2MNT
);
545 kprintf("EXT2-fs: unable to read group descriptors (%d)\n", error
);
548 /* Set the B_LOCKED flag on the buffer, then brelse() it */
549 LCK_BUF(fs
->s_group_desc
[i
])
551 if(!ext2_check_descriptors(fs
)) {
552 for (j
= 0; j
< db_count
; j
++)
553 ULCK_BUF(fs
->s_group_desc
[j
])
554 bsd_free(fs
->s_group_desc
, M_EXT2MNT
);
555 kprintf("EXT2-fs: (ext2_check_descriptors failure) "
556 "unable to read group descriptors\n");
560 for (i
= 0; i
< EXT2_MAX_GROUP_LOADED
; i
++) {
561 fs
->s_inode_bitmap_number
[i
] = 0;
562 fs
->s_inode_bitmap
[i
] = NULL
;
563 fs
->s_block_bitmap_number
[i
] = 0;
564 fs
->s_block_bitmap
[i
] = NULL
;
566 fs
->s_loaded_inode_bitmaps
= 0;
567 fs
->s_loaded_block_bitmaps
= 0;
572 * Reload all incore data for a filesystem (used after running fsck on
573 * the root filesystem and finding things to fix). The filesystem must
574 * be mounted read-only.
576 * Things to do to update the mount:
577 * 1) invalidate all cached meta-data.
578 * 2) re-read superblock from disk.
579 * 3) re-read summary information from disk.
580 * 4) invalidate all inactive vnodes.
581 * 5) invalidate all cached file data.
582 * 6) re-read inode data for all active vnodes.
584 static int ext2_reload_scan1(struct mount
*mp
, struct vnode
*vp
, void *rescan
);
585 static int ext2_reload_scan2(struct mount
*mp
, struct vnode
*vp
, void *rescan
);
592 struct ext2_sb_info
*fs
;
596 ext2_reload(struct mount
*mountp
, struct ucred
*cred
)
600 struct ext2_super_block
* es
;
601 struct ext2_sb_info
*fs
;
603 struct scaninfo scaninfo
;
605 if ((mountp
->mnt_flag
& MNT_RDONLY
) == 0)
608 * Step 1: invalidate all cached meta-data.
610 devvp
= VFSTOEXT2(mountp
)->um_devvp
;
611 if (vinvalbuf(devvp
, 0, 0, 0))
612 panic("ext2_reload: dirty1");
614 * Step 2: re-read superblock from disk.
615 * constants have been adjusted for ext2
617 if ((error
= bread(devvp
, SBOFF
, SBSIZE
, &bp
)) != 0)
619 es
= (struct ext2_super_block
*)bp
->b_data
;
620 if (ext2_check_sb_compat(es
, devvp
->v_rdev
, 0) != 0) {
622 return (EIO
); /* XXX needs translation */
624 fs
= VFSTOEXT2(mountp
)->um_e2fs
;
625 bcopy(bp
->b_data
, fs
->s_es
, sizeof(struct ext2_super_block
));
627 if((error
= compute_sb_data(devvp
, es
, fs
)) != 0) {
632 if (fs
->fs_sbsize
< SBSIZE
)
633 bp
->b_flags
|= B_INVAL
;
638 scaninfo
.devvp
= devvp
;
640 while (error
== 0 && scaninfo
.rescan
) {
642 error
= vmntvnodescan(mountp
, VMSC_GETVX
, ext2_reload_scan1
,
643 ext2_reload_scan2
, &scaninfo
);
649 ext2_reload_scan1(struct mount
*mp
, struct vnode
*vp
, void *data
)
651 /*struct scaninfo *info = data;*/
657 ext2_reload_scan2(struct mount
*mp
, struct vnode
*vp
, void *data
)
659 struct scaninfo
*info
= data
;
671 * Step 5: invalidate all cached file data.
673 if (vinvalbuf(vp
, 0, 0, 0))
674 panic("ext2_reload: dirty2");
676 * Step 6: re-read inode data for all active vnodes.
679 error
= bread(info
->devvp
,
680 fsbtodoff(info
->fs
, ino_to_fsba(info
->fs
, ip
->i_number
)),
681 (int)info
->fs
->s_blocksize
, &bp
);
684 ext2_ei2di((struct ext2_inode
*) ((char *)bp
->b_data
+
685 EXT2_INODE_SIZE
* ino_to_fsbo(info
->fs
, ip
->i_number
)),
692 * Common code for mount and mountroot
695 ext2_mountfs(struct vnode
*devvp
, struct mount
*mp
, struct ucred
*cred
)
697 struct ext2mount
*ump
;
699 struct ext2_sb_info
*fs
;
700 struct ext2_super_block
* es
;
702 struct partinfo dpart
;
707 * Disallow multiple mounts of the same device.
708 * Disallow mounting of a device that is currently in use
709 * (except for root, which might share swap device for miniroot).
710 * Flush out any old buffers remaining from a previous use.
712 if ((error
= vfs_mountedon(devvp
)) != 0)
714 if (count_udev(devvp
->v_umajor
, devvp
->v_uminor
) > 0)
716 if ((error
= vinvalbuf(devvp
, V_SAVE
, 0, 0)) != 0)
719 /* turn on this to force it to be read-only */
720 mp
->mnt_flag
|= MNT_RDONLY
;
723 ronly
= (mp
->mnt_flag
& MNT_RDONLY
) != 0;
724 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
725 error
= VOP_OPEN(devvp
, ronly
? FREAD
: FREAD
|FWRITE
, FSCRED
, NULL
);
730 if (dev
->si_iosize_max
!= 0)
731 mp
->mnt_iosize_max
= dev
->si_iosize_max
;
732 if (mp
->mnt_iosize_max
> MAXPHYS
)
733 mp
->mnt_iosize_max
= MAXPHYS
;
734 if (VOP_IOCTL(devvp
, DIOCGPART
, (caddr_t
)&dpart
, FREAD
, cred
) != 0) {
737 size
= dpart
.media_blksize
;
742 if ((error
= bread(devvp
, SBOFF
, SBSIZE
, &bp
)) != 0)
744 es
= (struct ext2_super_block
*)bp
->b_data
;
745 if (ext2_check_sb_compat(es
, dev
, ronly
) != 0) {
746 error
= EINVAL
; /* XXX needs translation */
749 if ((es
->s_state
& EXT2_VALID_FS
) == 0 ||
750 (es
->s_state
& EXT2_ERROR_FS
)) {
751 if (ronly
|| (mp
->mnt_flag
& MNT_FORCE
)) {
753 "WARNING: Filesystem was not properly dismounted\n");
756 "WARNING: R/W mount denied. Filesystem is not clean - run fsck\n");
761 ump
= bsd_malloc(sizeof *ump
, M_EXT2MNT
, M_WAITOK
| M_ZERO
);
762 ump
->um_malloctype
= M_EXT2NODE
;
763 ump
->um_blkatoff
= ext2_blkatoff
;
764 ump
->um_truncate
= ext2_truncate
;
765 ump
->um_update
= ext2_update
;
766 ump
->um_valloc
= ext2_valloc
;
767 ump
->um_vfree
= ext2_vfree
;
768 /* I don't know whether this is the right strategy. Note that
769 we dynamically allocate both a ext2_sb_info and a ext2_super_block
770 while Linux keeps the super block in a locked buffer
772 ump
->um_e2fs
= bsd_malloc(sizeof(struct ext2_sb_info
),
773 M_EXT2MNT
, M_WAITOK
);
774 ump
->um_e2fs
->s_es
= bsd_malloc(sizeof(struct ext2_super_block
),
775 M_EXT2MNT
, M_WAITOK
);
776 bcopy(es
, ump
->um_e2fs
->s_es
, (u_int
)sizeof(struct ext2_super_block
));
777 if ((error
= compute_sb_data(devvp
, ump
->um_e2fs
->s_es
, ump
->um_e2fs
)))
780 * We don't free the group descriptors allocated by compute_sb_data()
781 * until ext2_unmount(). This is OK since the mount will succeed.
786 fs
->s_rd_only
= ronly
; /* ronly is set according to mnt_flags */
787 /* if the fs is not mounted read-only, make sure the super block is
788 always written back on a sync()
790 fs
->s_wasvalid
= fs
->s_es
->s_state
& EXT2_VALID_FS
? 1 : 0;
792 fs
->s_dirt
= 1; /* mark it modified */
793 fs
->s_es
->s_state
&= ~EXT2_VALID_FS
; /* set fs invalid */
795 mp
->mnt_data
= (qaddr_t
)ump
;
796 mp
->mnt_stat
.f_fsid
.val
[0] = dev2udev(dev
);
797 mp
->mnt_stat
.f_fsid
.val
[1] = mp
->mnt_vfc
->vfc_typenum
;
798 mp
->mnt_maxsymlinklen
= EXT2_MAXSYMLINKLEN
;
799 mp
->mnt_flag
|= MNT_LOCAL
;
802 ump
->um_devvp
= devvp
;
803 /* setting those two parameters allows us to use
804 ext2_bmap w/o changse !
806 ump
->um_nindir
= EXT2_ADDR_PER_BLOCK(fs
);
807 ump
->um_bptrtodb
= fs
->s_es
->s_log_block_size
+ 1;
808 ump
->um_seqinc
= EXT2_FRAGS_PER_BLOCK(fs
);
809 for (i
= 0; i
< MAXQUOTAS
; i
++)
810 ump
->um_quotas
[i
] = NULLVP
;
811 dev
->si_mountpoint
= mp
;
813 vfs_add_vnodeops(mp
, &ext2_vnode_vops
, &mp
->mnt_vn_norm_ops
);
814 vfs_add_vnodeops(mp
, &ext2_spec_vops
, &mp
->mnt_vn_spec_ops
);
815 vfs_add_vnodeops(mp
, &ext2_fifo_vops
, &mp
->mnt_vn_fifo_ops
);
818 ext2_sbupdate(ump
, MNT_WAIT
);
823 VOP_CLOSE(devvp
, ronly
? FREAD
: FREAD
|FWRITE
);
825 bsd_free(ump
->um_e2fs
->s_es
, M_EXT2MNT
);
826 bsd_free(ump
->um_e2fs
, M_EXT2MNT
);
827 bsd_free(ump
, M_EXT2MNT
);
828 mp
->mnt_data
= (qaddr_t
)0;
834 * unmount system call
837 ext2_unmount(struct mount
*mp
, int mntflags
)
839 struct ext2mount
*ump
;
840 struct ext2_sb_info
*fs
;
841 int error
, flags
, ronly
, i
;
844 if (mntflags
& MNT_FORCE
) {
845 if (mp
->mnt_flag
& MNT_ROOTFS
)
849 if ((error
= ext2_flushfiles(mp
, flags
)) != 0)
853 ronly
= fs
->s_rd_only
;
856 fs
->s_es
->s_state
|= EXT2_VALID_FS
;
857 ext2_sbupdate(ump
, MNT_WAIT
);
860 /* release buffers containing group descriptors */
861 for(i
= 0; i
< fs
->s_db_per_group
; i
++)
862 ULCK_BUF(fs
->s_group_desc
[i
])
863 bsd_free(fs
->s_group_desc
, M_EXT2MNT
);
865 /* release cached inode/block bitmaps */
866 for (i
= 0; i
< EXT2_MAX_GROUP_LOADED
; i
++)
867 if (fs
->s_inode_bitmap
[i
])
868 ULCK_BUF(fs
->s_inode_bitmap
[i
])
870 for (i
= 0; i
< EXT2_MAX_GROUP_LOADED
; i
++)
871 if (fs
->s_block_bitmap
[i
])
872 ULCK_BUF(fs
->s_block_bitmap
[i
])
874 ump
->um_devvp
->v_rdev
->si_mountpoint
= NULL
;
875 error
= VOP_CLOSE(ump
->um_devvp
, ronly
? FREAD
: FREAD
|FWRITE
);
876 vrele(ump
->um_devvp
);
877 bsd_free(fs
->s_es
, M_EXT2MNT
);
878 bsd_free(fs
, M_EXT2MNT
);
879 bsd_free(ump
, M_EXT2MNT
);
880 mp
->mnt_data
= (qaddr_t
)0;
881 mp
->mnt_flag
&= ~MNT_LOCAL
;
886 * Flush out all the files in a filesystem.
889 ext2_flushfiles(struct mount
*mp
, int flags
)
891 struct ext2mount
*ump
;
899 if (mp
->mnt_flag
& MNT_QUOTA
) {
900 if ((error
= vflush(mp
, 0, SKIPSYSTEM
|flags
)) != 0)
902 for (i
= 0; i
< MAXQUOTAS
; i
++) {
903 if (ump
->um_quotas
[i
] == NULLVP
)
905 ext2_quotaoff(mp
, i
);
908 * Here we fall through to vflush again to ensure
909 * that we have gotten rid of all the system vnodes.
913 error
= vflush(mp
, 0, flags
);
918 * Get file system statistics.
919 * taken from ext2/super.c ext2_statfs
922 ext2_statfs(struct mount
*mp
, struct statfs
*sbp
, struct ucred
*cred
)
924 unsigned long overhead
;
925 struct ext2mount
*ump
;
926 struct ext2_sb_info
*fs
;
927 struct ext2_super_block
*es
;
934 if (es
->s_magic
!= EXT2_SUPER_MAGIC
)
935 panic("ext2_statfs - magic number spoiled");
938 * Compute the overhead (FS structures)
940 if (es
->s_feature_ro_compat
& EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
) {
942 for (i
= 0 ; i
< fs
->s_groups_count
; i
++)
943 if (ext2_group_sparse(i
))
946 nsb
= fs
->s_groups_count
;
947 overhead
= es
->s_first_data_block
+
948 /* Superblocks and block group descriptors: */
949 nsb
* (1 + fs
->s_db_per_group
) +
950 /* Inode bitmap, block bitmap, and inode table: */
951 fs
->s_groups_count
* (1 + 1 + fs
->s_itb_per_group
);
953 sbp
->f_bsize
= EXT2_FRAG_SIZE(fs
);
954 sbp
->f_iosize
= EXT2_BLOCK_SIZE(fs
);
955 sbp
->f_blocks
= es
->s_blocks_count
- overhead
;
956 sbp
->f_bfree
= es
->s_free_blocks_count
;
957 sbp
->f_bavail
= sbp
->f_bfree
- es
->s_r_blocks_count
;
958 sbp
->f_files
= es
->s_inodes_count
;
959 sbp
->f_ffree
= es
->s_free_inodes_count
;
960 if (sbp
!= &mp
->mnt_stat
) {
961 sbp
->f_type
= mp
->mnt_vfc
->vfc_typenum
;
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 static int ext2_sync_scan(struct mount
*mp
, struct vnode
*vp
, void *data
);
979 ext2_sync(struct mount
*mp
, int waitfor
)
981 struct ext2mount
*ump
= VFSTOEXT2(mp
);
982 struct ext2_sb_info
*fs
;
983 struct scaninfo scaninfo
;
987 if (fs
->s_dirt
!= 0 && fs
->s_rd_only
!= 0) { /* XXX */
988 kprintf("fs = %s\n", fs
->fs_fsmnt
);
989 panic("ext2_sync: rofs mod");
993 * Write back each (modified) inode.
995 scaninfo
.allerror
= 0;
997 scaninfo
.waitfor
= waitfor
;
998 while (scaninfo
.rescan
) {
1000 vmntvnodescan(mp
, VMSC_GETVP
|VMSC_NOWAIT
,
1001 NULL
, ext2_sync_scan
, &scaninfo
);
1005 * Force stale file system control information to be flushed.
1007 if (waitfor
!= MNT_LAZY
) {
1008 vn_lock(ump
->um_devvp
, LK_EXCLUSIVE
| LK_RETRY
);
1009 if ((error
= VOP_FSYNC(ump
->um_devvp
, waitfor
)) != 0)
1010 scaninfo
.allerror
= error
;
1011 vn_unlock(ump
->um_devvp
);
1017 * Write back modified superblock.
1019 if (fs
->s_dirt
!= 0) {
1021 fs
->s_es
->s_wtime
= time_second
;
1022 if ((error
= ext2_sbupdate(ump
, waitfor
)) != 0)
1023 scaninfo
.allerror
= error
;
1025 return (scaninfo
.allerror
);
1029 ext2_sync_scan(struct mount
*mp
, struct vnode
*vp
, void *data
)
1031 struct scaninfo
*info
= data
;
1036 if (vp
->v_type
== VNON
||
1038 (IN_ACCESS
| IN_CHANGE
| IN_MODIFIED
| IN_UPDATE
)) == 0 &&
1039 (RB_EMPTY(&vp
->v_rbdirty_tree
) || info
->waitfor
== MNT_LAZY
))) {
1042 if ((error
= VOP_FSYNC(vp
, info
->waitfor
)) != 0)
1043 info
->allerror
= error
;
1048 * Look up a EXT2FS dinode number to find its incore vnode, otherwise read it
1049 * in from disk. If it is in core, wait for the lock bit to clear, then
1050 * return the inode locked. Detection and handling of mount points must be
1051 * done by the calling routine.
1054 ext2_vget(struct mount
*mp
, ino_t ino
, struct vnode
**vpp
)
1056 struct ext2_sb_info
*fs
;
1058 struct ext2mount
*ump
;
1065 ump
= VFSTOEXT2(mp
);
1068 if ((*vpp
= ext2_ihashget(dev
, ino
)) != NULL
)
1072 * Lock out the creation of new entries in the FFS hash table in
1073 * case getnewvnode() or MALLOC() blocks, otherwise a duplicate
1076 if (ext2fs_inode_hash_lock
) {
1077 while (ext2fs_inode_hash_lock
) {
1078 ext2fs_inode_hash_lock
= -1;
1079 tsleep(&ext2fs_inode_hash_lock
, 0, "e2vget", 0);
1083 ext2fs_inode_hash_lock
= 1;
1086 * If this MALLOC() is performed after the getnewvnode()
1087 * it might block, leaving a vnode with a NULL v_data to be
1088 * found by ext2_sync() if a sync happens to fire right then,
1089 * which will cause a panic because ext2_sync() blindly
1090 * dereferences vp->v_data (as well it should).
1092 MALLOC(ip
, struct inode
*, sizeof(struct inode
), M_EXT2NODE
, M_WAITOK
);
1094 /* Allocate a new vnode/inode. */
1095 if ((error
= getnewvnode(VT_EXT2FS
, mp
, &vp
, 0, LK_CANRECURSE
)) != 0) {
1096 if (ext2fs_inode_hash_lock
< 0)
1097 wakeup(&ext2fs_inode_hash_lock
);
1098 ext2fs_inode_hash_lock
= 0;
1100 FREE(ip
, M_EXT2NODE
);
1103 bzero((caddr_t
)ip
, sizeof(struct inode
));
1106 ip
->i_e2fs
= fs
= ump
->um_e2fs
;
1110 for (i
= 0; i
< MAXQUOTAS
; i
++)
1111 ip
->i_dquot
[i
] = NODQUOT
;
1114 * Put it onto its hash chain. Since our vnode is locked, other
1115 * requests for this inode will block if they arrive while we are
1116 * sleeping waiting for old data structures to be purged or for the
1117 * contents of the disk portion of this inode to be read.
1121 if (ext2fs_inode_hash_lock
< 0)
1122 wakeup(&ext2fs_inode_hash_lock
);
1123 ext2fs_inode_hash_lock
= 0;
1125 /* Read in the disk contents for the inode, copy into the inode. */
1127 kprintf("ext2_vget(%d) dbn= %d ", ino
, fsbtodb(fs
, ino_to_fsba(fs
, ino
)));
1129 error
= bread(ump
->um_devvp
, fsbtodoff(fs
, ino_to_fsba(fs
, ino
)),
1130 (int)fs
->s_blocksize
, &bp
);
1133 * The inode does not contain anything useful, so it would
1134 * be misleading to leave it on its hash chain. With mode
1135 * still zero, it will be unlinked and returned to the free
1143 /* convert ext2 inode to dinode */
1144 ext2_ei2di((struct ext2_inode
*) ((char *)bp
->b_data
+ EXT2_INODE_SIZE
*
1145 ino_to_fsbo(fs
, ino
)), &ip
->i_din
);
1146 ip
->i_block_group
= ino_to_cg(fs
, ino
);
1147 ip
->i_next_alloc_block
= 0;
1148 ip
->i_next_alloc_goal
= 0;
1149 ip
->i_prealloc_count
= 0;
1150 ip
->i_prealloc_block
= 0;
1151 /* now we want to make sure that block pointers for unused
1152 blocks are zeroed out - ext2_balloc depends on this
1153 although for regular files and directories only
1155 if(S_ISDIR(ip
->i_mode
) || S_ISREG(ip
->i_mode
)) {
1156 used_blocks
= (ip
->i_size
+fs
->s_blocksize
-1) / fs
->s_blocksize
;
1157 for(i
= used_blocks
; i
< EXT2_NDIR_BLOCKS
; i
++)
1161 ext2_print_inode(ip
);
1166 * Initialize the vnode from the inode, check for aliases.
1167 * Note that the underlying vnode may have changed.
1169 if ((error
= ext2_vinit(mp
, &vp
)) != 0) {
1176 * Finish inode initialization now that aliasing has been resolved.
1178 ip
->i_devvp
= ump
->um_devvp
;
1181 * Set up a generation number for this inode if it does not
1182 * already have one. This should only happen on old filesystems.
1184 if (ip
->i_gen
== 0) {
1185 ip
->i_gen
= krandom() / 2 + 1;
1186 if ((vp
->v_mount
->mnt_flag
& MNT_RDONLY
) == 0)
1187 ip
->i_flag
|= IN_MODIFIED
;
1190 * Return the locked and refd vnode.
1197 * File handle to vnode
1199 * Have to be really careful about stale file handles:
1200 * - check that the inode number is valid
1201 * - call ext2_vget() to get the locked inode
1202 * - check for an unallocated inode (i_mode == 0)
1203 * - check that the given client host has export rights and return
1204 * those rights via. exflagsp and credanonp
1207 ext2_fhtovp(struct mount
*mp
, struct vnode
*rootvp
,
1208 struct fid
*fhp
, struct vnode
**vpp
)
1211 struct ext2_sb_info
*fs
;
1216 ufhp
= (struct ufid
*)fhp
;
1217 fs
= VFSTOEXT2(mp
)->um_e2fs
;
1218 if (ufhp
->ufid_ino
< ROOTINO
||
1219 ufhp
->ufid_ino
> fs
->s_groups_count
* fs
->s_es
->s_inodes_per_group
)
1222 error
= VFS_VGET(mp
, ufhp
->ufid_ino
, &nvp
);
1228 if (ip
->i_mode
== 0 ||
1229 ip
->i_gen
!= ufhp
->ufid_gen
||
1230 (VFSTOEXT2(mp
)->um_i_effnlink_valid
? ip
->i_effnlink
:
1231 ip
->i_nlink
) <= 0) {
1241 * Vnode pointer to File handle
1245 ext2_vptofh(struct vnode
*vp
, struct fid
*fhp
)
1251 ufhp
= (struct ufid
*)fhp
;
1252 ufhp
->ufid_len
= sizeof(struct ufid
);
1253 ufhp
->ufid_ino
= ip
->i_number
;
1254 ufhp
->ufid_gen
= ip
->i_gen
;
1259 * This is the generic part of fhtovp called after the underlying
1260 * filesystem has validated the file handle.
1262 * Verify that a host should have access to a filesystem.
1265 ext2_check_export(struct mount
*mp
, struct sockaddr
*nam
, int *exflagsp
,
1266 struct ucred
**credanonp
)
1269 struct ext2mount
*ump
;
1271 ump
= VFSTOEXT2(mp
);
1273 * Get the export permission structure for this <mp, client> tuple.
1275 np
= vfs_export_lookup(mp
, &ump
->um_export
, nam
);
1279 *exflagsp
= np
->netc_exflags
;
1280 *credanonp
= &np
->netc_anon
;
1285 * Write a superblock and associated information back to disk.
1288 ext2_sbupdate(struct ext2mount
*mp
, int waitfor
)
1290 struct ext2_sb_info
*fs
= mp
->um_e2fs
;
1291 struct ext2_super_block
*es
= fs
->s_es
;
1295 kprintf("\nupdating superblock, waitfor=%s\n", waitfor == MNT_WAIT ? "yes":"no");
1297 bp
= getblk(mp
->um_devvp
, SBOFF
, SBSIZE
, 0, 0);
1298 bcopy((caddr_t
)es
, bp
->b_data
, (u_int
)sizeof(struct ext2_super_block
));
1299 if (waitfor
== MNT_WAIT
)
1305 * The buffers for group descriptors, inode bitmaps and block bitmaps
1306 * are not busy at this point and are (hopefully) written by the
1307 * usual sync mechanism. No need to write them here