1 /* $NetBSD: ext2fs_vfsops.c,v 1.52 2002/09/21 18:14:49 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.52 2002/09/21 18:14:49 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 123 extern u_long ext2gennumber; 124 125 void 126 ext2fs_init() 127 { 128 ufs_init(); 129 130 /* 131 * XXX Same structure as FFS inodes? Should we share a common pool? 132 */ 133 pool_init(&ext2fs_inode_pool, sizeof(struct inode), 0, 0, 0, 134 "ext2fsinopl", &pool_allocator_nointr); 135 } 136 137 void 138 ext2fs_reinit() 139 { 140 ufs_reinit(); 141 } 142 143 void 144 ext2fs_done() 145 { 146 ufs_done(); 147 pool_destroy(&ext2fs_inode_pool); 148 } 149 150 /* 151 * Called by main() when ext2fs is going to be mounted as root. 152 * 153 * Name is updated by mount(8) after booting. 154 */ 155 #define ROOTNAME "root_device" 156 157 int 158 ext2fs_mountroot() 159 { 160 extern struct vnode *rootvp; 161 struct m_ext2fs *fs; 162 struct mount *mp; 163 struct proc *p = curproc; /* XXX */ 164 struct ufsmount *ump; 165 int error; 166 167 if (root_device->dv_class != DV_DISK) 168 return (ENODEV); 169 170 /* 171 * Get vnodes for rootdev. 172 */ 173 if (bdevvp(rootdev, &rootvp)) 174 panic("ext2fs_mountroot: can't setup bdevvp's"); 175 176 if ((error = vfs_rootmountalloc(MOUNT_EXT2FS, "root_device", &mp))) { 177 vrele(rootvp); 178 return (error); 179 } 180 181 if ((error = ext2fs_mountfs(rootvp, mp, p)) != 0) { 182 mp->mnt_op->vfs_refcount--; 183 vfs_unbusy(mp); 184 free(mp, M_MOUNT); 185 vrele(rootvp); 186 return (error); 187 } 188 simple_lock(&mountlist_slock); 189 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); 190 simple_unlock(&mountlist_slock); 191 ump = VFSTOUFS(mp); 192 fs = ump->um_e2fs; 193 memset(fs->e2fs_fsmnt, 0, sizeof(fs->e2fs_fsmnt)); 194 (void) copystr(mp->mnt_stat.f_mntonname, fs->e2fs_fsmnt, 195 sizeof(fs->e2fs_fsmnt) - 1, 0); 196 if (fs->e2fs.e2fs_rev > E2FS_REV0) { 197 memset(fs->e2fs.e2fs_fsmnt, 0, sizeof(fs->e2fs.e2fs_fsmnt)); 198 (void) copystr(mp->mnt_stat.f_mntonname, fs->e2fs.e2fs_fsmnt, 199 sizeof(fs->e2fs.e2fs_fsmnt) - 1, 0); 200 } 201 (void)ext2fs_statfs(mp, &mp->mnt_stat, p); 202 vfs_unbusy(mp); 203 inittodr(fs->e2fs.e2fs_wtime); 204 return (0); 205 } 206 207 /* 208 * VFS Operations. 209 * 210 * mount system call 211 */ 212 int 213 ext2fs_mount(mp, path, data, ndp, p) 214 struct mount *mp; 215 const char *path; 216 void * data; 217 struct nameidata *ndp; 218 struct proc *p; 219 { 220 struct vnode *devvp; 221 struct ufs_args args; 222 struct ufsmount *ump = NULL; 223 struct m_ext2fs *fs; 224 size_t size; 225 int error, flags; 226 mode_t accessmode; 227 228 if (mp->mnt_flag & MNT_GETARGS) { 229 ump = VFSTOUFS(mp); 230 if (ump == NULL) 231 return EIO; 232 args.fspec = NULL; 233 vfs_showexport(mp, &args.export, &ump->um_export); 234 return copyout(&args, data, sizeof(args)); 235 } 236 237 error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)); 238 if (error) 239 return (error); 240 /* 241 * If updating, check whether changing from read-only to 242 * read/write; if there is no device name, that's all we do. 243 */ 244 if (mp->mnt_flag & MNT_UPDATE) { 245 ump = VFSTOUFS(mp); 246 fs = ump->um_e2fs; 247 if (fs->e2fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { 248 flags = WRITECLOSE; 249 if (mp->mnt_flag & MNT_FORCE) 250 flags |= FORCECLOSE; 251 error = ext2fs_flushfiles(mp, flags, p); 252 if (error == 0 && 253 ext2fs_cgupdate(ump, MNT_WAIT) == 0 && 254 (fs->e2fs.e2fs_state & E2FS_ERRORS) == 0) { 255 fs->e2fs.e2fs_state = E2FS_ISCLEAN; 256 (void) ext2fs_sbupdate(ump, MNT_WAIT); 257 } 258 if (error) 259 return (error); 260 fs->e2fs_ronly = 1; 261 } 262 if (mp->mnt_flag & MNT_RELOAD) { 263 error = ext2fs_reload(mp, ndp->ni_cnd.cn_cred, p); 264 if (error) 265 return (error); 266 } 267 if (fs->e2fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) { 268 /* 269 * If upgrade to read-write by non-root, then verify 270 * that user has necessary permissions on the device. 271 */ 272 if (p->p_ucred->cr_uid != 0) { 273 devvp = ump->um_devvp; 274 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 275 error = VOP_ACCESS(devvp, VREAD | VWRITE, 276 p->p_ucred, p); 277 VOP_UNLOCK(devvp, 0); 278 if (error) 279 return (error); 280 } 281 fs->e2fs_ronly = 0; 282 if (fs->e2fs.e2fs_state == E2FS_ISCLEAN) 283 fs->e2fs.e2fs_state = 0; 284 else 285 fs->e2fs.e2fs_state = E2FS_ERRORS; 286 fs->e2fs_fmod = 1; 287 } 288 if (args.fspec == 0) { 289 /* 290 * Process export requests. 291 */ 292 return (vfs_export(mp, &ump->um_export, &args.export)); 293 } 294 } 295 /* 296 * Not an update, or updating the name: look up the name 297 * and verify that it refers to a sensible block device. 298 */ 299 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); 300 if ((error = namei(ndp)) != 0) 301 return (error); 302 devvp = ndp->ni_vp; 303 304 if (devvp->v_type != VBLK) { 305 vrele(devvp); 306 return (ENOTBLK); 307 } 308 if (bdevsw_lookup(devvp->v_rdev) == NULL) { 309 vrele(devvp); 310 return (ENXIO); 311 } 312 /* 313 * If mount by non-root, then verify that user has necessary 314 * permissions on the device. 315 */ 316 if (p->p_ucred->cr_uid != 0) { 317 accessmode = VREAD; 318 if ((mp->mnt_flag & MNT_RDONLY) == 0) 319 accessmode |= VWRITE; 320 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 321 error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p); 322 VOP_UNLOCK(devvp, 0); 323 if (error) { 324 vrele(devvp); 325 return (error); 326 } 327 } 328 if ((mp->mnt_flag & MNT_UPDATE) == 0) 329 error = ext2fs_mountfs(devvp, mp, p); 330 else { 331 if (devvp != ump->um_devvp) 332 error = EINVAL; /* needs translation */ 333 else 334 vrele(devvp); 335 } 336 if (error) { 337 vrele(devvp); 338 return (error); 339 } 340 ump = VFSTOUFS(mp); 341 fs = ump->um_e2fs; 342 (void) copyinstr(path, fs->e2fs_fsmnt, sizeof(fs->e2fs_fsmnt) - 1, 343 &size); 344 memset(fs->e2fs_fsmnt + size, 0, sizeof(fs->e2fs_fsmnt) - size); 345 if (fs->e2fs.e2fs_rev > E2FS_REV0) { 346 (void) copystr(mp->mnt_stat.f_mntonname, fs->e2fs.e2fs_fsmnt, 347 sizeof(fs->e2fs.e2fs_fsmnt) - 1, &size); 348 memset(fs->e2fs.e2fs_fsmnt, 0, 349 sizeof(fs->e2fs.e2fs_fsmnt) - size); 350 } 351 memcpy(mp->mnt_stat.f_mntonname, fs->e2fs_fsmnt, MNAMELEN); 352 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 353 &size); 354 memset(mp->mnt_stat.f_mntfromname + size, 0, MNAMELEN - size); 355 if (fs->e2fs_fmod != 0) { /* XXX */ 356 fs->e2fs_fmod = 0; 357 if (fs->e2fs.e2fs_state == 0) 358 fs->e2fs.e2fs_wtime = time.tv_sec; 359 else 360 printf("%s: file system not clean; please fsck(8)\n", 361 mp->mnt_stat.f_mntfromname); 362 (void) ext2fs_cgupdate(ump, MNT_WAIT); 363 } 364 return (0); 365 } 366 367 /* 368 * Reload all incore data for a filesystem (used after running fsck on 369 * the root filesystem and finding things to fix). The filesystem must 370 * be mounted read-only. 371 * 372 * Things to do to update the mount: 373 * 1) invalidate all cached meta-data. 374 * 2) re-read superblock from disk. 375 * 3) re-read summary information from disk. 376 * 4) invalidate all inactive vnodes. 377 * 5) invalidate all cached file data. 378 * 6) re-read inode data for all active vnodes. 379 */ 380 int 381 ext2fs_reload(mountp, cred, p) 382 struct mount *mountp; 383 struct ucred *cred; 384 struct proc *p; 385 { 386 struct vnode *vp, *nvp, *devvp; 387 struct inode *ip; 388 struct buf *bp; 389 struct m_ext2fs *fs; 390 struct ext2fs *newfs; 391 struct partinfo dpart; 392 int i, size, error; 393 caddr_t cp; 394 395 if ((mountp->mnt_flag & MNT_RDONLY) == 0) 396 return (EINVAL); 397 /* 398 * Step 1: invalidate all cached meta-data. 399 */ 400 devvp = VFSTOUFS(mountp)->um_devvp; 401 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 402 error = vinvalbuf(devvp, 0, cred, p, 0, 0); 403 VOP_UNLOCK(devvp, 0); 404 if (error) 405 panic("ext2fs_reload: dirty1"); 406 /* 407 * Step 2: re-read superblock from disk. 408 */ 409 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0) 410 size = DEV_BSIZE; 411 else 412 size = dpart.disklab->d_secsize; 413 error = bread(devvp, (ufs_daddr_t)(SBOFF / size), SBSIZE, NOCRED, &bp); 414 if (error) { 415 brelse(bp); 416 return (error); 417 } 418 newfs = (struct ext2fs *)bp->b_data; 419 error = ext2fs_checksb(newfs, (mountp->mnt_flag & MNT_RDONLY) != 0); 420 if (error) { 421 brelse(bp); 422 return (error); 423 } 424 425 fs = VFSTOUFS(mountp)->um_e2fs; 426 /* 427 * copy in new superblock, and compute in-memory values 428 */ 429 e2fs_sbload(newfs, &fs->e2fs); 430 fs->e2fs_ncg = 431 howmany(fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock, 432 fs->e2fs.e2fs_bpg); 433 /* XXX assume hw bsize = 512 */ 434 fs->e2fs_fsbtodb = fs->e2fs.e2fs_log_bsize + 1; 435 fs->e2fs_bsize = 1024 << fs->e2fs.e2fs_log_bsize; 436 fs->e2fs_bshift = LOG_MINBSIZE + fs->e2fs.e2fs_log_bsize; 437 fs->e2fs_qbmask = fs->e2fs_bsize - 1; 438 fs->e2fs_bmask = ~fs->e2fs_qbmask; 439 fs->e2fs_ngdb = howmany(fs->e2fs_ncg, 440 fs->e2fs_bsize / sizeof(struct ext2_gd)); 441 fs->e2fs_ipb = fs->e2fs_bsize / EXT2_DINODE_SIZE; 442 fs->e2fs_itpg = fs->e2fs.e2fs_ipg/fs->e2fs_ipb; 443 444 /* 445 * Step 3: re-read summary information from disk. 446 */ 447 448 for (i=0; i < fs->e2fs_ngdb; i++) { 449 error = bread(devvp , 450 fsbtodb(fs, ((fs->e2fs_bsize>1024)? 0 : 1) + i + 1), 451 fs->e2fs_bsize, NOCRED, &bp); 452 if (error) { 453 brelse(bp); 454 return (error); 455 } 456 e2fs_cgload((struct ext2_gd*)bp->b_data, 457 &fs->e2fs_gd[i* fs->e2fs_bsize / sizeof(struct ext2_gd)], 458 fs->e2fs_bsize); 459 brelse(bp); 460 } 461 462 loop: 463 simple_lock(&mntvnode_slock); 464 for (vp = mountp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) { 465 if (vp->v_mount != mountp) { 466 simple_unlock(&mntvnode_slock); 467 goto loop; 468 } 469 nvp = vp->v_mntvnodes.le_next; 470 /* 471 * Step 4: invalidate all inactive vnodes. 472 */ 473 if (vrecycle(vp, &mntvnode_slock, p)) 474 goto loop; 475 /* 476 * Step 5: invalidate all cached file data. 477 */ 478 simple_lock(&vp->v_interlock); 479 simple_unlock(&mntvnode_slock); 480 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK)) 481 goto loop; 482 if (vinvalbuf(vp, 0, cred, p, 0, 0)) 483 panic("ext2fs_reload: dirty2"); 484 /* 485 * Step 6: re-read inode data for all active vnodes. 486 */ 487 ip = VTOI(vp); 488 error = bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)), 489 (int)fs->e2fs_bsize, NOCRED, &bp); 490 if (error) { 491 vput(vp); 492 return (error); 493 } 494 cp = (caddr_t)bp->b_data + 495 (ino_to_fsbo(fs, ip->i_number) * EXT2_DINODE_SIZE); 496 e2fs_iload((struct ext2fs_dinode *)cp, &ip->i_din.e2fs_din); 497 brelse(bp); 498 vput(vp); 499 simple_lock(&mntvnode_slock); 500 } 501 simple_unlock(&mntvnode_slock); 502 return (0); 503 } 504 505 /* 506 * Common code for mount and mountroot 507 */ 508 int 509 ext2fs_mountfs(devvp, mp, p) 510 struct vnode *devvp; 511 struct mount *mp; 512 struct proc *p; 513 { 514 struct ufsmount *ump; 515 struct buf *bp; 516 struct ext2fs *fs; 517 struct m_ext2fs *m_fs; 518 dev_t dev; 519 struct partinfo dpart; 520 int error, i, size, ronly; 521 struct ucred *cred; 522 extern struct vnode *rootvp; 523 524 dev = devvp->v_rdev; 525 cred = p ? p->p_ucred : NOCRED; 526 /* 527 * Disallow multiple mounts of the same device. 528 * Disallow mounting of a device that is currently in use 529 * (except for root, which might share swap device for miniroot). 530 * Flush out any old buffers remaining from a previous use. 531 */ 532 if ((error = vfs_mountedon(devvp)) != 0) 533 return (error); 534 if (vcount(devvp) > 1 && devvp != rootvp) 535 return (EBUSY); 536 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 537 error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0); 538 VOP_UNLOCK(devvp, 0); 539 if (error) 540 return (error); 541 542 ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 543 error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p); 544 if (error) 545 return (error); 546 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0) 547 size = DEV_BSIZE; 548 else 549 size = dpart.disklab->d_secsize; 550 551 bp = NULL; 552 ump = NULL; 553 554 #ifdef DEBUG_EXT2 555 printf("sb size: %d ino size %d\n", sizeof(struct ext2fs), 556 EXT2_DINODE_SIZE); 557 #endif 558 error = bread(devvp, (SBOFF / size), SBSIZE, cred, &bp); 559 if (error) 560 goto out; 561 fs = (struct ext2fs *)bp->b_data; 562 error = ext2fs_checksb(fs, ronly); 563 if (error) 564 goto out; 565 ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK); 566 memset((caddr_t)ump, 0, sizeof *ump); 567 ump->um_e2fs = malloc(sizeof(struct m_ext2fs), M_UFSMNT, M_WAITOK); 568 memset((caddr_t)ump->um_e2fs, 0, sizeof(struct m_ext2fs)); 569 e2fs_sbload((struct ext2fs*)bp->b_data, &ump->um_e2fs->e2fs); 570 brelse(bp); 571 bp = NULL; 572 m_fs = ump->um_e2fs; 573 m_fs->e2fs_ronly = ronly; 574 if (ronly == 0) { 575 if (m_fs->e2fs.e2fs_state == E2FS_ISCLEAN) 576 m_fs->e2fs.e2fs_state = 0; 577 else 578 m_fs->e2fs.e2fs_state = E2FS_ERRORS; 579 m_fs->e2fs_fmod = 1; 580 } 581 582 /* compute dynamic sb infos */ 583 m_fs->e2fs_ncg = 584 howmany(m_fs->e2fs.e2fs_bcount - m_fs->e2fs.e2fs_first_dblock, 585 m_fs->e2fs.e2fs_bpg); 586 /* XXX assume hw bsize = 512 */ 587 m_fs->e2fs_fsbtodb = m_fs->e2fs.e2fs_log_bsize + 1; 588 m_fs->e2fs_bsize = 1024 << m_fs->e2fs.e2fs_log_bsize; 589 m_fs->e2fs_bshift = LOG_MINBSIZE + m_fs->e2fs.e2fs_log_bsize; 590 m_fs->e2fs_qbmask = m_fs->e2fs_bsize - 1; 591 m_fs->e2fs_bmask = ~m_fs->e2fs_qbmask; 592 m_fs->e2fs_ngdb = howmany(m_fs->e2fs_ncg, 593 m_fs->e2fs_bsize / sizeof(struct ext2_gd)); 594 m_fs->e2fs_ipb = m_fs->e2fs_bsize / EXT2_DINODE_SIZE; 595 m_fs->e2fs_itpg = m_fs->e2fs.e2fs_ipg/m_fs->e2fs_ipb; 596 597 m_fs->e2fs_gd = malloc(m_fs->e2fs_ngdb * m_fs->e2fs_bsize, 598 M_UFSMNT, M_WAITOK); 599 for (i=0; i < m_fs->e2fs_ngdb; i++) { 600 error = bread(devvp , 601 fsbtodb(m_fs, ((m_fs->e2fs_bsize>1024)? 0 : 1) + i + 1), 602 m_fs->e2fs_bsize, NOCRED, &bp); 603 if (error) { 604 free(m_fs->e2fs_gd, M_UFSMNT); 605 goto out; 606 } 607 e2fs_cgload((struct ext2_gd*)bp->b_data, 608 &m_fs->e2fs_gd[ 609 i * m_fs->e2fs_bsize / sizeof(struct ext2_gd)], 610 m_fs->e2fs_bsize); 611 brelse(bp); 612 bp = NULL; 613 } 614 615 mp->mnt_data = ump; 616 mp->mnt_stat.f_fsid.val[0] = (long)dev; 617 mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_EXT2FS); 618 mp->mnt_maxsymlinklen = EXT2_MAXSYMLINKLEN; 619 mp->mnt_flag |= MNT_LOCAL; 620 mp->mnt_dev_bshift = DEV_BSHIFT; /* XXX */ 621 mp->mnt_fs_bshift = m_fs->e2fs_bshift; 622 ump->um_flags = 0; 623 ump->um_mountp = mp; 624 ump->um_dev = dev; 625 ump->um_devvp = devvp; 626 ump->um_nindir = NINDIR(m_fs); 627 ump->um_lognindir = ffs(NINDIR(m_fs)) - 1; 628 ump->um_bptrtodb = m_fs->e2fs_fsbtodb; 629 ump->um_seqinc = 1; /* no frags */ 630 devvp->v_specmountpoint = mp; 631 return (0); 632 633 out: 634 if (bp) 635 brelse(bp); 636 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 637 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p); 638 VOP_UNLOCK(devvp, 0); 639 if (ump) { 640 free(ump->um_e2fs, M_UFSMNT); 641 free(ump, M_UFSMNT); 642 mp->mnt_data = NULL; 643 } 644 return (error); 645 } 646 647 /* 648 * unmount system call 649 */ 650 int 651 ext2fs_unmount(mp, mntflags, p) 652 struct mount *mp; 653 int mntflags; 654 struct proc *p; 655 { 656 struct ufsmount *ump; 657 struct m_ext2fs *fs; 658 int error, flags; 659 660 flags = 0; 661 if (mntflags & MNT_FORCE) 662 flags |= FORCECLOSE; 663 if ((error = ext2fs_flushfiles(mp, flags, p)) != 0) 664 return (error); 665 ump = VFSTOUFS(mp); 666 fs = ump->um_e2fs; 667 if (fs->e2fs_ronly == 0 && 668 ext2fs_cgupdate(ump, MNT_WAIT) == 0 && 669 (fs->e2fs.e2fs_state & E2FS_ERRORS) == 0) { 670 fs->e2fs.e2fs_state = E2FS_ISCLEAN; 671 (void) ext2fs_sbupdate(ump, MNT_WAIT); 672 } 673 if (ump->um_devvp->v_type != VBAD) 674 ump->um_devvp->v_specmountpoint = NULL; 675 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY); 676 error = VOP_CLOSE(ump->um_devvp, fs->e2fs_ronly ? FREAD : FREAD|FWRITE, 677 NOCRED, p); 678 vput(ump->um_devvp); 679 free(fs->e2fs_gd, M_UFSMNT); 680 free(fs, M_UFSMNT); 681 free(ump, M_UFSMNT); 682 mp->mnt_data = NULL; 683 mp->mnt_flag &= ~MNT_LOCAL; 684 return (error); 685 } 686 687 /* 688 * Flush out all the files in a filesystem. 689 */ 690 int 691 ext2fs_flushfiles(mp, flags, p) 692 struct mount *mp; 693 int flags; 694 struct proc *p; 695 { 696 extern int doforce; 697 int error; 698 699 if (!doforce) 700 flags &= ~FORCECLOSE; 701 error = vflush(mp, NULLVP, flags); 702 return (error); 703 } 704 705 /* 706 * Get file system statistics. 707 */ 708 int 709 ext2fs_statfs(mp, sbp, p) 710 struct mount *mp; 711 struct statfs *sbp; 712 struct proc *p; 713 { 714 struct ufsmount *ump; 715 struct m_ext2fs *fs; 716 u_int32_t overhead, overhead_per_group; 717 int i, ngroups; 718 719 ump = VFSTOUFS(mp); 720 fs = ump->um_e2fs; 721 if (fs->e2fs.e2fs_magic != E2FS_MAGIC) 722 panic("ext2fs_statfs"); 723 724 #ifdef COMPAT_09 725 sbp->f_type = 1; 726 #else 727 sbp->f_type = 0; 728 #endif 729 730 /* 731 * Compute the overhead (FS structures) 732 */ 733 overhead_per_group = 1 /* block bitmap */ + 734 1 /* inode bitmap */ + 735 fs->e2fs_itpg; 736 overhead = fs->e2fs.e2fs_first_dblock + 737 fs->e2fs_ncg * overhead_per_group; 738 if (fs->e2fs.e2fs_rev > E2FS_REV0 && 739 fs->e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_SPARSESUPER) { 740 for (i = 0, ngroups = 0; i < fs->e2fs_ncg; i++) { 741 if (cg_has_sb(i)) 742 ngroups++; 743 } 744 } else { 745 ngroups = fs->e2fs_ncg; 746 } 747 overhead += ngroups * (1 + fs->e2fs_ngdb); 748 749 sbp->f_bsize = fs->e2fs_bsize; 750 sbp->f_iosize = fs->e2fs_bsize; 751 sbp->f_blocks = fs->e2fs.e2fs_bcount - overhead; 752 sbp->f_bfree = fs->e2fs.e2fs_fbcount; 753 sbp->f_bavail = sbp->f_bfree - fs->e2fs.e2fs_rbcount; 754 sbp->f_files = fs->e2fs.e2fs_icount; 755 sbp->f_ffree = fs->e2fs.e2fs_ficount; 756 if (sbp != &mp->mnt_stat) { 757 memcpy(sbp->f_mntonname, mp->mnt_stat.f_mntonname, MNAMELEN); 758 memcpy(sbp->f_mntfromname, mp->mnt_stat.f_mntfromname, MNAMELEN); 759 } 760 strncpy(sbp->f_fstypename, mp->mnt_op->vfs_name, MFSNAMELEN); 761 return (0); 762 } 763 764 /* 765 * Go through the disk queues to initiate sandbagged IO; 766 * go through the inodes to write those that have been modified; 767 * initiate the writing of the super block if it has been modified. 768 * 769 * Note: we are always called with the filesystem marked `MPBUSY'. 770 */ 771 int 772 ext2fs_sync(mp, waitfor, cred, p) 773 struct mount *mp; 774 int waitfor; 775 struct ucred *cred; 776 struct proc *p; 777 { 778 struct vnode *vp, *nvp; 779 struct inode *ip; 780 struct ufsmount *ump = VFSTOUFS(mp); 781 struct m_ext2fs *fs; 782 int error, allerror = 0; 783 784 fs = ump->um_e2fs; 785 if (fs->e2fs_fmod != 0 && fs->e2fs_ronly != 0) { /* XXX */ 786 printf("fs = %s\n", fs->e2fs_fsmnt); 787 panic("update: rofs mod"); 788 } 789 /* 790 * Write back each (modified) inode. 791 */ 792 simple_lock(&mntvnode_slock); 793 loop: 794 for (vp = LIST_FIRST(&mp->mnt_vnodelist); vp != NULL; vp = nvp) { 795 /* 796 * If the vnode that we are about to sync is no longer 797 * associated with this mount point, start over. 798 */ 799 if (vp->v_mount != mp) 800 goto loop; 801 simple_lock(&vp->v_interlock); 802 nvp = LIST_NEXT(vp, v_mntvnodes); 803 ip = VTOI(vp); 804 if (waitfor == MNT_LAZY || vp->v_type == VNON || 805 ((ip->i_flag & 806 (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFIED | IN_ACCESSED)) == 0 && 807 LIST_EMPTY(&vp->v_dirtyblkhd) && 808 vp->v_uobj.uo_npages == 0)) 809 { 810 simple_unlock(&vp->v_interlock); 811 continue; 812 } 813 simple_unlock(&mntvnode_slock); 814 error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK); 815 if (error) { 816 simple_lock(&mntvnode_slock); 817 if (error == ENOENT) 818 goto loop; 819 continue; 820 } 821 if ((error = VOP_FSYNC(vp, cred, 822 waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0, p)) != 0) 823 allerror = error; 824 vput(vp); 825 simple_lock(&mntvnode_slock); 826 } 827 simple_unlock(&mntvnode_slock); 828 /* 829 * Force stale file system control information to be flushed. 830 */ 831 if (waitfor != MNT_LAZY) { 832 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY); 833 if ((error = VOP_FSYNC(ump->um_devvp, cred, 834 waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0, p)) != 0) 835 allerror = error; 836 VOP_UNLOCK(ump->um_devvp, 0); 837 } 838 /* 839 * Write back modified superblock. 840 */ 841 if (fs->e2fs_fmod != 0) { 842 fs->e2fs_fmod = 0; 843 fs->e2fs.e2fs_wtime = time.tv_sec; 844 if ((error = ext2fs_cgupdate(ump, waitfor))) 845 allerror = error; 846 } 847 return (allerror); 848 } 849 850 /* 851 * Look up a EXT2FS dinode number to find its incore vnode, otherwise read it 852 * in from disk. If it is in core, wait for the lock bit to clear, then 853 * return the inode locked. Detection and handling of mount points must be 854 * done by the calling routine. 855 */ 856 int 857 ext2fs_vget(mp, ino, vpp) 858 struct mount *mp; 859 ino_t ino; 860 struct vnode **vpp; 861 { 862 struct m_ext2fs *fs; 863 struct inode *ip; 864 struct ufsmount *ump; 865 struct buf *bp; 866 struct vnode *vp; 867 dev_t dev; 868 int error; 869 caddr_t cp; 870 871 ump = VFSTOUFS(mp); 872 dev = ump->um_dev; 873 874 if ((*vpp = ufs_ihashget(dev, ino, LK_EXCLUSIVE)) != NULL) 875 return (0); 876 877 /* Allocate a new vnode/inode. */ 878 if ((error = getnewvnode(VT_EXT2FS, mp, ext2fs_vnodeop_p, &vp)) != 0) { 879 *vpp = NULL; 880 return (error); 881 } 882 883 do { 884 if ((*vpp = ufs_ihashget(dev, ino, LK_EXCLUSIVE)) != NULL) { 885 ungetnewvnode(vp); 886 return (0); 887 } 888 } while (lockmgr(&ufs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0)); 889 890 ip = pool_get(&ext2fs_inode_pool, PR_WAITOK); 891 memset(ip, 0, sizeof(struct inode)); 892 vp->v_data = ip; 893 ip->i_vnode = vp; 894 ip->i_e2fs = fs = ump->um_e2fs; 895 ip->i_dev = dev; 896 ip->i_number = ino; 897 ip->i_e2fs_last_lblk = 0; 898 ip->i_e2fs_last_blk = 0; 899 900 /* 901 * Put it onto its hash chain and lock it so that other requests for 902 * this inode will block if they arrive while we are sleeping waiting 903 * for old data structures to be purged or for the contents of the 904 * disk portion of this inode to be read. 905 */ 906 907 ufs_ihashins(ip); 908 lockmgr(&ufs_hashlock, LK_RELEASE, 0); 909 910 /* Read in the disk contents for the inode, copy into the inode. */ 911 error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)), 912 (int)fs->e2fs_bsize, NOCRED, &bp); 913 if (error) { 914 915 /* 916 * The inode does not contain anything useful, so it would 917 * be misleading to leave it on its hash chain. With mode 918 * still zero, it will be unlinked and returned to the free 919 * list by vput(). 920 */ 921 922 vput(vp); 923 brelse(bp); 924 *vpp = NULL; 925 return (error); 926 } 927 cp = (caddr_t)bp->b_data + 928 (ino_to_fsbo(fs, ino) * EXT2_DINODE_SIZE); 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