1 /* $OpenBSD: ext2fs_vfsops.c,v 1.97 2016/09/15 02:00:18 dlg Exp $ */ 2 /* $NetBSD: ext2fs_vfsops.c,v 1.1 1997/06/11 09:34:07 bouyer Exp $ */ 3 4 /* 5 * Copyright (c) 1997 Manuel Bouyer. 6 * Copyright (c) 1989, 1991, 1993, 1994 7 * The Regents of the University of California. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)ffs_vfsops.c 8.14 (Berkeley) 11/28/94 34 * Modified for ext2fs by Manuel Bouyer. 35 */ 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/namei.h> 40 #include <sys/proc.h> 41 #include <sys/kernel.h> 42 #include <sys/vnode.h> 43 #include <sys/socket.h> 44 #include <sys/mount.h> 45 #include <sys/buf.h> 46 #include <sys/disk.h> 47 #include <sys/mbuf.h> 48 #include <sys/file.h> 49 #include <sys/disklabel.h> 50 #include <sys/ioctl.h> 51 #include <sys/errno.h> 52 #include <sys/malloc.h> 53 #include <sys/pool.h> 54 #include <sys/lock.h> 55 #include <sys/dkio.h> 56 #include <sys/specdev.h> 57 58 #include <ufs/ufs/quota.h> 59 #include <ufs/ufs/ufsmount.h> 60 #include <ufs/ufs/inode.h> 61 #include <ufs/ufs/dir.h> 62 #include <ufs/ufs/ufs_extern.h> 63 64 #include <ufs/ext2fs/ext2fs.h> 65 #include <ufs/ext2fs/ext2fs_extern.h> 66 67 extern struct lock ufs_hashlock; 68 69 int ext2fs_sbupdate(struct ufsmount *, int); 70 static int e2fs_sbcheck(struct ext2fs *, int); 71 72 const struct vfsops ext2fs_vfsops = { 73 ext2fs_mount, 74 ufs_start, 75 ext2fs_unmount, 76 ufs_root, 77 ufs_quotactl, 78 ext2fs_statfs, 79 ext2fs_sync, 80 ext2fs_vget, 81 ext2fs_fhtovp, 82 ext2fs_vptofh, 83 ext2fs_init, 84 ext2fs_sysctl, 85 ufs_check_export 86 }; 87 88 struct pool ext2fs_inode_pool; 89 struct pool ext2fs_dinode_pool; 90 91 extern u_long ext2gennumber; 92 93 int 94 ext2fs_init(struct vfsconf *vfsp) 95 { 96 pool_init(&ext2fs_inode_pool, sizeof(struct inode), 0, 97 IPL_NONE, PR_WAITOK, "ext2inopl", NULL); 98 pool_init(&ext2fs_dinode_pool, sizeof(struct ext2fs_dinode), 0, 99 IPL_NONE, PR_WAITOK, "ext2dinopl", NULL); 100 101 return (ufs_init(vfsp)); 102 } 103 104 /* 105 * Called by main() when ext2fs is going to be mounted as root. 106 * 107 * Name is updated by mount(8) after booting. 108 */ 109 #define ROOTNAME "root_device" 110 111 int 112 ext2fs_mountroot(void) 113 { 114 struct m_ext2fs *fs; 115 struct mount *mp; 116 struct proc *p = curproc; /* XXX */ 117 struct ufsmount *ump; 118 int error; 119 120 /* 121 * Get vnodes for swapdev and rootdev. 122 */ 123 if (bdevvp(swapdev, &swapdev_vp) || bdevvp(rootdev, &rootvp)) 124 panic("ext2fs_mountroot: can't setup bdevvp's"); 125 126 if ((error = vfs_rootmountalloc("ext2fs", "root_device", &mp)) != 0) { 127 vrele(rootvp); 128 return (error); 129 } 130 131 if ((error = ext2fs_mountfs(rootvp, mp, p)) != 0) { 132 mp->mnt_vfc->vfc_refcount--; 133 vfs_unbusy(mp); 134 free(mp, M_MOUNT, sizeof *mp); 135 vrele(rootvp); 136 return (error); 137 } 138 139 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list); 140 ump = VFSTOUFS(mp); 141 fs = ump->um_e2fs; 142 memset(fs->e2fs_fsmnt, 0, sizeof(fs->e2fs_fsmnt)); 143 strlcpy(fs->e2fs_fsmnt, mp->mnt_stat.f_mntonname, sizeof(fs->e2fs_fsmnt)); 144 if (fs->e2fs.e2fs_rev > E2FS_REV0) { 145 memset(fs->e2fs.e2fs_fsmnt, 0, sizeof(fs->e2fs.e2fs_fsmnt)); 146 strlcpy(fs->e2fs.e2fs_fsmnt, mp->mnt_stat.f_mntonname, 147 sizeof(fs->e2fs.e2fs_fsmnt)); 148 } 149 (void)ext2fs_statfs(mp, &mp->mnt_stat, p); 150 vfs_unbusy(mp); 151 inittodr(fs->e2fs.e2fs_wtime); 152 return (0); 153 } 154 155 /* 156 * VFS Operations. 157 * 158 * mount system call 159 */ 160 int 161 ext2fs_mount(struct mount *mp, const char *path, void *data, 162 struct nameidata *ndp, struct proc *p) 163 { 164 struct vnode *devvp; 165 struct ufs_args args; 166 struct ufsmount *ump = NULL; 167 struct m_ext2fs *fs; 168 char fname[MNAMELEN]; 169 char fspec[MNAMELEN]; 170 int error, flags; 171 172 error = copyin(data, &args, sizeof(struct ufs_args)); 173 if (error) 174 return (error); 175 176 /* 177 * If updating, check whether changing from read-only to 178 * read/write; if there is no device name, that's all we do. 179 */ 180 if (mp->mnt_flag & MNT_UPDATE) { 181 ump = VFSTOUFS(mp); 182 fs = ump->um_e2fs; 183 if (fs->e2fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { 184 flags = WRITECLOSE; 185 if (mp->mnt_flag & MNT_FORCE) 186 flags |= FORCECLOSE; 187 error = ext2fs_flushfiles(mp, flags, p); 188 if (error == 0 && 189 ext2fs_cgupdate(ump, MNT_WAIT) == 0 && 190 (fs->e2fs.e2fs_state & E2FS_ERRORS) == 0) { 191 fs->e2fs.e2fs_state = E2FS_ISCLEAN; 192 (void)ext2fs_sbupdate(ump, MNT_WAIT); 193 } 194 if (error) 195 return (error); 196 fs->e2fs_ronly = 1; 197 } 198 if (mp->mnt_flag & MNT_RELOAD) { 199 error = ext2fs_reload(mp, ndp->ni_cnd.cn_cred, p); 200 if (error) 201 return (error); 202 } 203 if (fs->e2fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) { 204 fs->e2fs_ronly = 0; 205 if (fs->e2fs.e2fs_state == E2FS_ISCLEAN) 206 fs->e2fs.e2fs_state = 0; 207 else 208 fs->e2fs.e2fs_state = E2FS_ERRORS; 209 fs->e2fs_fmod = 1; 210 } 211 if (args.fspec == NULL) { 212 /* 213 * Process export requests. 214 */ 215 return (vfs_export(mp, &ump->um_export, 216 &args.export_info)); 217 } 218 } 219 /* 220 * Not an update, or updating the name: look up the name 221 * and verify that it refers to a sensible block device. 222 */ 223 error = copyinstr(args.fspec, fspec, sizeof(fspec), NULL); 224 if (error) 225 goto error; 226 227 if (disk_map(fspec, fname, MNAMELEN, DM_OPENBLCK) == -1) 228 memcpy(fname, fspec, sizeof(fname)); 229 230 NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fname, p); 231 if ((error = namei(ndp)) != 0) 232 goto error; 233 devvp = ndp->ni_vp; 234 235 if (devvp->v_type != VBLK) { 236 error = ENOTBLK; 237 goto error_devvp; 238 } 239 if (major(devvp->v_rdev) >= nblkdev) { 240 error = ENXIO; 241 goto error_devvp; 242 } 243 if ((mp->mnt_flag & MNT_UPDATE) == 0) 244 error = ext2fs_mountfs(devvp, mp, p); 245 else { 246 if (devvp != ump->um_devvp) 247 error = EINVAL; /* XXX needs translation */ 248 else 249 vrele(devvp); 250 } 251 if (error) 252 goto error_devvp; 253 ump = VFSTOUFS(mp); 254 fs = ump->um_e2fs; 255 256 memset(fs->e2fs_fsmnt, 0, sizeof(fs->e2fs_fsmnt)); 257 strlcpy(fs->e2fs_fsmnt, path, sizeof(fs->e2fs_fsmnt)); 258 if (fs->e2fs.e2fs_rev > E2FS_REV0) { 259 memset(fs->e2fs.e2fs_fsmnt, 0, sizeof(fs->e2fs.e2fs_fsmnt)); 260 strlcpy(fs->e2fs.e2fs_fsmnt, mp->mnt_stat.f_mntonname, 261 sizeof(fs->e2fs.e2fs_fsmnt)); 262 } 263 memcpy(mp->mnt_stat.f_mntonname, fs->e2fs_fsmnt, MNAMELEN); 264 memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN); 265 strlcpy(mp->mnt_stat.f_mntfromname, fname, MNAMELEN); 266 memset(mp->mnt_stat.f_mntfromspec, 0, MNAMELEN); 267 strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN); 268 memcpy(&mp->mnt_stat.mount_info.ufs_args, &args, sizeof(args)); 269 270 if (fs->e2fs_fmod != 0) { /* XXX */ 271 fs->e2fs_fmod = 0; 272 if (fs->e2fs.e2fs_state == 0) 273 fs->e2fs.e2fs_wtime = time_second; 274 else 275 printf("%s: file system not clean; please fsck(8)\n", 276 mp->mnt_stat.f_mntfromname); 277 ext2fs_cgupdate(ump, MNT_WAIT); 278 } 279 280 goto success; 281 282 error_devvp: 283 /* Error with devvp held. */ 284 vrele(devvp); 285 286 error: 287 /* Error with no state to backout. */ 288 289 success: 290 return (error); 291 } 292 293 int ext2fs_reload_vnode(struct vnode *, void *args); 294 295 struct ext2fs_reload_args { 296 struct m_ext2fs *fs; 297 struct proc *p; 298 struct ucred *cred; 299 struct vnode *devvp; 300 }; 301 302 int 303 ext2fs_reload_vnode(struct vnode *vp, void *args) 304 { 305 struct ext2fs_reload_args *era = args; 306 struct buf *bp; 307 struct inode *ip; 308 int error; 309 caddr_t cp; 310 311 /* 312 * Step 4: invalidate all inactive vnodes. 313 */ 314 if (vp->v_usecount == 0) { 315 vgonel(vp, era->p); 316 return (0); 317 } 318 319 /* 320 * Step 5: invalidate all cached file data. 321 */ 322 if (vget(vp, LK_EXCLUSIVE, era->p)) 323 return (0); 324 325 if (vinvalbuf(vp, 0, era->cred, era->p, 0, 0)) 326 panic("ext2fs_reload: dirty2"); 327 /* 328 * Step 6: re-read inode data for all active vnodes. 329 */ 330 ip = VTOI(vp); 331 error = bread(era->devvp, 332 fsbtodb(era->fs, ino_to_fsba(era->fs, ip->i_number)), 333 (int)era->fs->e2fs_bsize, &bp); 334 if (error) { 335 vput(vp); 336 return (error); 337 } 338 cp = (caddr_t)bp->b_data + 339 (ino_to_fsbo(era->fs, ip->i_number) * EXT2_DINODE_SIZE(era->fs)); 340 e2fs_iload(era->fs, (struct ext2fs_dinode *)cp, ip->i_e2din); 341 brelse(bp); 342 vput(vp); 343 return (0); 344 } 345 346 static off_t 347 ext2fs_maxfilesize(struct m_ext2fs *fs) 348 { 349 bool huge = fs->e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_HUGE_FILE; 350 off_t b = fs->e2fs_bsize / 4; 351 off_t physically, logically; 352 353 physically = dbtob(huge ? ((1ULL << 48) - 1) : UINT_MAX); 354 logically = (12ULL + b + b*b + b*b*b) * fs->e2fs_bsize; 355 356 return MIN(logically, physically); 357 } 358 359 static int 360 e2fs_sbfill(struct vnode *devvp, struct m_ext2fs *fs) 361 { 362 struct buf *bp = NULL; 363 int i, error; 364 365 /* XXX assume hardware block size == 512 */ 366 fs->e2fs_ncg = howmany(fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock, 367 fs->e2fs.e2fs_bpg); 368 fs->e2fs_fsbtodb = fs->e2fs.e2fs_log_bsize + 1; 369 fs->e2fs_bsize = 1024 << fs->e2fs.e2fs_log_bsize; 370 fs->e2fs_bshift = LOG_MINBSIZE + fs->e2fs.e2fs_log_bsize; 371 fs->e2fs_fsize = 1024 << fs->e2fs.e2fs_log_fsize; 372 373 fs->e2fs_qbmask = fs->e2fs_bsize - 1; 374 fs->e2fs_bmask = ~fs->e2fs_qbmask; 375 376 fs->e2fs_ipb = fs->e2fs_bsize / EXT2_DINODE_SIZE(fs); 377 fs->e2fs_itpg = fs->e2fs.e2fs_ipg / fs->e2fs_ipb; 378 379 /* Re-read group descriptors from the disk. */ 380 fs->e2fs_ngdb = howmany(fs->e2fs_ncg, 381 fs->e2fs_bsize / sizeof(struct ext2_gd)); 382 fs->e2fs_gd = mallocarray(fs->e2fs_ngdb, fs->e2fs_bsize, 383 M_UFSMNT, M_WAITOK); 384 385 for (i = 0; i < fs->e2fs_ngdb; ++i) { 386 daddr_t dblk = ((fs->e2fs_bsize > 1024) ? 0 : 1) + i + 1; 387 size_t gdesc = i * fs->e2fs_bsize / sizeof(struct ext2_gd); 388 struct ext2_gd *gd; 389 390 error = bread(devvp, fsbtodb(fs, dblk), fs->e2fs_bsize, &bp); 391 if (error) { 392 size_t gdescs_space = fs->e2fs_ngdb * fs->e2fs_bsize; 393 394 free(fs->e2fs_gd, M_UFSMNT, gdescs_space); 395 fs->e2fs_gd = NULL; 396 brelse(bp); 397 return (error); 398 } 399 400 gd = (struct ext2_gd *) bp->b_data; 401 e2fs_cgload(gd, fs->e2fs_gd + gdesc, fs->e2fs_bsize); 402 brelse(bp); 403 bp = NULL; 404 } 405 406 if ((fs->e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_LARGEFILE) == 0 || 407 (fs->e2fs.e2fs_rev == E2FS_REV0)) 408 fs->e2fs_maxfilesize = INT_MAX; 409 else 410 fs->e2fs_maxfilesize = ext2fs_maxfilesize(fs); 411 412 if (fs->e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_EXTENTS) 413 fs->e2fs_maxfilesize *= 4; 414 415 return (0); 416 } 417 418 /* 419 * Reload all incore data for a filesystem (used after running fsck on 420 * the root filesystem and finding things to fix). The filesystem must 421 * be mounted read-only. 422 * 423 * Things to do to update the mount: 424 * 1) invalidate all cached meta-data. 425 * 2) re-read superblock from disk. 426 * 3) re-read summary information from disk. 427 * 4) invalidate all inactive vnodes. 428 * 5) invalidate all cached file data. 429 * 6) re-read inode data for all active vnodes. 430 */ 431 int 432 ext2fs_reload(struct mount *mountp, struct ucred *cred, struct proc *p) 433 { 434 struct vnode *devvp; 435 struct buf *bp; 436 struct m_ext2fs *fs; 437 struct ext2fs *newfs; 438 int error; 439 struct ext2fs_reload_args era; 440 441 if ((mountp->mnt_flag & MNT_RDONLY) == 0) 442 return (EINVAL); 443 /* 444 * Step 1: invalidate all cached meta-data. 445 */ 446 devvp = VFSTOUFS(mountp)->um_devvp; 447 if (vinvalbuf(devvp, 0, cred, p, 0, 0)) 448 panic("ext2fs_reload: dirty1"); 449 450 /* 451 * Step 2: re-read superblock from disk. 452 */ 453 error = bread(devvp, (daddr_t)(SBOFF / DEV_BSIZE), SBSIZE, &bp); 454 if (error) { 455 brelse(bp); 456 return (error); 457 } 458 newfs = (struct ext2fs *)bp->b_data; 459 error = e2fs_sbcheck(newfs, (mountp->mnt_flag & MNT_RDONLY)); 460 if (error) { 461 brelse(bp); 462 return (error); 463 } 464 465 fs = VFSTOUFS(mountp)->um_e2fs; 466 /* 467 * Copy in the new superblock, compute in-memory values 468 * and load group descriptors. 469 */ 470 e2fs_sbload(newfs, &fs->e2fs); 471 if ((error = e2fs_sbfill(devvp, fs)) != 0) 472 return (error); 473 474 era.p = p; 475 era.cred = cred; 476 era.fs = fs; 477 era.devvp = devvp; 478 479 error = vfs_mount_foreach_vnode(mountp, ext2fs_reload_vnode, &era); 480 481 return (error); 482 } 483 484 /* 485 * Common code for mount and mountroot 486 */ 487 int 488 ext2fs_mountfs(struct vnode *devvp, struct mount *mp, struct proc *p) 489 { 490 struct ufsmount *ump; 491 struct buf *bp; 492 struct ext2fs *fs; 493 dev_t dev; 494 int error, ronly; 495 struct ucred *cred; 496 497 dev = devvp->v_rdev; 498 cred = p ? p->p_ucred : NOCRED; 499 /* 500 * Disallow multiple mounts of the same device. 501 * Disallow mounting of a device that is currently in use 502 * (except for root, which might share swap device for miniroot). 503 * Flush out any old buffers remaining from a previous use. 504 */ 505 if ((error = vfs_mountedon(devvp)) != 0) 506 return (error); 507 if (vcount(devvp) > 1 && devvp != rootvp) 508 return (EBUSY); 509 if ((error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0)) != 0) 510 return (error); 511 512 ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 513 error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p); 514 if (error) 515 return (error); 516 517 bp = NULL; 518 ump = NULL; 519 520 /* 521 * Read the superblock from disk. 522 */ 523 error = bread(devvp, (daddr_t)(SBOFF / DEV_BSIZE), SBSIZE, &bp); 524 if (error) 525 goto out; 526 fs = (struct ext2fs *)bp->b_data; 527 error = e2fs_sbcheck(fs, ronly); 528 if (error) 529 goto out; 530 531 ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK | M_ZERO); 532 ump->um_e2fs = malloc(sizeof(struct m_ext2fs), M_UFSMNT, 533 M_WAITOK | M_ZERO); 534 535 /* 536 * Copy in the superblock, compute in-memory values 537 * and load group descriptors. 538 */ 539 e2fs_sbload(fs, &ump->um_e2fs->e2fs); 540 if ((error = e2fs_sbfill(devvp, ump->um_e2fs)) != 0) 541 goto out; 542 brelse(bp); 543 bp = NULL; 544 fs = &ump->um_e2fs->e2fs; 545 ump->um_e2fs->e2fs_ronly = ronly; 546 ump->um_fstype = UM_EXT2FS; 547 548 if (ronly == 0) { 549 if (fs->e2fs_state == E2FS_ISCLEAN) 550 fs->e2fs_state = 0; 551 else 552 fs->e2fs_state = E2FS_ERRORS; 553 ump->um_e2fs->e2fs_fmod = 1; 554 } 555 556 mp->mnt_data = ump; 557 mp->mnt_stat.f_fsid.val[0] = (long)dev; 558 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; 559 mp->mnt_stat.f_namemax = MAXNAMLEN; 560 mp->mnt_flag |= MNT_LOCAL; 561 ump->um_mountp = mp; 562 ump->um_dev = dev; 563 ump->um_devvp = devvp; 564 ump->um_nindir = NINDIR(ump->um_e2fs); 565 ump->um_bptrtodb = ump->um_e2fs->e2fs_fsbtodb; 566 ump->um_seqinc = 1; /* no frags */ 567 ump->um_maxsymlinklen = EXT2_MAXSYMLINKLEN; 568 devvp->v_specmountpoint = mp; 569 return (0); 570 out: 571 if (devvp->v_specinfo) 572 devvp->v_specmountpoint = NULL; 573 if (bp) 574 brelse(bp); 575 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); 576 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p); 577 VOP_UNLOCK(devvp, p); 578 if (ump) { 579 free(ump->um_e2fs, M_UFSMNT, sizeof *ump->um_e2fs); 580 free(ump, M_UFSMNT, sizeof *ump); 581 mp->mnt_data = NULL; 582 } 583 return (error); 584 } 585 586 /* 587 * unmount system call 588 */ 589 int 590 ext2fs_unmount(struct mount *mp, int mntflags, struct proc *p) 591 { 592 struct ufsmount *ump; 593 struct m_ext2fs *fs; 594 int error, flags; 595 size_t gdescs_space; 596 597 flags = 0; 598 if (mntflags & MNT_FORCE) 599 flags |= FORCECLOSE; 600 if ((error = ext2fs_flushfiles(mp, flags, p)) != 0) 601 return (error); 602 ump = VFSTOUFS(mp); 603 fs = ump->um_e2fs; 604 gdescs_space = fs->e2fs_ngdb * fs->e2fs_bsize; 605 606 if (!fs->e2fs_ronly && ext2fs_cgupdate(ump, MNT_WAIT) == 0 && 607 (fs->e2fs.e2fs_state & E2FS_ERRORS) == 0) { 608 fs->e2fs.e2fs_state = E2FS_ISCLEAN; 609 (void) ext2fs_sbupdate(ump, MNT_WAIT); 610 } 611 612 if (ump->um_devvp->v_type != VBAD) 613 ump->um_devvp->v_specmountpoint = NULL; 614 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p); 615 (void)VOP_CLOSE(ump->um_devvp, fs->e2fs_ronly ? FREAD : FREAD|FWRITE, 616 NOCRED, p); 617 vput(ump->um_devvp); 618 free(fs->e2fs_gd, M_UFSMNT, gdescs_space); 619 free(fs, M_UFSMNT, sizeof *fs); 620 free(ump, M_UFSMNT, sizeof *ump); 621 mp->mnt_data = NULL; 622 mp->mnt_flag &= ~MNT_LOCAL; 623 return (0); 624 } 625 626 /* 627 * Flush out all the files in a filesystem. 628 */ 629 int 630 ext2fs_flushfiles(struct mount *mp, int flags, struct proc *p) 631 { 632 struct ufsmount *ump; 633 int error; 634 635 ump = VFSTOUFS(mp); 636 /* 637 * Flush all the files. 638 */ 639 if ((error = vflush(mp, NULL, flags)) != 0) 640 return (error); 641 /* 642 * Flush filesystem metadata. 643 */ 644 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p); 645 error = VOP_FSYNC(ump->um_devvp, p->p_ucred, MNT_WAIT, p); 646 VOP_UNLOCK(ump->um_devvp, p); 647 return (error); 648 } 649 650 /* 651 * Get file system statistics. 652 */ 653 int 654 ext2fs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p) 655 { 656 struct ufsmount *ump; 657 struct m_ext2fs *fs; 658 u_int32_t overhead, overhead_per_group; 659 int i, ngroups; 660 661 ump = VFSTOUFS(mp); 662 fs = ump->um_e2fs; 663 if (fs->e2fs.e2fs_magic != E2FS_MAGIC) 664 panic("ext2fs_statfs"); 665 666 /* 667 * Compute the overhead (FS structures) 668 */ 669 overhead_per_group = 1 /* block bitmap */ + 1 /* inode bitmap */ + 670 fs->e2fs_itpg; 671 overhead = fs->e2fs.e2fs_first_dblock + 672 fs->e2fs_ncg * overhead_per_group; 673 if (fs->e2fs.e2fs_rev > E2FS_REV0 && 674 fs->e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_SPARSESUPER) { 675 for (i = 0, ngroups = 0; i < fs->e2fs_ncg; i++) { 676 if (cg_has_sb(i)) 677 ngroups++; 678 } 679 } else { 680 ngroups = fs->e2fs_ncg; 681 } 682 overhead += ngroups * (1 + fs->e2fs_ngdb); 683 684 sbp->f_bsize = fs->e2fs_bsize; 685 sbp->f_iosize = fs->e2fs_bsize; 686 sbp->f_blocks = fs->e2fs.e2fs_bcount - overhead; 687 sbp->f_bfree = fs->e2fs.e2fs_fbcount; 688 sbp->f_bavail = sbp->f_bfree - fs->e2fs.e2fs_rbcount; 689 sbp->f_files = fs->e2fs.e2fs_icount; 690 sbp->f_favail = sbp->f_ffree = fs->e2fs.e2fs_ficount; 691 copy_statfs_info(sbp, mp); 692 693 return (0); 694 } 695 696 int ext2fs_sync_vnode(struct vnode *vp, void *); 697 698 struct ext2fs_sync_args { 699 int allerror; 700 int waitfor; 701 struct proc *p; 702 struct ucred *cred; 703 }; 704 705 int 706 ext2fs_sync_vnode(struct vnode *vp, void *args) 707 { 708 struct ext2fs_sync_args *esa = args; 709 struct inode *ip; 710 int error; 711 712 ip = VTOI(vp); 713 if (vp->v_type == VNON || 714 ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 && 715 LIST_EMPTY(&vp->v_dirtyblkhd)) || 716 esa->waitfor == MNT_LAZY) { 717 return (0); 718 } 719 720 if (vget(vp, LK_EXCLUSIVE | LK_NOWAIT, esa->p)) 721 return (0); 722 723 if ((error = VOP_FSYNC(vp, esa->cred, esa->waitfor, esa->p)) != 0) 724 esa->allerror = error; 725 vput(vp); 726 return (0); 727 } 728 /* 729 * Go through the disk queues to initiate sandbagged IO; 730 * go through the inodes to write those that have been modified; 731 * initiate the writing of the super block if it has been modified. 732 * 733 * Should always be called with the mount point locked. 734 */ 735 int 736 ext2fs_sync(struct mount *mp, int waitfor, struct ucred *cred, struct proc *p) 737 { 738 struct ufsmount *ump = VFSTOUFS(mp); 739 struct m_ext2fs *fs; 740 int error, allerror = 0; 741 struct ext2fs_sync_args esa; 742 743 fs = ump->um_e2fs; 744 if (fs->e2fs_ronly != 0) { /* XXX */ 745 printf("fs = %s\n", fs->e2fs_fsmnt); 746 panic("update: rofs mod"); 747 } 748 749 /* 750 * Write back each (modified) inode. 751 */ 752 esa.p = p; 753 esa.cred = cred; 754 esa.allerror = 0; 755 esa.waitfor = waitfor; 756 757 vfs_mount_foreach_vnode(mp, ext2fs_sync_vnode, &esa); 758 if (esa.allerror != 0) 759 allerror = esa.allerror; 760 761 /* 762 * Force stale file system control information to be flushed. 763 */ 764 if (waitfor != MNT_LAZY) { 765 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p); 766 if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0) 767 allerror = error; 768 VOP_UNLOCK(ump->um_devvp, p); 769 } 770 /* 771 * Write back modified superblock. 772 */ 773 if (fs->e2fs_fmod != 0) { 774 fs->e2fs_fmod = 0; 775 fs->e2fs.e2fs_wtime = time_second; 776 if ((error = ext2fs_cgupdate(ump, waitfor))) 777 allerror = error; 778 } 779 return (allerror); 780 } 781 782 /* 783 * Look up a EXT2FS dinode number to find its incore vnode, otherwise read it 784 * in from disk. If it is in core, wait for the lock bit to clear, then 785 * return the inode locked. Detection and handling of mount points must be 786 * done by the calling routine. 787 */ 788 int 789 ext2fs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) 790 { 791 struct m_ext2fs *fs; 792 struct inode *ip; 793 struct ext2fs_dinode *dp; 794 struct ufsmount *ump; 795 struct buf *bp; 796 struct vnode *vp; 797 dev_t dev; 798 int error; 799 800 if (ino > (ufsino_t)-1) 801 panic("ext2fs_vget: alien ino_t %llu", 802 (unsigned long long)ino); 803 804 ump = VFSTOUFS(mp); 805 dev = ump->um_dev; 806 807 retry: 808 if ((*vpp = ufs_ihashget(dev, ino)) != NULL) 809 return (0); 810 811 /* Allocate a new vnode/inode. */ 812 if ((error = getnewvnode(VT_EXT2FS, mp, &ext2fs_vops, &vp)) != 0) { 813 *vpp = NULL; 814 return (error); 815 } 816 817 ip = pool_get(&ext2fs_inode_pool, PR_WAITOK|PR_ZERO); 818 rrw_init(&ip->i_lock, "inode"); 819 vp->v_data = ip; 820 ip->i_vnode = vp; 821 ip->i_ump = ump; 822 ip->i_e2fs = fs = ump->um_e2fs; 823 ip->i_dev = dev; 824 ip->i_number = ino; 825 ip->i_e2fs_last_lblk = 0; 826 ip->i_e2fs_last_blk = 0; 827 828 /* 829 * Put it onto its hash chain and lock it so that other requests for 830 * this inode will block if they arrive while we are sleeping waiting 831 * for old data structures to be purged or for the contents of the 832 * disk portion of this inode to be read. 833 */ 834 error = ufs_ihashins(ip); 835 836 if (error) { 837 vrele(vp); 838 839 if (error == EEXIST) 840 goto retry; 841 842 return (error); 843 } 844 845 /* Read in the disk contents for the inode, copy into the inode. */ 846 error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)), 847 (int)fs->e2fs_bsize, &bp); 848 if (error) { 849 /* 850 * The inode does not contain anything useful, so it would 851 * be misleading to leave it on its hash chain. With mode 852 * still zero, it will be unlinked and returned to the free 853 * list by vput(). 854 */ 855 vput(vp); 856 brelse(bp); 857 *vpp = NULL; 858 return (error); 859 } 860 861 dp = (struct ext2fs_dinode *) ((char *)bp->b_data 862 + EXT2_DINODE_SIZE(fs) * ino_to_fsbo(fs, ino)); 863 864 ip->i_e2din = pool_get(&ext2fs_dinode_pool, PR_WAITOK); 865 e2fs_iload(fs, dp, ip->i_e2din); 866 brelse(bp); 867 868 ip->i_effnlink = ip->i_e2fs_nlink; 869 870 /* 871 * The fields for storing the UID and GID of an ext2fs inode are 872 * limited to 16 bits. To overcome this limitation, Linux decided to 873 * scatter the highest bits of these values into a previously reserved 874 * area on the disk inode. We deal with this situation by having two 875 * 32-bit fields *out* of the disk inode to hold the complete values. 876 * Now that we are reading in the inode, compute these fields. 877 */ 878 ip->i_e2fs_uid = ip->i_e2fs_uid_low | (ip->i_e2fs_uid_high << 16); 879 ip->i_e2fs_gid = ip->i_e2fs_gid_low | (ip->i_e2fs_gid_high << 16); 880 881 /* If the inode was deleted, reset all fields */ 882 if (ip->i_e2fs_dtime != 0) { 883 ip->i_e2fs_mode = ip->i_e2fs_nblock = 0; 884 (void)ext2fs_setsize(ip, 0); 885 } 886 887 /* 888 * Initialize the vnode from the inode, check for aliases. 889 * Note that the underlying vnode may have changed. 890 */ 891 error = ext2fs_vinit(mp, &vp); 892 if (error) { 893 vput(vp); 894 *vpp = NULL; 895 return (error); 896 } 897 898 /* 899 * Finish inode initialization now that aliasing has been resolved. 900 */ 901 vref(ip->i_devvp); 902 /* 903 * Set up a generation number for this inode if it does not 904 * already have one. This should only happen on old filesystems. 905 */ 906 if (ip->i_e2fs_gen == 0) { 907 if (++ext2gennumber < (u_long)time_second) 908 ext2gennumber = time_second; 909 ip->i_e2fs_gen = ext2gennumber; 910 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) 911 ip->i_flag |= IN_MODIFIED; 912 } 913 914 *vpp = vp; 915 return (0); 916 } 917 918 /* 919 * File handle to vnode 920 * 921 * Have to be really careful about stale file handles: 922 * - check that the inode number is valid 923 * - call ext2fs_vget() to get the locked inode 924 * - check for an unallocated inode (i_mode == 0) 925 * - check that the given client host has export rights and return 926 * those rights via. exflagsp and credanonp 927 */ 928 int 929 ext2fs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) 930 { 931 struct inode *ip; 932 struct vnode *nvp; 933 int error; 934 struct ufid *ufhp; 935 struct m_ext2fs *fs; 936 937 ufhp = (struct ufid *)fhp; 938 fs = VFSTOUFS(mp)->um_e2fs; 939 if ((ufhp->ufid_ino < EXT2_FIRSTINO && ufhp->ufid_ino != EXT2_ROOTINO) || 940 ufhp->ufid_ino > fs->e2fs_ncg * fs->e2fs.e2fs_ipg) 941 return (ESTALE); 942 943 if ((error = VFS_VGET(mp, ufhp->ufid_ino, &nvp)) != 0) { 944 *vpp = NULLVP; 945 return (error); 946 } 947 ip = VTOI(nvp); 948 if (ip->i_e2fs_mode == 0 || ip->i_e2fs_dtime != 0 || 949 ip->i_e2fs_gen != ufhp->ufid_gen) { 950 vput(nvp); 951 *vpp = NULLVP; 952 return (ESTALE); 953 } 954 *vpp = nvp; 955 return (0); 956 } 957 958 /* 959 * Vnode pointer to File handle 960 */ 961 /* ARGSUSED */ 962 int 963 ext2fs_vptofh(struct vnode *vp, struct fid *fhp) 964 { 965 struct inode *ip; 966 struct ufid *ufhp; 967 968 ip = VTOI(vp); 969 ufhp = (struct ufid *)fhp; 970 ufhp->ufid_len = sizeof(struct ufid); 971 ufhp->ufid_ino = ip->i_number; 972 ufhp->ufid_gen = ip->i_e2fs_gen; 973 return (0); 974 } 975 976 /* 977 * no sysctl for ext2fs 978 */ 979 980 int 981 ext2fs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, 982 void *newp, size_t newlen, struct proc *p) 983 { 984 return (EOPNOTSUPP); 985 } 986 987 /* 988 * Write a superblock and associated information back to disk. 989 */ 990 int 991 ext2fs_sbupdate(struct ufsmount *mp, int waitfor) 992 { 993 struct m_ext2fs *fs = mp->um_e2fs; 994 struct buf *bp; 995 int error = 0; 996 997 bp = getblk(mp->um_devvp, SBLOCK, SBSIZE, 0, 0); 998 e2fs_sbsave(&fs->e2fs, (struct ext2fs *) bp->b_data); 999 if (waitfor == MNT_WAIT) 1000 error = bwrite(bp); 1001 else 1002 bawrite(bp); 1003 return (error); 1004 } 1005 1006 int 1007 ext2fs_cgupdate(struct ufsmount *mp, int waitfor) 1008 { 1009 struct m_ext2fs *fs = mp->um_e2fs; 1010 struct buf *bp; 1011 int i, error = 0, allerror = 0; 1012 1013 allerror = ext2fs_sbupdate(mp, waitfor); 1014 for (i = 0; i < fs->e2fs_ngdb; i++) { 1015 bp = getblk(mp->um_devvp, fsbtodb(fs, ((fs->e2fs_bsize>1024)?0:1)+i+1), 1016 fs->e2fs_bsize, 0, 0); 1017 e2fs_cgsave(&fs->e2fs_gd[i* fs->e2fs_bsize / sizeof(struct ext2_gd)], (struct ext2_gd*)bp->b_data, fs->e2fs_bsize); 1018 if (waitfor == MNT_WAIT) 1019 error = bwrite(bp); 1020 else 1021 bawrite(bp); 1022 } 1023 1024 if (!allerror && error) 1025 allerror = error; 1026 return (allerror); 1027 } 1028 1029 /* This is called before the superblock is copied. Watch out for endianity! */ 1030 static int 1031 e2fs_sbcheck(struct ext2fs *fs, int ronly) 1032 { 1033 u_int32_t tmp; 1034 1035 tmp = letoh16(fs->e2fs_magic); 1036 if (tmp != E2FS_MAGIC) { 1037 printf("ext2fs: wrong magic number 0x%x\n", tmp); 1038 return (EIO); /* XXX needs translation */ 1039 } 1040 1041 tmp = letoh32(fs->e2fs_log_bsize); 1042 if (tmp > 2) { 1043 /* skewed log(block size): 1024 -> 0 | 2048 -> 1 | 4096 -> 2 */ 1044 tmp += 10; 1045 printf("ext2fs: wrong log2(block size) %d\n", tmp); 1046 return (EIO); /* XXX needs translation */ 1047 } 1048 1049 if (fs->e2fs_bpg == 0) { 1050 printf("ext2fs: zero blocks per group\n"); 1051 return (EIO); 1052 } 1053 1054 tmp = letoh32(fs->e2fs_rev); 1055 if (tmp > E2FS_REV1) { 1056 printf("ext2fs: wrong revision number 0x%x\n", tmp); 1057 return (EIO); /* XXX needs translation */ 1058 } 1059 else if (tmp == E2FS_REV0) 1060 return (0); 1061 1062 tmp = letoh32(fs->e2fs_first_ino); 1063 if (tmp != EXT2_FIRSTINO) { 1064 printf("ext2fs: first inode at 0x%x\n", tmp); 1065 return (EINVAL); /* XXX needs translation */ 1066 } 1067 1068 tmp = letoh32(fs->e2fs_features_incompat); 1069 if (tmp & ~(EXT2F_INCOMPAT_SUPP | EXT4F_RO_INCOMPAT_SUPP)) { 1070 printf("ext2fs: unsupported incompat features 0x%x\n", tmp); 1071 return (EINVAL); /* XXX needs translation */ 1072 } 1073 1074 if (!ronly && (tmp & EXT4F_RO_INCOMPAT_SUPP)) { 1075 printf("ext4fs: only read-only support right now\n"); 1076 return (EROFS); /* XXX needs translation */ 1077 } 1078 1079 if (tmp & EXT2F_INCOMPAT_RECOVER) { 1080 printf("ext2fs: your file system says it needs recovery\n"); 1081 if (!ronly) 1082 return (EROFS); /* XXX needs translation */ 1083 } 1084 1085 tmp = letoh32(fs->e2fs_features_rocompat); 1086 if (!ronly && (tmp & ~EXT2F_ROCOMPAT_SUPP)) { 1087 printf("ext2fs: unsupported R/O compat features 0x%x\n", tmp); 1088 return (EROFS); /* XXX needs translation */ 1089 } 1090 1091 return (0); 1092 } 1093