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