X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/031fd966fbe94f6ea8034d526bb72ae8a5f9655f..d7961b1db4e049660ccbe7026f356c9ee87c2cda:/usr/src/sys/ufs/ffs/ufs_vnops.c diff --git a/usr/src/sys/ufs/ffs/ufs_vnops.c b/usr/src/sys/ufs/ffs/ufs_vnops.c index 938f3760da..85c4a232e4 100644 --- a/usr/src/sys/ufs/ffs/ufs_vnops.c +++ b/usr/src/sys/ufs/ffs/ufs_vnops.c @@ -4,7 +4,7 @@ * * %sccs.include.redist.c% * - * @(#)ufs_vnops.c 7.65 (Berkeley) %G% + * @(#)ufs_vnops.c 7.74 (Berkeley) %G% */ #include @@ -30,82 +30,8 @@ #include #include -static int ufs_chmod __P((struct vnode *, int, struct proc *)); -static int ufs_chown __P((struct vnode *, u_int, u_int, struct proc *)); - -#ifdef FIFO -struct vnodeops fifo_inodeops = { - fifo_lookup, /* lookup */ - fifo_create, /* create */ - fifo_mknod, /* mknod */ - fifo_open, /* open */ - ufsfifo_close, /* close */ - ufs_access, /* access */ - ufs_getattr, /* getattr */ - ufs_setattr, /* setattr */ - ufsfifo_read, /* read */ - ufsfifo_write, /* write */ - fifo_ioctl, /* ioctl */ - fifo_select, /* select */ - fifo_mmap, /* mmap */ - fifo_fsync, /* fsync */ - fifo_seek, /* seek */ - fifo_remove, /* remove */ - fifo_link, /* link */ - fifo_rename, /* rename */ - fifo_mkdir, /* mkdir */ - fifo_rmdir, /* rmdir */ - fifo_symlink, /* symlink */ - fifo_readdir, /* readdir */ - fifo_readlink, /* readlink */ - fifo_abortop, /* abortop */ - ufs_inactive, /* inactive */ - ufs_reclaim, /* reclaim */ - ufs_lock, /* lock */ - ufs_unlock, /* unlock */ - fifo_bmap, /* bmap */ - fifo_strategy, /* strategy */ - ufs_print, /* print */ - ufs_islocked, /* islocked */ - fifo_advlock, /* advlock */ -}; -#endif /* FIFO */ - -struct vnodeops spec_inodeops = { - spec_lookup, /* lookup */ - spec_create, /* create */ - spec_mknod, /* mknod */ - spec_open, /* open */ - ufsspec_close, /* close */ - ufs_access, /* access */ - ufs_getattr, /* getattr */ - ufs_setattr, /* setattr */ - ufsspec_read, /* read */ - ufsspec_write, /* write */ - spec_ioctl, /* ioctl */ - spec_select, /* select */ - spec_mmap, /* mmap */ - spec_fsync, /* fsync */ - spec_seek, /* seek */ - spec_remove, /* remove */ - spec_link, /* link */ - spec_rename, /* rename */ - spec_mkdir, /* mkdir */ - spec_rmdir, /* rmdir */ - spec_symlink, /* symlink */ - spec_readdir, /* readdir */ - spec_readlink, /* readlink */ - spec_abortop, /* abortop */ - ufs_inactive, /* inactive */ - ufs_reclaim, /* reclaim */ - ufs_lock, /* lock */ - ufs_unlock, /* unlock */ - spec_bmap, /* bmap */ - spec_strategy, /* strategy */ - ufs_print, /* print */ - ufs_islocked, /* islocked */ - spec_advlock, /* advlock */ -}; +int ufs_chmod __P((struct vnode *, int, struct proc *)); +int ufs_chown __P((struct vnode *, u_int, u_int, struct proc *)); enum vtype iftovt_tab[16] = { VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON, @@ -115,24 +41,43 @@ int vttoif_tab[9] = { 0, IFREG, IFDIR, IFBLK, IFCHR, IFLNK, IFSOCK, IFIFO, IFMT, }; +#ifdef _NOQUAD +#define SETHIGH(q, h) (q).val[_QUAD_HIGHWORD] = (h) +#define SETLOW(q, l) (q).val[_QUAD_LOWWORD] = (l) +#else /* QUAD */ +union _qcvt { + quad_t qcvt; + long val[2]; +}; +#define SETHIGH(q, h) { \ + union _qcvt tmp; \ + tmp.qcvt = (q); \ + tmp.val[_QUAD_HIGHWORD] = (h); \ + (q) = tmp.qcvt; \ +} +#define SETLOW(q, l) { \ + union _qcvt tmp; \ + tmp.qcvt = (q); \ + tmp.val[_QUAD_LOWWORD] = (l); \ + (q) = tmp.qcvt; \ +} +#endif /* QUAD */ + /* * Create a regular file */ int -ufs_create(ndp, vap, p) - struct nameidata *ndp; +ufs_create(dvp, vpp, cnp, vap) + struct vnode *dvp; + struct vnode **vpp; + struct componentname *cnp; struct vattr *vap; - struct proc *p; { - struct ufsmount *ump; - struct inode *ip; int error; - ump = VFSTOUFS(ndp->ni_dvp->v_mount); if (error = - ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode), ndp, &ip)) + ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode), dvp, vpp, cnp)) return (error); - ndp->ni_vp = ITOV(ip); return (0); } @@ -141,21 +86,19 @@ ufs_create(ndp, vap, p) */ /* ARGSUSED */ int -ufs_mknod(ndp, vap, cred, p) - struct nameidata *ndp; +ufs_mknod(dvp, vpp, cnp, vap) + struct vnode *dvp; + struct vnode **vpp; + struct componentname *cnp; struct vattr *vap; - struct ucred *cred; - struct proc *p; { - register struct vnode *vp; - struct inode *ip; - struct ufsmount *ump; + register struct inode *ip; int error; - ump = VFSTOUFS(ndp->ni_dvp->v_mount); if (error = - ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode), ndp, &ip)) + ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode), dvp, vpp, cnp)) return (error); + ip = VTOI(*vpp); ip->i_flag |= IACC|IUPD|ICHG; if (vap->va_rdev != VNOVAL) { /* @@ -169,10 +112,10 @@ ufs_mknod(ndp, vap, cred, p) * checked to see if it is an alias of an existing entry * in the inode cache. */ - vp = ITOV(ip); - vput(vp); - vp->v_type = VNON; - vgone(vp); + vput(*vpp); + (*vpp)->v_type = VNON; + vgone(*vpp); + *vpp = 0; return (0); } @@ -312,10 +255,13 @@ ufs_getattr(vp, vap, cred, p) else if (vp->v_type == VCHR) vap->va_blocksize = MAXBSIZE; else - vap->va_blocksize = vp->v_mount->mnt_stat.f_bsize; + vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize; vap->va_bytes = dbtob(ip->i_blocks); +#ifdef _NOQUAD vap->va_bytes_rsv = 0; +#endif vap->va_type = vp->v_type; + vap->va_filerev = ip->i_modrev; return (0); } @@ -330,7 +276,6 @@ ufs_setattr(vp, vap, cred, p) struct proc *p; { register struct inode *ip; - struct ufsmount *ump; int error; /* @@ -348,15 +293,13 @@ ufs_setattr(vp, vap, cred, p) if (vap->va_uid != (u_short)VNOVAL || vap->va_gid != (u_short)VNOVAL) if (error = ufs_chown(vp, vap->va_uid, vap->va_gid, p)) return (error); - ip = VTOI(vp); - ump = VFSTOUFS(vp->v_mount); if (vap->va_size != VNOVAL) { if (vp->v_type == VDIR) return (EISDIR); - if (error = - (ump->um_itrunc)(ip, vap->va_size, 0)) /* XXX IO_SYNC? */ + if (error = VOP_TRUNCATE(vp, vap->va_size, 0)) /* IO_SYNC? */ return (error); } + ip = VTOI(vp); if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { if (cred->cr_uid != ip->i_uid && (error = suser(cred, &p->p_acflag))) @@ -366,8 +309,7 @@ ufs_setattr(vp, vap, cred, p) if (vap->va_mtime.tv_sec != VNOVAL) ip->i_flag |= IUPD; ip->i_flag |= ICHG; - if (error = - (ump->um_iupdat)(ip, &vap->va_atime, &vap->va_mtime, 1)) + if (error = VOP_UPDATE(vp, &vap->va_atime, &vap->va_mtime, 1)) return (error); } error = 0; @@ -392,7 +334,7 @@ ufs_setattr(vp, vap, cred, p) * Change the mode on a file. * Inode must be locked before calling. */ -int +static int ufs_chmod(vp, mode, p) register struct vnode *vp; register int mode; @@ -423,7 +365,7 @@ ufs_chmod(vp, mode, p) * Perform chown operation on inode ip; * inode must be locked prior to call. */ -int +static int ufs_chown(vp, uid, gid, p) register struct vnode *vp; u_int uid; @@ -594,16 +536,16 @@ ufs_seek(vp, oldoff, newoff, cred) * in unlinking directories. */ int -ufs_remove(ndp, p) - struct nameidata *ndp; - struct proc *p; +ufs_remove(dvp, vp, cnp) + struct vnode *dvp, *vp; + struct componentname *cnp; { register struct inode *ip, *dp; int error; - ip = VTOI(ndp->ni_vp); - dp = VTOI(ndp->ni_dvp); - error = ufs_dirremove(ndp); + ip = VTOI(vp); + dp = VTOI(dvp); + error = ufs_dirremove(dvp, cnp); if (!error) { ip->i_nlink--; ip->i_flag |= ICHG; @@ -620,36 +562,34 @@ ufs_remove(ndp, p) * link vnode call */ int -ufs_link(vp, ndp, p) - register struct vnode *vp; - register struct nameidata *ndp; - struct proc *p; +ufs_link(vp, tdvp, cnp) + register struct vnode *vp; /* source vnode */ + struct vnode *tdvp; + struct componentname *cnp; { register struct inode *ip; - struct ufsmount *ump; int error; #ifdef DIANOSTIC - if ((ndp->ni_nameiop & HASBUF) == 0) + if ((cnp->cn_flags & HASBUF) == 0) panic("ufs_link: no name"); #endif ip = VTOI(vp); if ((unsigned short)ip->i_nlink >= LINK_MAX) { - free(ndp->ni_pnbuf, M_NAMEI); + free(cnp->cn_pnbuf, M_NAMEI); return (EMLINK); } - if (ndp->ni_dvp != vp) + if (tdvp != vp) ILOCK(ip); ip->i_nlink++; ip->i_flag |= ICHG; - ump = VFSTOUFS(ndp->ni_dvp->v_mount); - error = (ump->um_iupdat)(ip, &time, &time, 1); + error = VOP_UPDATE(vp, &time, &time, 1); if (!error) - error = ufs_direnter(ip, ndp); - if (ndp->ni_dvp != vp) + error = ufs_direnter(ip, tdvp, cnp); + if (tdvp != vp) IUNLOCK(ip); - FREE(ndp->ni_pnbuf, M_NAMEI); - vput(ndp->ni_dvp); + FREE(cnp->cn_pnbuf, M_NAMEI); + vput(tdvp); if (error) { ip->i_nlink--; ip->i_flag |= ICHG; @@ -657,6 +597,182 @@ ufs_link(vp, ndp, p) return (error); } + + +/* + * relookup - lookup a path name component + * Used by lookup to re-aquire things. + */ +int +relookup(dvp, vpp, cnp) + struct vnode *dvp, **vpp; + struct componentname *cnp; +{ + register char *cp; /* pointer into pathname argument */ + register struct vnode *dp = 0; /* the directory we are searching */ + struct vnode *tdp; /* saved dp */ + struct mount *mp; /* mount table entry */ + int docache; /* == 0 do not cache last component */ + int wantparent; /* 1 => wantparent or lockparent flag */ + int rdonly; /* lookup read-only flag bit */ + int error = 0; + int newhash; + + /* + * Setup: break out flag bits into variables. + */ + wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT); + docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE; + if (cnp->cn_nameiop == DELETE || + (wantparent && cnp->cn_nameiop != CREATE)) + docache = 0; + rdonly = cnp->cn_flags & RDONLY; + cnp->cn_flags &= ~ISSYMLINK; + dp = dvp; + VOP_LOCK(dp); + +/* dirloop: */ + /* + * Search a new directory. + * + * The cn_hash value is for use by vfs_cache. + * The last component of the filename is left accessible via + * cnp->cn_nameptr for callers that need the name. Callers needing + * the name set the SAVENAME flag. When done, they assume + * responsibility for freeing the pathname buffer. + */ +#ifdef NAMEI_DIAGNOSTIC + newhash = 0; + for (cp = cnp->cn_nameptr; *cp != 0 && *cp != '/'; cp++) + newhash += (unsigned char)*cp; + if (newhash != cnp->cn_hash) + panic("relookup: bad hash"); + if (cnp->cn_namelen != cp - cnp->cn_nameptr) + panic ("relookup: bad len"); + { char c = *cp; + *cp = '\0'; + printf("{%s}: ", cnp->cn_nameptr); + *cp = c; } +#endif + + /* + * Check for degenerate name (e.g. / or "") + * which is a way of talking about a directory, + * e.g. like "/." or ".". + */ + if (cnp->cn_nameptr[0] == '\0') { + if (cnp->cn_nameiop != LOOKUP || wantparent) { + error = EISDIR; + goto bad; + } + if (dp->v_type != VDIR) { + error = ENOTDIR; + goto bad; + } + if (!(cnp->cn_flags & LOCKLEAF)) + VOP_UNLOCK(dp); + *vpp = dp; + if (cnp->cn_flags & SAVESTART) + panic("lookup: SAVESTART"); + return (0); + } + + if (cnp->cn_flags & ISDOTDOT) + panic ("relookup: lookup on dot-dot"); + + /* + * We now have a segment name to search for, and a directory to search. + */ + if (error = VOP_LOOKUP(dp, vpp, cnp)) { +#ifdef DIAGNOSTIC + if (*vpp != NULL) + panic("leaf should be empty"); +#endif +#ifdef NAMEI_DIAGNOSTIC + printf("not found\n"); +#endif + if (cnp->cn_nameiop == LOOKUP || cnp->cn_nameiop == DELETE || + error != ENOENT || *cp != 0) + goto bad; + /* + * If creating and at end of pathname, then can consider + * allowing file to be created. + */ + if (rdonly || (dvp->v_mount->mnt_flag & MNT_RDONLY)) { + error = EROFS; + goto bad; + } + /* + * We return with ni_vp NULL to indicate that the entry + * doesn't currently exist, leaving a pointer to the + * (possibly locked) directory inode in ndp->ni_dvp. + */ + if (cnp->cn_flags & SAVESTART) { + /* + * startdir == dvp, always + */ + VREF(dvp); + } + return (0); + } +#ifdef NAMEI_DIAGNOSTIC + printf("found\n"); +#endif + + dp = *vpp; +#ifdef DIAGNOSTIC + /* + * Check for symbolic link + */ + if (dp->v_type == VLNK) { + panic ("relookup: symlink found.\n"); + }; + + /* + * Check to see if the vnode has been mounted on; + * if so find the root of the mounted file system. + */ +#endif + + +nextname: + /* + * Check for read-only file systems. + */ + if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) { + /* + * Disallow directory write attempts on read-only + * file systems. + */ + if (rdonly || (dp->v_mount->mnt_flag & MNT_RDONLY) || + (wantparent && + (dvp->v_mount->mnt_flag & MNT_RDONLY))) { + error = EROFS; + goto bad2; + } + } + if (cnp->cn_flags & SAVESTART) { + /* ASSERT(dvp==ndp->ni_startdir) */ + VREF(dvp); + } + + if (!wantparent) + vrele(dvp); + if ((cnp->cn_flags & LOCKLEAF) == 0) + VOP_UNLOCK(dp); + return (0); + +bad2: + if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN)) + VOP_UNLOCK(dvp); + vrele(dvp); +bad: + vput(dp); + *vpp = NULL; + return (error); +} + + /* * Rename system call. * rename("foo", "bar"); @@ -682,34 +798,37 @@ ufs_link(vp, ndp, p) * directory. */ int -ufs_rename(fndp, tndp, p) - register struct nameidata *fndp, *tndp; - struct proc *p; +ufs_rename(fdvp, fvp, fcnp, + tdvp, tvp, tcnp) + struct vnode *fdvp, *fvp; + struct componentname *fcnp; + struct vnode *tdvp, *tvp; + struct componentname *tcnp; { register struct inode *ip, *xp, *dp; struct dirtemplate dirbuf; - struct ufsmount *ump; int doingdirectory = 0, oldparent = 0, newparent = 0; int error = 0; + int fdvpneedsrele = 1, tdvpneedsrele = 1; #ifdef DIANOSTIC - if ((tndp->ni_nameiop & HASBUF) == 0 || - (fndp->ni_nameiop & HASBUF) == 0) + if ((tcnp->cn_flags & HASBUF) == 0 || + (fcnp->cn_flags & HASBUF) == 0) panic("ufs_rename: no name"); #endif - dp = VTOI(fndp->ni_dvp); - ip = VTOI(fndp->ni_vp); + dp = VTOI(fdvp); + ip = VTOI(fvp); /* * Check if just deleting a link name. */ - if (fndp->ni_vp == tndp->ni_vp) { - VOP_ABORTOP(tndp); - vput(tndp->ni_dvp); - vput(tndp->ni_vp); - vrele(fndp->ni_dvp); + if (fvp == tvp) { + VOP_ABORTOP(tdvp, tcnp); + vput(tdvp); + vput(tvp); + vrele(fdvp); if ((ip->i_mode&IFMT) == IFDIR) { - VOP_ABORTOP(fndp); - vrele(fndp->ni_vp); + VOP_ABORTOP(fdvp, fcnp); + vrele(fvp); return (EINVAL); } doingdirectory = 0; @@ -720,22 +839,22 @@ ufs_rename(fndp, tndp, p) /* * Avoid ".", "..", and aliases of "." for obvious reasons. */ - if ((fndp->ni_namelen == 1 && fndp->ni_ptr[0] == '.') || - dp == ip || fndp->ni_isdotdot || (ip->i_flag & IRENAME)) { - VOP_ABORTOP(tndp); - vput(tndp->ni_dvp); - if (tndp->ni_vp) - vput(tndp->ni_vp); - VOP_ABORTOP(fndp); - vrele(fndp->ni_dvp); - vput(fndp->ni_vp); + if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') || + dp == ip || (fcnp->cn_flags&ISDOTDOT) || (ip->i_flag & IRENAME)) { + VOP_ABORTOP(tdvp, tcnp); + vput(tdvp); + if (tvp) + vput(tvp); + VOP_ABORTOP(fdvp, fcnp); + vrele(fdvp); + vput(fvp); return (EINVAL); } ip->i_flag |= IRENAME; oldparent = dp->i_number; doingdirectory++; } - vrele(fndp->ni_dvp); + vrele(fdvp); /* * 1) Bump link count while we're moving stuff @@ -745,18 +864,17 @@ ufs_rename(fndp, tndp, p) */ ip->i_nlink++; ip->i_flag |= ICHG; - ump = VFSTOUFS(fndp->ni_dvp->v_mount); - error = (ump->um_iupdat)(ip, &time, &time, 1); + error = VOP_UPDATE(fvp, &time, &time, 1); IUNLOCK(ip); /* * When the target exists, both the directory * and target vnodes are returned locked. */ - dp = VTOI(tndp->ni_dvp); + dp = VTOI(tdvp); xp = NULL; - if (tndp->ni_vp) - xp = VTOI(tndp->ni_vp); + if (tvp) + xp = VTOI(tvp); /* * If ".." must be changed (ie the directory gets a new * parent) then the source directory must not be in the @@ -770,24 +888,24 @@ ufs_rename(fndp, tndp, p) if (oldparent != dp->i_number) newparent = dp->i_number; if (doingdirectory && newparent) { - VOP_LOCK(fndp->ni_vp); - error = ufs_access(fndp->ni_vp, VWRITE, tndp->ni_cred, p); - VOP_UNLOCK(fndp->ni_vp); + VOP_LOCK(fvp); + error = ufs_access(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc); + VOP_UNLOCK(fvp); if (error) goto bad; if (xp != NULL) ufs_iput(xp); - if (error = ufs_checkpath(ip, dp, tndp->ni_cred)) + if (error = ufs_checkpath(ip, dp, tcnp->cn_cred)) goto out; - if ((tndp->ni_nameiop & SAVESTART) == 0) + if ((tcnp->cn_flags & SAVESTART) == 0) panic("ufs_rename: lost to startdir"); p->p_spare[1]--; - if (error = lookup(tndp, p)) + if (error = relookup(tdvp, &tvp, tcnp)) goto out; - dp = VTOI(tndp->ni_dvp); + dp = VTOI(tdvp); xp = NULL; - if (tndp->ni_vp) - xp = VTOI(tndp->ni_vp); + if (tvp) + xp = VTOI(tvp); } /* * 2) If target doesn't exist, link the target @@ -811,14 +929,14 @@ ufs_rename(fndp, tndp, p) } dp->i_nlink++; dp->i_flag |= ICHG; - if (error = (ump->um_iupdat)(dp, &time, &time, 1)) + if (error = VOP_UPDATE(ITOV(dp), &time, &time, 1)) goto bad; } - if (error = ufs_direnter(ip, tndp)) { + if (error = ufs_direnter(ip, tdvp, tcnp)) { if (doingdirectory && newparent) { dp->i_nlink--; dp->i_flag |= ICHG; - (void)(ump->um_iupdat)(dp, &time, &time, 1); + (void)VOP_UPDATE(ITOV(dp), &time, &time, 1); } goto bad; } @@ -837,9 +955,9 @@ ufs_rename(fndp, tndp, p) * otherwise the destination may not be changed (except by * root). This implements append-only directories. */ - if ((dp->i_mode & ISVTX) && tndp->ni_cred->cr_uid != 0 && - tndp->ni_cred->cr_uid != dp->i_uid && - xp->i_uid != tndp->ni_cred->cr_uid) { + if ((dp->i_mode & ISVTX) && tcnp->cn_cred->cr_uid != 0 && + tcnp->cn_cred->cr_uid != dp->i_uid && + xp->i_uid != tcnp->cn_cred->cr_uid) { error = EPERM; goto bad; } @@ -849,7 +967,7 @@ ufs_rename(fndp, tndp, p) * (both directories, or both not directories). */ if ((xp->i_mode&IFMT) == IFDIR) { - if (!ufs_dirempty(xp, dp->i_number, tndp->ni_cred) || + if (!ufs_dirempty(xp, dp->i_number, tcnp->cn_cred) || xp->i_nlink > 2) { error = ENOTEMPTY; goto bad; @@ -863,7 +981,7 @@ ufs_rename(fndp, tndp, p) error = EISDIR; goto bad; } - if (error = ufs_dirrewrite(dp, ip, tndp)) + if (error = ufs_dirrewrite(dp, ip, tcnp)) goto bad; /* * If the target directory is in the same @@ -875,7 +993,7 @@ ufs_rename(fndp, tndp, p) dp->i_nlink--; dp->i_flag |= ICHG; } - vput(ITOV(dp)); + ufs_iput(dp); /* * Adjust the link count of the target to * reflect the dirrewrite above. If this is @@ -890,7 +1008,7 @@ ufs_rename(fndp, tndp, p) if (doingdirectory) { if (--xp->i_nlink != 0) panic("rename: linked directory"); - error = (ump->um_itrunc)(xp, (u_long)0, IO_SYNC); + error = VOP_TRUNCATE(ITOV(xp), (u_long)0, IO_SYNC); } xp->i_flag |= ICHG; ufs_iput(xp); @@ -901,15 +1019,15 @@ ufs_rename(fndp, tndp, p) * 3) Unlink the source. */ unlinkit: - fndp->ni_nameiop &= ~MODMASK; - fndp->ni_nameiop |= LOCKPARENT | LOCKLEAF; - if ((fndp->ni_nameiop & SAVESTART) == 0) + fcnp->cn_flags &= ~MODMASK; + fcnp->cn_flags |= LOCKPARENT | LOCKLEAF; + if ((fcnp->cn_flags & SAVESTART) == 0) panic("ufs_rename: lost from startdir"); p->p_spare[1]--; - (void) lookup(fndp, p); - if (fndp->ni_vp != NULL) { - xp = VTOI(fndp->ni_vp); - dp = VTOI(fndp->ni_dvp); + (void) relookup(fdvp, &fvp, fcnp); /* NEEDSWORK: startdir stuff */ + if (fvp != NULL) { + xp = VTOI(fvp); + dp = VTOI(fdvp); } else { /* * From name has disappeared. @@ -945,7 +1063,7 @@ unlinkit: error = vn_rdwr(UIO_READ, ITOV(xp), (caddr_t)&dirbuf, sizeof (struct dirtemplate), (off_t)0, UIO_SYSSPACE, IO_NODELOCKED, - tndp->ni_cred, (int *)0, (struct proc *)0); + tcnp->cn_cred, (int *)0, (struct proc *)0); if (error == 0) { if (dirbuf.dotdot_namlen != 2 || dirbuf.dotdot_name[0] != '.' || @@ -959,13 +1077,13 @@ unlinkit: sizeof (struct dirtemplate), (off_t)0, UIO_SYSSPACE, IO_NODELOCKED|IO_SYNC, - tndp->ni_cred, (int *)0, + tcnp->cn_cred, (int *)0, (struct proc *)0); cache_purge(ITOV(dp)); } } } - error = ufs_dirremove(fndp); + error = ufs_dirremove(fdvp, fcnp); if (!error) { xp->i_nlink--; xp->i_flag |= ICHG; @@ -1002,27 +1120,25 @@ static struct dirtemplate mastertemplate = { * Mkdir system call */ int -ufs_mkdir(ndp, vap, p) - struct nameidata *ndp; +ufs_mkdir(dvp, vpp, cnp, vap) + struct vnode *dvp; + struct vnode **vpp; + struct componentname *cnp; struct vattr *vap; - struct proc *p; { register struct inode *ip, *dp; - struct inode *tip; - struct ufsmount *ump; - struct vnode *dvp; + struct vnode *tvp; struct dirtemplate dirtemplate; int error; int dmode; #ifdef DIANOSTIC - if ((ndp->ni_nameiop & HASBUF) == 0) + if ((cnp->cn_flags & HASBUF) == 0) panic("ufs_mkdir: no name"); #endif - dvp = ndp->ni_dvp; dp = VTOI(dvp); if ((unsigned short)dp->i_nlink >= LINK_MAX) { - free(ndp->ni_pnbuf, M_NAMEI); + free(cnp->cn_pnbuf, M_NAMEI); ufs_iput(dp); return (EMLINK); } @@ -1033,20 +1149,19 @@ ufs_mkdir(ndp, vap, p) * not have it entered in the parent directory. The entry is made * later after writing "." and ".." entries. */ - ump = VFSTOUFS(ndp->ni_dvp->v_mount); - if (error = (ump->um_ialloc)(dp, dmode, ndp->ni_cred, &tip)) { - free(ndp->ni_pnbuf, M_NAMEI); + if (error = VOP_VALLOC(dvp, dmode, cnp->cn_cred, &tvp)) { + free(cnp->cn_pnbuf, M_NAMEI); ufs_iput(dp); return (error); } - ip = tip; - ip->i_uid = ndp->ni_cred->cr_uid; + ip = VTOI(tvp); + ip->i_uid = cnp->cn_cred->cr_uid; ip->i_gid = dp->i_gid; #ifdef QUOTA if ((error = getinoquota(ip)) || - (error = chkiq(ip, 1, ndp->ni_cred, 0))) { - free(ndp->ni_pnbuf, M_NAMEI); - (ump->um_ifree)(ip, ip->i_number, dmode); + (error = chkiq(ip, 1, cnp->cn_cred, 0))) { + free(cnp->cn_pnbuf, M_NAMEI); + VOP_VFREE(tvp, ip->i_number, dmode); ufs_iput(ip); ufs_iput(dp); return (error); @@ -1056,7 +1171,7 @@ ufs_mkdir(ndp, vap, p) ip->i_mode = dmode; ITOV(ip)->v_type = VDIR; /* Rest init'd in iget() */ ip->i_nlink = 2; - error = (ump->um_iupdat)(ip, &time, &time, 1); + error = VOP_UPDATE(ITOV(ip), &time, &time, 1); /* * Bump link count in parent directory @@ -1066,7 +1181,7 @@ ufs_mkdir(ndp, vap, p) */ dp->i_nlink++; dp->i_flag |= ICHG; - if (error = (ump->um_iupdat)(dp, &time, &time, 1)) + if (error = VOP_UPDATE(ITOV(dp), &time, &time, 1)) goto bad; /* Initialize directory with "." and ".." from static template. */ @@ -1075,13 +1190,13 @@ ufs_mkdir(ndp, vap, p) dirtemplate.dotdot_ino = dp->i_number; error = vn_rdwr(UIO_WRITE, ITOV(ip), (caddr_t)&dirtemplate, sizeof (dirtemplate), (off_t)0, UIO_SYSSPACE, - IO_NODELOCKED|IO_SYNC, ndp->ni_cred, (int *)0, (struct proc *)0); + IO_NODELOCKED|IO_SYNC, cnp->cn_cred, (int *)0, (struct proc *)0); if (error) { dp->i_nlink--; dp->i_flag |= ICHG; goto bad; } - if (DIRBLKSIZ > ump->um_mountp->mnt_stat.f_fsize) + if (DIRBLKSIZ > VFSTOUFS(dvp->v_mount)->um_mountp->mnt_stat.f_bsize) panic("ufs_mkdir: blksize"); /* XXX should grow with balloc() */ else { ip->i_size = DIRBLKSIZ; @@ -1089,22 +1204,22 @@ ufs_mkdir(ndp, vap, p) } /* Directory set up, now install it's entry in the parent directory. */ - if (error = ufs_direnter(ip, ndp)) { + if (error = ufs_direnter(ip, dvp, cnp)) { dp->i_nlink--; dp->i_flag |= ICHG; } bad: /* - * No need to do an explicit itrunc here, vrele will do this for us - * because we set the link count to 0. + * No need to do an explicit VOP_TRUNCATE here, vrele will do this + * for us because we set the link count to 0. */ if (error) { ip->i_nlink = 0; ip->i_flag |= ICHG; ufs_iput(ip); } else - ndp->ni_vp = ITOV(ip); - FREE(ndp->ni_pnbuf, M_NAMEI); + *vpp = ITOV(ip); + FREE(cnp->cn_pnbuf, M_NAMEI); ufs_iput(dp); return (error); } @@ -1113,21 +1228,21 @@ bad: * Rmdir system call. */ int -ufs_rmdir(ndp, p) - register struct nameidata *ndp; - struct proc *p; +ufs_rmdir(dvp, vp, cnp) + struct vnode *dvp; + struct vnode *vp; + struct componentname *cnp; { register struct inode *ip, *dp; - struct ufsmount *ump; int error; - ip = VTOI(ndp->ni_vp); - dp = VTOI(ndp->ni_dvp); + ip = VTOI(vp); + dp = VTOI(dvp); /* * No rmdir "." please. */ if (dp == ip) { - vrele(ITOV(dp)); + vrele(dvp); ufs_iput(ip); return (EINVAL); } @@ -1140,7 +1255,7 @@ ufs_rmdir(ndp, p) */ error = 0; if (ip->i_nlink != 2 || - !ufs_dirempty(ip, dp->i_number, ndp->ni_cred)) { + !ufs_dirempty(ip, dp->i_number, cnp->cn_cred)) { error = ENOTEMPTY; goto out; } @@ -1149,13 +1264,13 @@ ufs_rmdir(ndp, p) * inode. If we crash in between, the directory * will be reattached to lost+found, */ - if (error = ufs_dirremove(ndp)) + if (error = ufs_dirremove(dvp, cnp)) goto out; dp->i_nlink--; dp->i_flag |= ICHG; - cache_purge(ITOV(dp)); + cache_purge(dvp); ufs_iput(dp); - ndp->ni_dvp = NULL; + dvp = NULL; /* * Truncate inode. The only stuff left * in the directory is "." and "..". The @@ -1168,11 +1283,10 @@ ufs_rmdir(ndp, p) * worry about them later. */ ip->i_nlink -= 2; - ump = VFSTOUFS(ndp->ni_dvp->v_mount); - error = (ump->um_itrunc)(ip, (u_long)0, IO_SYNC); + error = VOP_TRUNCATE(vp, (u_long)0, IO_SYNC); cache_purge(ITOV(ip)); out: - if (ndp->ni_dvp) + if (dvp) ufs_iput(dp); ufs_iput(ip); return (error); @@ -1182,23 +1296,21 @@ out: * symlink -- make a symbolic link */ int -ufs_symlink(ndp, vap, target, p) - struct nameidata *ndp; +ufs_symlink(dvp, vpp, cnp, vap, target) + struct vnode *dvp; + struct vnode **vpp; + struct componentname *cnp; struct vattr *vap; char *target; - struct proc *p; { - struct inode *ip; - struct ufsmount *ump; int error; - ump = VFSTOUFS(ndp->ni_dvp->v_mount); - if (error = ufs_makeinode(IFLNK | vap->va_mode, ndp, &ip)) + if (error = ufs_makeinode(IFLNK | vap->va_mode, dvp, vpp, cnp)) return (error); - error = vn_rdwr(UIO_WRITE, ITOV(ip), target, strlen(target), (off_t)0, - UIO_SYSSPACE, IO_NODELOCKED, ndp->ni_cred, (int *)0, + error = vn_rdwr(UIO_WRITE, *vpp, target, strlen(target), (off_t)0, + UIO_SYSSPACE, IO_NODELOCKED, cnp->cn_cred, (int *)0, (struct proc *)0); - ufs_iput(ip); + vput(*vpp); return (error); } @@ -1249,12 +1361,12 @@ ufs_readlink(vp, uiop, cred) */ /* ARGSUSED */ int -ufs_abortop(ndp) - struct nameidata *ndp; +ufs_abortop(dvp, cnp) + struct vnode *dvp; + struct componentname *cnp; { - - if ((ndp->ni_nameiop & (HASBUF | SAVESTART)) == HASBUF) - FREE(ndp->ni_pnbuf, M_NAMEI); + if ((cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) + FREE(cnp->cn_pnbuf, M_NAMEI); return (0); } @@ -1299,28 +1411,6 @@ ufs_islocked(vp) return (0); } -/* - * Get access to bmap - */ -int -ufs_bmap(vp, bn, vpp, bnp) - struct vnode *vp; - daddr_t bn; - struct vnode **vpp; - daddr_t *bnp; -{ - struct inode *ip; - struct ufsmount *ump; - - ip = VTOI(vp); - if (vpp != NULL) - *vpp = ip->i_devvp; - if (bnp == NULL) - return (0); - ump = VFSTOUFS(vp->v_mount); - return ((ump->um_bmap)(ip, bn, bnp)); -} - /* * Calculate the logical to physical mapping if not done already, * then call the device strategy routine. @@ -1332,7 +1422,6 @@ ufs_strategy(bp) register struct buf *bp; { register struct inode *ip; - struct ufsmount *ump; struct vnode *vp; int error; @@ -1340,8 +1429,8 @@ ufs_strategy(bp) if (bp->b_vp->v_type == VBLK || bp->b_vp->v_type == VCHR) panic("ufs_strategy: spec"); if (bp->b_blkno == bp->b_lblkno) { - ump = VFSTOUFS(bp->b_vp->v_mount); - if (error = (ump->um_bmap)(ip, bp->b_lblkno, &bp->b_blkno)) + if (error = + VOP_BMAP(bp->b_vp, bp->b_lblkno, NULL, &bp->b_blkno)) return (error); if ((long)bp->b_blkno == -1) clrbuf(bp); @@ -1377,11 +1466,11 @@ ufs_print(vp) fifo_printinfo(vp); #endif /* FIFO */ printf("%s\n", (ip->i_flag & ILOCKED) ? " (LOCKED)" : ""); - if (ip->i_spare0 == 0) + if (ip->i_lockholder == 0) return (0); - printf("\towner pid %d", ip->i_spare0); - if (ip->i_spare1) - printf(" waiting pid %d", ip->i_spare1); + printf("\towner pid %d", ip->i_lockholder); + if (ip->i_lockwaiter) + printf(" waiting pid %d", ip->i_lockwaiter); printf("\n"); return (0); } @@ -1590,50 +1679,55 @@ ufs_advlock(vp, id, op, fl, flags) * vnodes. */ int -ufs_vinit(mntp, vpp) +ufs_vinit(mntp, specops, fifoops, vpp) struct mount *mntp; + struct vnodeops *specops, *fifoops; struct vnode **vpp; { struct inode *ip, *nip; struct vnode *vp, *nvp; + extern struct vnodeops spec_vnodeops; vp = *vpp; ip = VTOI(vp); switch(vp->v_type = IFTOVT(ip->i_mode)) { case VCHR: case VBLK: - vp->v_op = &spec_inodeops; + vp->v_op = specops; if (nvp = checkalias(vp, ip->i_rdev, mntp)) { - /* Reinitialize aliased inode. */ + /* + * Discard unneeded vnode, but save its inode. + */ + remque(ip); + IUNLOCK(ip); + nvp->v_data = vp->v_data; + vp->v_data = NULL; + vp->v_op = &spec_vnodeops; + vrele(vp); + vgone(vp); + /* + * Reinitialize aliased inode. + */ vp = nvp; - nip = VTOI(vp); - nip->i_vnode = vp; - nip->i_flag = 0; - nip->i_din = ip->i_din; - nip->i_dev = ip->i_dev; - nip->i_number = ip->i_number; - ufs_ihashins(nip); - - /* Discard unneeded inode. */ - ip->i_mode = 0; - ufs_iput(ip); - - ip = nip; + ip->i_vnode = vp; + ufs_ihashins(ip); } break; case VFIFO: #ifdef FIFO - vp->v_op = &fifo_inodeops; + vp->v_op = fifoops; break; #else return (EOPNOTSUPP); #endif } - VREF(ip->i_devvp); - if (ip->i_number == ROOTINO) vp->v_flag |= VROOT; - + /* + * Initialize modrev times + */ + SETHIGH(ip->i_modrev, mono_time.tv_sec); + SETLOW(ip->i_modrev, mono_time.tv_usec * 4294); *vpp = vp; return (0); } @@ -1642,39 +1736,38 @@ ufs_vinit(mntp, vpp) * Allocate a new inode. */ int -ufs_makeinode(mode, ndp, ipp) +ufs_makeinode(mode, dvp, vpp, cnp) int mode; - register struct nameidata *ndp; - struct inode **ipp; + struct vnode *dvp; + struct vnode **vpp; + struct componentname *cnp; { register struct inode *ip, *pdir; - struct inode *tip; - struct ufsmount *ump; + struct vnode *tvp; int error; - pdir = VTOI(ndp->ni_dvp); + pdir = VTOI(dvp); #ifdef DIANOSTIC - if ((ndp->ni_nameiop & HASBUF) == 0) + if ((cnp->cn_flags & HASBUF) == 0) panic("ufs_makeinode: no name"); #endif - *ipp = NULL; + *vpp = NULL; if ((mode & IFMT) == 0) mode |= IFREG; - ump = VFSTOUFS(ndp->ni_dvp->v_mount); - if (error = (ump->um_ialloc)(pdir, mode, ndp->ni_cred, &tip)) { - free(ndp->ni_pnbuf, M_NAMEI); + if (error = VOP_VALLOC(dvp, mode, cnp->cn_cred, &tvp)) { + free(cnp->cn_pnbuf, M_NAMEI); ufs_iput(pdir); return (error); } - ip = tip; - ip->i_uid = ndp->ni_cred->cr_uid; + ip = VTOI(tvp); + ip->i_uid = cnp->cn_cred->cr_uid; ip->i_gid = pdir->i_gid; #ifdef QUOTA if ((error = getinoquota(ip)) || - (error = chkiq(ip, 1, ndp->ni_cred, 0))) { - free(ndp->ni_pnbuf, M_NAMEI); - (ump->um_ifree)(ip, ip->i_number, mode); + (error = chkiq(ip, 1, cnp->cn_cred, 0))) { + free(cnp->cn_pnbuf, M_NAMEI); + VOP_VFREE(tvp, ip->i_number, mode); ufs_iput(ip); ufs_iput(pdir); return (error); @@ -1682,23 +1775,23 @@ ufs_makeinode(mode, ndp, ipp) #endif ip->i_flag |= IACC|IUPD|ICHG; ip->i_mode = mode; - ITOV(ip)->v_type = IFTOVT(mode); /* Rest init'd in iget() */ + tvp->v_type = IFTOVT(mode); /* Rest init'd in iget() */ ip->i_nlink = 1; - if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, ndp->ni_cred) && - suser(ndp->ni_cred, NULL)) + if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) && + suser(cnp->cn_cred, NULL)) ip->i_mode &= ~ISGID; /* * Make sure inode goes to disk before directory entry. */ - if (error = (ump->um_iupdat)(ip, &time, &time, 1)) + if (error = VOP_UPDATE(tvp, &time, &time, 1)) goto bad; - if (error = ufs_direnter(ip, ndp)) + if (error = ufs_direnter(ip, dvp, cnp)) goto bad; - if ((ndp->ni_nameiop & SAVESTART) == 0) - FREE(ndp->ni_pnbuf, M_NAMEI); + if ((cnp->cn_flags & SAVESTART) == 0) + FREE(cnp->cn_pnbuf, M_NAMEI); ufs_iput(pdir); - *ipp = ip; + *vpp = tvp; return (0); bad: @@ -1706,10 +1799,28 @@ bad: * Write error occurred trying to update the inode * or the directory so must deallocate the inode. */ - free(ndp->ni_pnbuf, M_NAMEI); + free(cnp->cn_pnbuf, M_NAMEI); ufs_iput(pdir); ip->i_nlink = 0; ip->i_flag |= ICHG; ufs_iput(ip); return (error); } + + +#if defined(JOHNH) && 0 +/* + * A hack to get the kernel to compile. + */ +int +hang_addrlist() +{ + return 0; +} +int +free_addrlist() +{ + return 0; +} +#endif +