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