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