ext2_vfsops.c revision 55313
1/* 2 * modified for EXT2FS support in Lites 1.1 3 * 4 * Aug 1995, Godmar Back (gback@cs.utah.edu) 5 * University of Utah, Department of Computer Science 6 */ 7/* 8 * Copyright (c) 1989, 1991, 1993, 1994 9 * The Regents of the University of California. All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * @(#)ffs_vfsops.c 8.8 (Berkeley) 4/18/94 40 * $FreeBSD: head/sys/gnu/fs/ext2fs/ext2_vfsops.c 55313 2000-01-02 17:40:02Z bde $ 41 */ 42 43#include "opt_quota.h" 44 45#include <sys/param.h> 46#include <sys/systm.h> 47#include <sys/namei.h> 48#include <sys/proc.h> 49#include <sys/kernel.h> 50#include <sys/vnode.h> 51#include <sys/mount.h> 52#include <sys/buf.h> 53#include <sys/conf.h> 54#include <sys/fcntl.h> 55#include <sys/disklabel.h> 56#include <sys/malloc.h> 57#include <sys/stat.h> 58 59#include <ufs/ufs/quota.h> 60#include <ufs/ufs/ufsmount.h> 61#include <ufs/ufs/inode.h> 62#include <ufs/ufs/ufs_extern.h> 63 64#include <vm/vm_zone.h> 65 66#include <gnu/ext2fs/fs.h> 67#include <gnu/ext2fs/ext2_extern.h> 68#include <gnu/ext2fs/ext2_fs.h> 69#include <gnu/ext2fs/ext2_fs_sb.h> 70 71static int ext2_fhtovp __P((struct mount *, struct fid *, struct vnode **)); 72static int ext2_flushfiles __P((struct mount *mp, int flags, struct proc *p)); 73static int ext2_mount __P((struct mount *, 74 char *, caddr_t, struct nameidata *, struct proc *)); 75static int ext2_mountfs __P((struct vnode *, struct mount *, struct proc *)); 76static int ext2_reload __P((struct mount *mountp, struct ucred *cred, 77 struct proc *p)); 78static int ext2_sbupdate __P((struct ufsmount *, int)); 79static int ext2_statfs __P((struct mount *, struct statfs *, struct proc *)); 80static int ext2_sync __P((struct mount *, int, struct ucred *, struct proc *)); 81static int ext2_unmount __P((struct mount *, int, struct proc *)); 82static int ext2_vget __P((struct mount *, ino_t, struct vnode **)); 83static int ext2_vptofh __P((struct vnode *, struct fid *)); 84 85static MALLOC_DEFINE(M_EXT2NODE, "EXT2 node", "EXT2 vnode private part"); 86 87static struct vfsops ext2fs_vfsops = { 88 ext2_mount, 89 ufs_start, /* empty function */ 90 ext2_unmount, 91 ufs_root, /* root inode via vget */ 92 ufs_quotactl, /* does operations associated with quotas */ 93 ext2_statfs, 94 ext2_sync, 95 ext2_vget, 96 ext2_fhtovp, 97 ufs_check_export, 98 ext2_vptofh, 99 ext2_init, 100 vfs_stduninit, 101 vfs_stdextattrctl, 102}; 103 104VFS_SET(ext2fs_vfsops, ext2fs, 0); 105#define bsd_malloc malloc 106#define bsd_free free 107 108static int ext2fs_inode_hash_lock; 109 110static int ext2_check_sb_compat __P((struct ext2_super_block *es, 111 dev_t dev, int ronly)); 112static int compute_sb_data __P((struct vnode * devvp, 113 struct ext2_super_block * es, 114 struct ext2_sb_info * fs)); 115 116#ifdef notyet 117static int ext2_mountroot __P((void)); 118 119/* 120 * Called by main() when ext2fs is going to be mounted as root. 121 * 122 * Name is updated by mount(8) after booting. 123 */ 124#define ROOTNAME "root_device" 125 126static int 127ext2_mountroot() 128{ 129 register struct ext2_sb_info *fs; 130 register struct mount *mp; 131 struct proc *p = curproc; 132 struct ufsmount *ump; 133 u_int size; 134 int error; 135 136 if ((error = bdevvp(rootdev, &rootvp))) { 137 printf("ext2_mountroot: can't find rootvp\n"); 138 return (error); 139 } 140 mp = bsd_malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK); 141 bzero((char *)mp, (u_long)sizeof(struct mount)); 142 mp->mnt_op = &ext2fs_vfsops; 143 mp->mnt_flag = MNT_RDONLY; 144 if (error = ext2_mountfs(rootvp, mp, p)) { 145 bsd_free(mp, M_MOUNT); 146 return (error); 147 } 148 if (error = vfs_lock(mp)) { 149 (void)ext2_unmount(mp, 0, p); 150 bsd_free(mp, M_MOUNT); 151 return (error); 152 } 153 TAILQ_INSERT_HEAD(&mountlist, mp, mnt_list); 154 mp->mnt_flag |= MNT_ROOTFS; 155 mp->mnt_vnodecovered = NULLVP; 156 ump = VFSTOUFS(mp); 157 fs = ump->um_e2fs; 158 bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt)); 159 fs->fs_fsmnt[0] = '/'; 160 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 161 MNAMELEN); 162 (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 163 &size); 164 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 165 (void)ext2_statfs(mp, &mp->mnt_stat, p); 166 vfs_unlock(mp); 167 inittodr(fs->s_es->s_wtime); /* this helps to set the time */ 168 return (0); 169} 170#endif 171 172/* 173 * VFS Operations. 174 * 175 * mount system call 176 */ 177static int 178ext2_mount(mp, path, data, ndp, p) 179 register struct mount *mp; 180 char *path; 181 caddr_t data; /* this is actually a (struct ufs_args *) */ 182 struct nameidata *ndp; 183 struct proc *p; 184{ 185 struct vnode *devvp; 186 struct ufs_args args; 187 struct ufsmount *ump = 0; 188 register struct ext2_sb_info *fs; 189 u_int size; 190 int error, flags; 191 mode_t accessmode; 192 193 if ((error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) != 0) 194 return (error); 195 /* 196 * If updating, check whether changing from read-only to 197 * read/write; if there is no device name, that's all we do. 198 */ 199 if (mp->mnt_flag & MNT_UPDATE) { 200 ump = VFSTOUFS(mp); 201 fs = ump->um_e2fs; 202 error = 0; 203 if (fs->s_rd_only == 0 && (mp->mnt_flag & MNT_RDONLY)) { 204 flags = WRITECLOSE; 205 if (mp->mnt_flag & MNT_FORCE) 206 flags |= FORCECLOSE; 207 if (vfs_busy(mp, LK_NOWAIT, 0, p)) 208 return (EBUSY); 209 error = ext2_flushfiles(mp, flags, p); 210 vfs_unbusy(mp, p); 211 if (!error && fs->s_wasvalid) { 212 fs->s_es->s_state |= EXT2_VALID_FS; 213 ext2_sbupdate(ump, MNT_WAIT); 214 } 215 fs->s_rd_only = 1; 216 } 217 if (!error && (mp->mnt_flag & MNT_RELOAD)) 218 error = ext2_reload(mp, ndp->ni_cnd.cn_cred, p); 219 if (error) 220 return (error); 221 if (fs->s_rd_only && (mp->mnt_kern_flag & MNTK_WANTRDWR)) { 222 /* 223 * If upgrade to read-write by non-root, then verify 224 * that user has necessary permissions on the device. 225 */ 226 if (p->p_ucred->cr_uid != 0) { 227 devvp = ump->um_devvp; 228 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); 229 if ((error = VOP_ACCESS(devvp, VREAD | VWRITE, 230 p->p_ucred, p)) != 0) { 231 VOP_UNLOCK(devvp, 0, p); 232 return (error); 233 } 234 VOP_UNLOCK(devvp, 0, p); 235 } 236 237 if ((fs->s_es->s_state & EXT2_VALID_FS) == 0 || 238 (fs->s_es->s_state & EXT2_ERROR_FS)) { 239 if (mp->mnt_flag & MNT_FORCE) { 240 printf( 241"WARNING: %s was not properly dismounted\n", 242 fs->fs_fsmnt); 243 } else { 244 printf( 245"WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n", 246 fs->fs_fsmnt); 247 return (EPERM); 248 } 249 } 250 fs->s_es->s_state &= ~EXT2_VALID_FS; 251 ext2_sbupdate(ump, MNT_WAIT); 252 fs->s_rd_only = 0; 253 } 254 if (args.fspec == 0) { 255 /* 256 * Process export requests. 257 */ 258 return (vfs_export(mp, &ump->um_export, &args.export)); 259 } 260 } 261 /* 262 * Not an update, or updating the name: look up the name 263 * and verify that it refers to a sensible block device. 264 */ 265 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); 266 if ((error = namei(ndp)) != 0) 267 return (error); 268 NDFREE(ndp, NDF_ONLY_PNBUF); 269 devvp = ndp->ni_vp; 270 271 if (!vn_isdisk(devvp)) { 272 vrele(devvp); 273 return (ENOTBLK); 274 } 275 276 /* 277 * If mount by non-root, then verify that user has necessary 278 * permissions on the device. 279 */ 280 if (p->p_ucred->cr_uid != 0) { 281 accessmode = VREAD; 282 if ((mp->mnt_flag & MNT_RDONLY) == 0) 283 accessmode |= VWRITE; 284 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); 285 if ((error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) != 0) { 286 vput(devvp); 287 return (error); 288 } 289 VOP_UNLOCK(devvp, 0, p); 290 } 291 292 if ((mp->mnt_flag & MNT_UPDATE) == 0) { 293 error = ext2_mountfs(devvp, mp, p); 294 } else { 295 if (devvp != ump->um_devvp) 296 error = EINVAL; /* needs translation */ 297 else 298 vrele(devvp); 299 } 300 if (error) { 301 vrele(devvp); 302 return (error); 303 } 304 ump = VFSTOUFS(mp); 305 fs = ump->um_e2fs; 306 (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 307 bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 308 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 309 MNAMELEN); 310 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 311 &size); 312 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 313 (void)ext2_statfs(mp, &mp->mnt_stat, p); 314 return (0); 315} 316 317/* 318 * checks that the data in the descriptor blocks make sense 319 * this is taken from ext2/super.c 320 */ 321static int ext2_check_descriptors (struct ext2_sb_info * sb) 322{ 323 int i; 324 int desc_block = 0; 325 unsigned long block = sb->s_es->s_first_data_block; 326 struct ext2_group_desc * gdp = NULL; 327 328 /* ext2_debug ("Checking group descriptors"); */ 329 330 for (i = 0; i < sb->s_groups_count; i++) 331 { 332 /* examine next descriptor block */ 333 if ((i % EXT2_DESC_PER_BLOCK(sb)) == 0) 334 gdp = (struct ext2_group_desc *) 335 sb->s_group_desc[desc_block++]->b_data; 336 if (gdp->bg_block_bitmap < block || 337 gdp->bg_block_bitmap >= block + EXT2_BLOCKS_PER_GROUP(sb)) 338 { 339 printf ("ext2_check_descriptors: " 340 "Block bitmap for group %d" 341 " not in group (block %lu)!\n", 342 i, (unsigned long) gdp->bg_block_bitmap); 343 return 0; 344 } 345 if (gdp->bg_inode_bitmap < block || 346 gdp->bg_inode_bitmap >= block + EXT2_BLOCKS_PER_GROUP(sb)) 347 { 348 printf ("ext2_check_descriptors: " 349 "Inode bitmap for group %d" 350 " not in group (block %lu)!\n", 351 i, (unsigned long) gdp->bg_inode_bitmap); 352 return 0; 353 } 354 if (gdp->bg_inode_table < block || 355 gdp->bg_inode_table + sb->s_itb_per_group >= 356 block + EXT2_BLOCKS_PER_GROUP(sb)) 357 { 358 printf ("ext2_check_descriptors: " 359 "Inode table for group %d" 360 " not in group (block %lu)!\n", 361 i, (unsigned long) gdp->bg_inode_table); 362 return 0; 363 } 364 block += EXT2_BLOCKS_PER_GROUP(sb); 365 gdp++; 366 } 367 return 1; 368} 369 370static int 371ext2_check_sb_compat(es, dev, ronly) 372 struct ext2_super_block *es; 373 dev_t dev; 374 int ronly; 375{ 376 377 if (es->s_magic != EXT2_SUPER_MAGIC) { 378 printf("ext2fs: %s: wrong magic number %#x (expected %#x)\n", 379 devtoname(dev), es->s_magic, EXT2_SUPER_MAGIC); 380 return (1); 381 } 382 if (es->s_rev_level > EXT2_GOOD_OLD_REV) { 383 if (es->s_feature_incompat & ~EXT2_FEATURE_INCOMPAT_SUPP) { 384 printf( 385"WARNING: mount of %s denied due to unsupported optional features\n", 386 devtoname(dev)); 387 return (1); 388 } 389 if (!ronly && 390 (es->s_feature_ro_compat & ~EXT2_FEATURE_RO_COMPAT_SUPP)) { 391 printf( 392"WARNING: R/W mount of %s denied due to unsupported optional features\n", 393 devtoname(dev)); 394 return (1); 395 } 396 } 397 return (0); 398} 399 400/* 401 * this computes the fields of the ext2_sb_info structure from the 402 * data in the ext2_super_block structure read in 403 */ 404static int compute_sb_data(devvp, es, fs) 405 struct vnode * devvp; 406 struct ext2_super_block * es; 407 struct ext2_sb_info * fs; 408{ 409 int db_count, error; 410 int i, j; 411 int logic_sb_block = 1; /* XXX for now */ 412 413#if 1 414#define V(v) 415#else 416#define V(v) printf(#v"= %d\n", fs->v); 417#endif 418 419 fs->s_blocksize = EXT2_MIN_BLOCK_SIZE << es->s_log_block_size; 420 V(s_blocksize) 421 fs->s_bshift = EXT2_MIN_BLOCK_LOG_SIZE + es->s_log_block_size; 422 V(s_bshift) 423 fs->s_fsbtodb = es->s_log_block_size + 1; 424 V(s_fsbtodb) 425 fs->s_qbmask = fs->s_blocksize - 1; 426 V(s_bmask) 427 fs->s_blocksize_bits = EXT2_BLOCK_SIZE_BITS(es); 428 V(s_blocksize_bits) 429 fs->s_frag_size = EXT2_MIN_FRAG_SIZE << es->s_log_frag_size; 430 V(s_frag_size) 431 if (fs->s_frag_size) 432 fs->s_frags_per_block = fs->s_blocksize / fs->s_frag_size; 433 V(s_frags_per_block) 434 fs->s_blocks_per_group = es->s_blocks_per_group; 435 V(s_blocks_per_group) 436 fs->s_frags_per_group = es->s_frags_per_group; 437 V(s_frags_per_group) 438 fs->s_inodes_per_group = es->s_inodes_per_group; 439 V(s_inodes_per_group) 440 fs->s_inodes_per_block = fs->s_blocksize / EXT2_INODE_SIZE; 441 V(s_inodes_per_block) 442 fs->s_itb_per_group = fs->s_inodes_per_group /fs->s_inodes_per_block; 443 V(s_itb_per_group) 444 fs->s_desc_per_block = fs->s_blocksize / sizeof (struct ext2_group_desc); 445 V(s_desc_per_block) 446 /* s_resuid / s_resgid ? */ 447 fs->s_groups_count = (es->s_blocks_count - 448 es->s_first_data_block + 449 EXT2_BLOCKS_PER_GROUP(fs) - 1) / 450 EXT2_BLOCKS_PER_GROUP(fs); 451 V(s_groups_count) 452 db_count = (fs->s_groups_count + EXT2_DESC_PER_BLOCK(fs) - 1) / 453 EXT2_DESC_PER_BLOCK(fs); 454 fs->s_db_per_group = db_count; 455 V(s_db_per_group) 456 457 fs->s_group_desc = bsd_malloc(db_count * sizeof (struct buf *), 458 M_UFSMNT, M_WAITOK); 459 460 /* adjust logic_sb_block */ 461 if(fs->s_blocksize > SBSIZE) 462 /* Godmar thinks: if the blocksize is greater than 1024, then 463 the superblock is logically part of block zero. 464 */ 465 logic_sb_block = 0; 466 467 for (i = 0; i < db_count; i++) { 468 error = bread(devvp , fsbtodb(fs, logic_sb_block + i + 1), 469 fs->s_blocksize, NOCRED, &fs->s_group_desc[i]); 470 if(error) { 471 for (j = 0; j < i; j++) 472 brelse(fs->s_group_desc[j]); 473 bsd_free(fs->s_group_desc, M_UFSMNT); 474 printf("EXT2-fs: unable to read group descriptors (%d)\n", error); 475 return EIO; 476 } 477 /* Set the B_LOCKED flag on the buffer, then brelse() it */ 478 LCK_BUF(fs->s_group_desc[i]) 479 } 480 if(!ext2_check_descriptors(fs)) { 481 for (j = 0; j < db_count; j++) 482 ULCK_BUF(fs->s_group_desc[j]) 483 bsd_free(fs->s_group_desc, M_UFSMNT); 484 printf("EXT2-fs: (ext2_check_descriptors failure) " 485 "unable to read group descriptors\n"); 486 return EIO; 487 } 488 489 for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) { 490 fs->s_inode_bitmap_number[i] = 0; 491 fs->s_inode_bitmap[i] = NULL; 492 fs->s_block_bitmap_number[i] = 0; 493 fs->s_block_bitmap[i] = NULL; 494 } 495 fs->s_loaded_inode_bitmaps = 0; 496 fs->s_loaded_block_bitmaps = 0; 497 return 0; 498} 499 500/* 501 * Reload all incore data for a filesystem (used after running fsck on 502 * the root filesystem and finding things to fix). The filesystem must 503 * be mounted read-only. 504 * 505 * Things to do to update the mount: 506 * 1) invalidate all cached meta-data. 507 * 2) re-read superblock from disk. 508 * 3) re-read summary information from disk. 509 * 4) invalidate all inactive vnodes. 510 * 5) invalidate all cached file data. 511 * 6) re-read inode data for all active vnodes. 512 */ 513static int 514ext2_reload(mountp, cred, p) 515 register struct mount *mountp; 516 struct ucred *cred; 517 struct proc *p; 518{ 519 register struct vnode *vp, *nvp, *devvp; 520 struct inode *ip; 521 struct buf *bp; 522 struct ext2_super_block * es; 523 struct ext2_sb_info *fs; 524 int error; 525 526 if ((mountp->mnt_flag & MNT_RDONLY) == 0) 527 return (EINVAL); 528 /* 529 * Step 1: invalidate all cached meta-data. 530 */ 531 devvp = VFSTOUFS(mountp)->um_devvp; 532 if (vinvalbuf(devvp, 0, cred, p, 0, 0)) 533 panic("ext2_reload: dirty1"); 534 /* 535 * Step 2: re-read superblock from disk. 536 * constants have been adjusted for ext2 537 */ 538 if ((error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) != 0) 539 return (error); 540 es = (struct ext2_super_block *)bp->b_data; 541 if (ext2_check_sb_compat(es, devvp->v_rdev, 0) != 0) { 542 brelse(bp); 543 return (EIO); /* XXX needs translation */ 544 } 545 fs = VFSTOUFS(mountp)->um_e2fs; 546 bcopy(bp->b_data, fs->s_es, sizeof(struct ext2_super_block)); 547 548 if((error = compute_sb_data(devvp, es, fs)) != 0) { 549 brelse(bp); 550 return error; 551 } 552#ifdef UNKLAR 553 if (fs->fs_sbsize < SBSIZE) 554 bp->b_flags |= B_INVAL; 555#endif 556 brelse(bp); 557 558loop: 559 simple_lock(&mntvnode_slock); 560 for (vp = mountp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) { 561 if (vp->v_mount != mountp) { 562 simple_unlock(&mntvnode_slock); 563 goto loop; 564 } 565 nvp = vp->v_mntvnodes.le_next; 566 /* 567 * Step 4: invalidate all inactive vnodes. 568 */ 569 if (vrecycle(vp, &mntvnode_slock, p)) 570 goto loop; 571 /* 572 * Step 5: invalidate all cached file data. 573 */ 574 simple_lock(&vp->v_interlock); 575 simple_unlock(&mntvnode_slock); 576 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) { 577 goto loop; 578 } 579 if (vinvalbuf(vp, 0, cred, p, 0, 0)) 580 panic("ext2_reload: dirty2"); 581 /* 582 * Step 6: re-read inode data for all active vnodes. 583 */ 584 ip = VTOI(vp); 585 error = 586 bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)), 587 (int)fs->s_blocksize, NOCRED, &bp); 588 if (error) { 589 vput(vp); 590 return (error); 591 } 592 ext2_ei2di((struct ext2_inode *) ((char *)bp->b_data + 593 EXT2_INODE_SIZE * ino_to_fsbo(fs, ip->i_number)), 594 &ip->i_din); 595 brelse(bp); 596 vput(vp); 597 simple_lock(&mntvnode_slock); 598 } 599 simple_unlock(&mntvnode_slock); 600 return (0); 601} 602 603/* 604 * Common code for mount and mountroot 605 */ 606static int 607ext2_mountfs(devvp, mp, p) 608 register struct vnode *devvp; 609 struct mount *mp; 610 struct proc *p; 611{ 612 register struct ufsmount *ump; 613 struct buf *bp; 614 register struct ext2_sb_info *fs; 615 struct ext2_super_block * es; 616 dev_t dev = devvp->v_rdev; 617 struct partinfo dpart; 618 int havepart = 0; 619 int error, i, size; 620 int ronly; 621 622 /* 623 * Disallow multiple mounts of the same device. 624 * Disallow mounting of a device that is currently in use 625 * (except for root, which might share swap device for miniroot). 626 * Flush out any old buffers remaining from a previous use. 627 */ 628 if ((error = vfs_mountedon(devvp)) != 0) 629 return (error); 630 if (vcount(devvp) > 1 && devvp != rootvp) 631 return (EBUSY); 632 if ((error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0)) != 0) 633 return (error); 634#ifdef READONLY 635/* turn on this to force it to be read-only */ 636 mp->mnt_flag |= MNT_RDONLY; 637#endif 638 639 ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 640 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); 641 error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p); 642 VOP_UNLOCK(devvp, 0, p); 643 if (error) 644 return (error); 645 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0) 646 size = DEV_BSIZE; 647 else { 648 havepart = 1; 649 size = dpart.disklab->d_secsize; 650 } 651 652 bp = NULL; 653 ump = NULL; 654 if ((error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) != 0) 655 goto out; 656 es = (struct ext2_super_block *)bp->b_data; 657 if (ext2_check_sb_compat(es, dev, ronly) != 0) { 658 error = EINVAL; /* XXX needs translation */ 659 goto out; 660 } 661 if ((es->s_state & EXT2_VALID_FS) == 0 || 662 (es->s_state & EXT2_ERROR_FS)) { 663 if (ronly || (mp->mnt_flag & MNT_FORCE)) { 664 printf( 665"WARNING: Filesystem was not properly dismounted\n"); 666 } else { 667 printf( 668"WARNING: R/W mount denied. Filesystem is not clean - run fsck\n"); 669 error = EPERM; 670 goto out; 671 } 672 } 673 ump = bsd_malloc(sizeof *ump, M_UFSMNT, M_WAITOK); 674 bzero((caddr_t)ump, sizeof *ump); 675 ump->um_malloctype = M_EXT2NODE; 676 ump->um_blkatoff = ext2_blkatoff; 677 ump->um_truncate = ext2_truncate; 678 ump->um_update = ext2_update; 679 ump->um_valloc = ext2_valloc; 680 ump->um_vfree = ext2_vfree; 681 /* I don't know whether this is the right strategy. Note that 682 we dynamically allocate both a ext2_sb_info and a ext2_super_block 683 while Linux keeps the super block in a locked buffer 684 */ 685 ump->um_e2fs = bsd_malloc(sizeof(struct ext2_sb_info), 686 M_UFSMNT, M_WAITOK); 687 ump->um_e2fs->s_es = bsd_malloc(sizeof(struct ext2_super_block), 688 M_UFSMNT, M_WAITOK); 689 bcopy(es, ump->um_e2fs->s_es, (u_int)sizeof(struct ext2_super_block)); 690 if ((error = compute_sb_data(devvp, ump->um_e2fs->s_es, ump->um_e2fs))) 691 goto out; 692 /* 693 * We don't free the group descriptors allocated by compute_sb_data() 694 * until ext2_unmount(). This is OK since the mount will succeed. 695 */ 696 brelse(bp); 697 bp = NULL; 698 fs = ump->um_e2fs; 699 fs->s_rd_only = ronly; /* ronly is set according to mnt_flags */ 700 /* if the fs is not mounted read-only, make sure the super block is 701 always written back on a sync() 702 */ 703 fs->s_wasvalid = fs->s_es->s_state & EXT2_VALID_FS ? 1 : 0; 704 if (ronly == 0) { 705 fs->s_dirt = 1; /* mark it modified */ 706 fs->s_es->s_state &= ~EXT2_VALID_FS; /* set fs invalid */ 707 } 708 mp->mnt_data = (qaddr_t)ump; 709 mp->mnt_stat.f_fsid.val[0] = dev2udev(dev); 710 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; 711 mp->mnt_maxsymlinklen = EXT2_MAXSYMLINKLEN; 712 mp->mnt_flag |= MNT_LOCAL; 713 ump->um_mountp = mp; 714 ump->um_dev = dev; 715 ump->um_devvp = devvp; 716 /* setting those two parameters allows us to use 717 ufs_bmap w/o changse ! 718 */ 719 ump->um_nindir = EXT2_ADDR_PER_BLOCK(fs); 720 ump->um_bptrtodb = fs->s_es->s_log_block_size + 1; 721 ump->um_seqinc = EXT2_FRAGS_PER_BLOCK(fs); 722 for (i = 0; i < MAXQUOTAS; i++) 723 ump->um_quotas[i] = NULLVP; 724 devvp->v_specmountpoint = mp; 725 if (ronly == 0) 726 ext2_sbupdate(ump, MNT_WAIT); 727 return (0); 728out: 729 if (bp) 730 brelse(bp); 731 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); 732 if (ump) { 733 bsd_free(ump->um_e2fs->s_es, M_UFSMNT); 734 bsd_free(ump->um_e2fs, M_UFSMNT); 735 bsd_free(ump, M_UFSMNT); 736 mp->mnt_data = (qaddr_t)0; 737 } 738 return (error); 739} 740 741/* 742 * unmount system call 743 */ 744static int 745ext2_unmount(mp, mntflags, p) 746 struct mount *mp; 747 int mntflags; 748 struct proc *p; 749{ 750 register struct ufsmount *ump; 751 register struct ext2_sb_info *fs; 752 int error, flags, ronly, i; 753 754 flags = 0; 755 if (mntflags & MNT_FORCE) { 756 if (mp->mnt_flag & MNT_ROOTFS) 757 return (EINVAL); 758 flags |= FORCECLOSE; 759 } 760 if ((error = ext2_flushfiles(mp, flags, p)) != 0) 761 return (error); 762 ump = VFSTOUFS(mp); 763 fs = ump->um_e2fs; 764 ronly = fs->s_rd_only; 765 if (ronly == 0) { 766 if (fs->s_wasvalid) 767 fs->s_es->s_state |= EXT2_VALID_FS; 768 ext2_sbupdate(ump, MNT_WAIT); 769 } 770 771 /* release buffers containing group descriptors */ 772 for(i = 0; i < fs->s_db_per_group; i++) 773 ULCK_BUF(fs->s_group_desc[i]) 774 bsd_free(fs->s_group_desc, M_UFSMNT); 775 776 /* release cached inode/block bitmaps */ 777 for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) 778 if (fs->s_inode_bitmap[i]) 779 ULCK_BUF(fs->s_inode_bitmap[i]) 780 781 for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) 782 if (fs->s_block_bitmap[i]) 783 ULCK_BUF(fs->s_block_bitmap[i]) 784 785 ump->um_devvp->v_specmountpoint = NULL; 786 error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE, 787 NOCRED, p); 788 vrele(ump->um_devvp); 789 bsd_free(fs->s_es, M_UFSMNT); 790 bsd_free(fs, M_UFSMNT); 791 bsd_free(ump, M_UFSMNT); 792 mp->mnt_data = (qaddr_t)0; 793 mp->mnt_flag &= ~MNT_LOCAL; 794 return (error); 795} 796 797/* 798 * Flush out all the files in a filesystem. 799 */ 800static int 801ext2_flushfiles(mp, flags, p) 802 register struct mount *mp; 803 int flags; 804 struct proc *p; 805{ 806 register struct ufsmount *ump; 807 int error; 808#if QUOTA 809 int i; 810#endif 811 812 ump = VFSTOUFS(mp); 813#if QUOTA 814 if (mp->mnt_flag & MNT_QUOTA) { 815 if ((error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) != 0) 816 return (error); 817 for (i = 0; i < MAXQUOTAS; i++) { 818 if (ump->um_quotas[i] == NULLVP) 819 continue; 820 quotaoff(p, mp, i); 821 } 822 /* 823 * Here we fall through to vflush again to ensure 824 * that we have gotten rid of all the system vnodes. 825 */ 826 } 827#endif 828 error = vflush(mp, NULLVP, flags); 829 return (error); 830} 831 832/* 833 * Get file system statistics. 834 * taken from ext2/super.c ext2_statfs 835 */ 836static int 837ext2_statfs(mp, sbp, p) 838 struct mount *mp; 839 register struct statfs *sbp; 840 struct proc *p; 841{ 842 unsigned long overhead; 843 unsigned long overhead_per_group; 844 845 register struct ufsmount *ump; 846 register struct ext2_sb_info *fs; 847 register struct ext2_super_block *es; 848 849 ump = VFSTOUFS(mp); 850 fs = ump->um_e2fs; 851 es = fs->s_es; 852 853 if (es->s_magic != EXT2_SUPER_MAGIC) 854 panic("ext2_statfs - magic number spoiled"); 855 856 /* 857 * Compute the overhead (FS structures) 858 */ 859 overhead_per_group = 1 /* super block */ + 860 fs->s_db_per_group + 861 1 /* block bitmap */ + 862 1 /* inode bitmap */ + 863 fs->s_itb_per_group; 864 overhead = es->s_first_data_block + 865 fs->s_groups_count * overhead_per_group; 866 867 sbp->f_bsize = EXT2_FRAG_SIZE(fs); 868 sbp->f_iosize = EXT2_BLOCK_SIZE(fs); 869 sbp->f_blocks = es->s_blocks_count - overhead; 870 sbp->f_bfree = es->s_free_blocks_count; 871 sbp->f_bavail = sbp->f_bfree - es->s_r_blocks_count; 872 sbp->f_files = es->s_inodes_count; 873 sbp->f_ffree = es->s_free_inodes_count; 874 if (sbp != &mp->mnt_stat) { 875 sbp->f_type = mp->mnt_vfc->vfc_typenum; 876 bcopy((caddr_t)mp->mnt_stat.f_mntonname, 877 (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 878 bcopy((caddr_t)mp->mnt_stat.f_mntfromname, 879 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 880 } 881 return (0); 882} 883 884/* 885 * Go through the disk queues to initiate sandbagged IO; 886 * go through the inodes to write those that have been modified; 887 * initiate the writing of the super block if it has been modified. 888 * 889 * Note: we are always called with the filesystem marked `MPBUSY'. 890 */ 891static int 892ext2_sync(mp, waitfor, cred, p) 893 struct mount *mp; 894 int waitfor; 895 struct ucred *cred; 896 struct proc *p; 897{ 898 struct vnode *nvp, *vp; 899 struct inode *ip; 900 struct ufsmount *ump = VFSTOUFS(mp); 901 struct ext2_sb_info *fs; 902 int error, allerror = 0; 903 904 fs = ump->um_e2fs; 905 if (fs->s_dirt != 0 && fs->s_rd_only != 0) { /* XXX */ 906 printf("fs = %s\n", fs->fs_fsmnt); 907 panic("ext2_sync: rofs mod"); 908 } 909 /* 910 * Write back each (modified) inode. 911 */ 912 simple_lock(&mntvnode_slock); 913loop: 914 for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) { 915 /* 916 * If the vnode that we are about to sync is no longer 917 * associated with this mount point, start over. 918 */ 919 if (vp->v_mount != mp) 920 goto loop; 921 simple_lock(&vp->v_interlock); 922 nvp = vp->v_mntvnodes.le_next; 923 ip = VTOI(vp); 924 if (vp->v_type == VNON || 925 ((ip->i_flag & 926 (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 && 927 (TAILQ_EMPTY(&vp->v_dirtyblkhd) || waitfor == MNT_LAZY))) { 928 simple_unlock(&vp->v_interlock); 929 continue; 930 } 931 simple_unlock(&mntvnode_slock); 932 error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p); 933 if (error) { 934 simple_lock(&mntvnode_slock); 935 if (error == ENOENT) 936 goto loop; 937 continue; 938 } 939 if ((error = VOP_FSYNC(vp, cred, waitfor, p)) != 0) 940 allerror = error; 941 VOP_UNLOCK(vp, 0, p); 942 vrele(vp); 943 simple_lock(&mntvnode_slock); 944 } 945 simple_unlock(&mntvnode_slock); 946 /* 947 * Force stale file system control information to be flushed. 948 */ 949 if (waitfor != MNT_LAZY) { 950 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p); 951 if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0) 952 allerror = error; 953 VOP_UNLOCK(ump->um_devvp, 0, p); 954 } 955#if QUOTA 956 qsync(mp); 957#endif 958 /* 959 * Write back modified superblock. 960 */ 961 if (fs->s_dirt != 0) { 962 fs->s_dirt = 0; 963 fs->s_es->s_wtime = time_second; 964 if ((error = ext2_sbupdate(ump, waitfor)) != 0) 965 allerror = error; 966 } 967 return (allerror); 968} 969 970/* 971 * Look up a EXT2FS dinode number to find its incore vnode, otherwise read it 972 * in from disk. If it is in core, wait for the lock bit to clear, then 973 * return the inode locked. Detection and handling of mount points must be 974 * done by the calling routine. 975 */ 976static int 977ext2_vget(mp, ino, vpp) 978 struct mount *mp; 979 ino_t ino; 980 struct vnode **vpp; 981{ 982 register struct ext2_sb_info *fs; 983 register struct inode *ip; 984 struct ufsmount *ump; 985 struct buf *bp; 986 struct vnode *vp; 987 dev_t dev; 988 int i, error; 989 int used_blocks; 990 991 ump = VFSTOUFS(mp); 992 dev = ump->um_dev; 993restart: 994 if ((*vpp = ufs_ihashget(dev, ino)) != NULL) 995 return (0); 996 997 /* 998 * Lock out the creation of new entries in the FFS hash table in 999 * case getnewvnode() or MALLOC() blocks, otherwise a duplicate 1000 * may occur! 1001 */ 1002 if (ext2fs_inode_hash_lock) { 1003 while (ext2fs_inode_hash_lock) { 1004 ext2fs_inode_hash_lock = -1; 1005 tsleep(&ext2fs_inode_hash_lock, PVM, "e2vget", 0); 1006 } 1007 goto restart; 1008 } 1009 ext2fs_inode_hash_lock = 1; 1010 1011 /* 1012 * If this MALLOC() is performed after the getnewvnode() 1013 * it might block, leaving a vnode with a NULL v_data to be 1014 * found by ext2_sync() if a sync happens to fire right then, 1015 * which will cause a panic because ext2_sync() blindly 1016 * dereferences vp->v_data (as well it should). 1017 */ 1018 MALLOC(ip, struct inode *, sizeof(struct inode), M_EXT2NODE, M_WAITOK); 1019 1020 /* Allocate a new vnode/inode. */ 1021 if ((error = getnewvnode(VT_UFS, mp, ext2_vnodeop_p, &vp)) != 0) { 1022 if (ext2fs_inode_hash_lock < 0) 1023 wakeup(&ext2fs_inode_hash_lock); 1024 ext2fs_inode_hash_lock = 0; 1025 *vpp = NULL; 1026 FREE(ip, M_EXT2NODE); 1027 return (error); 1028 } 1029 bzero((caddr_t)ip, sizeof(struct inode)); 1030 lockinit(&ip->i_lock, PINOD, "ext2in", 0, 0); 1031 vp->v_data = ip; 1032 ip->i_vnode = vp; 1033 ip->i_e2fs = fs = ump->um_e2fs; 1034 ip->i_dev = dev; 1035 ip->i_number = ino; 1036#if QUOTA 1037 for (i = 0; i < MAXQUOTAS; i++) 1038 ip->i_dquot[i] = NODQUOT; 1039#endif 1040 /* 1041 * Put it onto its hash chain and lock it so that other requests for 1042 * this inode will block if they arrive while we are sleeping waiting 1043 * for old data structures to be purged or for the contents of the 1044 * disk portion of this inode to be read. 1045 */ 1046 ufs_ihashins(ip); 1047 1048 if (ext2fs_inode_hash_lock < 0) 1049 wakeup(&ext2fs_inode_hash_lock); 1050 ext2fs_inode_hash_lock = 0; 1051 1052 /* Read in the disk contents for the inode, copy into the inode. */ 1053#if 0 1054printf("ext2_vget(%d) dbn= %d ", ino, fsbtodb(fs, ino_to_fsba(fs, ino))); 1055#endif 1056 if ((error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)), 1057 (int)fs->s_blocksize, NOCRED, &bp)) != 0) { 1058 /* 1059 * The inode does not contain anything useful, so it would 1060 * be misleading to leave it on its hash chain. With mode 1061 * still zero, it will be unlinked and returned to the free 1062 * list by vput(). 1063 */ 1064 vput(vp); 1065 brelse(bp); 1066 *vpp = NULL; 1067 return (error); 1068 } 1069 /* convert ext2 inode to dinode */ 1070 ext2_ei2di((struct ext2_inode *) ((char *)bp->b_data + EXT2_INODE_SIZE * 1071 ino_to_fsbo(fs, ino)), &ip->i_din); 1072 ip->i_block_group = ino_to_cg(fs, ino); 1073 ip->i_next_alloc_block = 0; 1074 ip->i_next_alloc_goal = 0; 1075 ip->i_prealloc_count = 0; 1076 ip->i_prealloc_block = 0; 1077 /* now we want to make sure that block pointers for unused 1078 blocks are zeroed out - ext2_balloc depends on this 1079 although for regular files and directories only 1080 */ 1081 if(S_ISDIR(ip->i_mode) || S_ISREG(ip->i_mode)) { 1082 used_blocks = (ip->i_size+fs->s_blocksize-1) / fs->s_blocksize; 1083 for(i = used_blocks; i < EXT2_NDIR_BLOCKS; i++) 1084 ip->i_db[i] = 0; 1085 } 1086/* 1087 ext2_print_inode(ip); 1088*/ 1089 brelse(bp); 1090 1091 /* 1092 * Initialize the vnode from the inode, check for aliases. 1093 * Note that the underlying vnode may have changed. 1094 */ 1095 if ((error = ufs_vinit(mp, ext2_specop_p, ext2_fifoop_p, &vp)) != 0) { 1096 vput(vp); 1097 *vpp = NULL; 1098 return (error); 1099 } 1100 /* 1101 * Finish inode initialization now that aliasing has been resolved. 1102 */ 1103 ip->i_devvp = ump->um_devvp; 1104 VREF(ip->i_devvp); 1105 /* 1106 * Set up a generation number for this inode if it does not 1107 * already have one. This should only happen on old filesystems. 1108 */ 1109 if (ip->i_gen == 0) { 1110 ip->i_gen = random() / 2 + 1; 1111 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) 1112 ip->i_flag |= IN_MODIFIED; 1113 } 1114 *vpp = vp; 1115 return (0); 1116} 1117 1118/* 1119 * File handle to vnode 1120 * 1121 * Have to be really careful about stale file handles: 1122 * - check that the inode number is valid 1123 * - call ext2_vget() to get the locked inode 1124 * - check for an unallocated inode (i_mode == 0) 1125 * - check that the given client host has export rights and return 1126 * those rights via. exflagsp and credanonp 1127 */ 1128static int 1129ext2_fhtovp(mp, fhp, vpp) 1130 register struct mount *mp; 1131 struct fid *fhp; 1132 struct vnode **vpp; 1133{ 1134 register struct ufid *ufhp; 1135 struct ext2_sb_info *fs; 1136 1137 ufhp = (struct ufid *)fhp; 1138 fs = VFSTOUFS(mp)->um_e2fs; 1139 if (ufhp->ufid_ino < ROOTINO || 1140 ufhp->ufid_ino >= fs->s_groups_count * fs->s_es->s_inodes_per_group) 1141 return (ESTALE); 1142 return (ufs_fhtovp(mp, ufhp, vpp)); 1143} 1144 1145/* 1146 * Vnode pointer to File handle 1147 */ 1148/* ARGSUSED */ 1149static int 1150ext2_vptofh(vp, fhp) 1151 struct vnode *vp; 1152 struct fid *fhp; 1153{ 1154 register struct inode *ip; 1155 register struct ufid *ufhp; 1156 1157 ip = VTOI(vp); 1158 ufhp = (struct ufid *)fhp; 1159 ufhp->ufid_len = sizeof(struct ufid); 1160 ufhp->ufid_ino = ip->i_number; 1161 ufhp->ufid_gen = ip->i_gen; 1162 return (0); 1163} 1164 1165/* 1166 * Write a superblock and associated information back to disk. 1167 */ 1168static int 1169ext2_sbupdate(mp, waitfor) 1170 struct ufsmount *mp; 1171 int waitfor; 1172{ 1173 register struct ext2_sb_info *fs = mp->um_e2fs; 1174 register struct ext2_super_block *es = fs->s_es; 1175 register struct buf *bp; 1176 int error = 0; 1177/* 1178printf("\nupdating superblock, waitfor=%s\n", waitfor == MNT_WAIT ? "yes":"no"); 1179*/ 1180 bp = getblk(mp->um_devvp, SBLOCK, SBSIZE, 0, 0); 1181 bcopy((caddr_t)es, bp->b_data, (u_int)sizeof(struct ext2_super_block)); 1182 if (waitfor == MNT_WAIT) 1183 error = bwrite(bp); 1184 else 1185 bawrite(bp); 1186 1187 /* 1188 * The buffers for group descriptors, inode bitmaps and block bitmaps 1189 * are not busy at this point and are (hopefully) written by the 1190 * usual sync mechanism. No need to write them here 1191 */ 1192 1193 return (error); 1194} 1195