]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/fs/ext2fs/ext2_vfsops.c
Upgrade Unbound to 1.6.1. More to follow.
[FreeBSD/FreeBSD.git] / sys / 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  * SPDX-License-Identifier: BSD-3-Clause
9  *
10  * Copyright (c) 1989, 1991, 1993, 1994
11  *      The Regents of the University of California.  All rights reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  *      @(#)ffs_vfsops.c        8.8 (Berkeley) 4/18/94
38  * $FreeBSD$
39  */
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/namei.h>
44 #include <sys/priv.h>
45 #include <sys/proc.h>
46 #include <sys/kernel.h>
47 #include <sys/vnode.h>
48 #include <sys/mount.h>
49 #include <sys/bio.h>
50 #include <sys/buf.h>
51 #include <sys/conf.h>
52 #include <sys/endian.h>
53 #include <sys/fcntl.h>
54 #include <sys/malloc.h>
55 #include <sys/stat.h>
56 #include <sys/mutex.h>
57
58 #include <geom/geom.h>
59 #include <geom/geom_vfs.h>
60
61 #include <fs/ext2fs/ext2_mount.h>
62 #include <fs/ext2fs/inode.h>
63
64 #include <fs/ext2fs/fs.h>
65 #include <fs/ext2fs/ext2fs.h>
66 #include <fs/ext2fs/ext2_dinode.h>
67 #include <fs/ext2fs/ext2_extern.h>
68
69 static int      ext2_flushfiles(struct mount *mp, int flags, struct thread *td);
70 static int      ext2_mountfs(struct vnode *, struct mount *);
71 static int      ext2_reload(struct mount *mp, struct thread *td);
72 static int      ext2_sbupdate(struct ext2mount *, int);
73 static int      ext2_cgupdate(struct ext2mount *, int);
74 static vfs_unmount_t            ext2_unmount;
75 static vfs_root_t               ext2_root;
76 static vfs_statfs_t             ext2_statfs;
77 static vfs_sync_t               ext2_sync;
78 static vfs_vget_t               ext2_vget;
79 static vfs_fhtovp_t             ext2_fhtovp;
80 static vfs_mount_t              ext2_mount;
81
82 MALLOC_DEFINE(M_EXT2NODE, "ext2_node", "EXT2 vnode private part");
83 static MALLOC_DEFINE(M_EXT2MNT, "ext2_mount", "EXT2 mount structure");
84
85 static struct vfsops ext2fs_vfsops = {
86         .vfs_fhtovp =           ext2_fhtovp,
87         .vfs_mount =            ext2_mount,
88         .vfs_root =             ext2_root,      /* root inode via vget */
89         .vfs_statfs =           ext2_statfs,
90         .vfs_sync =             ext2_sync,
91         .vfs_unmount =          ext2_unmount,
92         .vfs_vget =             ext2_vget,
93 };
94
95 VFS_SET(ext2fs_vfsops, ext2fs, 0);
96
97 static int      ext2_check_sb_compat(struct ext2fs *es, struct cdev *dev,
98                     int ronly);
99 static int      compute_sb_data(struct vnode * devvp,
100                     struct ext2fs * es, struct m_ext2fs * fs);
101
102 static const char *ext2_opts[] = { "acls", "async", "noatime", "noclusterr", 
103     "noclusterw", "noexec", "export", "force", "from", "multilabel",
104     "suiddir", "nosymfollow", "sync", "union", NULL };
105
106 /*
107  * VFS Operations.
108  *
109  * mount system call
110  */
111 static int
112 ext2_mount(struct mount *mp)
113 {
114         struct vfsoptlist *opts;
115         struct vnode *devvp;
116         struct thread *td;
117         struct ext2mount *ump = NULL;
118         struct m_ext2fs *fs;
119         struct nameidata nd, *ndp = &nd;
120         accmode_t accmode;
121         char *path, *fspec;
122         int error, flags, len;
123
124         td = curthread;
125         opts = mp->mnt_optnew;
126
127         if (vfs_filteropt(opts, ext2_opts))
128                 return (EINVAL);
129
130         vfs_getopt(opts, "fspath", (void **)&path, NULL);
131         /* Double-check the length of path.. */
132         if (strlen(path) >= MAXMNTLEN)
133                 return (ENAMETOOLONG);
134
135         fspec = NULL;
136         error = vfs_getopt(opts, "from", (void **)&fspec, &len);
137         if (!error && fspec[len - 1] != '\0')
138                 return (EINVAL);
139
140         /*
141          * If updating, check whether changing from read-only to
142          * read/write; if there is no device name, that's all we do.
143          */
144         if (mp->mnt_flag & MNT_UPDATE) {
145                 ump = VFSTOEXT2(mp);
146                 fs = ump->um_e2fs;
147                 error = 0;
148                 if (fs->e2fs_ronly == 0 &&
149                     vfs_flagopt(opts, "ro", NULL, 0)) {
150                         error = VFS_SYNC(mp, MNT_WAIT);
151                         if (error)
152                                 return (error);
153                         flags = WRITECLOSE;
154                         if (mp->mnt_flag & MNT_FORCE)
155                                 flags |= FORCECLOSE;
156                         error = ext2_flushfiles(mp, flags, td);
157                         if (error == 0 && fs->e2fs_wasvalid &&
158                             ext2_cgupdate(ump, MNT_WAIT) == 0) {
159                                 fs->e2fs->e2fs_state |= E2FS_ISCLEAN;
160                                 ext2_sbupdate(ump, MNT_WAIT);
161                         }
162                         fs->e2fs_ronly = 1;
163                         vfs_flagopt(opts, "ro", &mp->mnt_flag, MNT_RDONLY);
164                         g_topology_lock();
165                         g_access(ump->um_cp, 0, -1, 0);
166                         g_topology_unlock();
167                 }
168                 if (!error && (mp->mnt_flag & MNT_RELOAD))
169                         error = ext2_reload(mp, td);
170                 if (error)
171                         return (error);
172                 devvp = ump->um_devvp;
173                 if (fs->e2fs_ronly && !vfs_flagopt(opts, "ro", NULL, 0)) {
174                         if (ext2_check_sb_compat(fs->e2fs, devvp->v_rdev, 0))
175                                 return (EPERM);
176
177                         /*
178                          * If upgrade to read-write by non-root, then verify
179                          * that user has necessary permissions on the device.
180                          */
181                         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
182                         error = VOP_ACCESS(devvp, VREAD | VWRITE,
183                             td->td_ucred, td);
184                         if (error)
185                                 error = priv_check(td, PRIV_VFS_MOUNT_PERM);
186                         if (error) {
187                                 VOP_UNLOCK(devvp, 0);
188                                 return (error);
189                         }
190                         VOP_UNLOCK(devvp, 0);
191                         g_topology_lock();
192                         error = g_access(ump->um_cp, 0, 1, 0);
193                         g_topology_unlock();
194                         if (error)
195                                 return (error);
196
197                         if ((fs->e2fs->e2fs_state & E2FS_ISCLEAN) == 0 ||
198                             (fs->e2fs->e2fs_state & E2FS_ERRORS)) {
199                                 if (mp->mnt_flag & MNT_FORCE) {
200                                         printf(
201 "WARNING: %s was not properly dismounted\n", fs->e2fs_fsmnt);
202                                 } else {
203                                         printf(
204 "WARNING: R/W mount of %s denied.  Filesystem is not clean - run fsck\n",
205                                             fs->e2fs_fsmnt);
206                                         return (EPERM);
207                                 }
208                         }
209                         fs->e2fs->e2fs_state &= ~E2FS_ISCLEAN;
210                         (void)ext2_cgupdate(ump, MNT_WAIT);
211                         fs->e2fs_ronly = 0;
212                         MNT_ILOCK(mp);
213                         mp->mnt_flag &= ~MNT_RDONLY;
214                         MNT_IUNLOCK(mp);
215                 }
216                 if (vfs_flagopt(opts, "export", NULL, 0)) {
217                         /* Process export requests in vfs_mount.c. */
218                         return (error);
219                 }
220         }
221
222         /*
223          * Not an update, or updating the name: look up the name
224          * and verify that it refers to a sensible disk device.
225          */
226         if (fspec == NULL)
227                 return (EINVAL);
228         NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspec, td);
229         if ((error = namei(ndp)) != 0)
230                 return (error);
231         NDFREE(ndp, NDF_ONLY_PNBUF);
232         devvp = ndp->ni_vp;
233
234         if (!vn_isdisk(devvp, &error)) {
235                 vput(devvp);
236                 return (error);
237         }
238
239         /*
240          * If mount by non-root, then verify that user has necessary
241          * permissions on the device.
242          *
243          * XXXRW: VOP_ACCESS() enough?
244          */
245         accmode = VREAD;
246         if ((mp->mnt_flag & MNT_RDONLY) == 0)
247                 accmode |= VWRITE;
248         error = VOP_ACCESS(devvp, accmode, td->td_ucred, td);
249         if (error)
250                 error = priv_check(td, PRIV_VFS_MOUNT_PERM);
251         if (error) {
252                 vput(devvp);
253                 return (error);
254         }
255
256         if ((mp->mnt_flag & MNT_UPDATE) == 0) {
257                 error = ext2_mountfs(devvp, mp);
258         } else {
259                 if (devvp != ump->um_devvp) {
260                         vput(devvp);
261                         return (EINVAL);        /* needs translation */
262                 } else
263                         vput(devvp);
264         }
265         if (error) {
266                 vrele(devvp);
267                 return (error);
268         }
269         ump = VFSTOEXT2(mp);
270         fs = ump->um_e2fs;
271
272         /*
273          * Note that this strncpy() is ok because of a check at the start
274          * of ext2_mount().
275          */
276         strncpy(fs->e2fs_fsmnt, path, MAXMNTLEN);
277         fs->e2fs_fsmnt[MAXMNTLEN - 1] = '\0';
278         vfs_mountedfrom(mp, fspec);
279         return (0);
280 }
281
282 static int
283 ext2_check_sb_compat(struct ext2fs *es, struct cdev *dev, int ronly)
284 {
285         uint32_t i, mask;
286
287         if (es->e2fs_magic != E2FS_MAGIC) {
288                 printf("ext2fs: %s: wrong magic number %#x (expected %#x)\n",
289                     devtoname(dev), es->e2fs_magic, E2FS_MAGIC);
290                 return (1);
291         }
292         if (es->e2fs_rev > E2FS_REV0) {
293                 mask = es->e2fs_features_incompat & ~(EXT2F_INCOMPAT_SUPP);
294                 if (mask) {
295                         printf("WARNING: mount of %s denied due to "
296                             "unsupported optional features:\n", devtoname(dev));
297                         for (i = 0;
298                             i < sizeof(incompat)/sizeof(struct ext2_feature);
299                             i++)
300                                 if (mask & incompat[i].mask)
301                                         printf("%s ", incompat[i].name);
302                         printf("\n");
303                         return (1);
304                 }
305                 mask = es->e2fs_features_rocompat & ~EXT2F_ROCOMPAT_SUPP;
306                 if (!ronly && mask) {
307                         printf("WARNING: R/W mount of %s denied due to "
308                             "unsupported optional features:\n", devtoname(dev));
309                         for (i = 0;
310                             i < sizeof(ro_compat)/sizeof(struct ext2_feature);
311                             i++)
312                                 if (mask & ro_compat[i].mask)
313                                         printf("%s ", ro_compat[i].name);
314                         printf("\n");
315                         return (1);
316                 }
317         }
318         return (0);
319 }
320
321 static e4fs_daddr_t
322 cg_location(struct m_ext2fs *fs, int number)
323 {
324         int cg, descpb, logical_sb, has_super = 0;
325
326         /*
327          * Adjust logical superblock block number.
328          * Godmar thinks: if the blocksize is greater than 1024, then
329          * the superblock is logically part of block zero.
330          */
331         logical_sb = fs->e2fs_bsize > SBSIZE ? 0 : 1;
332
333         if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG) ||
334             number < fs->e2fs->e3fs_first_meta_bg)
335                 return (logical_sb + number + 1);
336
337         if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT))
338                 descpb = fs->e2fs_bsize / sizeof(struct ext2_gd);
339         else
340                 descpb = fs->e2fs_bsize / E2FS_REV0_GD_SIZE;
341
342         cg = descpb * number;
343
344         if (ext2_cg_has_sb(fs, cg))
345                 has_super = 1;
346
347         return (has_super + cg * (e4fs_daddr_t)EXT2_BLOCKS_PER_GROUP(fs) +
348             fs->e2fs->e2fs_first_dblock);
349 }
350
351 /*
352  * This computes the fields of the m_ext2fs structure from the
353  * data in the ext2fs structure read in.
354  */
355 static int
356 compute_sb_data(struct vnode *devvp, struct ext2fs *es,
357     struct m_ext2fs *fs)
358 {
359         int g_count = 0, error;
360         int i, j;
361         struct buf *bp;
362         uint32_t e2fs_descpb, e2fs_gdbcount_alloc;
363
364         fs->e2fs_bcount = es->e2fs_bcount;
365         fs->e2fs_rbcount = es->e2fs_rbcount;
366         fs->e2fs_fbcount = es->e2fs_fbcount;
367         if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) {
368                 fs->e2fs_bcount |= (uint64_t)(es->e4fs_bcount_hi) << 32;
369                 fs->e2fs_rbcount |= (uint64_t)(es->e4fs_rbcount_hi) << 32;
370                 fs->e2fs_fbcount |= (uint64_t)(es->e4fs_fbcount_hi) << 32;
371         }
372         fs->e2fs_bshift = EXT2_MIN_BLOCK_LOG_SIZE + es->e2fs_log_bsize;
373         fs->e2fs_bsize = 1U << fs->e2fs_bshift;
374         fs->e2fs_fsbtodb = es->e2fs_log_bsize + 1;
375         fs->e2fs_qbmask = fs->e2fs_bsize - 1;
376         fs->e2fs_fsize = EXT2_MIN_FRAG_SIZE << es->e2fs_log_fsize;
377         if (fs->e2fs_fsize)
378                 fs->e2fs_fpb = fs->e2fs_bsize / fs->e2fs_fsize;
379         fs->e2fs_bpg = es->e2fs_bpg;
380         fs->e2fs_fpg = es->e2fs_fpg;
381         fs->e2fs_ipg = es->e2fs_ipg;
382         if (es->e2fs_rev == E2FS_REV0) {
383                 fs->e2fs_isize = E2FS_REV0_INODE_SIZE;
384         } else {
385                 fs->e2fs_isize = es->e2fs_inode_size;
386
387                 /*
388                  * Simple sanity check for superblock inode size value.
389                  */
390                 if (EXT2_INODE_SIZE(fs) < E2FS_REV0_INODE_SIZE ||
391                     EXT2_INODE_SIZE(fs) > fs->e2fs_bsize ||
392                     (fs->e2fs_isize & (fs->e2fs_isize - 1)) != 0) {
393                         printf("ext2fs: invalid inode size %d\n",
394                             fs->e2fs_isize);
395                         return (EIO);
396                 }
397         }
398         /* Check for extra isize in big inodes. */
399         if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_EXTRA_ISIZE) &&
400             EXT2_INODE_SIZE(fs) < sizeof(struct ext2fs_dinode)) {
401                 printf("ext2fs: no space for extra inode timestamps\n");
402                 return (EINVAL);
403         }
404         /* Check checksum features */
405         if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM) &&
406             EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM)) {
407                 printf("ext2fs: incorrect checksum features combination\n");
408                 return (EINVAL);
409         }
410         /* Check for group descriptor size */
411         if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT) &&
412             (es->e3fs_desc_size != sizeof(struct ext2_gd))) {
413                 printf("ext2fs: group descriptor size unsupported %d\n",
414                     es->e3fs_desc_size);
415                 return (EINVAL);
416         }
417         /* Check for group size */
418         if (fs->e2fs_bpg != fs->e2fs_bsize * 8) {
419                 printf("ext2fs: non-standard group size unsupported %d\n",
420                     fs->e2fs_bpg);
421                 return (EINVAL);
422         }
423
424         fs->e2fs_ipb = fs->e2fs_bsize / EXT2_INODE_SIZE(fs);
425         fs->e2fs_itpg = fs->e2fs_ipg / fs->e2fs_ipb;
426         /* s_resuid / s_resgid ? */
427         fs->e2fs_gcount = howmany(fs->e2fs_bcount - es->e2fs_first_dblock,
428             EXT2_BLOCKS_PER_GROUP(fs));
429         if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) {
430                 e2fs_descpb = fs->e2fs_bsize / sizeof(struct ext2_gd);
431                 e2fs_gdbcount_alloc = howmany(fs->e2fs_gcount, e2fs_descpb);
432         } else {
433                 e2fs_descpb = fs->e2fs_bsize / E2FS_REV0_GD_SIZE;
434                 e2fs_gdbcount_alloc = howmany(fs->e2fs_gcount,
435                     fs->e2fs_bsize / sizeof(struct ext2_gd));
436         }
437         fs->e2fs_gdbcount = howmany(fs->e2fs_gcount, e2fs_descpb);
438         fs->e2fs_gd = malloc(e2fs_gdbcount_alloc * fs->e2fs_bsize,
439             M_EXT2MNT, M_WAITOK | M_ZERO);
440         fs->e2fs_contigdirs = malloc(fs->e2fs_gcount *
441             sizeof(*fs->e2fs_contigdirs), M_EXT2MNT, M_WAITOK | M_ZERO);
442
443         for (i = 0; i < fs->e2fs_gdbcount; i++) {
444                 error = bread(devvp,
445                     fsbtodb(fs, cg_location(fs, i)),
446                     fs->e2fs_bsize, NOCRED, &bp);
447                 if (error) {
448                         free(fs->e2fs_contigdirs, M_EXT2MNT);
449                         free(fs->e2fs_gd, M_EXT2MNT);
450                         brelse(bp);
451                         return (error);
452                 }
453                 if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) {
454                         memcpy(&fs->e2fs_gd[
455                             i * fs->e2fs_bsize / sizeof(struct ext2_gd)],
456                             bp->b_data, fs->e2fs_bsize);
457                 } else {
458                         for (j = 0; j < e2fs_descpb &&
459                             g_count < fs->e2fs_gcount; j++, g_count++)
460                                 memcpy(&fs->e2fs_gd[g_count],
461                                     bp->b_data + j * E2FS_REV0_GD_SIZE,
462                                     E2FS_REV0_GD_SIZE);
463                 }
464                 brelse(bp);
465                 bp = NULL;
466         }
467         /* Precompute checksum seed for all metadata */
468         ext2_sb_csum_set_seed(fs);
469         /* Verfy cg csum */
470         if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM) ||
471             EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM)) {
472                 error = ext2_gd_csum_verify(fs, devvp->v_rdev);
473                 if (error)
474                         return (error);
475         }
476         /* Initialization for the ext2 Orlov allocator variant. */
477         fs->e2fs_total_dir = 0;
478         for (i = 0; i < fs->e2fs_gcount; i++)
479                 fs->e2fs_total_dir += e2fs_gd_get_ndirs(&fs->e2fs_gd[i]);
480
481         if (es->e2fs_rev == E2FS_REV0 ||
482             !EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_LARGEFILE))
483                 fs->e2fs_maxfilesize = 0x7fffffff;
484         else {
485                 fs->e2fs_maxfilesize = 0xffffffffffff;
486                 if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_HUGE_FILE))
487                         fs->e2fs_maxfilesize = 0x7fffffffffffffff;
488         }
489         if (es->e4fs_flags & E2FS_UNSIGNED_HASH) {
490                 fs->e2fs_uhash = 3;
491         } else if ((es->e4fs_flags & E2FS_SIGNED_HASH) == 0) {
492 #ifdef __CHAR_UNSIGNED__
493                 es->e4fs_flags |= E2FS_UNSIGNED_HASH;
494                 fs->e2fs_uhash = 3;
495 #else
496                 es->e4fs_flags |= E2FS_SIGNED_HASH;
497 #endif
498         }
499         if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
500                 error = ext2_sb_csum_verify(fs);
501
502         return (error);
503 }
504
505 /*
506  * Reload all incore data for a filesystem (used after running fsck on
507  * the root filesystem and finding things to fix). The filesystem must
508  * be mounted read-only.
509  *
510  * Things to do to update the mount:
511  *      1) invalidate all cached meta-data.
512  *      2) re-read superblock from disk.
513  *      3) invalidate all cluster summary information.
514  *      4) invalidate all inactive vnodes.
515  *      5) invalidate all cached file data.
516  *      6) re-read inode data for all active vnodes.
517  * XXX we are missing some steps, in particular # 3, this has to be reviewed.
518  */
519 static int
520 ext2_reload(struct mount *mp, struct thread *td)
521 {
522         struct vnode *vp, *mvp, *devvp;
523         struct inode *ip;
524         struct buf *bp;
525         struct ext2fs *es;
526         struct m_ext2fs *fs;
527         struct csum *sump;
528         int error, i;
529         int32_t *lp;
530
531         if ((mp->mnt_flag & MNT_RDONLY) == 0)
532                 return (EINVAL);
533         /*
534          * Step 1: invalidate all cached meta-data.
535          */
536         devvp = VFSTOEXT2(mp)->um_devvp;
537         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
538         if (vinvalbuf(devvp, 0, 0, 0) != 0)
539                 panic("ext2_reload: dirty1");
540         VOP_UNLOCK(devvp, 0);
541
542         /*
543          * Step 2: re-read superblock from disk.
544          * constants have been adjusted for ext2
545          */
546         if ((error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) != 0)
547                 return (error);
548         es = (struct ext2fs *)bp->b_data;
549         if (ext2_check_sb_compat(es, devvp->v_rdev, 0) != 0) {
550                 brelse(bp);
551                 return (EIO);           /* XXX needs translation */
552         }
553         fs = VFSTOEXT2(mp)->um_e2fs;
554         bcopy(bp->b_data, fs->e2fs, sizeof(struct ext2fs));
555
556         if ((error = compute_sb_data(devvp, es, fs)) != 0) {
557                 brelse(bp);
558                 return (error);
559         }
560 #ifdef UNKLAR
561         if (fs->fs_sbsize < SBSIZE)
562                 bp->b_flags |= B_INVAL;
563 #endif
564         brelse(bp);
565
566         /*
567          * Step 3: invalidate all cluster summary information.
568          */
569         if (fs->e2fs_contigsumsize > 0) {
570                 lp = fs->e2fs_maxcluster;
571                 sump = fs->e2fs_clustersum;
572                 for (i = 0; i < fs->e2fs_gcount; i++, sump++) {
573                         *lp++ = fs->e2fs_contigsumsize;
574                         sump->cs_init = 0;
575                         bzero(sump->cs_sum, fs->e2fs_contigsumsize + 1);
576                 }
577         }
578
579 loop:
580         MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
581                 /*
582                  * Step 4: invalidate all cached file data.
583                  */
584                 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
585                         MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
586                         goto loop;
587                 }
588                 if (vinvalbuf(vp, 0, 0, 0))
589                         panic("ext2_reload: dirty2");
590
591                 /*
592                  * Step 5: re-read inode data for all active vnodes.
593                  */
594                 ip = VTOI(vp);
595                 error = bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
596                     (int)fs->e2fs_bsize, NOCRED, &bp);
597                 if (error) {
598                         VOP_UNLOCK(vp, 0);
599                         vrele(vp);
600                         MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
601                         return (error);
602                 }
603                 ext2_ei2i((struct ext2fs_dinode *)((char *)bp->b_data +
604                     EXT2_INODE_SIZE(fs) * ino_to_fsbo(fs, ip->i_number)), ip);
605                 brelse(bp);
606                 VOP_UNLOCK(vp, 0);
607                 vrele(vp);
608         }
609         return (0);
610 }
611
612 /*
613  * Common code for mount and mountroot.
614  */
615 static int
616 ext2_mountfs(struct vnode *devvp, struct mount *mp)
617 {
618         struct ext2mount *ump;
619         struct buf *bp;
620         struct m_ext2fs *fs;
621         struct ext2fs *es;
622         struct cdev *dev = devvp->v_rdev;
623         struct g_consumer *cp;
624         struct bufobj *bo;
625         struct csum *sump;
626         int error;
627         int ronly;
628         int i;
629         u_long size;
630         int32_t *lp;
631         int32_t e2fs_maxcontig;
632
633         ronly = vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0);
634         /* XXX: use VOP_ACESS to check FS perms */
635         g_topology_lock();
636         error = g_vfs_open(devvp, &cp, "ext2fs", ronly ? 0 : 1);
637         g_topology_unlock();
638         VOP_UNLOCK(devvp, 0);
639         if (error)
640                 return (error);
641
642         /* XXX: should we check for some sectorsize or 512 instead? */
643         if (((SBSIZE % cp->provider->sectorsize) != 0) ||
644             (SBSIZE < cp->provider->sectorsize)) {
645                 g_topology_lock();
646                 g_vfs_close(cp);
647                 g_topology_unlock();
648                 return (EINVAL);
649         }
650
651         bo = &devvp->v_bufobj;
652         bo->bo_private = cp;
653         bo->bo_ops = g_vfs_bufops;
654         if (devvp->v_rdev->si_iosize_max != 0)
655                 mp->mnt_iosize_max = devvp->v_rdev->si_iosize_max;
656         if (mp->mnt_iosize_max > MAXPHYS)
657                 mp->mnt_iosize_max = MAXPHYS;
658
659         bp = NULL;
660         ump = NULL;
661         if ((error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) != 0)
662                 goto out;
663         es = (struct ext2fs *)bp->b_data;
664         if (ext2_check_sb_compat(es, dev, ronly) != 0) {
665                 error = EINVAL;         /* XXX needs translation */
666                 goto out;
667         }
668         if ((es->e2fs_state & E2FS_ISCLEAN) == 0 ||
669             (es->e2fs_state & E2FS_ERRORS)) {
670                 if (ronly || (mp->mnt_flag & MNT_FORCE)) {
671                         printf(
672 "WARNING: Filesystem was not properly dismounted\n");
673                 } else {
674                         printf(
675 "WARNING: R/W mount denied.  Filesystem is not clean - run fsck\n");
676                         error = EPERM;
677                         goto out;
678                 }
679         }
680         ump = malloc(sizeof(*ump), M_EXT2MNT, M_WAITOK | M_ZERO);
681
682         /*
683          * I don't know whether this is the right strategy. Note that
684          * we dynamically allocate both an m_ext2fs and an ext2fs
685          * while Linux keeps the super block in a locked buffer.
686          */
687         ump->um_e2fs = malloc(sizeof(struct m_ext2fs),
688             M_EXT2MNT, M_WAITOK | M_ZERO);
689         ump->um_e2fs->e2fs = malloc(sizeof(struct ext2fs),
690             M_EXT2MNT, M_WAITOK);
691         mtx_init(EXT2_MTX(ump), "EXT2FS", "EXT2FS Lock", MTX_DEF);
692         bcopy(es, ump->um_e2fs->e2fs, (u_int)sizeof(struct ext2fs));
693         if ((error = compute_sb_data(devvp, ump->um_e2fs->e2fs, ump->um_e2fs)))
694                 goto out;
695
696         /*
697          * Calculate the maximum contiguous blocks and size of cluster summary
698          * array.  In FFS this is done by newfs; however, the superblock
699          * in ext2fs doesn't have these variables, so we can calculate
700          * them here.
701          */
702         e2fs_maxcontig = MAX(1, MAXPHYS / ump->um_e2fs->e2fs_bsize);
703         ump->um_e2fs->e2fs_contigsumsize = MIN(e2fs_maxcontig, EXT2_MAXCONTIG);
704         if (ump->um_e2fs->e2fs_contigsumsize > 0) {
705                 size = ump->um_e2fs->e2fs_gcount * sizeof(int32_t);
706                 ump->um_e2fs->e2fs_maxcluster = malloc(size, M_EXT2MNT, M_WAITOK);
707                 size = ump->um_e2fs->e2fs_gcount * sizeof(struct csum);
708                 ump->um_e2fs->e2fs_clustersum = malloc(size, M_EXT2MNT, M_WAITOK);
709                 lp = ump->um_e2fs->e2fs_maxcluster;
710                 sump = ump->um_e2fs->e2fs_clustersum;
711                 for (i = 0; i < ump->um_e2fs->e2fs_gcount; i++, sump++) {
712                         *lp++ = ump->um_e2fs->e2fs_contigsumsize;
713                         sump->cs_init = 0;
714                         sump->cs_sum = malloc((ump->um_e2fs->e2fs_contigsumsize + 1) *
715                             sizeof(int32_t), M_EXT2MNT, M_WAITOK | M_ZERO);
716                 }
717         }
718
719         brelse(bp);
720         bp = NULL;
721         fs = ump->um_e2fs;
722         fs->e2fs_ronly = ronly; /* ronly is set according to mnt_flags */
723
724         /*
725          * If the fs is not mounted read-only, make sure the super block is
726          * always written back on a sync().
727          */
728         fs->e2fs_wasvalid = fs->e2fs->e2fs_state & E2FS_ISCLEAN ? 1 : 0;
729         if (ronly == 0) {
730                 fs->e2fs_fmod = 1;      /* mark it modified */
731                 fs->e2fs->e2fs_state &= ~E2FS_ISCLEAN;  /* set fs invalid */
732         }
733         mp->mnt_data = ump;
734         mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
735         mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
736         mp->mnt_maxsymlinklen = EXT2_MAXSYMLINKLEN;
737         MNT_ILOCK(mp);
738         mp->mnt_flag |= MNT_LOCAL;
739         MNT_IUNLOCK(mp);
740         ump->um_mountp = mp;
741         ump->um_dev = dev;
742         ump->um_devvp = devvp;
743         ump->um_bo = &devvp->v_bufobj;
744         ump->um_cp = cp;
745
746         /*
747          * Setting those two parameters allowed us to use
748          * ufs_bmap w/o changse!
749          */
750         ump->um_nindir = EXT2_ADDR_PER_BLOCK(fs);
751         ump->um_bptrtodb = fs->e2fs->e2fs_log_bsize + 1;
752         ump->um_seqinc = EXT2_FRAGS_PER_BLOCK(fs);
753         if (ronly == 0)
754                 ext2_sbupdate(ump, MNT_WAIT);
755         /*
756          * Initialize filesystem stat information in mount struct.
757          */
758         MNT_ILOCK(mp);
759         mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_EXTENDED_SHARED |
760             MNTK_USES_BCACHE;
761         MNT_IUNLOCK(mp);
762         return (0);
763 out:
764         if (bp)
765                 brelse(bp);
766         if (cp != NULL) {
767                 g_topology_lock();
768                 g_vfs_close(cp);
769                 g_topology_unlock();
770         }
771         if (ump) {
772                 mtx_destroy(EXT2_MTX(ump));
773                 free(ump->um_e2fs->e2fs_gd, M_EXT2MNT);
774                 free(ump->um_e2fs->e2fs_contigdirs, M_EXT2MNT);
775                 free(ump->um_e2fs->e2fs, M_EXT2MNT);
776                 free(ump->um_e2fs, M_EXT2MNT);
777                 free(ump, M_EXT2MNT);
778                 mp->mnt_data = NULL;
779         }
780         return (error);
781 }
782
783 /*
784  * Unmount system call.
785  */
786 static int
787 ext2_unmount(struct mount *mp, int mntflags)
788 {
789         struct ext2mount *ump;
790         struct m_ext2fs *fs;
791         struct csum *sump;
792         int error, flags, i, ronly;
793
794         flags = 0;
795         if (mntflags & MNT_FORCE) {
796                 if (mp->mnt_flag & MNT_ROOTFS)
797                         return (EINVAL);
798                 flags |= FORCECLOSE;
799         }
800         if ((error = ext2_flushfiles(mp, flags, curthread)) != 0)
801                 return (error);
802         ump = VFSTOEXT2(mp);
803         fs = ump->um_e2fs;
804         ronly = fs->e2fs_ronly;
805         if (ronly == 0 && ext2_cgupdate(ump, MNT_WAIT) == 0) {
806                 if (fs->e2fs_wasvalid)
807                         fs->e2fs->e2fs_state |= E2FS_ISCLEAN;
808                 ext2_sbupdate(ump, MNT_WAIT);
809         }
810
811         g_topology_lock();
812         g_vfs_close(ump->um_cp);
813         g_topology_unlock();
814         vrele(ump->um_devvp);
815         sump = fs->e2fs_clustersum;
816         for (i = 0; i < fs->e2fs_gcount; i++, sump++)
817                 free(sump->cs_sum, M_EXT2MNT);
818         free(fs->e2fs_clustersum, M_EXT2MNT);
819         free(fs->e2fs_maxcluster, M_EXT2MNT);
820         free(fs->e2fs_gd, M_EXT2MNT);
821         free(fs->e2fs_contigdirs, M_EXT2MNT);
822         free(fs->e2fs, M_EXT2MNT);
823         free(fs, M_EXT2MNT);
824         free(ump, M_EXT2MNT);
825         mp->mnt_data = NULL;
826         MNT_ILOCK(mp);
827         mp->mnt_flag &= ~MNT_LOCAL;
828         MNT_IUNLOCK(mp);
829         return (error);
830 }
831
832 /*
833  * Flush out all the files in a filesystem.
834  */
835 static int
836 ext2_flushfiles(struct mount *mp, int flags, struct thread *td)
837 {
838         int error;
839
840         error = vflush(mp, 0, flags, td);
841         return (error);
842 }
843
844 /*
845  * Get filesystem statistics.
846  */
847 int
848 ext2_statfs(struct mount *mp, struct statfs *sbp)
849 {
850         struct ext2mount *ump;
851         struct m_ext2fs *fs;
852         uint32_t overhead, overhead_per_group, ngdb;
853         int i, ngroups;
854
855         ump = VFSTOEXT2(mp);
856         fs = ump->um_e2fs;
857         if (fs->e2fs->e2fs_magic != E2FS_MAGIC)
858                 panic("ext2_statfs");
859
860         /*
861          * Compute the overhead (FS structures)
862          */
863         overhead_per_group =
864             1 /* block bitmap */ +
865             1 /* inode bitmap */ +
866             fs->e2fs_itpg;
867         overhead = fs->e2fs->e2fs_first_dblock +
868             fs->e2fs_gcount * overhead_per_group;
869         if (fs->e2fs->e2fs_rev > E2FS_REV0 &&
870             fs->e2fs->e2fs_features_rocompat & EXT2F_ROCOMPAT_SPARSESUPER) {
871                 for (i = 0, ngroups = 0; i < fs->e2fs_gcount; i++) {
872                         if (ext2_cg_has_sb(fs, i))
873                                 ngroups++;
874                 }
875         } else {
876                 ngroups = fs->e2fs_gcount;
877         }
878         ngdb = fs->e2fs_gdbcount;
879         if (fs->e2fs->e2fs_rev > E2FS_REV0 &&
880             fs->e2fs->e2fs_features_compat & EXT2F_COMPAT_RESIZE)
881                 ngdb += fs->e2fs->e2fs_reserved_ngdb;
882         overhead += ngroups * (1 /* superblock */ + ngdb);
883
884         sbp->f_bsize = EXT2_FRAG_SIZE(fs);
885         sbp->f_iosize = EXT2_BLOCK_SIZE(fs);
886         sbp->f_blocks = fs->e2fs_bcount - overhead;
887         sbp->f_bfree = fs->e2fs_fbcount;
888         sbp->f_bavail = sbp->f_bfree - fs->e2fs_rbcount;
889         sbp->f_files = fs->e2fs->e2fs_icount;
890         sbp->f_ffree = fs->e2fs->e2fs_ficount;
891         return (0);
892 }
893
894 /*
895  * Go through the disk queues to initiate sandbagged IO;
896  * go through the inodes to write those that have been modified;
897  * initiate the writing of the super block if it has been modified.
898  *
899  * Note: we are always called with the filesystem marked `MPBUSY'.
900  */
901 static int
902 ext2_sync(struct mount *mp, int waitfor)
903 {
904         struct vnode *mvp, *vp;
905         struct thread *td;
906         struct inode *ip;
907         struct ext2mount *ump = VFSTOEXT2(mp);
908         struct m_ext2fs *fs;
909         int error, allerror = 0;
910
911         td = curthread;
912         fs = ump->um_e2fs;
913         if (fs->e2fs_fmod != 0 && fs->e2fs_ronly != 0) {                /* XXX */
914                 printf("fs = %s\n", fs->e2fs_fsmnt);
915                 panic("ext2_sync: rofs mod");
916         }
917
918         /*
919          * Write back each (modified) inode.
920          */
921 loop:
922         MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
923                 if (vp->v_type == VNON) {
924                         VI_UNLOCK(vp);
925                         continue;
926                 }
927                 ip = VTOI(vp);
928                 if ((ip->i_flag &
929                     (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
930                     (vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
931                     waitfor == MNT_LAZY)) {
932                         VI_UNLOCK(vp);
933                         continue;
934                 }
935                 error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, td);
936                 if (error) {
937                         if (error == ENOENT) {
938                                 MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
939                                 goto loop;
940                         }
941                         continue;
942                 }
943                 if ((error = VOP_FSYNC(vp, waitfor, td)) != 0)
944                         allerror = error;
945                 VOP_UNLOCK(vp, 0);
946                 vrele(vp);
947         }
948
949         /*
950          * Force stale filesystem control information to be flushed.
951          */
952         if (waitfor != MNT_LAZY) {
953                 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
954                 if ((error = VOP_FSYNC(ump->um_devvp, waitfor, td)) != 0)
955                         allerror = error;
956                 VOP_UNLOCK(ump->um_devvp, 0);
957         }
958
959         /*
960          * Write back modified superblock.
961          */
962         if (fs->e2fs_fmod != 0) {
963                 fs->e2fs_fmod = 0;
964                 fs->e2fs->e2fs_wtime = time_second;
965                 if ((error = ext2_cgupdate(ump, waitfor)) != 0)
966                         allerror = error;
967         }
968         return (allerror);
969 }
970
971 /*
972  * Look up an EXT2FS dinode number to find its incore vnode, otherwise read it
973  * in from disk.  If it is in core, wait for the lock bit to clear, then
974  * return the inode locked.  Detection and handling of mount points must be
975  * done by the calling routine.
976  */
977 static int
978 ext2_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
979 {
980         struct m_ext2fs *fs;
981         struct inode *ip;
982         struct ext2mount *ump;
983         struct buf *bp;
984         struct vnode *vp;
985         struct thread *td;
986         int i, error;
987         int used_blocks;
988
989         td = curthread;
990         error = vfs_hash_get(mp, ino, flags, td, vpp, NULL, NULL);
991         if (error || *vpp != NULL)
992                 return (error);
993
994         ump = VFSTOEXT2(mp);
995         ip = malloc(sizeof(struct inode), M_EXT2NODE, M_WAITOK | M_ZERO);
996
997         /* Allocate a new vnode/inode. */
998         if ((error = getnewvnode("ext2fs", mp, &ext2_vnodeops, &vp)) != 0) {
999                 *vpp = NULL;
1000                 free(ip, M_EXT2NODE);
1001                 return (error);
1002         }
1003         vp->v_data = ip;
1004         ip->i_vnode = vp;
1005         ip->i_e2fs = fs = ump->um_e2fs;
1006         ip->i_ump = ump;
1007         ip->i_number = ino;
1008
1009         lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL);
1010         error = insmntque(vp, mp);
1011         if (error != 0) {
1012                 free(ip, M_EXT2NODE);
1013                 *vpp = NULL;
1014                 return (error);
1015         }
1016         error = vfs_hash_insert(vp, ino, flags, td, vpp, NULL, NULL);
1017         if (error || *vpp != NULL)
1018                 return (error);
1019
1020         /* Read in the disk contents for the inode, copy into the inode. */
1021         if ((error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
1022             (int)fs->e2fs_bsize, NOCRED, &bp)) != 0) {
1023                 /*
1024                  * The inode does not contain anything useful, so it would
1025                  * be misleading to leave it on its hash chain. With mode
1026                  * still zero, it will be unlinked and returned to the free
1027                  * list by vput().
1028                  */
1029                 brelse(bp);
1030                 vput(vp);
1031                 *vpp = NULL;
1032                 return (error);
1033         }
1034         /* convert ext2 inode to dinode */
1035         error = ext2_ei2i((struct ext2fs_dinode *)((char *)bp->b_data +
1036             EXT2_INODE_SIZE(fs) * ino_to_fsbo(fs, ino)), ip);
1037         if (error) {
1038                 printf("ext2fs: Bad inode %lu csum - run fsck\n",
1039                     (unsigned long)ino);
1040                 brelse(bp);
1041                 vput(vp);
1042                 *vpp = NULL;
1043                 return (error);
1044         }
1045         ip->i_block_group = ino_to_cg(fs, ino);
1046         ip->i_next_alloc_block = 0;
1047         ip->i_next_alloc_goal = 0;
1048
1049         /*
1050          * Now we want to make sure that block pointers for unused
1051          * blocks are zeroed out - ext2_balloc depends on this
1052          * although for regular files and directories only
1053          *
1054          * If IN_E4EXTENTS is enabled, unused blocks are not zeroed
1055          * out because we could corrupt the extent tree.
1056          */
1057         if (!(ip->i_flag & IN_E4EXTENTS) &&
1058             (S_ISDIR(ip->i_mode) || S_ISREG(ip->i_mode))) {
1059                 used_blocks = howmany(ip->i_size, fs->e2fs_bsize);
1060                 for (i = used_blocks; i < EXT2_NDIR_BLOCKS; i++)
1061                         ip->i_db[i] = 0;
1062         }
1063 #ifdef EXT2FS_DEBUG
1064         ext2_print_inode(ip);
1065         ext4_ext_print_extent_tree_status(ip);
1066 #endif
1067         bqrelse(bp);
1068
1069         /*
1070          * Initialize the vnode from the inode, check for aliases.
1071          * Note that the underlying vnode may have changed.
1072          */
1073         if ((error = ext2_vinit(mp, &ext2_fifoops, &vp)) != 0) {
1074                 vput(vp);
1075                 *vpp = NULL;
1076                 return (error);
1077         }
1078
1079         /*
1080          * Finish inode initialization.
1081          */
1082
1083         *vpp = vp;
1084         return (0);
1085 }
1086
1087 /*
1088  * File handle to vnode
1089  *
1090  * Have to be really careful about stale file handles:
1091  * - check that the inode number is valid
1092  * - call ext2_vget() to get the locked inode
1093  * - check for an unallocated inode (i_mode == 0)
1094  * - check that the given client host has export rights and return
1095  *   those rights via. exflagsp and credanonp
1096  */
1097 static int
1098 ext2_fhtovp(struct mount *mp, struct fid *fhp, int flags, struct vnode **vpp)
1099 {
1100         struct inode *ip;
1101         struct ufid *ufhp;
1102         struct vnode *nvp;
1103         struct m_ext2fs *fs;
1104         int error;
1105
1106         ufhp = (struct ufid *)fhp;
1107         fs = VFSTOEXT2(mp)->um_e2fs;
1108         if (ufhp->ufid_ino < EXT2_ROOTINO ||
1109             ufhp->ufid_ino > fs->e2fs_gcount * fs->e2fs->e2fs_ipg)
1110                 return (ESTALE);
1111
1112         error = VFS_VGET(mp, ufhp->ufid_ino, LK_EXCLUSIVE, &nvp);
1113         if (error) {
1114                 *vpp = NULLVP;
1115                 return (error);
1116         }
1117         ip = VTOI(nvp);
1118         if (ip->i_mode == 0 ||
1119             ip->i_gen != ufhp->ufid_gen || ip->i_nlink <= 0) {
1120                 vput(nvp);
1121                 *vpp = NULLVP;
1122                 return (ESTALE);
1123         }
1124         *vpp = nvp;
1125         vnode_create_vobject(*vpp, 0, curthread);
1126         return (0);
1127 }
1128
1129 /*
1130  * Write a superblock and associated information back to disk.
1131  */
1132 static int
1133 ext2_sbupdate(struct ext2mount *mp, int waitfor)
1134 {
1135         struct m_ext2fs *fs = mp->um_e2fs;
1136         struct ext2fs *es = fs->e2fs;
1137         struct buf *bp;
1138         int error = 0;
1139
1140         es->e2fs_bcount = fs->e2fs_bcount & 0xffffffff;
1141         es->e2fs_rbcount = fs->e2fs_rbcount & 0xffffffff;
1142         es->e2fs_fbcount = fs->e2fs_fbcount & 0xffffffff;
1143         if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) {
1144                 es->e4fs_bcount_hi = fs->e2fs_bcount >> 32;
1145                 es->e4fs_rbcount_hi = fs->e2fs_rbcount >> 32;
1146                 es->e4fs_fbcount_hi = fs->e2fs_fbcount >> 32;
1147         }
1148
1149         if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
1150                 ext2_sb_csum_set(fs);
1151
1152         bp = getblk(mp->um_devvp, SBLOCK, SBSIZE, 0, 0, 0);
1153         bcopy((caddr_t)es, bp->b_data, (u_int)sizeof(struct ext2fs));
1154         if (waitfor == MNT_WAIT)
1155                 error = bwrite(bp);
1156         else
1157                 bawrite(bp);
1158
1159         /*
1160          * The buffers for group descriptors, inode bitmaps and block bitmaps
1161          * are not busy at this point and are (hopefully) written by the
1162          * usual sync mechanism. No need to write them here.
1163          */
1164         return (error);
1165 }
1166 int
1167 ext2_cgupdate(struct ext2mount *mp, int waitfor)
1168 {
1169         struct m_ext2fs *fs = mp->um_e2fs;
1170         struct buf *bp;
1171         int i, j, g_count = 0, error = 0, allerror = 0;
1172
1173         allerror = ext2_sbupdate(mp, waitfor);
1174
1175         /* Update gd csums */
1176         if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM) ||
1177             EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
1178                 ext2_gd_csum_set(fs);
1179
1180         for (i = 0; i < fs->e2fs_gdbcount; i++) {
1181                 bp = getblk(mp->um_devvp, fsbtodb(fs,
1182                     cg_location(fs, i)),
1183                     fs->e2fs_bsize, 0, 0, 0);
1184                 if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) {
1185                         memcpy(bp->b_data, &fs->e2fs_gd[
1186                             i * fs->e2fs_bsize / sizeof(struct ext2_gd)],
1187                             fs->e2fs_bsize);
1188                 } else {
1189                         for (j = 0; j < fs->e2fs_bsize / E2FS_REV0_GD_SIZE &&
1190                             g_count < fs->e2fs_gcount; j++, g_count++)
1191                                 memcpy(bp->b_data + j * E2FS_REV0_GD_SIZE,
1192                                     &fs->e2fs_gd[g_count], E2FS_REV0_GD_SIZE);
1193                 }
1194                 if (waitfor == MNT_WAIT)
1195                         error = bwrite(bp);
1196                 else
1197                         bawrite(bp);
1198         }
1199
1200         if (!allerror && error)
1201                 allerror = error;
1202         return (allerror);
1203 }
1204
1205 /*
1206  * Return the root of a filesystem.
1207  */
1208 static int
1209 ext2_root(struct mount *mp, int flags, struct vnode **vpp)
1210 {
1211         struct vnode *nvp;
1212         int error;
1213
1214         error = VFS_VGET(mp, EXT2_ROOTINO, LK_EXCLUSIVE, &nvp);
1215         if (error)
1216                 return (error);
1217         *vpp = nvp;
1218         return (0);
1219 }