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