Deleted Added
full compact
ext2_vfsops.c (53059) ext2_vfsops.c (53452)
1/*
2 * modified for EXT2FS support in Lites 1.1
3 *
4 * Aug 1995, Godmar Back (gback@cs.utah.edu)
5 * University of Utah, Department of Computer Science
6 */
7/*
8 * Copyright (c) 1989, 1991, 1993, 1994
9 * The Regents of the University of California. All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
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.
26 *
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
37 * SUCH DAMAGE.
38 *
39 * @(#)ffs_vfsops.c 8.8 (Berkeley) 4/18/94
1/*
2 * modified for EXT2FS support in Lites 1.1
3 *
4 * Aug 1995, Godmar Back (gback@cs.utah.edu)
5 * University of Utah, Department of Computer Science
6 */
7/*
8 * Copyright (c) 1989, 1991, 1993, 1994
9 * The Regents of the University of California. All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
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.
26 *
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
37 * SUCH DAMAGE.
38 *
39 * @(#)ffs_vfsops.c 8.8 (Berkeley) 4/18/94
40 * $FreeBSD: head/sys/gnu/fs/ext2fs/ext2_vfsops.c 53059 1999-11-09 14:15:33Z phk $
40 * $FreeBSD: head/sys/gnu/fs/ext2fs/ext2_vfsops.c 53452 1999-11-20 10:00:46Z phk $
41 */
42
43#include "opt_quota.h"
44
45#include <sys/param.h>
46#include <sys/systm.h>
47#include <sys/namei.h>
48#include <sys/proc.h>
49#include <sys/kernel.h>
50#include <sys/vnode.h>
51#include <sys/mount.h>
52#include <sys/buf.h>
53#include <sys/conf.h>
54#include <sys/fcntl.h>
55#include <sys/disklabel.h>
56#include <sys/malloc.h>
57#include <sys/stat.h>
58
59#include <ufs/ufs/quota.h>
60#include <ufs/ufs/ufsmount.h>
61#include <ufs/ufs/inode.h>
62#include <ufs/ufs/ufs_extern.h>
63
64#include <gnu/ext2fs/fs.h>
65#include <gnu/ext2fs/ext2_extern.h>
66#include <gnu/ext2fs/ext2_fs.h>
67#include <gnu/ext2fs/ext2_fs_sb.h>
68
69static int ext2_fhtovp __P((struct mount *, struct fid *, struct vnode **));
70static int ext2_flushfiles __P((struct mount *mp, int flags, struct proc *p));
71static int ext2_mount __P((struct mount *,
72 char *, caddr_t, struct nameidata *, struct proc *));
73static int ext2_mountfs __P((struct vnode *, struct mount *, struct proc *));
74static int ext2_reload __P((struct mount *mountp, struct ucred *cred,
75 struct proc *p));
76static int ext2_sbupdate __P((struct ufsmount *, int));
77static int ext2_statfs __P((struct mount *, struct statfs *, struct proc *));
78static int ext2_sync __P((struct mount *, int, struct ucred *, struct proc *));
79static int ext2_unmount __P((struct mount *, int, struct proc *));
80static int ext2_vget __P((struct mount *, ino_t, struct vnode **));
81static int ext2_vptofh __P((struct vnode *, struct fid *));
82
83static MALLOC_DEFINE(M_EXT2NODE, "EXT2 node", "EXT2 vnode private part");
84
85static struct vfsops ext2fs_vfsops = {
86 ext2_mount,
87 ufs_start, /* empty function */
88 ext2_unmount,
89 ufs_root, /* root inode via vget */
90 ufs_quotactl, /* does operations associated with quotas */
91 ext2_statfs,
92 ext2_sync,
93 ext2_vget,
94 ext2_fhtovp,
95 ufs_check_export,
96 ext2_vptofh,
97 ext2_init,
98};
99
100VFS_SET(ext2fs_vfsops, ext2fs, 0);
101#define bsd_malloc malloc
102#define bsd_free free
103
104static int ext2fs_inode_hash_lock;
105
106static int compute_sb_data __P((struct vnode * devvp,
107 struct ext2_super_block * es,
108 struct ext2_sb_info * fs));
109
110#ifdef notyet
111static int ext2_mountroot __P((void));
112
113/*
114 * Called by main() when ext2fs is going to be mounted as root.
115 *
116 * Name is updated by mount(8) after booting.
117 */
118#define ROOTNAME "root_device"
119
120static int
121ext2_mountroot()
122{
123 register struct ext2_sb_info *fs;
124 register struct mount *mp;
125 struct proc *p = curproc;
126 struct ufsmount *ump;
127 u_int size;
128 int error;
129
130 if ((error = bdevvp(rootdev, &rootvp))) {
131 printf("ext2_mountroot: can't find rootvp\n");
132 return (error);
133 }
134 mp = bsd_malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK);
135 bzero((char *)mp, (u_long)sizeof(struct mount));
136 mp->mnt_op = &ext2fs_vfsops;
137 mp->mnt_flag = MNT_RDONLY;
138 if (error = ext2_mountfs(rootvp, mp, p)) {
139 bsd_free(mp, M_MOUNT);
140 return (error);
141 }
142 if (error = vfs_lock(mp)) {
143 (void)ext2_unmount(mp, 0, p);
144 bsd_free(mp, M_MOUNT);
145 return (error);
146 }
41 */
42
43#include "opt_quota.h"
44
45#include <sys/param.h>
46#include <sys/systm.h>
47#include <sys/namei.h>
48#include <sys/proc.h>
49#include <sys/kernel.h>
50#include <sys/vnode.h>
51#include <sys/mount.h>
52#include <sys/buf.h>
53#include <sys/conf.h>
54#include <sys/fcntl.h>
55#include <sys/disklabel.h>
56#include <sys/malloc.h>
57#include <sys/stat.h>
58
59#include <ufs/ufs/quota.h>
60#include <ufs/ufs/ufsmount.h>
61#include <ufs/ufs/inode.h>
62#include <ufs/ufs/ufs_extern.h>
63
64#include <gnu/ext2fs/fs.h>
65#include <gnu/ext2fs/ext2_extern.h>
66#include <gnu/ext2fs/ext2_fs.h>
67#include <gnu/ext2fs/ext2_fs_sb.h>
68
69static int ext2_fhtovp __P((struct mount *, struct fid *, struct vnode **));
70static int ext2_flushfiles __P((struct mount *mp, int flags, struct proc *p));
71static int ext2_mount __P((struct mount *,
72 char *, caddr_t, struct nameidata *, struct proc *));
73static int ext2_mountfs __P((struct vnode *, struct mount *, struct proc *));
74static int ext2_reload __P((struct mount *mountp, struct ucred *cred,
75 struct proc *p));
76static int ext2_sbupdate __P((struct ufsmount *, int));
77static int ext2_statfs __P((struct mount *, struct statfs *, struct proc *));
78static int ext2_sync __P((struct mount *, int, struct ucred *, struct proc *));
79static int ext2_unmount __P((struct mount *, int, struct proc *));
80static int ext2_vget __P((struct mount *, ino_t, struct vnode **));
81static int ext2_vptofh __P((struct vnode *, struct fid *));
82
83static MALLOC_DEFINE(M_EXT2NODE, "EXT2 node", "EXT2 vnode private part");
84
85static struct vfsops ext2fs_vfsops = {
86 ext2_mount,
87 ufs_start, /* empty function */
88 ext2_unmount,
89 ufs_root, /* root inode via vget */
90 ufs_quotactl, /* does operations associated with quotas */
91 ext2_statfs,
92 ext2_sync,
93 ext2_vget,
94 ext2_fhtovp,
95 ufs_check_export,
96 ext2_vptofh,
97 ext2_init,
98};
99
100VFS_SET(ext2fs_vfsops, ext2fs, 0);
101#define bsd_malloc malloc
102#define bsd_free free
103
104static int ext2fs_inode_hash_lock;
105
106static int compute_sb_data __P((struct vnode * devvp,
107 struct ext2_super_block * es,
108 struct ext2_sb_info * fs));
109
110#ifdef notyet
111static int ext2_mountroot __P((void));
112
113/*
114 * Called by main() when ext2fs is going to be mounted as root.
115 *
116 * Name is updated by mount(8) after booting.
117 */
118#define ROOTNAME "root_device"
119
120static int
121ext2_mountroot()
122{
123 register struct ext2_sb_info *fs;
124 register struct mount *mp;
125 struct proc *p = curproc;
126 struct ufsmount *ump;
127 u_int size;
128 int error;
129
130 if ((error = bdevvp(rootdev, &rootvp))) {
131 printf("ext2_mountroot: can't find rootvp\n");
132 return (error);
133 }
134 mp = bsd_malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK);
135 bzero((char *)mp, (u_long)sizeof(struct mount));
136 mp->mnt_op = &ext2fs_vfsops;
137 mp->mnt_flag = MNT_RDONLY;
138 if (error = ext2_mountfs(rootvp, mp, p)) {
139 bsd_free(mp, M_MOUNT);
140 return (error);
141 }
142 if (error = vfs_lock(mp)) {
143 (void)ext2_unmount(mp, 0, p);
144 bsd_free(mp, M_MOUNT);
145 return (error);
146 }
147 CIRCLEQ_INSERT_HEAD(&mountlist, mp, mnt_list);
147 TAILQ_INSERT_HEAD(&mountlist, mp, mnt_list);
148 mp->mnt_flag |= MNT_ROOTFS;
149 mp->mnt_vnodecovered = NULLVP;
150 ump = VFSTOUFS(mp);
151 fs = ump->um_e2fs;
152 bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt));
153 fs->fs_fsmnt[0] = '/';
154 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
155 MNAMELEN);
156 (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
157 &size);
158 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
159 (void)ext2_statfs(mp, &mp->mnt_stat, p);
160 vfs_unlock(mp);
161 inittodr(fs->s_es->s_wtime); /* this helps to set the time */
162 return (0);
163}
164#endif
165
166/*
167 * VFS Operations.
168 *
169 * mount system call
170 */
171static int
172ext2_mount(mp, path, data, ndp, p)
173 register struct mount *mp;
174 char *path;
175 caddr_t data; /* this is actually a (struct ufs_args *) */
176 struct nameidata *ndp;
177 struct proc *p;
178{
179 struct vnode *devvp;
180 struct ufs_args args;
181 struct ufsmount *ump = 0;
182 register struct ext2_sb_info *fs;
183 u_int size;
184 int error, flags;
185 mode_t accessmode;
186
187 if ((error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) != 0)
188 return (error);
189 /*
190 * If updating, check whether changing from read-only to
191 * read/write; if there is no device name, that's all we do.
192 */
193 if (mp->mnt_flag & MNT_UPDATE) {
194 ump = VFSTOUFS(mp);
195 fs = ump->um_e2fs;
196 error = 0;
197 if (fs->s_rd_only == 0 && (mp->mnt_flag & MNT_RDONLY)) {
198 flags = WRITECLOSE;
199 if (mp->mnt_flag & MNT_FORCE)
200 flags |= FORCECLOSE;
201 if (vfs_busy(mp, LK_NOWAIT, 0, p))
202 return (EBUSY);
203 error = ext2_flushfiles(mp, flags, p);
204 vfs_unbusy(mp, p);
205 if (!error && fs->s_wasvalid) {
206 fs->s_es->s_state |= EXT2_VALID_FS;
207 ext2_sbupdate(ump, MNT_WAIT);
208 }
209 fs->s_rd_only = 1;
210 }
211 if (!error && (mp->mnt_flag & MNT_RELOAD))
212 error = ext2_reload(mp, ndp->ni_cnd.cn_cred, p);
213 if (error)
214 return (error);
215 if (fs->s_rd_only && (mp->mnt_kern_flag & MNTK_WANTRDWR)) {
216 /*
217 * If upgrade to read-write by non-root, then verify
218 * that user has necessary permissions on the device.
219 */
220 if (p->p_ucred->cr_uid != 0) {
221 devvp = ump->um_devvp;
222 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
223 if ((error = VOP_ACCESS(devvp, VREAD | VWRITE,
224 p->p_ucred, p)) != 0) {
225 VOP_UNLOCK(devvp, 0, p);
226 return (error);
227 }
228 VOP_UNLOCK(devvp, 0, p);
229 }
230
231 if ((fs->s_es->s_state & EXT2_VALID_FS) == 0 ||
232 (fs->s_es->s_state & EXT2_ERROR_FS)) {
233 if (mp->mnt_flag & MNT_FORCE) {
234 printf(
235"WARNING: %s was not properly dismounted\n",
236 fs->fs_fsmnt);
237 } else {
238 printf(
239"WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n",
240 fs->fs_fsmnt);
241 return (EPERM);
242 }
243 }
244 fs->s_es->s_state &= ~EXT2_VALID_FS;
245 ext2_sbupdate(ump, MNT_WAIT);
246 fs->s_rd_only = 0;
247 }
248 if (args.fspec == 0) {
249 /*
250 * Process export requests.
251 */
252 return (vfs_export(mp, &ump->um_export, &args.export));
253 }
254 }
255 /*
256 * Not an update, or updating the name: look up the name
257 * and verify that it refers to a sensible block device.
258 */
259 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
260 if ((error = namei(ndp)) != 0)
261 return (error);
262 devvp = ndp->ni_vp;
263
264 if (!vn_isdisk(devvp)) {
265 vrele(devvp);
266 return (ENOTBLK);
267 }
268
269 /*
270 * If mount by non-root, then verify that user has necessary
271 * permissions on the device.
272 */
273 if (p->p_ucred->cr_uid != 0) {
274 accessmode = VREAD;
275 if ((mp->mnt_flag & MNT_RDONLY) == 0)
276 accessmode |= VWRITE;
277 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
278 if ((error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) != 0) {
279 vput(devvp);
280 return (error);
281 }
282 VOP_UNLOCK(devvp, 0, p);
283 }
284
285 if ((mp->mnt_flag & MNT_UPDATE) == 0) {
286 error = ext2_mountfs(devvp, mp, p);
287 } else {
288 if (devvp != ump->um_devvp)
289 error = EINVAL; /* needs translation */
290 else
291 vrele(devvp);
292 }
293 if (error) {
294 vrele(devvp);
295 return (error);
296 }
297 ump = VFSTOUFS(mp);
298 fs = ump->um_e2fs;
299 (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
300 bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
301 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
302 MNAMELEN);
303 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
304 &size);
305 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
306 (void)ext2_statfs(mp, &mp->mnt_stat, p);
307 return (0);
308}
309
310/*
311 * checks that the data in the descriptor blocks make sense
312 * this is taken from ext2/super.c
313 */
314static int ext2_check_descriptors (struct ext2_sb_info * sb)
315{
316 int i;
317 int desc_block = 0;
318 unsigned long block = sb->s_es->s_first_data_block;
319 struct ext2_group_desc * gdp = NULL;
320
321 /* ext2_debug ("Checking group descriptors"); */
322
323 for (i = 0; i < sb->s_groups_count; i++)
324 {
325 /* examine next descriptor block */
326 if ((i % EXT2_DESC_PER_BLOCK(sb)) == 0)
327 gdp = (struct ext2_group_desc *)
328 sb->s_group_desc[desc_block++]->b_data;
329 if (gdp->bg_block_bitmap < block ||
330 gdp->bg_block_bitmap >= block + EXT2_BLOCKS_PER_GROUP(sb))
331 {
332 printf ("ext2_check_descriptors: "
333 "Block bitmap for group %d"
334 " not in group (block %lu)!\n",
335 i, (unsigned long) gdp->bg_block_bitmap);
336 return 0;
337 }
338 if (gdp->bg_inode_bitmap < block ||
339 gdp->bg_inode_bitmap >= block + EXT2_BLOCKS_PER_GROUP(sb))
340 {
341 printf ("ext2_check_descriptors: "
342 "Inode bitmap for group %d"
343 " not in group (block %lu)!\n",
344 i, (unsigned long) gdp->bg_inode_bitmap);
345 return 0;
346 }
347 if (gdp->bg_inode_table < block ||
348 gdp->bg_inode_table + sb->s_itb_per_group >=
349 block + EXT2_BLOCKS_PER_GROUP(sb))
350 {
351 printf ("ext2_check_descriptors: "
352 "Inode table for group %d"
353 " not in group (block %lu)!\n",
354 i, (unsigned long) gdp->bg_inode_table);
355 return 0;
356 }
357 block += EXT2_BLOCKS_PER_GROUP(sb);
358 gdp++;
359 }
360 return 1;
361}
362
363/*
364 * this computes the fields of the ext2_sb_info structure from the
365 * data in the ext2_super_block structure read in
366 */
367static int compute_sb_data(devvp, es, fs)
368 struct vnode * devvp;
369 struct ext2_super_block * es;
370 struct ext2_sb_info * fs;
371{
372 int db_count, error;
373 int i, j;
374 int logic_sb_block = 1; /* XXX for now */
375
376#if 1
377#define V(v)
378#else
379#define V(v) printf(#v"= %d\n", fs->v);
380#endif
381
382 fs->s_blocksize = EXT2_MIN_BLOCK_SIZE << es->s_log_block_size;
383 V(s_blocksize)
384 fs->s_bshift = EXT2_MIN_BLOCK_LOG_SIZE + es->s_log_block_size;
385 V(s_bshift)
386 fs->s_fsbtodb = es->s_log_block_size + 1;
387 V(s_fsbtodb)
388 fs->s_qbmask = fs->s_blocksize - 1;
389 V(s_bmask)
390 fs->s_blocksize_bits = EXT2_BLOCK_SIZE_BITS(es);
391 V(s_blocksize_bits)
392 fs->s_frag_size = EXT2_MIN_FRAG_SIZE << es->s_log_frag_size;
393 V(s_frag_size)
394 if (fs->s_frag_size)
395 fs->s_frags_per_block = fs->s_blocksize / fs->s_frag_size;
396 V(s_frags_per_block)
397 fs->s_blocks_per_group = es->s_blocks_per_group;
398 V(s_blocks_per_group)
399 fs->s_frags_per_group = es->s_frags_per_group;
400 V(s_frags_per_group)
401 fs->s_inodes_per_group = es->s_inodes_per_group;
402 V(s_inodes_per_group)
403 fs->s_inodes_per_block = fs->s_blocksize / EXT2_INODE_SIZE;
404 V(s_inodes_per_block)
405 fs->s_itb_per_group = fs->s_inodes_per_group /fs->s_inodes_per_block;
406 V(s_itb_per_group)
407 fs->s_desc_per_block = fs->s_blocksize / sizeof (struct ext2_group_desc);
408 V(s_desc_per_block)
409 /* s_resuid / s_resgid ? */
410 fs->s_groups_count = (es->s_blocks_count -
411 es->s_first_data_block +
412 EXT2_BLOCKS_PER_GROUP(fs) - 1) /
413 EXT2_BLOCKS_PER_GROUP(fs);
414 V(s_groups_count)
415 db_count = (fs->s_groups_count + EXT2_DESC_PER_BLOCK(fs) - 1) /
416 EXT2_DESC_PER_BLOCK(fs);
417 fs->s_db_per_group = db_count;
418 V(s_db_per_group)
419
420 fs->s_group_desc = bsd_malloc(db_count * sizeof (struct buf *),
421 M_UFSMNT, M_WAITOK);
422
423 /* adjust logic_sb_block */
424 if(fs->s_blocksize > SBSIZE)
425 /* Godmar thinks: if the blocksize is greater than 1024, then
426 the superblock is logically part of block zero.
427 */
428 logic_sb_block = 0;
429
430 for (i = 0; i < db_count; i++) {
431 error = bread(devvp , fsbtodb(fs, logic_sb_block + i + 1),
432 fs->s_blocksize, NOCRED, &fs->s_group_desc[i]);
433 if(error) {
434 for (j = 0; j < i; j++)
435 brelse(fs->s_group_desc[j]);
436 bsd_free(fs->s_group_desc, M_UFSMNT);
437 printf("EXT2-fs: unable to read group descriptors (%d)\n", error);
438 return EIO;
439 }
440 /* Set the B_LOCKED flag on the buffer, then brelse() it */
441 LCK_BUF(fs->s_group_desc[i])
442 }
443 if(!ext2_check_descriptors(fs)) {
444 for (j = 0; j < db_count; j++)
445 ULCK_BUF(fs->s_group_desc[j])
446 bsd_free(fs->s_group_desc, M_UFSMNT);
447 printf("EXT2-fs: (ext2_check_descriptors failure) "
448 "unable to read group descriptors\n");
449 return EIO;
450 }
451
452 for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) {
453 fs->s_inode_bitmap_number[i] = 0;
454 fs->s_inode_bitmap[i] = NULL;
455 fs->s_block_bitmap_number[i] = 0;
456 fs->s_block_bitmap[i] = NULL;
457 }
458 fs->s_loaded_inode_bitmaps = 0;
459 fs->s_loaded_block_bitmaps = 0;
460 return 0;
461}
462
463/*
464 * Reload all incore data for a filesystem (used after running fsck on
465 * the root filesystem and finding things to fix). The filesystem must
466 * be mounted read-only.
467 *
468 * Things to do to update the mount:
469 * 1) invalidate all cached meta-data.
470 * 2) re-read superblock from disk.
471 * 3) re-read summary information from disk.
472 * 4) invalidate all inactive vnodes.
473 * 5) invalidate all cached file data.
474 * 6) re-read inode data for all active vnodes.
475 */
476static int
477ext2_reload(mountp, cred, p)
478 register struct mount *mountp;
479 struct ucred *cred;
480 struct proc *p;
481{
482 register struct vnode *vp, *nvp, *devvp;
483 struct inode *ip;
484 struct buf *bp;
485 struct ext2_super_block * es;
486 struct ext2_sb_info *fs;
487 int error;
488
489 if ((mountp->mnt_flag & MNT_RDONLY) == 0)
490 return (EINVAL);
491 /*
492 * Step 1: invalidate all cached meta-data.
493 */
494 devvp = VFSTOUFS(mountp)->um_devvp;
495 if (vinvalbuf(devvp, 0, cred, p, 0, 0))
496 panic("ext2_reload: dirty1");
497 /*
498 * Step 2: re-read superblock from disk.
499 * constants have been adjusted for ext2
500 */
501 if ((error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) != 0)
502 return (error);
503 es = (struct ext2_super_block *)bp->b_data;
504 if (es->s_magic != EXT2_SUPER_MAGIC) {
505 if(es->s_magic == EXT2_PRE_02B_MAGIC)
506 printf("This filesystem bears the magic number of a pre "
507 "0.2b version of ext2. This is not supported by "
508 "Lites.\n");
509 else
510 printf("Wrong magic number: %x (expected %x for ext2 fs\n",
511 es->s_magic, EXT2_SUPER_MAGIC);
512 brelse(bp);
513 return (EIO); /* XXX needs translation */
514 }
515 fs = VFSTOUFS(mountp)->um_e2fs;
516 bcopy(bp->b_data, fs->s_es, sizeof(struct ext2_super_block));
517
518 if((error = compute_sb_data(devvp, es, fs)) != 0) {
519 brelse(bp);
520 return error;
521 }
522#ifdef UNKLAR
523 if (fs->fs_sbsize < SBSIZE)
524 bp->b_flags |= B_INVAL;
525#endif
526 brelse(bp);
527
528loop:
529 simple_lock(&mntvnode_slock);
530 for (vp = mountp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
531 if (vp->v_mount != mountp) {
532 simple_unlock(&mntvnode_slock);
533 goto loop;
534 }
535 nvp = vp->v_mntvnodes.le_next;
536 /*
537 * Step 4: invalidate all inactive vnodes.
538 */
539 if (vrecycle(vp, &mntvnode_slock, p))
540 goto loop;
541 /*
542 * Step 5: invalidate all cached file data.
543 */
544 simple_lock(&vp->v_interlock);
545 simple_unlock(&mntvnode_slock);
546 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) {
547 goto loop;
548 }
549 if (vinvalbuf(vp, 0, cred, p, 0, 0))
550 panic("ext2_reload: dirty2");
551 /*
552 * Step 6: re-read inode data for all active vnodes.
553 */
554 ip = VTOI(vp);
555 error =
556 bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
557 (int)fs->s_blocksize, NOCRED, &bp);
558 if (error) {
559 vput(vp);
560 return (error);
561 }
562 ext2_ei2di((struct ext2_inode *) ((char *)bp->b_data +
563 EXT2_INODE_SIZE * ino_to_fsbo(fs, ip->i_number)),
564 &ip->i_din);
565 brelse(bp);
566 vput(vp);
567 simple_lock(&mntvnode_slock);
568 }
569 simple_unlock(&mntvnode_slock);
570 return (0);
571}
572
573/*
574 * Common code for mount and mountroot
575 */
576static int
577ext2_mountfs(devvp, mp, p)
578 register struct vnode *devvp;
579 struct mount *mp;
580 struct proc *p;
581{
582 register struct ufsmount *ump;
583 struct buf *bp;
584 register struct ext2_sb_info *fs;
585 struct ext2_super_block * es;
586 dev_t dev = devvp->v_rdev;
587 struct partinfo dpart;
588 int havepart = 0;
589 int error, i, size;
590 int ronly;
591
592 /*
593 * Disallow multiple mounts of the same device.
594 * Disallow mounting of a device that is currently in use
595 * (except for root, which might share swap device for miniroot).
596 * Flush out any old buffers remaining from a previous use.
597 */
598 if ((error = vfs_mountedon(devvp)) != 0)
599 return (error);
600 if (vcount(devvp) > 1 && devvp != rootvp)
601 return (EBUSY);
602 if ((error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0)) != 0)
603 return (error);
604#ifdef READONLY
605/* turn on this to force it to be read-only */
606 mp->mnt_flag |= MNT_RDONLY;
607#endif
608
609 ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
610 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
611 error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
612 VOP_UNLOCK(devvp, 0, p);
613 if (error)
614 return (error);
615 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
616 size = DEV_BSIZE;
617 else {
618 havepart = 1;
619 size = dpart.disklab->d_secsize;
620 }
621
622 bp = NULL;
623 ump = NULL;
624 if ((error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) != 0)
625 goto out;
626 es = (struct ext2_super_block *)bp->b_data;
627 if (es->s_magic != EXT2_SUPER_MAGIC) {
628 if(es->s_magic == EXT2_PRE_02B_MAGIC)
629 printf("This filesystem bears the magic number of a pre "
630 "0.2b version of ext2. This is not supported by "
631 "Lites.\n");
632 else
633 printf("Wrong magic number: %x (expected %x for EXT2FS)\n",
634 es->s_magic, EXT2_SUPER_MAGIC);
635 error = EINVAL; /* XXX needs translation */
636 goto out;
637 }
638 if ((es->s_state & EXT2_VALID_FS) == 0 ||
639 (es->s_state & EXT2_ERROR_FS)) {
640 if (ronly || (mp->mnt_flag & MNT_FORCE)) {
641 printf(
642"WARNING: Filesystem was not properly dismounted\n");
643 } else {
644 printf(
645"WARNING: R/W mount denied. Filesystem is not clean - run fsck\n");
646 error = EPERM;
647 goto out;
648 }
649 }
650 ump = bsd_malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
651 bzero((caddr_t)ump, sizeof *ump);
652 ump->um_malloctype = M_EXT2NODE;
653 ump->um_blkatoff = ext2_blkatoff;
654 ump->um_truncate = ext2_truncate;
655 ump->um_update = ext2_update;
656 ump->um_valloc = ext2_valloc;
657 ump->um_vfree = ext2_vfree;
658 /* I don't know whether this is the right strategy. Note that
659 we dynamically allocate both a ext2_sb_info and a ext2_super_block
660 while Linux keeps the super block in a locked buffer
661 */
662 ump->um_e2fs = bsd_malloc(sizeof(struct ext2_sb_info),
663 M_UFSMNT, M_WAITOK);
664 ump->um_e2fs->s_es = bsd_malloc(sizeof(struct ext2_super_block),
665 M_UFSMNT, M_WAITOK);
666 bcopy(es, ump->um_e2fs->s_es, (u_int)sizeof(struct ext2_super_block));
667 if ((error = compute_sb_data(devvp, ump->um_e2fs->s_es, ump->um_e2fs)))
668 goto out;
669 /*
670 * We don't free the group descriptors allocated by compute_sb_data()
671 * until ext2_unmount(). This is OK since the mount will succeed.
672 */
673 brelse(bp);
674 bp = NULL;
675 fs = ump->um_e2fs;
676 fs->s_rd_only = ronly; /* ronly is set according to mnt_flags */
677 /* if the fs is not mounted read-only, make sure the super block is
678 always written back on a sync()
679 */
680 fs->s_wasvalid = fs->s_es->s_state & EXT2_VALID_FS ? 1 : 0;
681 if (ronly == 0) {
682 fs->s_dirt = 1; /* mark it modified */
683 fs->s_es->s_state &= ~EXT2_VALID_FS; /* set fs invalid */
684 }
685 mp->mnt_data = (qaddr_t)ump;
686 mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
687 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
688 mp->mnt_maxsymlinklen = EXT2_MAXSYMLINKLEN;
689 mp->mnt_flag |= MNT_LOCAL;
690 ump->um_mountp = mp;
691 ump->um_dev = dev;
692 ump->um_devvp = devvp;
693 /* setting those two parameters allows us to use
694 ufs_bmap w/o changse !
695 */
696 ump->um_nindir = EXT2_ADDR_PER_BLOCK(fs);
697 ump->um_bptrtodb = fs->s_es->s_log_block_size + 1;
698 ump->um_seqinc = EXT2_FRAGS_PER_BLOCK(fs);
699 for (i = 0; i < MAXQUOTAS; i++)
700 ump->um_quotas[i] = NULLVP;
701 devvp->v_specmountpoint = mp;
702 if (ronly == 0)
703 ext2_sbupdate(ump, MNT_WAIT);
704 return (0);
705out:
706 if (bp)
707 brelse(bp);
708 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
709 if (ump) {
710 bsd_free(ump->um_e2fs->s_es, M_UFSMNT);
711 bsd_free(ump->um_e2fs, M_UFSMNT);
712 bsd_free(ump, M_UFSMNT);
713 mp->mnt_data = (qaddr_t)0;
714 }
715 return (error);
716}
717
718/*
719 * unmount system call
720 */
721static int
722ext2_unmount(mp, mntflags, p)
723 struct mount *mp;
724 int mntflags;
725 struct proc *p;
726{
727 register struct ufsmount *ump;
728 register struct ext2_sb_info *fs;
729 int error, flags, ronly, i;
730
731 flags = 0;
732 if (mntflags & MNT_FORCE) {
733 if (mp->mnt_flag & MNT_ROOTFS)
734 return (EINVAL);
735 flags |= FORCECLOSE;
736 }
737 if ((error = ext2_flushfiles(mp, flags, p)) != 0)
738 return (error);
739 ump = VFSTOUFS(mp);
740 fs = ump->um_e2fs;
741 ronly = fs->s_rd_only;
742 if (ronly == 0) {
743 if (fs->s_wasvalid)
744 fs->s_es->s_state |= EXT2_VALID_FS;
745 ext2_sbupdate(ump, MNT_WAIT);
746 }
747
748 /* release buffers containing group descriptors */
749 for(i = 0; i < fs->s_db_per_group; i++)
750 ULCK_BUF(fs->s_group_desc[i])
751 bsd_free(fs->s_group_desc, M_UFSMNT);
752
753 /* release cached inode/block bitmaps */
754 for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++)
755 if (fs->s_inode_bitmap[i])
756 ULCK_BUF(fs->s_inode_bitmap[i])
757
758 for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++)
759 if (fs->s_block_bitmap[i])
760 ULCK_BUF(fs->s_block_bitmap[i])
761
762 ump->um_devvp->v_specmountpoint = NULL;
763 error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE,
764 NOCRED, p);
765 vrele(ump->um_devvp);
766 bsd_free(fs->s_es, M_UFSMNT);
767 bsd_free(fs, M_UFSMNT);
768 bsd_free(ump, M_UFSMNT);
769 mp->mnt_data = (qaddr_t)0;
770 mp->mnt_flag &= ~MNT_LOCAL;
771 return (error);
772}
773
774/*
775 * Flush out all the files in a filesystem.
776 */
777static int
778ext2_flushfiles(mp, flags, p)
779 register struct mount *mp;
780 int flags;
781 struct proc *p;
782{
783 register struct ufsmount *ump;
784 int error;
785#if QUOTA
786 int i;
787#endif
788
789 ump = VFSTOUFS(mp);
790#if QUOTA
791 if (mp->mnt_flag & MNT_QUOTA) {
792 if ((error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) != 0)
793 return (error);
794 for (i = 0; i < MAXQUOTAS; i++) {
795 if (ump->um_quotas[i] == NULLVP)
796 continue;
797 quotaoff(p, mp, i);
798 }
799 /*
800 * Here we fall through to vflush again to ensure
801 * that we have gotten rid of all the system vnodes.
802 */
803 }
804#endif
805 error = vflush(mp, NULLVP, flags);
806 return (error);
807}
808
809/*
810 * Get file system statistics.
811 * taken from ext2/super.c ext2_statfs
812 */
813static int
814ext2_statfs(mp, sbp, p)
815 struct mount *mp;
816 register struct statfs *sbp;
817 struct proc *p;
818{
819 unsigned long overhead;
820 unsigned long overhead_per_group;
821
822 register struct ufsmount *ump;
823 register struct ext2_sb_info *fs;
824 register struct ext2_super_block *es;
825
826 ump = VFSTOUFS(mp);
827 fs = ump->um_e2fs;
828 es = fs->s_es;
829
830 if (es->s_magic != EXT2_SUPER_MAGIC)
831 panic("ext2_statfs - magic number spoiled");
832
833 /*
834 * Compute the overhead (FS structures)
835 */
836 overhead_per_group = 1 /* super block */ +
837 fs->s_db_per_group +
838 1 /* block bitmap */ +
839 1 /* inode bitmap */ +
840 fs->s_itb_per_group;
841 overhead = es->s_first_data_block +
842 fs->s_groups_count * overhead_per_group;
843
844 sbp->f_bsize = EXT2_FRAG_SIZE(fs);
845 sbp->f_iosize = EXT2_BLOCK_SIZE(fs);
846 sbp->f_blocks = es->s_blocks_count - overhead;
847 sbp->f_bfree = es->s_free_blocks_count;
848 sbp->f_bavail = sbp->f_bfree - es->s_r_blocks_count;
849 sbp->f_files = es->s_inodes_count;
850 sbp->f_ffree = es->s_free_inodes_count;
851 if (sbp != &mp->mnt_stat) {
852 sbp->f_type = mp->mnt_vfc->vfc_typenum;
853 bcopy((caddr_t)mp->mnt_stat.f_mntonname,
854 (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
855 bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
856 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
857 }
858 return (0);
859}
860
861/*
862 * Go through the disk queues to initiate sandbagged IO;
863 * go through the inodes to write those that have been modified;
864 * initiate the writing of the super block if it has been modified.
865 *
866 * Note: we are always called with the filesystem marked `MPBUSY'.
867 */
868static int
869ext2_sync(mp, waitfor, cred, p)
870 struct mount *mp;
871 int waitfor;
872 struct ucred *cred;
873 struct proc *p;
874{
875 struct vnode *nvp, *vp;
876 struct inode *ip;
877 struct ufsmount *ump = VFSTOUFS(mp);
878 struct ext2_sb_info *fs;
879 int error, allerror = 0;
880
881 fs = ump->um_e2fs;
882 if (fs->s_dirt != 0 && fs->s_rd_only != 0) { /* XXX */
883 printf("fs = %s\n", fs->fs_fsmnt);
884 panic("ext2_sync: rofs mod");
885 }
886 /*
887 * Write back each (modified) inode.
888 */
889 simple_lock(&mntvnode_slock);
890loop:
891 for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
892 /*
893 * If the vnode that we are about to sync is no longer
894 * associated with this mount point, start over.
895 */
896 if (vp->v_mount != mp)
897 goto loop;
898 simple_lock(&vp->v_interlock);
899 nvp = vp->v_mntvnodes.le_next;
900 ip = VTOI(vp);
901 if (vp->v_type == VNON ||
902 ((ip->i_flag &
903 (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
904 (TAILQ_EMPTY(&vp->v_dirtyblkhd) || waitfor == MNT_LAZY))) {
905 simple_unlock(&vp->v_interlock);
906 continue;
907 }
908 simple_unlock(&mntvnode_slock);
909 error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p);
910 if (error) {
911 simple_lock(&mntvnode_slock);
912 if (error == ENOENT)
913 goto loop;
914 continue;
915 }
916 if ((error = VOP_FSYNC(vp, cred, waitfor, p)) != 0)
917 allerror = error;
918 VOP_UNLOCK(vp, 0, p);
919 vrele(vp);
920 simple_lock(&mntvnode_slock);
921 }
922 simple_unlock(&mntvnode_slock);
923 /*
924 * Force stale file system control information to be flushed.
925 */
926 if (waitfor != MNT_LAZY) {
927 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
928 if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0)
929 allerror = error;
930 VOP_UNLOCK(ump->um_devvp, 0, p);
931 }
932#if QUOTA
933 qsync(mp);
934#endif
935 /*
936 * Write back modified superblock.
937 */
938 if (fs->s_dirt != 0) {
939 fs->s_dirt = 0;
940 fs->s_es->s_wtime = time_second;
941 if ((error = ext2_sbupdate(ump, waitfor)) != 0)
942 allerror = error;
943 }
944 return (allerror);
945}
946
947/*
948 * Look up a EXT2FS dinode number to find its incore vnode, otherwise read it
949 * in from disk. If it is in core, wait for the lock bit to clear, then
950 * return the inode locked. Detection and handling of mount points must be
951 * done by the calling routine.
952 */
953static int
954ext2_vget(mp, ino, vpp)
955 struct mount *mp;
956 ino_t ino;
957 struct vnode **vpp;
958{
959 register struct ext2_sb_info *fs;
960 register struct inode *ip;
961 struct ufsmount *ump;
962 struct buf *bp;
963 struct vnode *vp;
964 dev_t dev;
965 int i, error;
966 int used_blocks;
967
968 ump = VFSTOUFS(mp);
969 dev = ump->um_dev;
970restart:
971 if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
972 return (0);
973
974 /*
975 * Lock out the creation of new entries in the FFS hash table in
976 * case getnewvnode() or MALLOC() blocks, otherwise a duplicate
977 * may occur!
978 */
979 if (ext2fs_inode_hash_lock) {
980 while (ext2fs_inode_hash_lock) {
981 ext2fs_inode_hash_lock = -1;
982 tsleep(&ext2fs_inode_hash_lock, PVM, "e2vget", 0);
983 }
984 goto restart;
985 }
986 ext2fs_inode_hash_lock = 1;
987
988 /*
989 * If this MALLOC() is performed after the getnewvnode()
990 * it might block, leaving a vnode with a NULL v_data to be
991 * found by ext2_sync() if a sync happens to fire right then,
992 * which will cause a panic because ext2_sync() blindly
993 * dereferences vp->v_data (as well it should).
994 */
995 MALLOC(ip, struct inode *, sizeof(struct inode), M_EXT2NODE, M_WAITOK);
996
997 /* Allocate a new vnode/inode. */
998 if ((error = getnewvnode(VT_UFS, mp, ext2_vnodeop_p, &vp)) != 0) {
999 if (ext2fs_inode_hash_lock < 0)
1000 wakeup(&ext2fs_inode_hash_lock);
1001 ext2fs_inode_hash_lock = 0;
1002 *vpp = NULL;
1003 FREE(ip, M_EXT2NODE);
1004 return (error);
1005 }
1006 bzero((caddr_t)ip, sizeof(struct inode));
1007 lockinit(&ip->i_lock, PINOD, "ext2in", 0, 0);
1008 vp->v_data = ip;
1009 ip->i_vnode = vp;
1010 ip->i_e2fs = fs = ump->um_e2fs;
1011 ip->i_dev = dev;
1012 ip->i_number = ino;
1013#if QUOTA
1014 for (i = 0; i < MAXQUOTAS; i++)
1015 ip->i_dquot[i] = NODQUOT;
1016#endif
1017 /*
1018 * Put it onto its hash chain and lock it so that other requests for
1019 * this inode will block if they arrive while we are sleeping waiting
1020 * for old data structures to be purged or for the contents of the
1021 * disk portion of this inode to be read.
1022 */
1023 ufs_ihashins(ip);
1024
1025 if (ext2fs_inode_hash_lock < 0)
1026 wakeup(&ext2fs_inode_hash_lock);
1027 ext2fs_inode_hash_lock = 0;
1028
1029 /* Read in the disk contents for the inode, copy into the inode. */
1030#if 0
1031printf("ext2_vget(%d) dbn= %d ", ino, fsbtodb(fs, ino_to_fsba(fs, ino)));
1032#endif
1033 if ((error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
1034 (int)fs->s_blocksize, NOCRED, &bp)) != 0) {
1035 /*
1036 * The inode does not contain anything useful, so it would
1037 * be misleading to leave it on its hash chain. With mode
1038 * still zero, it will be unlinked and returned to the free
1039 * list by vput().
1040 */
1041 vput(vp);
1042 brelse(bp);
1043 *vpp = NULL;
1044 return (error);
1045 }
1046 /* convert ext2 inode to dinode */
1047 ext2_ei2di((struct ext2_inode *) ((char *)bp->b_data + EXT2_INODE_SIZE *
1048 ino_to_fsbo(fs, ino)), &ip->i_din);
1049 ip->i_block_group = ino_to_cg(fs, ino);
1050 ip->i_next_alloc_block = 0;
1051 ip->i_next_alloc_goal = 0;
1052 ip->i_prealloc_count = 0;
1053 ip->i_prealloc_block = 0;
1054 /* now we want to make sure that block pointers for unused
1055 blocks are zeroed out - ext2_balloc depends on this
1056 although for regular files and directories only
1057 */
1058 if(S_ISDIR(ip->i_mode) || S_ISREG(ip->i_mode)) {
1059 used_blocks = (ip->i_size+fs->s_blocksize-1) / fs->s_blocksize;
1060 for(i = used_blocks; i < EXT2_NDIR_BLOCKS; i++)
1061 ip->i_db[i] = 0;
1062 }
1063/*
1064 ext2_print_inode(ip);
1065*/
1066 brelse(bp);
1067
1068 /*
1069 * Initialize the vnode from the inode, check for aliases.
1070 * Note that the underlying vnode may have changed.
1071 */
1072 if ((error = ufs_vinit(mp, ext2_specop_p, ext2_fifoop_p, &vp)) != 0) {
1073 vput(vp);
1074 *vpp = NULL;
1075 return (error);
1076 }
1077 /*
1078 * Finish inode initialization now that aliasing has been resolved.
1079 */
1080 ip->i_devvp = ump->um_devvp;
1081 VREF(ip->i_devvp);
1082 /*
1083 * Set up a generation number for this inode if it does not
1084 * already have one. This should only happen on old filesystems.
1085 */
1086 if (ip->i_gen == 0) {
1087 ip->i_gen = random() / 2 + 1;
1088 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
1089 ip->i_flag |= IN_MODIFIED;
1090 }
1091 *vpp = vp;
1092 return (0);
1093}
1094
1095/*
1096 * File handle to vnode
1097 *
1098 * Have to be really careful about stale file handles:
1099 * - check that the inode number is valid
1100 * - call ext2_vget() to get the locked inode
1101 * - check for an unallocated inode (i_mode == 0)
1102 * - check that the given client host has export rights and return
1103 * those rights via. exflagsp and credanonp
1104 */
1105static int
1106ext2_fhtovp(mp, fhp, vpp)
1107 register struct mount *mp;
1108 struct fid *fhp;
1109 struct vnode **vpp;
1110{
1111 register struct ufid *ufhp;
1112 struct ext2_sb_info *fs;
1113
1114 ufhp = (struct ufid *)fhp;
1115 fs = VFSTOUFS(mp)->um_e2fs;
1116 if (ufhp->ufid_ino < ROOTINO ||
1117 ufhp->ufid_ino >= fs->s_groups_count * fs->s_es->s_inodes_per_group)
1118 return (ESTALE);
1119 return (ufs_fhtovp(mp, ufhp, vpp));
1120}
1121
1122/*
1123 * Vnode pointer to File handle
1124 */
1125/* ARGSUSED */
1126static int
1127ext2_vptofh(vp, fhp)
1128 struct vnode *vp;
1129 struct fid *fhp;
1130{
1131 register struct inode *ip;
1132 register struct ufid *ufhp;
1133
1134 ip = VTOI(vp);
1135 ufhp = (struct ufid *)fhp;
1136 ufhp->ufid_len = sizeof(struct ufid);
1137 ufhp->ufid_ino = ip->i_number;
1138 ufhp->ufid_gen = ip->i_gen;
1139 return (0);
1140}
1141
1142/*
1143 * Write a superblock and associated information back to disk.
1144 */
1145static int
1146ext2_sbupdate(mp, waitfor)
1147 struct ufsmount *mp;
1148 int waitfor;
1149{
1150 register struct ext2_sb_info *fs = mp->um_e2fs;
1151 register struct ext2_super_block *es = fs->s_es;
1152 register struct buf *bp;
1153 int error = 0;
1154/*
1155printf("\nupdating superblock, waitfor=%s\n", waitfor == MNT_WAIT ? "yes":"no");
1156*/
1157 bp = getblk(mp->um_devvp, SBLOCK, SBSIZE, 0, 0);
1158 bcopy((caddr_t)es, bp->b_data, (u_int)sizeof(struct ext2_super_block));
1159 if (waitfor == MNT_WAIT)
1160 error = bwrite(bp);
1161 else
1162 bawrite(bp);
1163
1164 /*
1165 * The buffers for group descriptors, inode bitmaps and block bitmaps
1166 * are not busy at this point and are (hopefully) written by the
1167 * usual sync mechanism. No need to write them here
1168 */
1169
1170 return (error);
1171}
148 mp->mnt_flag |= MNT_ROOTFS;
149 mp->mnt_vnodecovered = NULLVP;
150 ump = VFSTOUFS(mp);
151 fs = ump->um_e2fs;
152 bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt));
153 fs->fs_fsmnt[0] = '/';
154 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
155 MNAMELEN);
156 (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
157 &size);
158 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
159 (void)ext2_statfs(mp, &mp->mnt_stat, p);
160 vfs_unlock(mp);
161 inittodr(fs->s_es->s_wtime); /* this helps to set the time */
162 return (0);
163}
164#endif
165
166/*
167 * VFS Operations.
168 *
169 * mount system call
170 */
171static int
172ext2_mount(mp, path, data, ndp, p)
173 register struct mount *mp;
174 char *path;
175 caddr_t data; /* this is actually a (struct ufs_args *) */
176 struct nameidata *ndp;
177 struct proc *p;
178{
179 struct vnode *devvp;
180 struct ufs_args args;
181 struct ufsmount *ump = 0;
182 register struct ext2_sb_info *fs;
183 u_int size;
184 int error, flags;
185 mode_t accessmode;
186
187 if ((error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) != 0)
188 return (error);
189 /*
190 * If updating, check whether changing from read-only to
191 * read/write; if there is no device name, that's all we do.
192 */
193 if (mp->mnt_flag & MNT_UPDATE) {
194 ump = VFSTOUFS(mp);
195 fs = ump->um_e2fs;
196 error = 0;
197 if (fs->s_rd_only == 0 && (mp->mnt_flag & MNT_RDONLY)) {
198 flags = WRITECLOSE;
199 if (mp->mnt_flag & MNT_FORCE)
200 flags |= FORCECLOSE;
201 if (vfs_busy(mp, LK_NOWAIT, 0, p))
202 return (EBUSY);
203 error = ext2_flushfiles(mp, flags, p);
204 vfs_unbusy(mp, p);
205 if (!error && fs->s_wasvalid) {
206 fs->s_es->s_state |= EXT2_VALID_FS;
207 ext2_sbupdate(ump, MNT_WAIT);
208 }
209 fs->s_rd_only = 1;
210 }
211 if (!error && (mp->mnt_flag & MNT_RELOAD))
212 error = ext2_reload(mp, ndp->ni_cnd.cn_cred, p);
213 if (error)
214 return (error);
215 if (fs->s_rd_only && (mp->mnt_kern_flag & MNTK_WANTRDWR)) {
216 /*
217 * If upgrade to read-write by non-root, then verify
218 * that user has necessary permissions on the device.
219 */
220 if (p->p_ucred->cr_uid != 0) {
221 devvp = ump->um_devvp;
222 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
223 if ((error = VOP_ACCESS(devvp, VREAD | VWRITE,
224 p->p_ucred, p)) != 0) {
225 VOP_UNLOCK(devvp, 0, p);
226 return (error);
227 }
228 VOP_UNLOCK(devvp, 0, p);
229 }
230
231 if ((fs->s_es->s_state & EXT2_VALID_FS) == 0 ||
232 (fs->s_es->s_state & EXT2_ERROR_FS)) {
233 if (mp->mnt_flag & MNT_FORCE) {
234 printf(
235"WARNING: %s was not properly dismounted\n",
236 fs->fs_fsmnt);
237 } else {
238 printf(
239"WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n",
240 fs->fs_fsmnt);
241 return (EPERM);
242 }
243 }
244 fs->s_es->s_state &= ~EXT2_VALID_FS;
245 ext2_sbupdate(ump, MNT_WAIT);
246 fs->s_rd_only = 0;
247 }
248 if (args.fspec == 0) {
249 /*
250 * Process export requests.
251 */
252 return (vfs_export(mp, &ump->um_export, &args.export));
253 }
254 }
255 /*
256 * Not an update, or updating the name: look up the name
257 * and verify that it refers to a sensible block device.
258 */
259 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
260 if ((error = namei(ndp)) != 0)
261 return (error);
262 devvp = ndp->ni_vp;
263
264 if (!vn_isdisk(devvp)) {
265 vrele(devvp);
266 return (ENOTBLK);
267 }
268
269 /*
270 * If mount by non-root, then verify that user has necessary
271 * permissions on the device.
272 */
273 if (p->p_ucred->cr_uid != 0) {
274 accessmode = VREAD;
275 if ((mp->mnt_flag & MNT_RDONLY) == 0)
276 accessmode |= VWRITE;
277 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
278 if ((error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) != 0) {
279 vput(devvp);
280 return (error);
281 }
282 VOP_UNLOCK(devvp, 0, p);
283 }
284
285 if ((mp->mnt_flag & MNT_UPDATE) == 0) {
286 error = ext2_mountfs(devvp, mp, p);
287 } else {
288 if (devvp != ump->um_devvp)
289 error = EINVAL; /* needs translation */
290 else
291 vrele(devvp);
292 }
293 if (error) {
294 vrele(devvp);
295 return (error);
296 }
297 ump = VFSTOUFS(mp);
298 fs = ump->um_e2fs;
299 (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
300 bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
301 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
302 MNAMELEN);
303 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
304 &size);
305 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
306 (void)ext2_statfs(mp, &mp->mnt_stat, p);
307 return (0);
308}
309
310/*
311 * checks that the data in the descriptor blocks make sense
312 * this is taken from ext2/super.c
313 */
314static int ext2_check_descriptors (struct ext2_sb_info * sb)
315{
316 int i;
317 int desc_block = 0;
318 unsigned long block = sb->s_es->s_first_data_block;
319 struct ext2_group_desc * gdp = NULL;
320
321 /* ext2_debug ("Checking group descriptors"); */
322
323 for (i = 0; i < sb->s_groups_count; i++)
324 {
325 /* examine next descriptor block */
326 if ((i % EXT2_DESC_PER_BLOCK(sb)) == 0)
327 gdp = (struct ext2_group_desc *)
328 sb->s_group_desc[desc_block++]->b_data;
329 if (gdp->bg_block_bitmap < block ||
330 gdp->bg_block_bitmap >= block + EXT2_BLOCKS_PER_GROUP(sb))
331 {
332 printf ("ext2_check_descriptors: "
333 "Block bitmap for group %d"
334 " not in group (block %lu)!\n",
335 i, (unsigned long) gdp->bg_block_bitmap);
336 return 0;
337 }
338 if (gdp->bg_inode_bitmap < block ||
339 gdp->bg_inode_bitmap >= block + EXT2_BLOCKS_PER_GROUP(sb))
340 {
341 printf ("ext2_check_descriptors: "
342 "Inode bitmap for group %d"
343 " not in group (block %lu)!\n",
344 i, (unsigned long) gdp->bg_inode_bitmap);
345 return 0;
346 }
347 if (gdp->bg_inode_table < block ||
348 gdp->bg_inode_table + sb->s_itb_per_group >=
349 block + EXT2_BLOCKS_PER_GROUP(sb))
350 {
351 printf ("ext2_check_descriptors: "
352 "Inode table for group %d"
353 " not in group (block %lu)!\n",
354 i, (unsigned long) gdp->bg_inode_table);
355 return 0;
356 }
357 block += EXT2_BLOCKS_PER_GROUP(sb);
358 gdp++;
359 }
360 return 1;
361}
362
363/*
364 * this computes the fields of the ext2_sb_info structure from the
365 * data in the ext2_super_block structure read in
366 */
367static int compute_sb_data(devvp, es, fs)
368 struct vnode * devvp;
369 struct ext2_super_block * es;
370 struct ext2_sb_info * fs;
371{
372 int db_count, error;
373 int i, j;
374 int logic_sb_block = 1; /* XXX for now */
375
376#if 1
377#define V(v)
378#else
379#define V(v) printf(#v"= %d\n", fs->v);
380#endif
381
382 fs->s_blocksize = EXT2_MIN_BLOCK_SIZE << es->s_log_block_size;
383 V(s_blocksize)
384 fs->s_bshift = EXT2_MIN_BLOCK_LOG_SIZE + es->s_log_block_size;
385 V(s_bshift)
386 fs->s_fsbtodb = es->s_log_block_size + 1;
387 V(s_fsbtodb)
388 fs->s_qbmask = fs->s_blocksize - 1;
389 V(s_bmask)
390 fs->s_blocksize_bits = EXT2_BLOCK_SIZE_BITS(es);
391 V(s_blocksize_bits)
392 fs->s_frag_size = EXT2_MIN_FRAG_SIZE << es->s_log_frag_size;
393 V(s_frag_size)
394 if (fs->s_frag_size)
395 fs->s_frags_per_block = fs->s_blocksize / fs->s_frag_size;
396 V(s_frags_per_block)
397 fs->s_blocks_per_group = es->s_blocks_per_group;
398 V(s_blocks_per_group)
399 fs->s_frags_per_group = es->s_frags_per_group;
400 V(s_frags_per_group)
401 fs->s_inodes_per_group = es->s_inodes_per_group;
402 V(s_inodes_per_group)
403 fs->s_inodes_per_block = fs->s_blocksize / EXT2_INODE_SIZE;
404 V(s_inodes_per_block)
405 fs->s_itb_per_group = fs->s_inodes_per_group /fs->s_inodes_per_block;
406 V(s_itb_per_group)
407 fs->s_desc_per_block = fs->s_blocksize / sizeof (struct ext2_group_desc);
408 V(s_desc_per_block)
409 /* s_resuid / s_resgid ? */
410 fs->s_groups_count = (es->s_blocks_count -
411 es->s_first_data_block +
412 EXT2_BLOCKS_PER_GROUP(fs) - 1) /
413 EXT2_BLOCKS_PER_GROUP(fs);
414 V(s_groups_count)
415 db_count = (fs->s_groups_count + EXT2_DESC_PER_BLOCK(fs) - 1) /
416 EXT2_DESC_PER_BLOCK(fs);
417 fs->s_db_per_group = db_count;
418 V(s_db_per_group)
419
420 fs->s_group_desc = bsd_malloc(db_count * sizeof (struct buf *),
421 M_UFSMNT, M_WAITOK);
422
423 /* adjust logic_sb_block */
424 if(fs->s_blocksize > SBSIZE)
425 /* Godmar thinks: if the blocksize is greater than 1024, then
426 the superblock is logically part of block zero.
427 */
428 logic_sb_block = 0;
429
430 for (i = 0; i < db_count; i++) {
431 error = bread(devvp , fsbtodb(fs, logic_sb_block + i + 1),
432 fs->s_blocksize, NOCRED, &fs->s_group_desc[i]);
433 if(error) {
434 for (j = 0; j < i; j++)
435 brelse(fs->s_group_desc[j]);
436 bsd_free(fs->s_group_desc, M_UFSMNT);
437 printf("EXT2-fs: unable to read group descriptors (%d)\n", error);
438 return EIO;
439 }
440 /* Set the B_LOCKED flag on the buffer, then brelse() it */
441 LCK_BUF(fs->s_group_desc[i])
442 }
443 if(!ext2_check_descriptors(fs)) {
444 for (j = 0; j < db_count; j++)
445 ULCK_BUF(fs->s_group_desc[j])
446 bsd_free(fs->s_group_desc, M_UFSMNT);
447 printf("EXT2-fs: (ext2_check_descriptors failure) "
448 "unable to read group descriptors\n");
449 return EIO;
450 }
451
452 for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) {
453 fs->s_inode_bitmap_number[i] = 0;
454 fs->s_inode_bitmap[i] = NULL;
455 fs->s_block_bitmap_number[i] = 0;
456 fs->s_block_bitmap[i] = NULL;
457 }
458 fs->s_loaded_inode_bitmaps = 0;
459 fs->s_loaded_block_bitmaps = 0;
460 return 0;
461}
462
463/*
464 * Reload all incore data for a filesystem (used after running fsck on
465 * the root filesystem and finding things to fix). The filesystem must
466 * be mounted read-only.
467 *
468 * Things to do to update the mount:
469 * 1) invalidate all cached meta-data.
470 * 2) re-read superblock from disk.
471 * 3) re-read summary information from disk.
472 * 4) invalidate all inactive vnodes.
473 * 5) invalidate all cached file data.
474 * 6) re-read inode data for all active vnodes.
475 */
476static int
477ext2_reload(mountp, cred, p)
478 register struct mount *mountp;
479 struct ucred *cred;
480 struct proc *p;
481{
482 register struct vnode *vp, *nvp, *devvp;
483 struct inode *ip;
484 struct buf *bp;
485 struct ext2_super_block * es;
486 struct ext2_sb_info *fs;
487 int error;
488
489 if ((mountp->mnt_flag & MNT_RDONLY) == 0)
490 return (EINVAL);
491 /*
492 * Step 1: invalidate all cached meta-data.
493 */
494 devvp = VFSTOUFS(mountp)->um_devvp;
495 if (vinvalbuf(devvp, 0, cred, p, 0, 0))
496 panic("ext2_reload: dirty1");
497 /*
498 * Step 2: re-read superblock from disk.
499 * constants have been adjusted for ext2
500 */
501 if ((error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) != 0)
502 return (error);
503 es = (struct ext2_super_block *)bp->b_data;
504 if (es->s_magic != EXT2_SUPER_MAGIC) {
505 if(es->s_magic == EXT2_PRE_02B_MAGIC)
506 printf("This filesystem bears the magic number of a pre "
507 "0.2b version of ext2. This is not supported by "
508 "Lites.\n");
509 else
510 printf("Wrong magic number: %x (expected %x for ext2 fs\n",
511 es->s_magic, EXT2_SUPER_MAGIC);
512 brelse(bp);
513 return (EIO); /* XXX needs translation */
514 }
515 fs = VFSTOUFS(mountp)->um_e2fs;
516 bcopy(bp->b_data, fs->s_es, sizeof(struct ext2_super_block));
517
518 if((error = compute_sb_data(devvp, es, fs)) != 0) {
519 brelse(bp);
520 return error;
521 }
522#ifdef UNKLAR
523 if (fs->fs_sbsize < SBSIZE)
524 bp->b_flags |= B_INVAL;
525#endif
526 brelse(bp);
527
528loop:
529 simple_lock(&mntvnode_slock);
530 for (vp = mountp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
531 if (vp->v_mount != mountp) {
532 simple_unlock(&mntvnode_slock);
533 goto loop;
534 }
535 nvp = vp->v_mntvnodes.le_next;
536 /*
537 * Step 4: invalidate all inactive vnodes.
538 */
539 if (vrecycle(vp, &mntvnode_slock, p))
540 goto loop;
541 /*
542 * Step 5: invalidate all cached file data.
543 */
544 simple_lock(&vp->v_interlock);
545 simple_unlock(&mntvnode_slock);
546 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) {
547 goto loop;
548 }
549 if (vinvalbuf(vp, 0, cred, p, 0, 0))
550 panic("ext2_reload: dirty2");
551 /*
552 * Step 6: re-read inode data for all active vnodes.
553 */
554 ip = VTOI(vp);
555 error =
556 bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
557 (int)fs->s_blocksize, NOCRED, &bp);
558 if (error) {
559 vput(vp);
560 return (error);
561 }
562 ext2_ei2di((struct ext2_inode *) ((char *)bp->b_data +
563 EXT2_INODE_SIZE * ino_to_fsbo(fs, ip->i_number)),
564 &ip->i_din);
565 brelse(bp);
566 vput(vp);
567 simple_lock(&mntvnode_slock);
568 }
569 simple_unlock(&mntvnode_slock);
570 return (0);
571}
572
573/*
574 * Common code for mount and mountroot
575 */
576static int
577ext2_mountfs(devvp, mp, p)
578 register struct vnode *devvp;
579 struct mount *mp;
580 struct proc *p;
581{
582 register struct ufsmount *ump;
583 struct buf *bp;
584 register struct ext2_sb_info *fs;
585 struct ext2_super_block * es;
586 dev_t dev = devvp->v_rdev;
587 struct partinfo dpart;
588 int havepart = 0;
589 int error, i, size;
590 int ronly;
591
592 /*
593 * Disallow multiple mounts of the same device.
594 * Disallow mounting of a device that is currently in use
595 * (except for root, which might share swap device for miniroot).
596 * Flush out any old buffers remaining from a previous use.
597 */
598 if ((error = vfs_mountedon(devvp)) != 0)
599 return (error);
600 if (vcount(devvp) > 1 && devvp != rootvp)
601 return (EBUSY);
602 if ((error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0)) != 0)
603 return (error);
604#ifdef READONLY
605/* turn on this to force it to be read-only */
606 mp->mnt_flag |= MNT_RDONLY;
607#endif
608
609 ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
610 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
611 error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
612 VOP_UNLOCK(devvp, 0, p);
613 if (error)
614 return (error);
615 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
616 size = DEV_BSIZE;
617 else {
618 havepart = 1;
619 size = dpart.disklab->d_secsize;
620 }
621
622 bp = NULL;
623 ump = NULL;
624 if ((error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) != 0)
625 goto out;
626 es = (struct ext2_super_block *)bp->b_data;
627 if (es->s_magic != EXT2_SUPER_MAGIC) {
628 if(es->s_magic == EXT2_PRE_02B_MAGIC)
629 printf("This filesystem bears the magic number of a pre "
630 "0.2b version of ext2. This is not supported by "
631 "Lites.\n");
632 else
633 printf("Wrong magic number: %x (expected %x for EXT2FS)\n",
634 es->s_magic, EXT2_SUPER_MAGIC);
635 error = EINVAL; /* XXX needs translation */
636 goto out;
637 }
638 if ((es->s_state & EXT2_VALID_FS) == 0 ||
639 (es->s_state & EXT2_ERROR_FS)) {
640 if (ronly || (mp->mnt_flag & MNT_FORCE)) {
641 printf(
642"WARNING: Filesystem was not properly dismounted\n");
643 } else {
644 printf(
645"WARNING: R/W mount denied. Filesystem is not clean - run fsck\n");
646 error = EPERM;
647 goto out;
648 }
649 }
650 ump = bsd_malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
651 bzero((caddr_t)ump, sizeof *ump);
652 ump->um_malloctype = M_EXT2NODE;
653 ump->um_blkatoff = ext2_blkatoff;
654 ump->um_truncate = ext2_truncate;
655 ump->um_update = ext2_update;
656 ump->um_valloc = ext2_valloc;
657 ump->um_vfree = ext2_vfree;
658 /* I don't know whether this is the right strategy. Note that
659 we dynamically allocate both a ext2_sb_info and a ext2_super_block
660 while Linux keeps the super block in a locked buffer
661 */
662 ump->um_e2fs = bsd_malloc(sizeof(struct ext2_sb_info),
663 M_UFSMNT, M_WAITOK);
664 ump->um_e2fs->s_es = bsd_malloc(sizeof(struct ext2_super_block),
665 M_UFSMNT, M_WAITOK);
666 bcopy(es, ump->um_e2fs->s_es, (u_int)sizeof(struct ext2_super_block));
667 if ((error = compute_sb_data(devvp, ump->um_e2fs->s_es, ump->um_e2fs)))
668 goto out;
669 /*
670 * We don't free the group descriptors allocated by compute_sb_data()
671 * until ext2_unmount(). This is OK since the mount will succeed.
672 */
673 brelse(bp);
674 bp = NULL;
675 fs = ump->um_e2fs;
676 fs->s_rd_only = ronly; /* ronly is set according to mnt_flags */
677 /* if the fs is not mounted read-only, make sure the super block is
678 always written back on a sync()
679 */
680 fs->s_wasvalid = fs->s_es->s_state & EXT2_VALID_FS ? 1 : 0;
681 if (ronly == 0) {
682 fs->s_dirt = 1; /* mark it modified */
683 fs->s_es->s_state &= ~EXT2_VALID_FS; /* set fs invalid */
684 }
685 mp->mnt_data = (qaddr_t)ump;
686 mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
687 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
688 mp->mnt_maxsymlinklen = EXT2_MAXSYMLINKLEN;
689 mp->mnt_flag |= MNT_LOCAL;
690 ump->um_mountp = mp;
691 ump->um_dev = dev;
692 ump->um_devvp = devvp;
693 /* setting those two parameters allows us to use
694 ufs_bmap w/o changse !
695 */
696 ump->um_nindir = EXT2_ADDR_PER_BLOCK(fs);
697 ump->um_bptrtodb = fs->s_es->s_log_block_size + 1;
698 ump->um_seqinc = EXT2_FRAGS_PER_BLOCK(fs);
699 for (i = 0; i < MAXQUOTAS; i++)
700 ump->um_quotas[i] = NULLVP;
701 devvp->v_specmountpoint = mp;
702 if (ronly == 0)
703 ext2_sbupdate(ump, MNT_WAIT);
704 return (0);
705out:
706 if (bp)
707 brelse(bp);
708 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
709 if (ump) {
710 bsd_free(ump->um_e2fs->s_es, M_UFSMNT);
711 bsd_free(ump->um_e2fs, M_UFSMNT);
712 bsd_free(ump, M_UFSMNT);
713 mp->mnt_data = (qaddr_t)0;
714 }
715 return (error);
716}
717
718/*
719 * unmount system call
720 */
721static int
722ext2_unmount(mp, mntflags, p)
723 struct mount *mp;
724 int mntflags;
725 struct proc *p;
726{
727 register struct ufsmount *ump;
728 register struct ext2_sb_info *fs;
729 int error, flags, ronly, i;
730
731 flags = 0;
732 if (mntflags & MNT_FORCE) {
733 if (mp->mnt_flag & MNT_ROOTFS)
734 return (EINVAL);
735 flags |= FORCECLOSE;
736 }
737 if ((error = ext2_flushfiles(mp, flags, p)) != 0)
738 return (error);
739 ump = VFSTOUFS(mp);
740 fs = ump->um_e2fs;
741 ronly = fs->s_rd_only;
742 if (ronly == 0) {
743 if (fs->s_wasvalid)
744 fs->s_es->s_state |= EXT2_VALID_FS;
745 ext2_sbupdate(ump, MNT_WAIT);
746 }
747
748 /* release buffers containing group descriptors */
749 for(i = 0; i < fs->s_db_per_group; i++)
750 ULCK_BUF(fs->s_group_desc[i])
751 bsd_free(fs->s_group_desc, M_UFSMNT);
752
753 /* release cached inode/block bitmaps */
754 for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++)
755 if (fs->s_inode_bitmap[i])
756 ULCK_BUF(fs->s_inode_bitmap[i])
757
758 for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++)
759 if (fs->s_block_bitmap[i])
760 ULCK_BUF(fs->s_block_bitmap[i])
761
762 ump->um_devvp->v_specmountpoint = NULL;
763 error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE,
764 NOCRED, p);
765 vrele(ump->um_devvp);
766 bsd_free(fs->s_es, M_UFSMNT);
767 bsd_free(fs, M_UFSMNT);
768 bsd_free(ump, M_UFSMNT);
769 mp->mnt_data = (qaddr_t)0;
770 mp->mnt_flag &= ~MNT_LOCAL;
771 return (error);
772}
773
774/*
775 * Flush out all the files in a filesystem.
776 */
777static int
778ext2_flushfiles(mp, flags, p)
779 register struct mount *mp;
780 int flags;
781 struct proc *p;
782{
783 register struct ufsmount *ump;
784 int error;
785#if QUOTA
786 int i;
787#endif
788
789 ump = VFSTOUFS(mp);
790#if QUOTA
791 if (mp->mnt_flag & MNT_QUOTA) {
792 if ((error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) != 0)
793 return (error);
794 for (i = 0; i < MAXQUOTAS; i++) {
795 if (ump->um_quotas[i] == NULLVP)
796 continue;
797 quotaoff(p, mp, i);
798 }
799 /*
800 * Here we fall through to vflush again to ensure
801 * that we have gotten rid of all the system vnodes.
802 */
803 }
804#endif
805 error = vflush(mp, NULLVP, flags);
806 return (error);
807}
808
809/*
810 * Get file system statistics.
811 * taken from ext2/super.c ext2_statfs
812 */
813static int
814ext2_statfs(mp, sbp, p)
815 struct mount *mp;
816 register struct statfs *sbp;
817 struct proc *p;
818{
819 unsigned long overhead;
820 unsigned long overhead_per_group;
821
822 register struct ufsmount *ump;
823 register struct ext2_sb_info *fs;
824 register struct ext2_super_block *es;
825
826 ump = VFSTOUFS(mp);
827 fs = ump->um_e2fs;
828 es = fs->s_es;
829
830 if (es->s_magic != EXT2_SUPER_MAGIC)
831 panic("ext2_statfs - magic number spoiled");
832
833 /*
834 * Compute the overhead (FS structures)
835 */
836 overhead_per_group = 1 /* super block */ +
837 fs->s_db_per_group +
838 1 /* block bitmap */ +
839 1 /* inode bitmap */ +
840 fs->s_itb_per_group;
841 overhead = es->s_first_data_block +
842 fs->s_groups_count * overhead_per_group;
843
844 sbp->f_bsize = EXT2_FRAG_SIZE(fs);
845 sbp->f_iosize = EXT2_BLOCK_SIZE(fs);
846 sbp->f_blocks = es->s_blocks_count - overhead;
847 sbp->f_bfree = es->s_free_blocks_count;
848 sbp->f_bavail = sbp->f_bfree - es->s_r_blocks_count;
849 sbp->f_files = es->s_inodes_count;
850 sbp->f_ffree = es->s_free_inodes_count;
851 if (sbp != &mp->mnt_stat) {
852 sbp->f_type = mp->mnt_vfc->vfc_typenum;
853 bcopy((caddr_t)mp->mnt_stat.f_mntonname,
854 (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
855 bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
856 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
857 }
858 return (0);
859}
860
861/*
862 * Go through the disk queues to initiate sandbagged IO;
863 * go through the inodes to write those that have been modified;
864 * initiate the writing of the super block if it has been modified.
865 *
866 * Note: we are always called with the filesystem marked `MPBUSY'.
867 */
868static int
869ext2_sync(mp, waitfor, cred, p)
870 struct mount *mp;
871 int waitfor;
872 struct ucred *cred;
873 struct proc *p;
874{
875 struct vnode *nvp, *vp;
876 struct inode *ip;
877 struct ufsmount *ump = VFSTOUFS(mp);
878 struct ext2_sb_info *fs;
879 int error, allerror = 0;
880
881 fs = ump->um_e2fs;
882 if (fs->s_dirt != 0 && fs->s_rd_only != 0) { /* XXX */
883 printf("fs = %s\n", fs->fs_fsmnt);
884 panic("ext2_sync: rofs mod");
885 }
886 /*
887 * Write back each (modified) inode.
888 */
889 simple_lock(&mntvnode_slock);
890loop:
891 for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
892 /*
893 * If the vnode that we are about to sync is no longer
894 * associated with this mount point, start over.
895 */
896 if (vp->v_mount != mp)
897 goto loop;
898 simple_lock(&vp->v_interlock);
899 nvp = vp->v_mntvnodes.le_next;
900 ip = VTOI(vp);
901 if (vp->v_type == VNON ||
902 ((ip->i_flag &
903 (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
904 (TAILQ_EMPTY(&vp->v_dirtyblkhd) || waitfor == MNT_LAZY))) {
905 simple_unlock(&vp->v_interlock);
906 continue;
907 }
908 simple_unlock(&mntvnode_slock);
909 error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p);
910 if (error) {
911 simple_lock(&mntvnode_slock);
912 if (error == ENOENT)
913 goto loop;
914 continue;
915 }
916 if ((error = VOP_FSYNC(vp, cred, waitfor, p)) != 0)
917 allerror = error;
918 VOP_UNLOCK(vp, 0, p);
919 vrele(vp);
920 simple_lock(&mntvnode_slock);
921 }
922 simple_unlock(&mntvnode_slock);
923 /*
924 * Force stale file system control information to be flushed.
925 */
926 if (waitfor != MNT_LAZY) {
927 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
928 if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0)
929 allerror = error;
930 VOP_UNLOCK(ump->um_devvp, 0, p);
931 }
932#if QUOTA
933 qsync(mp);
934#endif
935 /*
936 * Write back modified superblock.
937 */
938 if (fs->s_dirt != 0) {
939 fs->s_dirt = 0;
940 fs->s_es->s_wtime = time_second;
941 if ((error = ext2_sbupdate(ump, waitfor)) != 0)
942 allerror = error;
943 }
944 return (allerror);
945}
946
947/*
948 * Look up a EXT2FS dinode number to find its incore vnode, otherwise read it
949 * in from disk. If it is in core, wait for the lock bit to clear, then
950 * return the inode locked. Detection and handling of mount points must be
951 * done by the calling routine.
952 */
953static int
954ext2_vget(mp, ino, vpp)
955 struct mount *mp;
956 ino_t ino;
957 struct vnode **vpp;
958{
959 register struct ext2_sb_info *fs;
960 register struct inode *ip;
961 struct ufsmount *ump;
962 struct buf *bp;
963 struct vnode *vp;
964 dev_t dev;
965 int i, error;
966 int used_blocks;
967
968 ump = VFSTOUFS(mp);
969 dev = ump->um_dev;
970restart:
971 if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
972 return (0);
973
974 /*
975 * Lock out the creation of new entries in the FFS hash table in
976 * case getnewvnode() or MALLOC() blocks, otherwise a duplicate
977 * may occur!
978 */
979 if (ext2fs_inode_hash_lock) {
980 while (ext2fs_inode_hash_lock) {
981 ext2fs_inode_hash_lock = -1;
982 tsleep(&ext2fs_inode_hash_lock, PVM, "e2vget", 0);
983 }
984 goto restart;
985 }
986 ext2fs_inode_hash_lock = 1;
987
988 /*
989 * If this MALLOC() is performed after the getnewvnode()
990 * it might block, leaving a vnode with a NULL v_data to be
991 * found by ext2_sync() if a sync happens to fire right then,
992 * which will cause a panic because ext2_sync() blindly
993 * dereferences vp->v_data (as well it should).
994 */
995 MALLOC(ip, struct inode *, sizeof(struct inode), M_EXT2NODE, M_WAITOK);
996
997 /* Allocate a new vnode/inode. */
998 if ((error = getnewvnode(VT_UFS, mp, ext2_vnodeop_p, &vp)) != 0) {
999 if (ext2fs_inode_hash_lock < 0)
1000 wakeup(&ext2fs_inode_hash_lock);
1001 ext2fs_inode_hash_lock = 0;
1002 *vpp = NULL;
1003 FREE(ip, M_EXT2NODE);
1004 return (error);
1005 }
1006 bzero((caddr_t)ip, sizeof(struct inode));
1007 lockinit(&ip->i_lock, PINOD, "ext2in", 0, 0);
1008 vp->v_data = ip;
1009 ip->i_vnode = vp;
1010 ip->i_e2fs = fs = ump->um_e2fs;
1011 ip->i_dev = dev;
1012 ip->i_number = ino;
1013#if QUOTA
1014 for (i = 0; i < MAXQUOTAS; i++)
1015 ip->i_dquot[i] = NODQUOT;
1016#endif
1017 /*
1018 * Put it onto its hash chain and lock it so that other requests for
1019 * this inode will block if they arrive while we are sleeping waiting
1020 * for old data structures to be purged or for the contents of the
1021 * disk portion of this inode to be read.
1022 */
1023 ufs_ihashins(ip);
1024
1025 if (ext2fs_inode_hash_lock < 0)
1026 wakeup(&ext2fs_inode_hash_lock);
1027 ext2fs_inode_hash_lock = 0;
1028
1029 /* Read in the disk contents for the inode, copy into the inode. */
1030#if 0
1031printf("ext2_vget(%d) dbn= %d ", ino, fsbtodb(fs, ino_to_fsba(fs, ino)));
1032#endif
1033 if ((error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
1034 (int)fs->s_blocksize, NOCRED, &bp)) != 0) {
1035 /*
1036 * The inode does not contain anything useful, so it would
1037 * be misleading to leave it on its hash chain. With mode
1038 * still zero, it will be unlinked and returned to the free
1039 * list by vput().
1040 */
1041 vput(vp);
1042 brelse(bp);
1043 *vpp = NULL;
1044 return (error);
1045 }
1046 /* convert ext2 inode to dinode */
1047 ext2_ei2di((struct ext2_inode *) ((char *)bp->b_data + EXT2_INODE_SIZE *
1048 ino_to_fsbo(fs, ino)), &ip->i_din);
1049 ip->i_block_group = ino_to_cg(fs, ino);
1050 ip->i_next_alloc_block = 0;
1051 ip->i_next_alloc_goal = 0;
1052 ip->i_prealloc_count = 0;
1053 ip->i_prealloc_block = 0;
1054 /* now we want to make sure that block pointers for unused
1055 blocks are zeroed out - ext2_balloc depends on this
1056 although for regular files and directories only
1057 */
1058 if(S_ISDIR(ip->i_mode) || S_ISREG(ip->i_mode)) {
1059 used_blocks = (ip->i_size+fs->s_blocksize-1) / fs->s_blocksize;
1060 for(i = used_blocks; i < EXT2_NDIR_BLOCKS; i++)
1061 ip->i_db[i] = 0;
1062 }
1063/*
1064 ext2_print_inode(ip);
1065*/
1066 brelse(bp);
1067
1068 /*
1069 * Initialize the vnode from the inode, check for aliases.
1070 * Note that the underlying vnode may have changed.
1071 */
1072 if ((error = ufs_vinit(mp, ext2_specop_p, ext2_fifoop_p, &vp)) != 0) {
1073 vput(vp);
1074 *vpp = NULL;
1075 return (error);
1076 }
1077 /*
1078 * Finish inode initialization now that aliasing has been resolved.
1079 */
1080 ip->i_devvp = ump->um_devvp;
1081 VREF(ip->i_devvp);
1082 /*
1083 * Set up a generation number for this inode if it does not
1084 * already have one. This should only happen on old filesystems.
1085 */
1086 if (ip->i_gen == 0) {
1087 ip->i_gen = random() / 2 + 1;
1088 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
1089 ip->i_flag |= IN_MODIFIED;
1090 }
1091 *vpp = vp;
1092 return (0);
1093}
1094
1095/*
1096 * File handle to vnode
1097 *
1098 * Have to be really careful about stale file handles:
1099 * - check that the inode number is valid
1100 * - call ext2_vget() to get the locked inode
1101 * - check for an unallocated inode (i_mode == 0)
1102 * - check that the given client host has export rights and return
1103 * those rights via. exflagsp and credanonp
1104 */
1105static int
1106ext2_fhtovp(mp, fhp, vpp)
1107 register struct mount *mp;
1108 struct fid *fhp;
1109 struct vnode **vpp;
1110{
1111 register struct ufid *ufhp;
1112 struct ext2_sb_info *fs;
1113
1114 ufhp = (struct ufid *)fhp;
1115 fs = VFSTOUFS(mp)->um_e2fs;
1116 if (ufhp->ufid_ino < ROOTINO ||
1117 ufhp->ufid_ino >= fs->s_groups_count * fs->s_es->s_inodes_per_group)
1118 return (ESTALE);
1119 return (ufs_fhtovp(mp, ufhp, vpp));
1120}
1121
1122/*
1123 * Vnode pointer to File handle
1124 */
1125/* ARGSUSED */
1126static int
1127ext2_vptofh(vp, fhp)
1128 struct vnode *vp;
1129 struct fid *fhp;
1130{
1131 register struct inode *ip;
1132 register struct ufid *ufhp;
1133
1134 ip = VTOI(vp);
1135 ufhp = (struct ufid *)fhp;
1136 ufhp->ufid_len = sizeof(struct ufid);
1137 ufhp->ufid_ino = ip->i_number;
1138 ufhp->ufid_gen = ip->i_gen;
1139 return (0);
1140}
1141
1142/*
1143 * Write a superblock and associated information back to disk.
1144 */
1145static int
1146ext2_sbupdate(mp, waitfor)
1147 struct ufsmount *mp;
1148 int waitfor;
1149{
1150 register struct ext2_sb_info *fs = mp->um_e2fs;
1151 register struct ext2_super_block *es = fs->s_es;
1152 register struct buf *bp;
1153 int error = 0;
1154/*
1155printf("\nupdating superblock, waitfor=%s\n", waitfor == MNT_WAIT ? "yes":"no");
1156*/
1157 bp = getblk(mp->um_devvp, SBLOCK, SBSIZE, 0, 0);
1158 bcopy((caddr_t)es, bp->b_data, (u_int)sizeof(struct ext2_super_block));
1159 if (waitfor == MNT_WAIT)
1160 error = bwrite(bp);
1161 else
1162 bawrite(bp);
1163
1164 /*
1165 * The buffers for group descriptors, inode bitmaps and block bitmaps
1166 * are not busy at this point and are (hopefully) written by the
1167 * usual sync mechanism. No need to write them here
1168 */
1169
1170 return (error);
1171}