]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/gnu/fs/ext2fs/ext2_vfsops.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / gnu / fs / ext2fs / ext2_vfsops.c
1 /*-
2  *  modified for EXT2FS support in Lites 1.1
3  *
4  *  Aug 1995, Godmar Back (gback@cs.utah.edu)
5  *  University of Utah, Department of Computer Science
6  */
7 /*-
8  * Copyright (c) 1989, 1991, 1993, 1994
9  *      The Regents of the University of California.  All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 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 /*-
40  * COPYRIGHT.INFO says this has some GPL'd code from ext2_super.c in it
41  *
42  *      This program is free software; you can redistribute it and/or modify
43  *      it under the terms of the GNU General Public License as published by
44  *      the Free Software Foundation; either version 2 of the License.
45  *
46  *      This program is distributed in the hope that it will be useful,
47  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
48  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
49  *      GNU General Public License for more details.
50  *
51  *      You should have received a copy of the GNU General Public License
52  *      along with this program; if not, write to the Free Software
53  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
54  *
55  */
56
57 #include <sys/param.h>
58 #include <sys/systm.h>
59 #include <sys/namei.h>
60 #include <sys/priv.h>
61 #include <sys/proc.h>
62 #include <sys/kernel.h>
63 #include <sys/vnode.h>
64 #include <sys/mount.h>
65 #include <sys/bio.h>
66 #include <sys/buf.h>
67 #include <sys/conf.h>
68 #include <sys/fcntl.h>
69 #include <sys/malloc.h>
70 #include <sys/stat.h>
71 #include <sys/mutex.h>
72
73 #include <geom/geom.h>
74 #include <geom/geom_vfs.h>
75
76 #include <gnu/fs/ext2fs/ext2_mount.h>
77 #include <gnu/fs/ext2fs/inode.h>
78
79 #include <gnu/fs/ext2fs/fs.h>
80 #include <gnu/fs/ext2fs/ext2_extern.h>
81 #include <gnu/fs/ext2fs/ext2_fs_sb.h>
82 #include <gnu/fs/ext2fs/ext2_fs.h>
83
84 static int      ext2_flushfiles(struct mount *mp, int flags, struct thread *td);
85 static int      ext2_mountfs(struct vnode *, struct mount *);
86 static int      ext2_reload(struct mount *mp, struct thread *td);
87 static int      ext2_sbupdate(struct ext2mount *, int);
88
89 static vfs_unmount_t            ext2_unmount;
90 static vfs_root_t               ext2_root;
91 static vfs_statfs_t             ext2_statfs;
92 static vfs_sync_t               ext2_sync;
93 static vfs_vget_t               ext2_vget;
94 static vfs_fhtovp_t             ext2_fhtovp;
95 static vfs_mount_t              ext2_mount;
96
97 MALLOC_DEFINE(M_EXT2NODE, "ext2_node", "EXT2 vnode private part");
98 static MALLOC_DEFINE(M_EXT2MNT, "ext2_mount", "EXT2 mount structure");
99
100 static struct vfsops ext2fs_vfsops = {
101         .vfs_fhtovp =           ext2_fhtovp,
102         .vfs_mount =            ext2_mount,
103         .vfs_root =             ext2_root,      /* root inode via vget */
104         .vfs_statfs =           ext2_statfs,
105         .vfs_sync =             ext2_sync,
106         .vfs_unmount =          ext2_unmount,
107         .vfs_vget =             ext2_vget,
108 };
109
110 VFS_SET(ext2fs_vfsops, ext2fs, 0);
111
112 static int      ext2_check_sb_compat(struct ext2_super_block *es, struct cdev *dev,
113                     int ronly);
114 static int      compute_sb_data(struct vnode * devvp,
115                     struct ext2_super_block * es, struct ext2_sb_info * fs);
116
117 static const char *ext2_opts[] = { "from", "export", "acls", "noexec",
118     "noatime", "union", "suiddir", "multilabel", "nosymfollow",
119     "noclusterr", "noclusterw", "force", NULL };
120
121 /*
122  * VFS Operations.
123  *
124  * mount system call
125  */
126 static int
127 ext2_mount(struct mount *mp)
128 {
129         struct vfsoptlist *opts;
130         struct vnode *devvp;
131         struct thread *td;
132         struct ext2mount *ump = 0;
133         struct ext2_sb_info *fs;
134         struct nameidata nd, *ndp = &nd;
135         accmode_t accmode;
136         char *path, *fspec;
137         int error, flags, len;
138
139         td = curthread;
140         opts = mp->mnt_optnew;
141
142         if (vfs_filteropt(opts, ext2_opts))
143                 return (EINVAL);
144
145         vfs_getopt(opts, "fspath", (void **)&path, NULL);
146         /* Double-check the length of path.. */
147         if (strlen(path) >= MAXMNTLEN - 1)
148                 return (ENAMETOOLONG);
149
150         fspec = NULL;
151         error = vfs_getopt(opts, "from", (void **)&fspec, &len);
152         if (!error && fspec[len - 1] != '\0')
153                 return (EINVAL);
154
155         /*
156          * If updating, check whether changing from read-only to
157          * read/write; if there is no device name, that's all we do.
158          */
159         if (mp->mnt_flag & MNT_UPDATE) {
160                 ump = VFSTOEXT2(mp);
161                 fs = ump->um_e2fs;
162                 error = 0;
163                 if (fs->s_rd_only == 0 &&
164                     vfs_flagopt(opts, "ro", NULL, 0)) {
165                         error = VFS_SYNC(mp, MNT_WAIT);
166                         if (error)
167                                 return (error);
168                         flags = WRITECLOSE;
169                         if (mp->mnt_flag & MNT_FORCE)
170                                 flags |= FORCECLOSE;
171                         if (vfs_busy(mp, MBF_NOWAIT))
172                                 return (EBUSY);
173                         error = ext2_flushfiles(mp, flags, td);
174                         vfs_unbusy(mp);
175                         if (!error && fs->s_wasvalid) {
176                                 fs->s_es->s_state |= EXT2_VALID_FS;
177                                 ext2_sbupdate(ump, MNT_WAIT);
178                         }
179                         fs->s_rd_only = 1;
180                         vfs_flagopt(opts, "ro", &mp->mnt_flag, MNT_RDONLY);
181                         DROP_GIANT();
182                         g_topology_lock();
183                         g_access(ump->um_cp, 0, -1, 0);
184                         g_topology_unlock();
185                         PICKUP_GIANT();
186                 }
187                 if (!error && (mp->mnt_flag & MNT_RELOAD))
188                         error = ext2_reload(mp, td);
189                 if (error)
190                         return (error);
191                 devvp = ump->um_devvp;
192                 if (fs->s_rd_only && !vfs_flagopt(opts, "ro", NULL, 0)) {
193                         if (ext2_check_sb_compat(fs->s_es, devvp->v_rdev, 0))
194                                 return (EPERM);
195
196                         /*
197                          * If upgrade to read-write by non-root, then verify
198                          * that user has necessary permissions on the device.
199                          */
200                         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
201                         error = VOP_ACCESS(devvp, VREAD | VWRITE,
202                             td->td_ucred, td);
203                         if (error)
204                                 error = priv_check(td, PRIV_VFS_MOUNT_PERM);
205                         if (error) {
206                                 VOP_UNLOCK(devvp, 0);
207                                 return (error);
208                         }
209                         VOP_UNLOCK(devvp, 0);
210                         DROP_GIANT();
211                         g_topology_lock();
212                         error = g_access(ump->um_cp, 0, 1, 0);
213                         g_topology_unlock();
214                         PICKUP_GIANT();
215                         if (error)
216                                 return (error);
217
218                         if ((fs->s_es->s_state & EXT2_VALID_FS) == 0 ||
219                             (fs->s_es->s_state & EXT2_ERROR_FS)) {
220                                 if (mp->mnt_flag & MNT_FORCE) {
221                                         printf(
222 "WARNING: %s was not properly dismounted\n", fs->fs_fsmnt);
223                                 } else {
224                                         printf(
225 "WARNING: R/W mount of %s denied.  Filesystem is not clean - run fsck\n",
226                                             fs->fs_fsmnt);
227                                         return (EPERM);
228                                 }
229                         }
230                         fs->s_es->s_state &= ~EXT2_VALID_FS;
231                         ext2_sbupdate(ump, MNT_WAIT);
232                         fs->s_rd_only = 0;
233                         MNT_ILOCK(mp);
234                         mp->mnt_flag &= ~MNT_RDONLY;
235                         MNT_IUNLOCK(mp);
236                 }
237                 if (vfs_flagopt(opts, "export", NULL, 0)) {
238                         /* Process export requests in vfs_mount.c. */
239                         return (error);
240                 }
241         }
242
243         /*
244          * Not an update, or updating the name: look up the name
245          * and verify that it refers to a sensible disk device.
246          */
247         if (fspec == NULL)
248                 return (EINVAL);
249         NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspec, td);
250         if ((error = namei(ndp)) != 0)
251                 return (error);
252         NDFREE(ndp, NDF_ONLY_PNBUF);
253         devvp = ndp->ni_vp;
254
255         if (!vn_isdisk(devvp, &error)) {
256                 vput(devvp);
257                 return (error);
258         }
259
260         /*
261          * If mount by non-root, then verify that user has necessary
262          * permissions on the device.
263          *
264          * XXXRW: VOP_ACCESS() enough?
265          */
266         accmode = VREAD;
267         if ((mp->mnt_flag & MNT_RDONLY) == 0)
268                 accmode |= VWRITE;
269         error = VOP_ACCESS(devvp, accmode, td->td_ucred, td);
270         if (error)
271                 error = priv_check(td, PRIV_VFS_MOUNT_PERM);
272         if (error) {
273                 vput(devvp);
274                 return (error);
275         }
276
277         if ((mp->mnt_flag & MNT_UPDATE) == 0) {
278                 error = ext2_mountfs(devvp, mp);
279         } else {
280                 if (devvp != ump->um_devvp) {
281                         vput(devvp);
282                         return (EINVAL);        /* needs translation */
283                 } else
284                         vput(devvp);
285         }
286         if (error) {
287                 vrele(devvp);
288                 return (error);
289         }
290         ump = VFSTOEXT2(mp);
291         fs = ump->um_e2fs;
292
293         /*
294          * Note that this strncpy() is ok because of a check at the start
295          * of ext2_mount().
296          */
297         strncpy(fs->fs_fsmnt, path, MAXMNTLEN);
298         fs->fs_fsmnt[MAXMNTLEN - 1] = '\0';
299         vfs_mountedfrom(mp, fspec);
300         return (0);
301 }
302
303 /*
304  * Checks that the data in the descriptor blocks make sense
305  * this is taken from ext2/super.c.
306  */
307 static int
308 ext2_check_descriptors(struct ext2_sb_info *sb)
309 {
310         struct ext2_group_desc *gdp = NULL;
311         unsigned long block = sb->s_es->s_first_data_block;
312         int desc_block = 0;
313         int i;
314
315         for (i = 0; i < sb->s_groups_count; i++) {
316                 /* examine next descriptor block */
317                 if ((i % EXT2_DESC_PER_BLOCK(sb)) == 0)
318                         gdp = (struct ext2_group_desc *)
319                             sb->s_group_desc[desc_block++]->b_data;
320                 if (gdp->bg_block_bitmap < block ||
321                     gdp->bg_block_bitmap >= block + EXT2_BLOCKS_PER_GROUP(sb)) {
322                         printf ("ext2_check_descriptors: "
323                             "Block bitmap for group %d"
324                             " not in group (block %lu)!\n",
325                             i, (unsigned long) gdp->bg_block_bitmap);
326                         return (0);
327                 }
328                 if (gdp->bg_inode_bitmap < block ||
329                     gdp->bg_inode_bitmap >= block + EXT2_BLOCKS_PER_GROUP(sb)) {
330                         printf ("ext2_check_descriptors: "
331                             "Inode bitmap for group %d"
332                             " not in group (block %lu)!\n",
333                             i, (unsigned long) gdp->bg_inode_bitmap);
334                         return (0);
335                 }
336                 if (gdp->bg_inode_table < block ||
337                     gdp->bg_inode_table + sb->s_itb_per_group >=
338                     block + EXT2_BLOCKS_PER_GROUP(sb)) {
339                         printf ("ext2_check_descriptors: "
340                             "Inode table for group %d"
341                             " not in group (block %lu)!\n",
342                             i, (unsigned long) gdp->bg_inode_table);
343                         return (0);
344                 }
345                 block += EXT2_BLOCKS_PER_GROUP(sb);
346                 gdp++;
347         }
348         return (1);
349 }
350
351 static int
352 ext2_check_sb_compat(struct ext2_super_block *es, struct cdev *dev, int ronly)
353 {
354
355         if (es->s_magic != EXT2_SUPER_MAGIC) {
356                 printf("ext2fs: %s: wrong magic number %#x (expected %#x)\n",
357                     devtoname(dev), es->s_magic, EXT2_SUPER_MAGIC);
358                 return (1);
359         }
360         if (es->s_rev_level > EXT2_GOOD_OLD_REV) {
361                 if (es->s_feature_incompat & ~EXT2_FEATURE_INCOMPAT_SUPP) {
362                         printf(
363 "WARNING: mount of %s denied due to unsupported optional features\n",
364                             devtoname(dev));
365                         return (1);
366                 }
367                 if (!ronly &&
368                     (es->s_feature_ro_compat & ~EXT2_FEATURE_RO_COMPAT_SUPP)) {
369                         printf("WARNING: R/W mount of %s denied due to "
370                             "unsupported optional features\n", devtoname(dev));
371                         return (1);
372                 }
373         }
374         return (0);
375 }
376
377 /*
378  * This computes the fields of the  ext2_sb_info structure from the
379  * data in the ext2_super_block structure read in.
380  */
381 static int
382 compute_sb_data(struct vnode *devvp, struct ext2_super_block *es,
383     struct ext2_sb_info *fs)
384 {
385         int db_count, error;
386         int i, j;
387         int logic_sb_block = 1; /* XXX for now */
388
389         fs->s_blocksize = EXT2_MIN_BLOCK_SIZE << es->s_log_block_size;
390         fs->s_bshift = EXT2_MIN_BLOCK_LOG_SIZE + es->s_log_block_size;
391         fs->s_fsbtodb = es->s_log_block_size + 1;
392         fs->s_qbmask = fs->s_blocksize - 1;
393         fs->s_blocksize_bits = es->s_log_block_size + 10;
394         fs->s_frag_size = EXT2_MIN_FRAG_SIZE << es->s_log_frag_size;
395         if (fs->s_frag_size)
396                 fs->s_frags_per_block = fs->s_blocksize / fs->s_frag_size;
397         fs->s_blocks_per_group = es->s_blocks_per_group;
398         fs->s_frags_per_group = es->s_frags_per_group;
399         fs->s_inodes_per_group = es->s_inodes_per_group;
400         if (es->s_rev_level == EXT2_GOOD_OLD_REV) {
401                 fs->s_first_ino = EXT2_GOOD_OLD_FIRST_INO;
402                 fs->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
403         } else {
404                 fs->s_first_ino = es->s_first_ino;
405                 fs->s_inode_size = es->s_inode_size;
406
407                 /*
408                  * Simple sanity check for superblock inode size value.
409                  */
410                 if (fs->s_inode_size < EXT2_GOOD_OLD_INODE_SIZE ||
411                     fs->s_inode_size > fs->s_blocksize ||
412                     (fs->s_inode_size & (fs->s_inode_size - 1)) != 0) {
413                         printf("EXT2-fs: invalid inode size %d\n",
414                             fs->s_inode_size);
415                         return (EIO);
416                 }
417         }
418         fs->s_inodes_per_block = fs->s_blocksize / EXT2_INODE_SIZE(fs);
419         fs->s_itb_per_group = fs->s_inodes_per_group /fs->s_inodes_per_block;
420         fs->s_desc_per_block = fs->s_blocksize / sizeof (struct ext2_group_desc);
421         /* s_resuid / s_resgid ? */
422         fs->s_groups_count = (es->s_blocks_count - es->s_first_data_block +
423             EXT2_BLOCKS_PER_GROUP(fs) - 1) / EXT2_BLOCKS_PER_GROUP(fs);
424         db_count = (fs->s_groups_count + EXT2_DESC_PER_BLOCK(fs) - 1) /
425             EXT2_DESC_PER_BLOCK(fs);
426         fs->s_gdb_count = db_count;
427         fs->s_group_desc = malloc(db_count * sizeof (struct buf *),
428             M_EXT2MNT, M_WAITOK);
429
430         /*
431          * Adjust logic_sb_block.
432          * Godmar thinks: if the blocksize is greater than 1024, then
433          * the superblock is logically part of block zero.
434          */
435         if(fs->s_blocksize > SBSIZE)
436                 logic_sb_block = 0;
437
438         for (i = 0; i < db_count; i++) {
439                 error = bread(devvp , fsbtodb(fs, logic_sb_block + i + 1),
440                     fs->s_blocksize, NOCRED, &fs->s_group_desc[i]);
441                 if(error) {
442                         for (j = 0; j < i; j++)
443                                 brelse(fs->s_group_desc[j]);
444                         free(fs->s_group_desc, M_EXT2MNT);
445                         printf("EXT2-fs: unable to read group descriptors"
446                             " (%d)\n", error);
447                         return (EIO);
448                 }
449                 LCK_BUF(fs->s_group_desc[i])
450         }
451         if(!ext2_check_descriptors(fs)) {
452                 for (j = 0; j < db_count; j++)
453                         ULCK_BUF(fs->s_group_desc[j])
454                 free(fs->s_group_desc, M_EXT2MNT);
455                 printf("EXT2-fs: (ext2_check_descriptors failure) "
456                     "unable to read group descriptors\n");
457                 return (EIO);
458         }
459         for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) {
460                 fs->s_inode_bitmap_number[i] = 0;
461                 fs->s_inode_bitmap[i] = NULL;
462                 fs->s_block_bitmap_number[i] = 0;
463                 fs->s_block_bitmap[i] = NULL;
464         }
465         fs->s_loaded_inode_bitmaps = 0;
466         fs->s_loaded_block_bitmaps = 0;
467         if (es->s_rev_level == EXT2_GOOD_OLD_REV ||
468             (es->s_feature_ro_compat & EXT2_FEATURE_RO_COMPAT_LARGE_FILE) == 0)
469                 fs->fs_maxfilesize = 0x7fffffff;
470         else
471                 fs->fs_maxfilesize = 0x7fffffffffffffff;
472         return (0);
473 }
474
475 /*
476  * Reload all incore data for a filesystem (used after running fsck on
477  * the root filesystem and finding things to fix). The filesystem must
478  * be mounted read-only.
479  *
480  * Things to do to update the mount:
481  *      1) invalidate all cached meta-data.
482  *      2) re-read superblock from disk.
483  *      3) re-read summary information from disk.
484  *      4) invalidate all inactive vnodes.
485  *      5) invalidate all cached file data.
486  *      6) re-read inode data for all active vnodes.
487  */
488 static int
489 ext2_reload(struct mount *mp, struct thread *td)
490 {
491         struct vnode *vp, *mvp, *devvp;
492         struct inode *ip;
493         struct buf *bp;
494         struct ext2_super_block *es;
495         struct ext2_sb_info *fs;
496         int error;
497
498         if ((mp->mnt_flag & MNT_RDONLY) == 0)
499                 return (EINVAL);
500         /*
501          * Step 1: invalidate all cached meta-data.
502          */
503         devvp = VFSTOEXT2(mp)->um_devvp;
504         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
505         if (vinvalbuf(devvp, 0, 0, 0) != 0)
506                 panic("ext2_reload: dirty1");
507         VOP_UNLOCK(devvp, 0);
508
509         /*
510          * Step 2: re-read superblock from disk.
511          * constants have been adjusted for ext2
512          */
513         if ((error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) != 0)
514                 return (error);
515         es = (struct ext2_super_block *)bp->b_data;
516         if (ext2_check_sb_compat(es, devvp->v_rdev, 0) != 0) {
517                 brelse(bp);
518                 return (EIO);           /* XXX needs translation */
519         }
520         fs = VFSTOEXT2(mp)->um_e2fs;
521         bcopy(bp->b_data, fs->s_es, sizeof(struct ext2_super_block));
522
523         if((error = compute_sb_data(devvp, es, fs)) != 0) {
524                 brelse(bp);
525                 return (error);
526         }
527 #ifdef UNKLAR
528         if (fs->fs_sbsize < SBSIZE)
529                 bp->b_flags |= B_INVAL;
530 #endif
531         brelse(bp);
532
533 loop:
534         MNT_ILOCK(mp);
535         MNT_VNODE_FOREACH(vp, mp, mvp) {
536                 VI_LOCK(vp);
537                 if (vp->v_iflag & VI_DOOMED) {
538                         VI_UNLOCK(vp);
539                         continue;
540                 }
541                 MNT_IUNLOCK(mp);
542                 /*
543                  * Step 4: invalidate all cached file data.
544                  */
545                 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
546                         MNT_VNODE_FOREACH_ABORT(mp, mvp);
547                         goto loop;
548                 }
549                 if (vinvalbuf(vp, 0, 0, 0))
550                         panic("ext2_reload: dirty2");
551
552                 /*
553                  * Step 5: re-read inode data for all active vnodes.
554                  */
555                 ip = VTOI(vp);
556                 error = bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
557                     (int)fs->s_blocksize, NOCRED, &bp);
558                 if (error) {
559                         VOP_UNLOCK(vp, 0);
560                         vrele(vp);
561                         MNT_VNODE_FOREACH_ABORT(mp, mvp);
562                         return (error);
563                 }
564                 ext2_ei2i((struct ext2_inode *) ((char *)bp->b_data +
565                     EXT2_INODE_SIZE(fs) * ino_to_fsbo(fs, ip->i_number)), ip);
566                 brelse(bp);
567                 VOP_UNLOCK(vp, 0);
568                 vrele(vp);
569                 MNT_ILOCK(mp);
570         }
571         MNT_IUNLOCK(mp);
572         return (0);
573 }
574
575 /*
576  * Common code for mount and mountroot.
577  */
578 static int
579 ext2_mountfs(struct vnode *devvp, struct mount *mp)
580 {
581         struct ext2mount *ump;
582         struct buf *bp;
583         struct ext2_sb_info *fs;
584         struct ext2_super_block *es;
585         struct cdev *dev = devvp->v_rdev;
586         struct g_consumer *cp;
587         struct bufobj *bo;
588         int error;
589         int ronly;
590
591         ronly = vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0);
592         /* XXX: use VOP_ACESS to check FS perms */
593         DROP_GIANT();
594         g_topology_lock();
595         error = g_vfs_open(devvp, &cp, "ext2fs", ronly ? 0 : 1);
596         g_topology_unlock();
597         PICKUP_GIANT();
598         VOP_UNLOCK(devvp, 0);
599         if (error)
600                 return (error);
601
602         /* XXX: should we check for some sectorsize or 512 instead? */
603         if (((SBSIZE % cp->provider->sectorsize) != 0) ||
604             (SBSIZE < cp->provider->sectorsize)) {
605                 DROP_GIANT();
606                 g_topology_lock();
607                 g_vfs_close(cp);
608                 g_topology_unlock();
609                 PICKUP_GIANT();
610                 return (EINVAL);
611         }
612
613         bo = &devvp->v_bufobj;
614         bo->bo_private = cp;
615         bo->bo_ops = g_vfs_bufops;
616         if (devvp->v_rdev->si_iosize_max != 0)
617                 mp->mnt_iosize_max = devvp->v_rdev->si_iosize_max;
618         if (mp->mnt_iosize_max > MAXPHYS)
619                 mp->mnt_iosize_max = MAXPHYS;
620
621         bp = NULL;
622         ump = NULL;
623         if ((error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) != 0)
624                 goto out;
625         es = (struct ext2_super_block *)bp->b_data;
626         if (ext2_check_sb_compat(es, dev, ronly) != 0) {
627                 error = EINVAL;         /* XXX needs translation */
628                 goto out;
629         }
630         if ((es->s_state & EXT2_VALID_FS) == 0 ||
631             (es->s_state & EXT2_ERROR_FS)) {
632                 if (ronly || (mp->mnt_flag & MNT_FORCE)) {
633                         printf(
634 "WARNING: Filesystem was not properly dismounted\n");
635                 } else {
636                         printf(
637 "WARNING: R/W mount denied.  Filesystem is not clean - run fsck\n");
638                         error = EPERM;
639                         goto out;
640                 }
641         }
642         ump = malloc(sizeof *ump, M_EXT2MNT, M_WAITOK);
643         bzero((caddr_t)ump, sizeof *ump);
644
645         /*
646          * I don't know whether this is the right strategy. Note that
647          * we dynamically allocate both an ext2_sb_info and an ext2_super_block
648          * while Linux keeps the super block in a locked buffer.
649          */
650         ump->um_e2fs = malloc(sizeof(struct ext2_sb_info),
651                 M_EXT2MNT, M_WAITOK);
652         ump->um_e2fs->s_es = malloc(sizeof(struct ext2_super_block),
653                 M_EXT2MNT, M_WAITOK);
654         bcopy(es, ump->um_e2fs->s_es, (u_int)sizeof(struct ext2_super_block));
655         if ((error = compute_sb_data(devvp, ump->um_e2fs->s_es, ump->um_e2fs)))
656                 goto out;
657
658         /*
659          * We don't free the group descriptors allocated by compute_sb_data()
660          * until ext2_unmount().  This is OK since the mount will succeed.
661          */
662         brelse(bp);
663         bp = NULL;
664         fs = ump->um_e2fs;
665         fs->s_rd_only = ronly;  /* ronly is set according to mnt_flags */
666
667         /*
668          * If the fs is not mounted read-only, make sure the super block is
669          * always written back on a sync().
670          */
671         fs->s_wasvalid = fs->s_es->s_state & EXT2_VALID_FS ? 1 : 0;
672         if (ronly == 0) {
673                 fs->s_dirt = 1;         /* mark it modified */
674                 fs->s_es->s_state &= ~EXT2_VALID_FS;    /* set fs invalid */
675         }
676         mp->mnt_data = ump;
677         mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
678         mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
679         mp->mnt_maxsymlinklen = EXT2_MAXSYMLINKLEN;
680         MNT_ILOCK(mp);
681         mp->mnt_flag |= MNT_LOCAL;
682         MNT_IUNLOCK(mp);
683         ump->um_mountp = mp;
684         ump->um_dev = dev;
685         ump->um_devvp = devvp;
686         ump->um_bo = &devvp->v_bufobj;
687         ump->um_cp = cp;
688
689         /*
690          * Setting those two parameters allowed us to use
691          * ufs_bmap w/o changse!
692          */
693         ump->um_nindir = EXT2_ADDR_PER_BLOCK(fs);
694         ump->um_bptrtodb = fs->s_es->s_log_block_size + 1;
695         ump->um_seqinc = EXT2_FRAGS_PER_BLOCK(fs);
696         if (ronly == 0)
697                 ext2_sbupdate(ump, MNT_WAIT);
698         return (0);
699 out:
700         if (bp)
701                 brelse(bp);
702         if (cp != NULL) {
703                 DROP_GIANT();
704                 g_topology_lock();
705                 g_vfs_close(cp);
706                 g_topology_unlock();
707                 PICKUP_GIANT();
708         }
709         if (ump) {
710                 free(ump->um_e2fs->s_es, M_EXT2MNT);
711                 free(ump->um_e2fs, M_EXT2MNT);
712                 free(ump, M_EXT2MNT);
713                 mp->mnt_data = NULL;
714         }
715         return (error);
716 }
717
718 /*
719  * Unmount system call.
720  */
721 static int
722 ext2_unmount(struct mount *mp, int mntflags)
723 {
724         struct ext2mount *ump;
725         struct ext2_sb_info *fs;
726         int error, flags, ronly, i;
727
728         flags = 0;
729         if (mntflags & MNT_FORCE) {
730                 if (mp->mnt_flag & MNT_ROOTFS)
731                         return (EINVAL);
732                 flags |= FORCECLOSE;
733         }
734         if ((error = ext2_flushfiles(mp, flags, curthread)) != 0)
735                 return (error);
736         ump = VFSTOEXT2(mp);
737         fs = ump->um_e2fs;
738         ronly = fs->s_rd_only;
739         if (ronly == 0) {
740                 if (fs->s_wasvalid)
741                         fs->s_es->s_state |= EXT2_VALID_FS;
742                 ext2_sbupdate(ump, MNT_WAIT);
743         }
744
745         /* release buffers containing group descriptors */
746         for(i = 0; i < fs->s_gdb_count; i++)
747                 ULCK_BUF(fs->s_group_desc[i])
748         free(fs->s_group_desc, M_EXT2MNT);
749
750         /* release cached inode/block bitmaps */
751         for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++)
752                 if (fs->s_inode_bitmap[i])
753                     ULCK_BUF(fs->s_inode_bitmap[i])
754         for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++)
755                 if (fs->s_block_bitmap[i])
756                     ULCK_BUF(fs->s_block_bitmap[i])
757
758         DROP_GIANT();
759         g_topology_lock();
760         g_vfs_close(ump->um_cp);
761         g_topology_unlock();
762         PICKUP_GIANT();
763         vrele(ump->um_devvp);
764         free(fs->s_es, M_EXT2MNT);
765         free(fs, M_EXT2MNT);
766         free(ump, M_EXT2MNT);
767         mp->mnt_data = NULL;
768         MNT_ILOCK(mp);
769         mp->mnt_flag &= ~MNT_LOCAL;
770         MNT_IUNLOCK(mp);
771         return (error);
772 }
773
774 /*
775  * Flush out all the files in a filesystem.
776  */
777 static int
778 ext2_flushfiles(struct mount *mp, int flags, struct thread *td)
779 {
780         int error;
781
782         error = vflush(mp, 0, flags, td);
783         return (error);
784 }
785
786 /*
787  * Get file system statistics.
788  * taken from ext2/super.c ext2_statfs.
789  */
790 static int
791 ext2_statfs(struct mount *mp, struct statfs *sbp)
792 {
793         struct ext2mount *ump;
794         struct ext2_sb_info *fs;
795         struct ext2_super_block *es;
796         unsigned long overhead;
797         int i, nsb;
798
799         ump = VFSTOEXT2(mp);
800         fs = ump->um_e2fs;
801         es = fs->s_es;
802
803         if (es->s_magic != EXT2_SUPER_MAGIC)
804                 panic("ext2_statfs - magic number spoiled");
805
806         /*
807          * Compute the overhead (FS structures)
808          */
809         if (es->s_feature_ro_compat & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) {
810                 nsb = 0;
811                 for (i = 0 ; i < fs->s_groups_count; i++)
812                         if (ext2_group_sparse(i))
813                                 nsb++;
814         } else
815                 nsb = fs->s_groups_count;
816         overhead = es->s_first_data_block +
817         /* Superblocks and block group descriptors: */
818         nsb * (1 + fs->s_gdb_count) +
819         /* Inode bitmap, block bitmap, and inode table: */
820         fs->s_groups_count * (1 + 1 + fs->s_itb_per_group);
821
822         sbp->f_bsize = EXT2_FRAG_SIZE(fs);
823         sbp->f_iosize = EXT2_BLOCK_SIZE(fs);
824         sbp->f_blocks = es->s_blocks_count - overhead;
825         sbp->f_bfree = es->s_free_blocks_count;
826         sbp->f_bavail = sbp->f_bfree - es->s_r_blocks_count;
827         sbp->f_files = es->s_inodes_count;
828         sbp->f_ffree = es->s_free_inodes_count;
829         return (0);
830 }
831
832 /*
833  * Go through the disk queues to initiate sandbagged IO;
834  * go through the inodes to write those that have been modified;
835  * initiate the writing of the super block if it has been modified.
836  *
837  * Note: we are always called with the filesystem marked `MPBUSY'.
838  */
839 static int
840 ext2_sync(struct mount *mp, int waitfor)
841 {
842         struct vnode *mvp, *vp;
843         struct thread *td;
844         struct inode *ip;
845         struct ext2mount *ump = VFSTOEXT2(mp);
846         struct ext2_sb_info *fs;
847         int error, allerror = 0;
848
849         td = curthread;
850         fs = ump->um_e2fs;
851         if (fs->s_dirt != 0 && fs->s_rd_only != 0) {            /* XXX */
852                 printf("fs = %s\n", fs->fs_fsmnt);
853                 panic("ext2_sync: rofs mod");
854         }
855
856         /*
857          * Write back each (modified) inode.
858          */
859         MNT_ILOCK(mp);
860 loop:
861         MNT_VNODE_FOREACH(vp, mp, mvp) {
862                 VI_LOCK(vp);
863                 if (vp->v_type == VNON || (vp->v_iflag & VI_DOOMED)) {
864                         VI_UNLOCK(vp);
865                         continue;
866                 }
867                 MNT_IUNLOCK(mp);
868                 ip = VTOI(vp);
869                 if ((ip->i_flag &
870                     (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
871                     (vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
872                     waitfor == MNT_LAZY)) {
873                         VI_UNLOCK(vp);
874                         MNT_ILOCK(mp);
875                         continue;
876                 }
877                 error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, td);
878                 if (error) {
879                         MNT_ILOCK(mp);
880                         if (error == ENOENT) {
881                                 MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp);
882                                 goto loop;
883                         }
884                         continue;
885                 }
886                 if ((error = VOP_FSYNC(vp, waitfor, td)) != 0)
887                         allerror = error;
888                 VOP_UNLOCK(vp, 0);
889                 vrele(vp);
890                 MNT_ILOCK(mp);
891         }
892         MNT_IUNLOCK(mp);
893
894         /*
895          * Force stale file system control information to be flushed.
896          */
897         if (waitfor != MNT_LAZY) {
898                 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
899                 if ((error = VOP_FSYNC(ump->um_devvp, waitfor, td)) != 0)
900                         allerror = error;
901                 VOP_UNLOCK(ump->um_devvp, 0);
902         }
903
904         /*
905          * Write back modified superblock.
906          */
907         if (fs->s_dirt != 0) {
908                 fs->s_dirt = 0;
909                 fs->s_es->s_wtime = time_second;
910                 if ((error = ext2_sbupdate(ump, waitfor)) != 0)
911                         allerror = error;
912         }
913         return (allerror);
914 }
915
916 /*
917  * Look up an EXT2FS dinode number to find its incore vnode, otherwise read it
918  * in from disk.  If it is in core, wait for the lock bit to clear, then
919  * return the inode locked.  Detection and handling of mount points must be
920  * done by the calling routine.
921  */
922 static int
923 ext2_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
924 {
925         struct ext2_sb_info *fs;
926         struct inode *ip;
927         struct ext2mount *ump;
928         struct buf *bp;
929         struct vnode *vp;
930         struct cdev *dev;
931         struct thread *td;
932         int i, error;
933         int used_blocks;
934
935         td = curthread;
936         error = vfs_hash_get(mp, ino, flags, td, vpp, NULL, NULL);
937         if (error || *vpp != NULL)
938                 return (error);
939
940         ump = VFSTOEXT2(mp);
941         dev = ump->um_dev;
942
943         /*
944          * If this malloc() is performed after the getnewvnode()
945          * it might block, leaving a vnode with a NULL v_data to be
946          * found by ext2_sync() if a sync happens to fire right then,
947          * which will cause a panic because ext2_sync() blindly
948          * dereferences vp->v_data (as well it should).
949          */
950         ip = malloc(sizeof(struct inode), M_EXT2NODE, M_WAITOK | M_ZERO);
951
952         /* Allocate a new vnode/inode. */
953         if ((error = getnewvnode("ext2fs", mp, &ext2_vnodeops, &vp)) != 0) {
954                 *vpp = NULL;
955                 free(ip, M_EXT2NODE);
956                 return (error);
957         }
958         vp->v_data = ip;
959         ip->i_vnode = vp;
960         ip->i_e2fs = fs = ump->um_e2fs;
961         ip->i_number = ino;
962
963         lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL);
964         error = insmntque(vp, mp);
965         if (error != 0) {
966                 free(ip, M_EXT2NODE);
967                 *vpp = NULL;
968                 return (error);
969         }
970         error = vfs_hash_insert(vp, ino, flags, td, vpp, NULL, NULL);
971         if (error || *vpp != NULL)
972                 return (error);
973
974         /* Read in the disk contents for the inode, copy into the inode. */
975         if ((error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
976             (int)fs->s_blocksize, NOCRED, &bp)) != 0) {
977                 /*
978                  * The inode does not contain anything useful, so it would
979                  * be misleading to leave it on its hash chain. With mode
980                  * still zero, it will be unlinked and returned to the free
981                  * list by vput().
982                  */
983                 vput(vp);
984                 brelse(bp);
985                 *vpp = NULL;
986                 return (error);
987         }
988         /* convert ext2 inode to dinode */
989         ext2_ei2i((struct ext2_inode *) ((char *)bp->b_data + EXT2_INODE_SIZE(fs) *
990                         ino_to_fsbo(fs, ino)), ip);
991         ip->i_block_group = ino_to_cg(fs, ino);
992         ip->i_next_alloc_block = 0;
993         ip->i_next_alloc_goal = 0;
994         ip->i_prealloc_count = 0;
995         ip->i_prealloc_block = 0;
996
997         /*
998          * Now we want to make sure that block pointers for unused
999          * blocks are zeroed out - ext2_balloc depends on this
1000          * although for regular files and directories only
1001          */
1002         if(S_ISDIR(ip->i_mode) || S_ISREG(ip->i_mode)) {
1003                 used_blocks = (ip->i_size+fs->s_blocksize-1) / fs->s_blocksize;
1004                 for(i = used_blocks; i < EXT2_NDIR_BLOCKS; i++)
1005                         ip->i_db[i] = 0;
1006         }
1007 /*
1008         ext2_print_inode(ip);
1009 */
1010         brelse(bp);
1011
1012         /*
1013          * Initialize the vnode from the inode, check for aliases.
1014          * Note that the underlying vnode may have changed.
1015          */
1016         if ((error = ext2_vinit(mp, &ext2_fifoops, &vp)) != 0) {
1017                 vput(vp);
1018                 *vpp = NULL;
1019                 return (error);
1020         }
1021
1022         /*
1023          * Finish inode initialization now that aliasing has been resolved.
1024          */
1025         ip->i_devvp = ump->um_devvp;
1026
1027         /*
1028          * Set up a generation number for this inode if it does not
1029          * already have one. This should only happen on old filesystems.
1030          */
1031         if (ip->i_gen == 0) {
1032                 ip->i_gen = random() / 2 + 1;
1033                 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
1034                         ip->i_flag |= IN_MODIFIED;
1035         }
1036         *vpp = vp;
1037         return (0);
1038 }
1039
1040 /*
1041  * File handle to vnode
1042  *
1043  * Have to be really careful about stale file handles:
1044  * - check that the inode number is valid
1045  * - call ext2_vget() to get the locked inode
1046  * - check for an unallocated inode (i_mode == 0)
1047  * - check that the given client host has export rights and return
1048  *   those rights via. exflagsp and credanonp
1049  */
1050 static int
1051 ext2_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
1052 {
1053         struct inode *ip;
1054         struct ufid *ufhp;
1055         struct vnode *nvp;
1056         struct ext2_sb_info *fs;
1057         int error;
1058
1059         ufhp = (struct ufid *)fhp;
1060         fs = VFSTOEXT2(mp)->um_e2fs;
1061         if (ufhp->ufid_ino < ROOTINO ||
1062             ufhp->ufid_ino > fs->s_groups_count * fs->s_es->s_inodes_per_group)
1063                 return (ESTALE);
1064
1065         error = VFS_VGET(mp, ufhp->ufid_ino, LK_EXCLUSIVE, &nvp);
1066         if (error) {
1067                 *vpp = NULLVP;
1068                 return (error);
1069         }
1070         ip = VTOI(nvp);
1071         if (ip->i_mode == 0 ||
1072             ip->i_gen != ufhp->ufid_gen || ip->i_nlink <= 0) {
1073                 vput(nvp);
1074                 *vpp = NULLVP;
1075                 return (ESTALE);
1076         }
1077         *vpp = nvp;
1078         vnode_create_vobject(*vpp, 0, curthread);
1079         return (0);
1080 }
1081
1082 /*
1083  * Write a superblock and associated information back to disk.
1084  */
1085 static int
1086 ext2_sbupdate(struct ext2mount *mp, int waitfor)
1087 {
1088         struct ext2_sb_info *fs = mp->um_e2fs;
1089         struct ext2_super_block *es = fs->s_es;
1090         struct buf *bp;
1091         int error = 0;
1092
1093         bp = getblk(mp->um_devvp, SBLOCK, SBSIZE, 0, 0, 0);
1094         bcopy((caddr_t)es, bp->b_data, (u_int)sizeof(struct ext2_super_block));
1095         if (waitfor == MNT_WAIT)
1096                 error = bwrite(bp);
1097         else
1098                 bawrite(bp);
1099
1100         /*
1101          * The buffers for group descriptors, inode bitmaps and block bitmaps
1102          * are not busy at this point and are (hopefully) written by the
1103          * usual sync mechanism. No need to write them here.
1104          */
1105         return (error);
1106 }
1107
1108 /*
1109  * Return the root of a filesystem.
1110  */
1111 static int
1112 ext2_root(struct mount *mp, int flags, struct vnode **vpp)
1113 {
1114         struct vnode *nvp;
1115         int error;
1116
1117         error = VFS_VGET(mp, (ino_t)ROOTINO, LK_EXCLUSIVE, &nvp);
1118         if (error)
1119                 return (error);
1120         *vpp = nvp;
1121         return (0);
1122 }