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