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