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