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