ffs_vfsops.c revision 50477
1/* 2 * Copyright (c) 1989, 1991, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95 34 * $FreeBSD: head/sys/ufs/ffs/ffs_vfsops.c 50477 1999-08-28 01:08:13Z peter $ 35 */ 36 37#include "opt_quota.h" 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/namei.h> 42#include <sys/proc.h> 43#include <sys/kernel.h> 44#include <sys/vnode.h> 45#include <sys/mount.h> 46#include <sys/buf.h> 47#include <sys/conf.h> 48#include <sys/fcntl.h> 49#include <sys/disklabel.h> 50#include <sys/malloc.h> 51 52#include <ufs/ufs/quota.h> 53#include <ufs/ufs/ufsmount.h> 54#include <ufs/ufs/inode.h> 55#include <ufs/ufs/ufs_extern.h> 56 57#include <ufs/ffs/fs.h> 58#include <ufs/ffs/ffs_extern.h> 59 60#include <vm/vm.h> 61#include <vm/vm_prot.h> 62#include <vm/vm_page.h> 63 64static MALLOC_DEFINE(M_FFSNODE, "FFS node", "FFS vnode private part"); 65 66static int ffs_sbupdate __P((struct ufsmount *, int)); 67static int ffs_reload __P((struct mount *,struct ucred *,struct proc *)); 68static int ffs_oldfscompat __P((struct fs *)); 69static int ffs_mount __P((struct mount *, char *, caddr_t, 70 struct nameidata *, struct proc *)); 71static int ffs_init __P((struct vfsconf *)); 72 73static struct vfsops ufs_vfsops = { 74 ffs_mount, 75 ufs_start, 76 ffs_unmount, 77 ufs_root, 78 ufs_quotactl, 79 ffs_statfs, 80 ffs_sync, 81 ffs_vget, 82 ffs_fhtovp, 83 ffs_vptofh, 84 ffs_init, 85}; 86 87VFS_SET(ufs_vfsops, ufs, 0); 88 89/* 90 * ffs_mount 91 * 92 * Called when mounting local physical media 93 * 94 * PARAMETERS: 95 * mountroot 96 * mp mount point structure 97 * path NULL (flag for root mount!!!) 98 * data <unused> 99 * ndp <unused> 100 * p process (user credentials check [statfs]) 101 * 102 * mount 103 * mp mount point structure 104 * path path to mount point 105 * data pointer to argument struct in user space 106 * ndp mount point namei() return (used for 107 * credentials on reload), reused to look 108 * up block device. 109 * p process (user credentials check) 110 * 111 * RETURNS: 0 Success 112 * !0 error number (errno.h) 113 * 114 * LOCK STATE: 115 * 116 * ENTRY 117 * mount point is locked 118 * EXIT 119 * mount point is locked 120 * 121 * NOTES: 122 * A NULL path can be used for a flag since the mount 123 * system call will fail with EFAULT in copyinstr in 124 * namei() if it is a genuine NULL from the user. 125 */ 126static int 127ffs_mount( mp, path, data, ndp, p) 128 struct mount *mp; /* mount struct pointer*/ 129 char *path; /* path to mount point*/ 130 caddr_t data; /* arguments to FS specific mount*/ 131 struct nameidata *ndp; /* mount point credentials*/ 132 struct proc *p; /* process requesting mount*/ 133{ 134 size_t size; 135 int err = 0; 136 struct vnode *devvp; 137 138 struct ufs_args args; 139 struct ufsmount *ump = 0; 140 register struct fs *fs; 141 int error, flags, ronly = 0; 142 mode_t accessmode; 143 144 /* 145 * Use NULL path to flag a root mount 146 */ 147 if( path == NULL) { 148 /* 149 *** 150 * Mounting root file system 151 *** 152 */ 153 154 if ((err = bdevvp(rootdev, &rootvp))) { 155 printf("ffs_mountroot: can't find rootvp"); 156 return (err); 157 } 158 159 if (devsw(rootdev)->d_flags & D_NOCLUSTERR) 160 mp->mnt_flag |= MNT_NOCLUSTERR; 161 if (devsw(rootdev)->d_flags & D_NOCLUSTERW) 162 mp->mnt_flag |= MNT_NOCLUSTERW; 163 if( ( err = ffs_mountfs(rootvp, mp, p, M_FFSNODE)) != 0) { 164 /* fs specific cleanup (if any)*/ 165 goto error_1; 166 } 167 168 goto dostatfs; /* success*/ 169 170 } 171 172 /* 173 *** 174 * Mounting non-root file system or updating a file system 175 *** 176 */ 177 178 /* copy in user arguments*/ 179 err = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)); 180 if (err) 181 goto error_1; /* can't get arguments*/ 182 183 /* 184 * If updating, check whether changing from read-only to 185 * read/write; if there is no device name, that's all we do. 186 * Disallow clearing MNT_NOCLUSTERR and MNT_NOCLUSTERW flags, 187 * if block device requests. 188 */ 189 if (mp->mnt_flag & MNT_UPDATE) { 190 ump = VFSTOUFS(mp); 191 fs = ump->um_fs; 192 devvp = ump->um_devvp; 193 err = 0; 194 ronly = fs->fs_ronly; /* MNT_RELOAD might change this */ 195 if (devsw(ump->um_dev)->d_flags & D_NOCLUSTERR) 196 mp->mnt_flag |= MNT_NOCLUSTERR; 197 if (devsw(ump->um_dev)->d_flags & D_NOCLUSTERW) 198 mp->mnt_flag |= MNT_NOCLUSTERW; 199 if (ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { 200 flags = WRITECLOSE; 201 if (mp->mnt_flag & MNT_FORCE) 202 flags |= FORCECLOSE; 203 if (mp->mnt_flag & MNT_SOFTDEP) { 204 err = softdep_flushfiles(mp, flags, p); 205 } else { 206 err = ffs_flushfiles(mp, flags, p); 207 } 208 ronly = 1; 209 } 210 if (!err && (mp->mnt_flag & MNT_RELOAD)) 211 err = ffs_reload(mp, ndp->ni_cnd.cn_cred, p); 212 if (err) { 213 goto error_1; 214 } 215 if (ronly && (mp->mnt_kern_flag & MNTK_WANTRDWR)) { 216 /* 217 * If upgrade to read-write by non-root, then verify 218 * that user has necessary permissions on the device. 219 */ 220 if (p->p_ucred->cr_uid != 0) { 221 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); 222 if ((error = VOP_ACCESS(devvp, VREAD | VWRITE, 223 p->p_ucred, p)) != 0) { 224 VOP_UNLOCK(devvp, 0, p); 225 return (error); 226 } 227 VOP_UNLOCK(devvp, 0, p); 228 } 229 230 if (fs->fs_clean == 0) { 231 if (mp->mnt_flag & MNT_FORCE) { 232 printf( 233"WARNING: %s was not properly dismounted\n", 234 fs->fs_fsmnt); 235 } else { 236 printf( 237"WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n", 238 fs->fs_fsmnt); 239 err = EPERM; 240 goto error_1; 241 } 242 } 243 244 /* check to see if we need to start softdep */ 245 if (fs->fs_flags & FS_DOSOFTDEP) { 246 err = softdep_mount(devvp, mp, fs, p->p_ucred); 247 if (err) 248 goto error_1; 249 } 250 251 ronly = 0; 252 } 253 /* 254 * Soft updates is incompatible with "async", 255 * so if we are doing softupdates stop the user 256 * from setting the async flag in an update. 257 * Softdep_mount() clears it in an initial mount 258 * or ro->rw remount. 259 */ 260 if (mp->mnt_flag & MNT_SOFTDEP) { 261 mp->mnt_flag &= ~MNT_ASYNC; 262 } 263 /* if not updating name...*/ 264 if (args.fspec == 0) { 265 /* 266 * Process export requests. Jumping to "success" 267 * will return the vfs_export() error code. 268 */ 269 err = vfs_export(mp, &ump->um_export, &args.export); 270 goto success; 271 } 272 } 273 274 /* 275 * Not an update, or updating the name: look up the name 276 * and verify that it refers to a sensible block device. 277 */ 278 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); 279 err = namei(ndp); 280 if (err) { 281 /* can't get devvp!*/ 282 goto error_1; 283 } 284 285 devvp = ndp->ni_vp; 286 287 if (!vn_isdisk(devvp)) { 288 err = ENOTBLK; 289 goto error_2; 290 } 291 292 /* 293 * If mount by non-root, then verify that user has necessary 294 * permissions on the device. 295 */ 296 if (p->p_ucred->cr_uid != 0) { 297 accessmode = VREAD; 298 if ((mp->mnt_flag & MNT_RDONLY) == 0) 299 accessmode |= VWRITE; 300 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); 301 if ((error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) != 0) { 302 vput(devvp); 303 return (error); 304 } 305 VOP_UNLOCK(devvp, 0, p); 306 } 307 308 if (mp->mnt_flag & MNT_UPDATE) { 309 /* 310 ******************** 311 * UPDATE 312 * If it's not the same vnode, or at least the same device 313 * then it's not correct. 314 ******************** 315 */ 316 317 if (devvp != ump->um_devvp) { 318 if ( devvp->v_rdev == ump->um_devvp->v_rdev) { 319 vrele(devvp); 320 } else { 321 err = EINVAL; /* needs translation */ 322 } 323 } else 324 vrele(devvp); 325 /* 326 * Update device name only on success 327 */ 328 if( !err) { 329 /* Save "mounted from" info for mount point (NULL pad)*/ 330 copyinstr( args.fspec, 331 mp->mnt_stat.f_mntfromname, 332 MNAMELEN - 1, 333 &size); 334 bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 335 } 336 } else { 337 /* 338 ******************** 339 * NEW MOUNT 340 ******************** 341 */ 342 343 if (devsw(devvp->v_rdev)->d_flags & D_NOCLUSTERR) 344 mp->mnt_flag |= MNT_NOCLUSTERR; 345 if (devsw(devvp->v_rdev)->d_flags & D_NOCLUSTERW) 346 mp->mnt_flag |= MNT_NOCLUSTERW; 347 348 /* 349 * Since this is a new mount, we want the names for 350 * the device and the mount point copied in. If an 351 * error occurs, the mountpoint is discarded by the 352 * upper level code. 353 */ 354 /* Save "last mounted on" info for mount point (NULL pad)*/ 355 copyinstr( path, /* mount point*/ 356 mp->mnt_stat.f_mntonname, /* save area*/ 357 MNAMELEN - 1, /* max size*/ 358 &size); /* real size*/ 359 bzero( mp->mnt_stat.f_mntonname + size, MNAMELEN - size); 360 361 /* Save "mounted from" info for mount point (NULL pad)*/ 362 copyinstr( args.fspec, /* device name*/ 363 mp->mnt_stat.f_mntfromname, /* save area*/ 364 MNAMELEN - 1, /* max size*/ 365 &size); /* real size*/ 366 bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 367 368 err = ffs_mountfs(devvp, mp, p, M_FFSNODE); 369 } 370 if (err) { 371 goto error_2; 372 } 373 374dostatfs: 375 /* 376 * Initialize FS stat information in mount struct; uses both 377 * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname 378 * 379 * This code is common to root and non-root mounts 380 */ 381 (void)VFS_STATFS(mp, &mp->mnt_stat, p); 382 383 goto success; 384 385 386error_2: /* error with devvp held*/ 387 388 /* release devvp before failing*/ 389 vrele(devvp); 390 391error_1: /* no state to back out*/ 392 393success: 394 if (!err && path && (mp->mnt_flag & MNT_UPDATE)) { 395 /* Update clean flag after changing read-onlyness. */ 396 fs = ump->um_fs; 397 if (ronly != fs->fs_ronly) { 398 fs->fs_ronly = ronly; 399 fs->fs_clean = ronly && 400 (fs->fs_flags & FS_UNCLEAN) == 0 ? 1 : 0; 401 ffs_sbupdate(ump, MNT_WAIT); 402 } 403 } 404 return (err); 405} 406 407/* 408 * Reload all incore data for a filesystem (used after running fsck on 409 * the root filesystem and finding things to fix). The filesystem must 410 * be mounted read-only. 411 * 412 * Things to do to update the mount: 413 * 1) invalidate all cached meta-data. 414 * 2) re-read superblock from disk. 415 * 3) re-read summary information from disk. 416 * 4) invalidate all inactive vnodes. 417 * 5) invalidate all cached file data. 418 * 6) re-read inode data for all active vnodes. 419 */ 420static int 421ffs_reload(mp, cred, p) 422 register struct mount *mp; 423 struct ucred *cred; 424 struct proc *p; 425{ 426 register struct vnode *vp, *nvp, *devvp; 427 struct inode *ip; 428 struct csum *space; 429 struct buf *bp; 430 struct fs *fs, *newfs; 431 struct partinfo dpart; 432 dev_t dev; 433 int i, blks, size, error; 434 int32_t *lp; 435 436 if ((mp->mnt_flag & MNT_RDONLY) == 0) 437 return (EINVAL); 438 /* 439 * Step 1: invalidate all cached meta-data. 440 */ 441 devvp = VFSTOUFS(mp)->um_devvp; 442 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); 443 error = vinvalbuf(devvp, 0, cred, p, 0, 0); 444 VOP_UNLOCK(devvp, 0, p); 445 if (error) 446 panic("ffs_reload: dirty1"); 447 448 dev = devvp->v_rdev; 449 450 /* 451 * Only VMIO the backing device if the backing device is a real 452 * block device. See ffs_mountmfs() for more details. 453 */ 454 if (devvp->v_tag != VT_MFS && devvp->v_type == VBLK) { 455 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); 456 vfs_object_create(devvp, p, p->p_ucred); 457 simple_lock(&devvp->v_interlock); 458 VOP_UNLOCK(devvp, LK_INTERLOCK, p); 459 } 460 461 /* 462 * Step 2: re-read superblock from disk. 463 */ 464 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0) 465 size = DEV_BSIZE; 466 else 467 size = dpart.disklab->d_secsize; 468 if ((error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, NOCRED,&bp)) != 0) 469 return (error); 470 newfs = (struct fs *)bp->b_data; 471 if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE || 472 newfs->fs_bsize < sizeof(struct fs)) { 473 brelse(bp); 474 return (EIO); /* XXX needs translation */ 475 } 476 fs = VFSTOUFS(mp)->um_fs; 477 /* 478 * Copy pointer fields back into superblock before copying in XXX 479 * new superblock. These should really be in the ufsmount. XXX 480 * Note that important parameters (eg fs_ncg) are unchanged. 481 */ 482 bcopy(&fs->fs_csp[0], &newfs->fs_csp[0], sizeof(fs->fs_csp)); 483 newfs->fs_maxcluster = fs->fs_maxcluster; 484 bcopy(newfs, fs, (u_int)fs->fs_sbsize); 485 if (fs->fs_sbsize < SBSIZE) 486 bp->b_flags |= B_INVAL; 487 brelse(bp); 488 mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen; 489 ffs_oldfscompat(fs); 490 491 /* 492 * Step 3: re-read summary information from disk. 493 */ 494 blks = howmany(fs->fs_cssize, fs->fs_fsize); 495 space = fs->fs_csp[0]; 496 for (i = 0; i < blks; i += fs->fs_frag) { 497 size = fs->fs_bsize; 498 if (i + fs->fs_frag > blks) 499 size = (blks - i) * fs->fs_fsize; 500 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, 501 NOCRED, &bp); 502 if (error) 503 return (error); 504 bcopy(bp->b_data, fs->fs_csp[fragstoblks(fs, i)], (u_int)size); 505 brelse(bp); 506 } 507 /* 508 * We no longer know anything about clusters per cylinder group. 509 */ 510 if (fs->fs_contigsumsize > 0) { 511 lp = fs->fs_maxcluster; 512 for (i = 0; i < fs->fs_ncg; i++) 513 *lp++ = fs->fs_contigsumsize; 514 } 515 516loop: 517 simple_lock(&mntvnode_slock); 518 for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) { 519 if (vp->v_mount != mp) { 520 simple_unlock(&mntvnode_slock); 521 goto loop; 522 } 523 nvp = vp->v_mntvnodes.le_next; 524 /* 525 * Step 4: invalidate all inactive vnodes. 526 */ 527 if (vrecycle(vp, &mntvnode_slock, p)) 528 goto loop; 529 /* 530 * Step 5: invalidate all cached file data. 531 */ 532 simple_lock(&vp->v_interlock); 533 simple_unlock(&mntvnode_slock); 534 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) { 535 goto loop; 536 } 537 if (vinvalbuf(vp, 0, cred, p, 0, 0)) 538 panic("ffs_reload: dirty2"); 539 /* 540 * Step 6: re-read inode data for all active vnodes. 541 */ 542 ip = VTOI(vp); 543 error = 544 bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)), 545 (int)fs->fs_bsize, NOCRED, &bp); 546 if (error) { 547 vput(vp); 548 return (error); 549 } 550 ip->i_din = *((struct dinode *)bp->b_data + 551 ino_to_fsbo(fs, ip->i_number)); 552 ip->i_effnlink = ip->i_nlink; 553 brelse(bp); 554 vput(vp); 555 simple_lock(&mntvnode_slock); 556 } 557 simple_unlock(&mntvnode_slock); 558 return (0); 559} 560 561/* 562 * Common code for mount and mountroot 563 */ 564int 565ffs_mountfs(devvp, mp, p, malloctype) 566 register struct vnode *devvp; 567 struct mount *mp; 568 struct proc *p; 569 struct malloc_type *malloctype; 570{ 571 register struct ufsmount *ump; 572 struct buf *bp; 573 register struct fs *fs; 574 dev_t dev; 575 struct partinfo dpart; 576 caddr_t base, space; 577 int error, i, blks, size, ronly; 578 int32_t *lp; 579 struct ucred *cred; 580 u_int64_t maxfilesize; /* XXX */ 581 size_t strsize; 582 int ncount; 583 584 dev = devvp->v_rdev; 585 cred = p ? p->p_ucred : NOCRED; 586 /* 587 * Disallow multiple mounts of the same device. 588 * Disallow mounting of a device that is currently in use 589 * (except for root, which might share swap device for miniroot). 590 * Flush out any old buffers remaining from a previous use. 591 */ 592 error = vfs_mountedon(devvp); 593 if (error) 594 return (error); 595 ncount = vcount(devvp); 596 597 if (ncount > 1 && devvp != rootvp) 598 return (EBUSY); 599 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); 600 error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0); 601 VOP_UNLOCK(devvp, 0, p); 602 if (error) 603 return (error); 604 605 /* 606 * Only VMIO the backing device if the backing device is a real 607 * block device. This excludes the original MFS implementation. 608 * Note that it is optional that the backing device be VMIOed. This 609 * increases the opportunity for metadata caching. 610 */ 611 if (devvp->v_tag != VT_MFS && devvp->v_type == VBLK) { 612 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); 613 vfs_object_create(devvp, p, p->p_ucred); 614 simple_lock(&devvp->v_interlock); 615 VOP_UNLOCK(devvp, LK_INTERLOCK, p); 616 } 617 618 ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 619 error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p); 620 if (error) 621 return (error); 622 623 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0) 624 size = DEV_BSIZE; 625 else 626 size = dpart.disklab->d_secsize; 627 628 bp = NULL; 629 ump = NULL; 630 if ((error = bread(devvp, SBLOCK, SBSIZE, cred, &bp)) != 0) 631 goto out; 632 fs = (struct fs *)bp->b_data; 633 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 634 fs->fs_bsize < sizeof(struct fs)) { 635 error = EINVAL; /* XXX needs translation */ 636 goto out; 637 } 638 fs->fs_fmod = 0; 639 fs->fs_flags &= ~FS_UNCLEAN; 640 if (fs->fs_clean == 0) { 641 fs->fs_flags |= FS_UNCLEAN; 642 if (ronly || (mp->mnt_flag & MNT_FORCE)) { 643 printf( 644"WARNING: %s was not properly dismounted\n", 645 fs->fs_fsmnt); 646 } else { 647 printf( 648"WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n", 649 fs->fs_fsmnt); 650 error = EPERM; 651 goto out; 652 } 653 } 654 /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */ 655 if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) { 656 error = EROFS; /* needs translation */ 657 goto out; 658 } 659 ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK); 660 bzero((caddr_t)ump, sizeof *ump); 661 ump->um_malloctype = malloctype; 662 ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT, 663 M_WAITOK); 664 ump->um_blkatoff = ffs_blkatoff; 665 ump->um_truncate = ffs_truncate; 666 ump->um_update = ffs_update; 667 ump->um_valloc = ffs_valloc; 668 ump->um_vfree = ffs_vfree; 669 bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize); 670 if (fs->fs_sbsize < SBSIZE) 671 bp->b_flags |= B_INVAL; 672 brelse(bp); 673 bp = NULL; 674 fs = ump->um_fs; 675 fs->fs_ronly = ronly; 676 if (ronly == 0) { 677 fs->fs_fmod = 1; 678 fs->fs_clean = 0; 679 } 680 size = fs->fs_cssize; 681 blks = howmany(size, fs->fs_fsize); 682 if (fs->fs_contigsumsize > 0) 683 size += fs->fs_ncg * sizeof(int32_t); 684 base = space = malloc((u_long)size, M_UFSMNT, M_WAITOK); 685 for (i = 0; i < blks; i += fs->fs_frag) { 686 size = fs->fs_bsize; 687 if (i + fs->fs_frag > blks) 688 size = (blks - i) * fs->fs_fsize; 689 if ((error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, 690 cred, &bp)) != 0) { 691 free(base, M_UFSMNT); 692 goto out; 693 } 694 bcopy(bp->b_data, space, (u_int)size); 695 fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space; 696 space += size; 697 brelse(bp); 698 bp = NULL; 699 } 700 if (fs->fs_contigsumsize > 0) { 701 fs->fs_maxcluster = lp = (int32_t *)space; 702 for (i = 0; i < fs->fs_ncg; i++) 703 *lp++ = fs->fs_contigsumsize; 704 } 705 mp->mnt_data = (qaddr_t)ump; 706 mp->mnt_stat.f_fsid.val[0] = fs->fs_id[0]; 707 mp->mnt_stat.f_fsid.val[1] = fs->fs_id[1]; 708 if (fs->fs_id[0] == 0 || fs->fs_id[1] == 0 || 709 vfs_getvfs(&mp->mnt_stat.f_fsid)) 710 vfs_getnewfsid(mp); 711 mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen; 712 mp->mnt_flag |= MNT_LOCAL; 713 ump->um_mountp = mp; 714 ump->um_dev = dev; 715 ump->um_devvp = devvp; 716 ump->um_nindir = fs->fs_nindir; 717 ump->um_bptrtodb = fs->fs_fsbtodb; 718 ump->um_seqinc = fs->fs_frag; 719 for (i = 0; i < MAXQUOTAS; i++) 720 ump->um_quotas[i] = NULLVP; 721 devvp->v_specmountpoint = mp; 722 ffs_oldfscompat(fs); 723 724 /* 725 * Set FS local "last mounted on" information (NULL pad) 726 */ 727 copystr( mp->mnt_stat.f_mntonname, /* mount point*/ 728 fs->fs_fsmnt, /* copy area*/ 729 sizeof(fs->fs_fsmnt) - 1, /* max size*/ 730 &strsize); /* real size*/ 731 bzero( fs->fs_fsmnt + strsize, sizeof(fs->fs_fsmnt) - strsize); 732 733 if( mp->mnt_flag & MNT_ROOTFS) { 734 /* 735 * Root mount; update timestamp in mount structure. 736 * this will be used by the common root mount code 737 * to update the system clock. 738 */ 739 mp->mnt_time = fs->fs_time; 740 } 741 742 ump->um_savedmaxfilesize = fs->fs_maxfilesize; /* XXX */ 743 maxfilesize = (u_int64_t)0x40000000 * fs->fs_bsize - 1; /* XXX */ 744 if (fs->fs_maxfilesize > maxfilesize) /* XXX */ 745 fs->fs_maxfilesize = maxfilesize; /* XXX */ 746 if (ronly == 0) { 747 if ((fs->fs_flags & FS_DOSOFTDEP) && 748 (error = softdep_mount(devvp, mp, fs, cred)) != 0) { 749 free(base, M_UFSMNT); 750 goto out; 751 } 752 fs->fs_clean = 0; 753 (void) ffs_sbupdate(ump, MNT_WAIT); 754 } 755 return (0); 756out: 757 devvp->v_specmountpoint = NULL; 758 if (bp) 759 brelse(bp); 760 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p); 761 if (ump) { 762 free(ump->um_fs, M_UFSMNT); 763 free(ump, M_UFSMNT); 764 mp->mnt_data = (qaddr_t)0; 765 } 766 return (error); 767} 768 769/* 770 * Sanity checks for old file systems. 771 * 772 * XXX - goes away some day. 773 */ 774static int 775ffs_oldfscompat(fs) 776 struct fs *fs; 777{ 778 779 fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */ 780 fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */ 781 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 782 fs->fs_nrpos = 8; /* XXX */ 783 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ 784#if 0 785 int i; /* XXX */ 786 u_int64_t sizepb = fs->fs_bsize; /* XXX */ 787 /* XXX */ 788 fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */ 789 for (i = 0; i < NIADDR; i++) { /* XXX */ 790 sizepb *= NINDIR(fs); /* XXX */ 791 fs->fs_maxfilesize += sizepb; /* XXX */ 792 } /* XXX */ 793#endif 794 fs->fs_maxfilesize = (u_quad_t) 1LL << 39; 795 fs->fs_qbmask = ~fs->fs_bmask; /* XXX */ 796 fs->fs_qfmask = ~fs->fs_fmask; /* XXX */ 797 } /* XXX */ 798 return (0); 799} 800 801/* 802 * unmount system call 803 */ 804int 805ffs_unmount(mp, mntflags, p) 806 struct mount *mp; 807 int mntflags; 808 struct proc *p; 809{ 810 register struct ufsmount *ump; 811 register struct fs *fs; 812 int error, flags; 813 814 flags = 0; 815 if (mntflags & MNT_FORCE) { 816 flags |= FORCECLOSE; 817 } 818 if (mp->mnt_flag & MNT_SOFTDEP) { 819 if ((error = softdep_flushfiles(mp, flags, p)) != 0) 820 return (error); 821 } else { 822 if ((error = ffs_flushfiles(mp, flags, p)) != 0) 823 return (error); 824 } 825 ump = VFSTOUFS(mp); 826 fs = ump->um_fs; 827 if (fs->fs_ronly == 0) { 828 fs->fs_clean = fs->fs_flags & FS_UNCLEAN ? 0 : 1; 829 error = ffs_sbupdate(ump, MNT_WAIT); 830 if (error) { 831 fs->fs_clean = 0; 832 return (error); 833 } 834 } 835 ump->um_devvp->v_specmountpoint = NULL; 836 837 vinvalbuf(ump->um_devvp, V_SAVE, NOCRED, p, 0, 0); 838 error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE, 839 NOCRED, p); 840 841 vrele(ump->um_devvp); 842 843 free(fs->fs_csp[0], M_UFSMNT); 844 free(fs, M_UFSMNT); 845 free(ump, M_UFSMNT); 846 mp->mnt_data = (qaddr_t)0; 847 mp->mnt_flag &= ~MNT_LOCAL; 848 return (error); 849} 850 851/* 852 * Flush out all the files in a filesystem. 853 */ 854int 855ffs_flushfiles(mp, flags, p) 856 register struct mount *mp; 857 int flags; 858 struct proc *p; 859{ 860 register struct ufsmount *ump; 861 int error; 862 863 ump = VFSTOUFS(mp); 864#ifdef QUOTA 865 if (mp->mnt_flag & MNT_QUOTA) { 866 int i; 867 error = vflush(mp, NULLVP, SKIPSYSTEM|flags); 868 if (error) 869 return (error); 870 for (i = 0; i < MAXQUOTAS; i++) { 871 if (ump->um_quotas[i] == NULLVP) 872 continue; 873 quotaoff(p, mp, i); 874 } 875 /* 876 * Here we fall through to vflush again to ensure 877 * that we have gotten rid of all the system vnodes. 878 */ 879 } 880#endif 881 /* 882 * Flush all the files. 883 */ 884 if ((error = vflush(mp, NULL, flags)) != 0) 885 return (error); 886 /* 887 * Flush filesystem metadata. 888 */ 889 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p); 890 error = VOP_FSYNC(ump->um_devvp, p->p_ucred, MNT_WAIT, p); 891 VOP_UNLOCK(ump->um_devvp, 0, p); 892 return (error); 893} 894 895/* 896 * Get file system statistics. 897 */ 898int 899ffs_statfs(mp, sbp, p) 900 struct mount *mp; 901 register struct statfs *sbp; 902 struct proc *p; 903{ 904 register struct ufsmount *ump; 905 register struct fs *fs; 906 907 ump = VFSTOUFS(mp); 908 fs = ump->um_fs; 909 if (fs->fs_magic != FS_MAGIC) 910 panic("ffs_statfs"); 911 sbp->f_bsize = fs->fs_fsize; 912 sbp->f_iosize = fs->fs_bsize; 913 sbp->f_blocks = fs->fs_dsize; 914 sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + 915 fs->fs_cstotal.cs_nffree; 916 sbp->f_bavail = freespace(fs, fs->fs_minfree); 917 sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO; 918 sbp->f_ffree = fs->fs_cstotal.cs_nifree; 919 if (sbp != &mp->mnt_stat) { 920 sbp->f_type = mp->mnt_vfc->vfc_typenum; 921 bcopy((caddr_t)mp->mnt_stat.f_mntonname, 922 (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 923 bcopy((caddr_t)mp->mnt_stat.f_mntfromname, 924 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 925 } 926 return (0); 927} 928 929/* 930 * Go through the disk queues to initiate sandbagged IO; 931 * go through the inodes to write those that have been modified; 932 * initiate the writing of the super block if it has been modified. 933 * 934 * Note: we are always called with the filesystem marked `MPBUSY'. 935 */ 936int 937ffs_sync(mp, waitfor, cred, p) 938 struct mount *mp; 939 int waitfor; 940 struct ucred *cred; 941 struct proc *p; 942{ 943 struct vnode *nvp, *vp; 944 struct inode *ip; 945 struct ufsmount *ump = VFSTOUFS(mp); 946 struct fs *fs; 947 int error, allerror = 0; 948 949 fs = ump->um_fs; 950 if (fs->fs_fmod != 0 && fs->fs_ronly != 0) { /* XXX */ 951 printf("fs = %s\n", fs->fs_fsmnt); 952 panic("ffs_sync: rofs mod"); 953 } 954 /* 955 * Write back each (modified) inode. 956 */ 957 simple_lock(&mntvnode_slock); 958loop: 959 for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) { 960 /* 961 * If the vnode that we are about to sync is no longer 962 * associated with this mount point, start over. 963 */ 964 if (vp->v_mount != mp) 965 goto loop; 966 simple_lock(&vp->v_interlock); 967 nvp = vp->v_mntvnodes.le_next; 968 ip = VTOI(vp); 969 if ((vp->v_type == VNON) || (((ip->i_flag & 970 (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0) && 971 (TAILQ_EMPTY(&vp->v_dirtyblkhd) || (waitfor == MNT_LAZY)))) { 972 simple_unlock(&vp->v_interlock); 973 continue; 974 } 975 if (vp->v_type != VCHR) { 976 simple_unlock(&mntvnode_slock); 977 error = 978 vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p); 979 if (error) { 980 simple_lock(&mntvnode_slock); 981 if (error == ENOENT) 982 goto loop; 983 continue; 984 } 985 if ((error = VOP_FSYNC(vp, cred, waitfor, p)) != 0) 986 allerror = error; 987 VOP_UNLOCK(vp, 0, p); 988 vrele(vp); 989 simple_lock(&mntvnode_slock); 990 } else { 991 simple_unlock(&mntvnode_slock); 992 simple_unlock(&vp->v_interlock); 993 /* UFS_UPDATE(vp, waitfor == MNT_WAIT); */ 994 UFS_UPDATE(vp, 0); 995 simple_lock(&mntvnode_slock); 996 } 997 } 998 simple_unlock(&mntvnode_slock); 999 /* 1000 * Force stale file system control information to be flushed. 1001 */ 1002 if (waitfor != MNT_LAZY) { 1003 if (ump->um_mountp->mnt_flag & MNT_SOFTDEP) 1004 waitfor = MNT_NOWAIT; 1005 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p); 1006 if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0) 1007 allerror = error; 1008 VOP_UNLOCK(ump->um_devvp, 0, p); 1009 } 1010#ifdef QUOTA 1011 qsync(mp); 1012#endif 1013 /* 1014 * Write back modified superblock. 1015 */ 1016 if (fs->fs_fmod != 0 && (error = ffs_sbupdate(ump, waitfor)) != 0) 1017 allerror = error; 1018 return (allerror); 1019} 1020 1021/* 1022 * Look up a FFS dinode number to find its incore vnode, otherwise read it 1023 * in from disk. If it is in core, wait for the lock bit to clear, then 1024 * return the inode locked. Detection and handling of mount points must be 1025 * done by the calling routine. 1026 */ 1027static int ffs_inode_hash_lock; 1028 1029int 1030ffs_vget(mp, ino, vpp) 1031 struct mount *mp; 1032 ino_t ino; 1033 struct vnode **vpp; 1034{ 1035 struct fs *fs; 1036 struct inode *ip; 1037 struct ufsmount *ump; 1038 struct buf *bp; 1039 struct vnode *vp; 1040 dev_t dev; 1041 int error; 1042 1043 ump = VFSTOUFS(mp); 1044 dev = ump->um_dev; 1045restart: 1046 if ((*vpp = ufs_ihashget(dev, ino)) != NULL) { 1047 return (0); 1048 } 1049 1050 /* 1051 * Lock out the creation of new entries in the FFS hash table in 1052 * case getnewvnode() or MALLOC() blocks, otherwise a duplicate 1053 * may occur! 1054 */ 1055 if (ffs_inode_hash_lock) { 1056 while (ffs_inode_hash_lock) { 1057 ffs_inode_hash_lock = -1; 1058 tsleep(&ffs_inode_hash_lock, PVM, "ffsvgt", 0); 1059 } 1060 goto restart; 1061 } 1062 ffs_inode_hash_lock = 1; 1063 1064 /* 1065 * If this MALLOC() is performed after the getnewvnode() 1066 * it might block, leaving a vnode with a NULL v_data to be 1067 * found by ffs_sync() if a sync happens to fire right then, 1068 * which will cause a panic because ffs_sync() blindly 1069 * dereferences vp->v_data (as well it should). 1070 */ 1071 MALLOC(ip, struct inode *, sizeof(struct inode), 1072 ump->um_malloctype, M_WAITOK); 1073 1074 /* Allocate a new vnode/inode. */ 1075 error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp); 1076 if (error) { 1077 if (ffs_inode_hash_lock < 0) 1078 wakeup(&ffs_inode_hash_lock); 1079 ffs_inode_hash_lock = 0; 1080 *vpp = NULL; 1081 FREE(ip, ump->um_malloctype); 1082 return (error); 1083 } 1084 bzero((caddr_t)ip, sizeof(struct inode)); 1085 lockinit(&ip->i_lock, PINOD, "inode", 0, 0); 1086 vp->v_data = ip; 1087 ip->i_vnode = vp; 1088 ip->i_fs = fs = ump->um_fs; 1089 ip->i_dev = dev; 1090 ip->i_number = ino; 1091#ifdef QUOTA 1092 { 1093 int i; 1094 for (i = 0; i < MAXQUOTAS; i++) 1095 ip->i_dquot[i] = NODQUOT; 1096 } 1097#endif 1098 /* 1099 * Put it onto its hash chain and lock it so that other requests for 1100 * this inode will block if they arrive while we are sleeping waiting 1101 * for old data structures to be purged or for the contents of the 1102 * disk portion of this inode to be read. 1103 */ 1104 ufs_ihashins(ip); 1105 1106 if (ffs_inode_hash_lock < 0) 1107 wakeup(&ffs_inode_hash_lock); 1108 ffs_inode_hash_lock = 0; 1109 1110 /* Read in the disk contents for the inode, copy into the inode. */ 1111 error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)), 1112 (int)fs->fs_bsize, NOCRED, &bp); 1113 if (error) { 1114 /* 1115 * The inode does not contain anything useful, so it would 1116 * be misleading to leave it on its hash chain. With mode 1117 * still zero, it will be unlinked and returned to the free 1118 * list by vput(). 1119 */ 1120 brelse(bp); 1121 vput(vp); 1122 *vpp = NULL; 1123 return (error); 1124 } 1125 ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino)); 1126 if (DOINGSOFTDEP(vp)) 1127 softdep_load_inodeblock(ip); 1128 else 1129 ip->i_effnlink = ip->i_nlink; 1130 bqrelse(bp); 1131 1132 /* 1133 * Initialize the vnode from the inode, check for aliases. 1134 * Note that the underlying vnode may have changed. 1135 */ 1136 error = ufs_vinit(mp, ffs_specop_p, ffs_fifoop_p, &vp); 1137 if (error) { 1138 vput(vp); 1139 *vpp = NULL; 1140 return (error); 1141 } 1142 /* 1143 * Finish inode initialization now that aliasing has been resolved. 1144 */ 1145 ip->i_devvp = ump->um_devvp; 1146 VREF(ip->i_devvp); 1147 /* 1148 * Set up a generation number for this inode if it does not 1149 * already have one. This should only happen on old filesystems. 1150 */ 1151 if (ip->i_gen == 0) { 1152 ip->i_gen = random() / 2 + 1; 1153 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) 1154 ip->i_flag |= IN_MODIFIED; 1155 } 1156 /* 1157 * Ensure that uid and gid are correct. This is a temporary 1158 * fix until fsck has been changed to do the update. 1159 */ 1160 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ 1161 ip->i_uid = ip->i_din.di_ouid; /* XXX */ 1162 ip->i_gid = ip->i_din.di_ogid; /* XXX */ 1163 } /* XXX */ 1164 1165 *vpp = vp; 1166 return (0); 1167} 1168 1169/* 1170 * File handle to vnode 1171 * 1172 * Have to be really careful about stale file handles: 1173 * - check that the inode number is valid 1174 * - call ffs_vget() to get the locked inode 1175 * - check for an unallocated inode (i_mode == 0) 1176 * - check that the given client host has export rights and return 1177 * those rights via. exflagsp and credanonp 1178 */ 1179int 1180ffs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) 1181 register struct mount *mp; 1182 struct fid *fhp; 1183 struct sockaddr *nam; 1184 struct vnode **vpp; 1185 int *exflagsp; 1186 struct ucred **credanonp; 1187{ 1188 register struct ufid *ufhp; 1189 struct fs *fs; 1190 1191 ufhp = (struct ufid *)fhp; 1192 fs = VFSTOUFS(mp)->um_fs; 1193 if (ufhp->ufid_ino < ROOTINO || 1194 ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) 1195 return (ESTALE); 1196 return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp)); 1197} 1198 1199/* 1200 * Vnode pointer to File handle 1201 */ 1202/* ARGSUSED */ 1203int 1204ffs_vptofh(vp, fhp) 1205 struct vnode *vp; 1206 struct fid *fhp; 1207{ 1208 register struct inode *ip; 1209 register struct ufid *ufhp; 1210 1211 ip = VTOI(vp); 1212 ufhp = (struct ufid *)fhp; 1213 ufhp->ufid_len = sizeof(struct ufid); 1214 ufhp->ufid_ino = ip->i_number; 1215 ufhp->ufid_gen = ip->i_gen; 1216 return (0); 1217} 1218 1219/* 1220 * Initialize the filesystem; just use ufs_init. 1221 */ 1222static int 1223ffs_init(vfsp) 1224 struct vfsconf *vfsp; 1225{ 1226 1227 softdep_initialize(); 1228 return (ufs_init(vfsp)); 1229} 1230 1231/* 1232 * Write a superblock and associated information back to disk. 1233 */ 1234static int 1235ffs_sbupdate(mp, waitfor) 1236 struct ufsmount *mp; 1237 int waitfor; 1238{ 1239 register struct fs *dfs, *fs = mp->um_fs; 1240 register struct buf *bp; 1241 int blks; 1242 caddr_t space; 1243 int i, size, error, allerror = 0; 1244 1245 /* 1246 * First write back the summary information. 1247 */ 1248 blks = howmany(fs->fs_cssize, fs->fs_fsize); 1249 space = (caddr_t)fs->fs_csp[0]; 1250 for (i = 0; i < blks; i += fs->fs_frag) { 1251 size = fs->fs_bsize; 1252 if (i + fs->fs_frag > blks) 1253 size = (blks - i) * fs->fs_fsize; 1254 bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), 1255 size, 0, 0); 1256 bcopy(space, bp->b_data, (u_int)size); 1257 space += size; 1258 if (waitfor != MNT_WAIT) 1259 bawrite(bp); 1260 else if ((error = bwrite(bp)) != 0) 1261 allerror = error; 1262 } 1263 /* 1264 * Now write back the superblock itself. If any errors occurred 1265 * up to this point, then fail so that the superblock avoids 1266 * being written out as clean. 1267 */ 1268 if (allerror) 1269 return (allerror); 1270 bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0); 1271 fs->fs_fmod = 0; 1272 fs->fs_time = time_second; 1273 bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize); 1274 /* Restore compatibility to old file systems. XXX */ 1275 dfs = (struct fs *)bp->b_data; /* XXX */ 1276 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 1277 dfs->fs_nrpos = -1; /* XXX */ 1278 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ 1279 int32_t *lp, tmp; /* XXX */ 1280 /* XXX */ 1281 lp = (int32_t *)&dfs->fs_qbmask; /* XXX */ 1282 tmp = lp[4]; /* XXX */ 1283 for (i = 4; i > 0; i--) /* XXX */ 1284 lp[i] = lp[i-1]; /* XXX */ 1285 lp[0] = tmp; /* XXX */ 1286 } /* XXX */ 1287 dfs->fs_maxfilesize = mp->um_savedmaxfilesize; /* XXX */ 1288 if (waitfor != MNT_WAIT) 1289 bawrite(bp); 1290 else if ((error = bwrite(bp)) != 0) 1291 allerror = error; 1292 return (allerror); 1293} 1294