X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/b9fc107764cb9ad04bba42829cfeb4f077c4143e..655da94564f7a532b437699be6af925d975ad125:/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 25e4356f4a..4757e49740 100644 --- a/usr/src/sys/ufs/ffs/ufs_vnops.c +++ b/usr/src/sys/ufs/ffs/ufs_vnops.c @@ -4,217 +4,38 @@ * * %sccs.include.redist.c% * - * @(#)ufs_vnops.c 7.55 (Berkeley) %G% + * @(#)ufs_vnops.c 7.63 (Berkeley) %G% */ #include "param.h" #include "systm.h" -#include "user.h" +#include "namei.h" +#include "resourcevar.h" #include "kernel.h" #include "file.h" #include "stat.h" #include "buf.h" #include "proc.h" -#include "socket.h" -#include "socketvar.h" #include "conf.h" #include "mount.h" #include "vnode.h" #include "specdev.h" -#include "fcntl.h" +#include "fifo.h" #include "malloc.h" -#include "../ufs/lockf.h" -#include "../ufs/quota.h" -#include "../ufs/inode.h" -#include "../ufs/fs.h" -/* - * Global vfs data structures for ufs - */ - -int ufs_lookup(), - ufs_create(), - ufs_mknod(), - ufs_open(), - ufs_close(), - ufs_access(), - ufs_getattr(), - ufs_setattr(), - ufs_read(), - ufs_write(), - ufs_ioctl(), - ufs_select(), - ufs_mmap(), - ufs_fsync(), - ufs_seek(), - ufs_remove(), - ufs_link(), - ufs_rename(), - ufs_mkdir(), - ufs_rmdir(), - ufs_symlink(), - ufs_readdir(), - ufs_readlink(), - ufs_abortop(), - ufs_inactive(), - ufs_reclaim(), - ufs_lock(), - ufs_unlock(), - ufs_bmap(), - ufs_strategy(), - ufs_print(), - ufs_islocked(), - ufs_advlock(); - -struct vnodeops ufs_vnodeops = { - ufs_lookup, /* lookup */ - ufs_create, /* create */ - ufs_mknod, /* mknod */ - ufs_open, /* open */ - ufs_close, /* close */ - ufs_access, /* access */ - ufs_getattr, /* getattr */ - ufs_setattr, /* setattr */ - ufs_read, /* read */ - ufs_write, /* write */ - ufs_ioctl, /* ioctl */ - ufs_select, /* select */ - ufs_mmap, /* mmap */ - ufs_fsync, /* fsync */ - ufs_seek, /* seek */ - ufs_remove, /* remove */ - ufs_link, /* link */ - ufs_rename, /* rename */ - ufs_mkdir, /* mkdir */ - ufs_rmdir, /* rmdir */ - ufs_symlink, /* symlink */ - ufs_readdir, /* readdir */ - ufs_readlink, /* readlink */ - ufs_abortop, /* abortop */ - ufs_inactive, /* inactive */ - ufs_reclaim, /* reclaim */ - ufs_lock, /* lock */ - ufs_unlock, /* unlock */ - ufs_bmap, /* bmap */ - ufs_strategy, /* strategy */ - ufs_print, /* print */ - ufs_islocked, /* islocked */ - ufs_advlock, /* advlock */ -}; - -int spec_lookup(), - spec_open(), - ufsspec_read(), - ufsspec_write(), - spec_strategy(), - spec_bmap(), - spec_ioctl(), - spec_select(), - ufsspec_close(), - spec_advlock(), - spec_badop(), - nullop(); - -struct vnodeops spec_inodeops = { - spec_lookup, /* lookup */ - spec_badop, /* create */ - spec_badop, /* 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_badop, /* mmap */ - nullop, /* fsync */ - spec_badop, /* seek */ - spec_badop, /* remove */ - spec_badop, /* link */ - spec_badop, /* rename */ - spec_badop, /* mkdir */ - spec_badop, /* rmdir */ - spec_badop, /* symlink */ - spec_badop, /* readdir */ - spec_badop, /* readlink */ - spec_badop, /* 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 */ -}; - -#ifdef FIFO -int fifo_lookup(), - fifo_open(), - ufsfifo_read(), - ufsfifo_write(), - fifo_bmap(), - fifo_ioctl(), - fifo_select(), - ufsfifo_close(), - fifo_print(), - fifo_advlock(), - fifo_badop(); - -struct vnodeops fifo_inodeops = { - fifo_lookup, /* lookup */ - fifo_badop, /* create */ - fifo_badop, /* 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_badop, /* mmap */ - nullop, /* fsync */ - fifo_badop, /* seek */ - fifo_badop, /* remove */ - fifo_badop, /* link */ - fifo_badop, /* rename */ - fifo_badop, /* mkdir */ - fifo_badop, /* rmdir */ - fifo_badop, /* symlink */ - fifo_badop, /* readdir */ - fifo_badop, /* readlink */ - fifo_badop, /* abortop */ - ufs_inactive, /* inactive */ - ufs_reclaim, /* reclaim */ - ufs_lock, /* lock */ - ufs_unlock, /* unlock */ - fifo_bmap, /* bmap */ - fifo_badop, /* strategy */ - ufs_print, /* print */ - ufs_islocked, /* islocked */ - fifo_advlock, /* advlock */ -}; -#endif /* FIFO */ - -enum vtype iftovt_tab[16] = { - VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON, - VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD, -}; -int vttoif_tab[9] = { - 0, IFREG, IFDIR, IFBLK, IFCHR, IFLNK, IFSOCK, IFIFO, IFMT, -}; +#include "lockf.h" +#include "quota.h" +#include "inode.h" +#include "dir.h" +#include "fs.h" /* * Create a regular file */ -ufs_create(ndp, vap) +ufs_create(ndp, vap, p) struct nameidata *ndp; struct vattr *vap; + struct proc *p; { struct inode *ip; int error; @@ -229,10 +50,11 @@ ufs_create(ndp, vap) * Mknod vnode call */ /* ARGSUSED */ -ufs_mknod(ndp, vap, cred) +ufs_mknod(ndp, vap, cred, p) struct nameidata *ndp; struct ucred *cred; struct vattr *vap; + struct proc *p; { register struct vnode *vp; struct inode *ip; @@ -266,10 +88,11 @@ ufs_mknod(ndp, vap, cred) * Nothing to do. */ /* ARGSUSED */ -ufs_open(vp, mode, cred) +ufs_open(vp, mode, cred, p) struct vnode *vp; int mode; struct ucred *cred; + struct proc *p; { return (0); @@ -281,10 +104,11 @@ ufs_open(vp, mode, cred) * Update the times on the inode. */ /* ARGSUSED */ -ufs_close(vp, fflag, cred) +ufs_close(vp, fflag, cred, p) struct vnode *vp; int fflag; struct ucred *cred; + struct proc *p; { register struct inode *ip = VTOI(vp); @@ -298,10 +122,11 @@ ufs_close(vp, fflag, cred) * The mode is shifted to select the owner/group/other fields. The * super user is granted all permissions. */ -ufs_access(vp, mode, cred) +ufs_access(vp, mode, cred, p) struct vnode *vp; register int mode; struct ucred *cred; + struct proc *p; { register struct inode *ip = VTOI(vp); register gid_t *gp; @@ -348,10 +173,11 @@ found: } /* ARGSUSED */ -ufs_getattr(vp, vap, cred) +ufs_getattr(vp, vap, cred, p) struct vnode *vp; register struct vattr *vap; struct ucred *cred; + struct proc *p; { register struct inode *ip = VTOI(vp); @@ -396,10 +222,11 @@ ufs_getattr(vp, vap, cred) /* * Set attribute vnode op. called from several syscalls */ -ufs_setattr(vp, vap, cred) +ufs_setattr(vp, vap, cred, p) register struct vnode *vp; register struct vattr *vap; register struct ucred *cred; + struct proc *p; { register struct inode *ip = VTOI(vp); int error = 0; @@ -417,7 +244,7 @@ ufs_setattr(vp, vap, cred) * Go through the fields and update iff not VNOVAL. */ if (vap->va_uid != (u_short)VNOVAL || vap->va_gid != (u_short)VNOVAL) - if (error = chown1(vp, vap->va_uid, vap->va_gid, cred)) + if (error = chown1(vp, vap->va_uid, vap->va_gid, p)) return (error); if (vap->va_size != VNOVAL) { if (vp->v_type == VDIR) @@ -427,7 +254,7 @@ ufs_setattr(vp, vap, cred) } if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { if (cred->cr_uid != ip->i_uid && - (error = suser(cred, &u.u_acflag))) + (error = suser(cred, &p->p_acflag))) return (error); if (vap->va_atime.tv_sec != VNOVAL) ip->i_flag |= IACC; @@ -438,10 +265,10 @@ ufs_setattr(vp, vap, cred) return (error); } if (vap->va_mode != (u_short)VNOVAL) - error = chmod1(vp, (int)vap->va_mode, cred); + error = chmod1(vp, (int)vap->va_mode, p); if (vap->va_flags != VNOVAL) { if (cred->cr_uid != ip->i_uid && - (error = suser(cred, &u.u_acflag))) + (error = suser(cred, &p->p_acflag))) return (error); if (cred->cr_uid == 0) { ip->i_flags = vap->va_flags; @@ -458,16 +285,17 @@ ufs_setattr(vp, vap, cred) * Change the mode on a file. * Inode must be locked before calling. */ -chmod1(vp, mode, cred) +chmod1(vp, mode, p) register struct vnode *vp; register int mode; - struct ucred *cred; + struct proc *p; { + register struct ucred *cred = p->p_ucred; register struct inode *ip = VTOI(vp); int error; if (cred->cr_uid != ip->i_uid && - (error = suser(cred, &u.u_acflag))) + (error = suser(cred, &p->p_acflag))) return (error); if (cred->cr_uid) { if (vp->v_type != VDIR && (mode & ISVTX)) @@ -487,13 +315,14 @@ chmod1(vp, mode, cred) * Perform chown operation on inode ip; * inode must be locked prior to call. */ -chown1(vp, uid, gid, cred) +chown1(vp, uid, gid, p) register struct vnode *vp; uid_t uid; gid_t gid; - struct ucred *cred; + struct proc *p; { register struct inode *ip = VTOI(vp); + register struct ucred *cred = p->p_ucred; uid_t ouid; gid_t ogid; int error = 0; @@ -513,7 +342,7 @@ chown1(vp, uid, gid, cred) */ if ((cred->cr_uid != ip->i_uid || uid != ip->i_uid || !groupmember((gid_t)gid, cred)) && - (error = suser(cred, &u.u_acflag))) + (error = suser(cred, &p->p_acflag))) return (error); ouid = ip->i_uid; ogid = ip->i_gid; @@ -605,11 +434,13 @@ ufs_read(vp, uio, ioflag, cred) int size, diff, error = 0; long n, on, type; +#ifdef DIAGNOSTIC if (uio->uio_rw != UIO_READ) panic("ufs_read mode"); type = ip->i_mode & IFMT; if (type != IFDIR && type != IFREG && type != IFLNK) panic("ufs_read type"); +#endif if (uio->uio_resid == 0) return (0); if (uio->uio_offset < 0) @@ -656,6 +487,7 @@ ufs_write(vp, uio, ioflag, cred) int ioflag; struct ucred *cred; { + struct proc *p = uio->uio_procp; register struct inode *ip = VTOI(vp); register struct fs *fs; struct buf *bp; @@ -664,8 +496,10 @@ ufs_write(vp, uio, ioflag, cred) int n, on, flags; int size, resid, error = 0; +#ifdef DIAGNOSTIC if (uio->uio_rw != UIO_WRITE) panic("ufs_write mode"); +#endif switch (vp->v_type) { case VREG: if (ioflag & IO_APPEND) @@ -690,10 +524,10 @@ ufs_write(vp, uio, ioflag, cred) * Maybe this should be above the vnode op call, but so long as * file servers have no limits, i don't think it matters */ - if (vp->v_type == VREG && + if (vp->v_type == VREG && p && uio->uio_offset + uio->uio_resid > - u.u_rlimit[RLIMIT_FSIZE].rlim_cur) { - psignal(u.u_procp, SIGXFSZ); + p->p_rlimit[RLIMIT_FSIZE].rlim_cur) { + psignal(p, SIGXFSZ); return (EFBIG); } resid = uio->uio_resid; @@ -743,25 +577,30 @@ ufs_write(vp, uio, ioflag, cred) } /* ARGSUSED */ -ufs_ioctl(vp, com, data, fflag, cred) +ufs_ioctl(vp, com, data, fflag, cred, p) struct vnode *vp; int com; caddr_t data; int fflag; struct ucred *cred; + struct proc *p; { return (ENOTTY); } /* ARGSUSED */ -ufs_select(vp, which, fflags, cred) +ufs_select(vp, which, fflags, cred, p) struct vnode *vp; int which, fflags; struct ucred *cred; + struct proc *p; { - return (1); /* XXX */ + /* + * We should really check to see if I/O is possible. + */ + return (1); } /* @@ -770,10 +609,11 @@ ufs_select(vp, which, fflags, cred) * NB Currently unsupported. */ /* ARGSUSED */ -ufs_mmap(vp, fflags, cred) +ufs_mmap(vp, fflags, cred, p) struct vnode *vp; int fflags; struct ucred *cred; + struct proc *p; { return (EINVAL); @@ -783,15 +623,16 @@ ufs_mmap(vp, fflags, cred) * Synch an open file. */ /* ARGSUSED */ -ufs_fsync(vp, fflags, cred, waitfor) +ufs_fsync(vp, fflags, cred, waitfor, p) struct vnode *vp; int fflags; struct ucred *cred; int waitfor; + struct proc *p; { struct inode *ip = VTOI(vp); - if (fflags&FWRITE) + if (fflags & FWRITE) ip->i_flag |= ICHG; vflushbuf(vp, waitfor == MNT_WAIT ? B_SYNC : 0); return (iupdat(ip, &time, &time, waitfor == MNT_WAIT)); @@ -817,8 +658,9 @@ ufs_seek(vp, oldoff, newoff, cred) * Hard to avoid races here, especially * in unlinking directories. */ -ufs_remove(ndp) +ufs_remove(ndp, p) struct nameidata *ndp; + struct proc *p; { register struct inode *ip, *dp; int error; @@ -841,15 +683,22 @@ ufs_remove(ndp) /* * link vnode call */ -ufs_link(vp, ndp) +ufs_link(vp, ndp, p) register struct vnode *vp; register struct nameidata *ndp; + struct proc *p; { register struct inode *ip = VTOI(vp); int error; - if ((unsigned short)ip->i_nlink >= LINK_MAX) +#ifdef DIANOSTIC + if ((ndp->ni_nameiop & HASBUF) == 0) + panic("ufs_link: no name"); +#endif + if ((unsigned short)ip->i_nlink >= LINK_MAX) { + free(ndp->ni_pnbuf, M_NAMEI); return (EMLINK); + } if (ndp->ni_dvp != vp) ILOCK(ip); ip->i_nlink++; @@ -859,6 +708,8 @@ ufs_link(vp, ndp) error = direnter(ip, ndp); if (ndp->ni_dvp != vp) IUNLOCK(ip); + FREE(ndp->ni_pnbuf, M_NAMEI); + vput(ndp->ni_dvp); if (error) { ip->i_nlink--; ip->i_flag |= ICHG; @@ -890,25 +741,45 @@ ufs_link(vp, ndp) * is different from the source, patch the ".." entry in the * directory. */ -ufs_rename(fndp, tndp) +ufs_rename(fndp, tndp, p) register struct nameidata *fndp, *tndp; + struct proc *p; { register struct inode *ip, *xp, *dp; struct dirtemplate dirbuf; int doingdirectory = 0, oldparent = 0, newparent = 0; int error = 0; +#ifdef DIANOSTIC + if ((tndp->ni_nameiop & HASBUF) == 0 || + (fndp->ni_nameiop & HASBUF) == 0) + panic("ufs_rename: no name"); +#endif dp = VTOI(fndp->ni_dvp); ip = VTOI(fndp->ni_vp); + /* + * 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 ((ip->i_mode&IFMT) == IFDIR) { + VOP_ABORTOP(fndp); + vrele(fndp->ni_vp); + return (EINVAL); + } + doingdirectory = 0; + goto unlinkit; + } ILOCK(ip); if ((ip->i_mode&IFMT) == IFDIR) { - register struct direct *d = &fndp->ni_dent; - /* * Avoid ".", "..", and aliases of "." for obvious reasons. */ - if ((d->d_namlen == 1 && d->d_name[0] == '.') || dp == ip || - fndp->ni_isdotdot || (ip->i_flag & IRENAME)) { + 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) @@ -957,24 +828,22 @@ ufs_rename(fndp, tndp) newparent = dp->i_number; if (doingdirectory && newparent) { VOP_LOCK(fndp->ni_vp); - error = ufs_access(fndp->ni_vp, VWRITE, tndp->ni_cred); + error = ufs_access(fndp->ni_vp, VWRITE, tndp->ni_cred, p); VOP_UNLOCK(fndp->ni_vp); if (error) goto bad; - tndp->ni_nameiop &= ~(MODMASK | OPMASK); - tndp->ni_nameiop |= RENAME | LOCKPARENT | LOCKLEAF | NOCACHE; - do { - dp = VTOI(tndp->ni_dvp); - if (xp != NULL) - iput(xp); - if (error = checkpath(ip, dp, tndp->ni_cred)) - goto out; - if (error = namei(tndp)) - goto out; - xp = NULL; - if (tndp->ni_vp) - xp = VTOI(tndp->ni_vp); - } while (dp != VTOI(tndp->ni_dvp)); + if (xp != NULL) + iput(xp); + if (error = checkpath(ip, dp, tndp->ni_cred)) + goto out; + if ((tndp->ni_nameiop & SAVESTART) == 0) + panic("ufs_rename: lost to startdir"); + if (error = lookup(tndp, p)) + goto out; + dp = VTOI(tndp->ni_dvp); + xp = NULL; + if (tndp->ni_vp) + xp = VTOI(tndp->ni_vp); } /* * 2) If target doesn't exist, link the target @@ -1001,8 +870,15 @@ ufs_rename(fndp, tndp) if (error = iupdat(dp, &time, &time, 1)) goto bad; } - if (error = direnter(ip, tndp)) - goto out; + if (error = direnter(ip, tndp)) { + if (doingdirectory && newparent) { + dp->i_nlink--; + dp->i_flag |= ICHG; + (void) iupdat(dp, &time, &time, 1); + } + goto bad; + } + iput(dp); } else { if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev) panic("rename: EXDEV"); @@ -1024,11 +900,9 @@ ufs_rename(fndp, tndp) goto bad; } /* - * Target must be empty if a directory - * and have no links to it. - * Also, insure source and target are - * compatible (both directories, or both - * not directories). + * Target must be empty if a directory and have no links + * to it. Also, ensure source and target are compatible + * (both directories, or both not directories). */ if ((xp->i_mode&IFMT) == IFDIR) { if (!dirempty(xp, dp->i_number, tndp->ni_cred) || @@ -1082,9 +956,12 @@ ufs_rename(fndp, tndp) /* * 3) Unlink the source. */ - fndp->ni_nameiop &= ~(MODMASK | OPMASK); - fndp->ni_nameiop |= DELETE | LOCKPARENT | LOCKLEAF; - (void)namei(fndp); +unlinkit: + fndp->ni_nameiop &= ~MODMASK; + fndp->ni_nameiop |= LOCKPARENT | LOCKLEAF; + if ((fndp->ni_nameiop & SAVESTART) == 0) + panic("ufs_rename: lost from startdir"); + (void) lookup(fndp, p); if (fndp->ni_vp != NULL) { xp = VTOI(fndp->ni_vp); dp = VTOI(fndp->ni_dvp); @@ -1123,7 +1000,7 @@ ufs_rename(fndp, tndp) 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); + tndp->ni_cred, (int *)0, (struct proc *)0); if (error == 0) { if (dirbuf.dotdot_namlen != 2 || dirbuf.dotdot_name[0] != '.' || @@ -1136,7 +1013,8 @@ ufs_rename(fndp, tndp) sizeof (struct dirtemplate), (off_t)0, UIO_SYSSPACE, IO_NODELOCKED|IO_SYNC, - tndp->ni_cred, (int *)0); + tndp->ni_cred, (int *)0, + (struct proc *)0); cache_purge(ITOV(dp)); } } @@ -1177,9 +1055,10 @@ struct dirtemplate mastertemplate = { /* * Mkdir system call */ -ufs_mkdir(ndp, vap) +ufs_mkdir(ndp, vap, p) struct nameidata *ndp; struct vattr *vap; + struct proc *p; { register struct inode *ip, *dp; struct inode *tip; @@ -1188,22 +1067,26 @@ ufs_mkdir(ndp, vap) int error; int dmode; +#ifdef DIANOSTIC + if ((ndp->ni_nameiop & 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); iput(dp); return (EMLINK); } dmode = vap->va_mode&0777; dmode |= IFDIR; /* - * Must simulate part of maknode here - * in order to acquire the inode, but - * not have it entered in the parent - * directory. The entry is made later - * after writing "." and ".." entries out. + * Must simulate part of maknode here to acquire the inode, but + * not have it entered in the parent directory. The entry is made + * later after writing "." and ".." entries. */ if (error = ialloc(dp, dirpref(dp->i_fs), dmode, ndp->ni_cred, &tip)) { + free(ndp->ni_pnbuf, M_NAMEI); iput(dp); return (error); } @@ -1213,6 +1096,7 @@ ufs_mkdir(ndp, vap) #ifdef QUOTA if ((error = getinoquota(ip)) || (error = chkiq(ip, 1, ndp->ni_cred, 0))) { + free(ndp->ni_pnbuf, M_NAMEI); ifree(ip, ip->i_number, dmode); iput(ip); iput(dp); @@ -1233,7 +1117,8 @@ ufs_mkdir(ndp, vap) */ dp->i_nlink++; dp->i_flag |= ICHG; - error = iupdat(dp, &time, &time, 1); + if (error = iupdat(dp, &time, &time, 1)) + goto bad; /* * Initialize directory with "." @@ -1243,8 +1128,8 @@ ufs_mkdir(ndp, vap) dirtemplate.dot_ino = ip->i_number; 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); + sizeof (dirtemplate), (off_t)0, UIO_SYSSPACE, + IO_NODELOCKED|IO_SYNC, ndp->ni_cred, (int *)0, (struct proc *)0); if (error) { dp->i_nlink--; dp->i_flag |= ICHG; @@ -1261,17 +1146,9 @@ ufs_mkdir(ndp, vap) * install the entry for it in * the parent directory. */ - error = direnter(ip, ndp); - dp = NULL; - if (error) { - ndp->ni_nameiop &= ~(MODMASK | OPMASK); - ndp->ni_nameiop |= LOOKUP | NOCACHE; - error = namei(ndp); - if (!error) { - dp = VTOI(ndp->ni_vp); - dp->i_nlink--; - dp->i_flag |= ICHG; - } + if (error = direnter(ip, ndp)) { + dp->i_nlink--; + dp->i_flag |= ICHG; } bad: /* @@ -1285,16 +1162,17 @@ bad: iput(ip); } else ndp->ni_vp = ITOV(ip); - if (dp) - iput(dp); + FREE(ndp->ni_pnbuf, M_NAMEI); + iput(dp); return (error); } /* * Rmdir system call. */ -ufs_rmdir(ndp) +ufs_rmdir(ndp, p) register struct nameidata *ndp; + struct proc *p; { register struct inode *ip, *dp; int error = 0; @@ -1356,10 +1234,11 @@ out: /* * symlink -- make a symbolic link */ -ufs_symlink(ndp, vap, target) +ufs_symlink(ndp, vap, target, p) struct nameidata *ndp; struct vattr *vap; char *target; + struct proc *p; { struct inode *ip; int error; @@ -1368,7 +1247,8 @@ ufs_symlink(ndp, vap, target) if (error) return (error); error = vn_rdwr(UIO_WRITE, ITOV(ip), target, strlen(target), (off_t)0, - UIO_SYSSPACE, IO_NODELOCKED, ndp->ni_cred, (int *)0); + UIO_SYSSPACE, IO_NODELOCKED, ndp->ni_cred, (int *)0, + (struct proc *)0); iput(ip); return (error); } @@ -1414,13 +1294,15 @@ ufs_readlink(vp, uiop, cred) /* * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually - * done. Nothing to do at the moment. + * done. If a buffer has been saved in anticipation of a CREATE, delete it. */ /* ARGSUSED */ ufs_abortop(ndp) struct nameidata *ndp; { + if ((ndp->ni_nameiop & (HASBUF | SAVESTART)) == HASBUF) + FREE(ndp->ni_pnbuf, M_NAMEI); return (0); } @@ -1602,16 +1484,17 @@ ufsspec_write(vp, uio, ioflag, cred) * * Update the times on the inode then do device close. */ -ufsspec_close(vp, fflag, cred) +ufsspec_close(vp, fflag, cred, p) struct vnode *vp; int fflag; struct ucred *cred; + struct proc *p; { register struct inode *ip = VTOI(vp); if (vp->v_usecount > 1 && !(ip->i_flag & ILOCKED)) ITIMES(ip, &time, &time); - return (spec_close(vp, fflag, cred)); + return (spec_close(vp, fflag, cred, p)); } #ifdef FIFO @@ -1654,21 +1537,22 @@ ufsfifo_write(vp, uio, ioflag, cred) * * Update the times on the inode then do device close. */ -ufsfifo_close(vp, fflag, cred) +ufsfifo_close(vp, fflag, cred, p) struct vnode *vp; int fflag; struct ucred *cred; + struct proc *p; { register struct inode *ip = VTOI(vp); if (vp->v_usecount > 1 && !(ip->i_flag & ILOCKED)) ITIMES(ip, &time, &time); - return (fifo_close(vp, fflag, cred)); + return (fifo_close(vp, fflag, cred, p)); } #endif /* FIFO */ /* - * Make a new file. + * Allocate a new inode. */ maknode(mode, ndp, ipp) int mode; @@ -1681,6 +1565,10 @@ maknode(mode, ndp, ipp) ino_t ipref; int error; +#ifdef DIANOSTIC + if ((ndp->ni_nameiop & HASBUF) == 0) + panic("maknode: no name"); +#endif *ipp = 0; if ((mode & IFMT) == 0) mode |= IFREG; @@ -1689,6 +1577,7 @@ maknode(mode, ndp, ipp) else ipref = pdir->i_number; if (error = ialloc(pdir, ipref, mode, ndp->ni_cred, &tip)) { + free(ndp->ni_pnbuf, M_NAMEI); iput(pdir); return (error); } @@ -1698,6 +1587,7 @@ maknode(mode, ndp, ipp) #ifdef QUOTA if ((error = getinoquota(ip)) || (error = chkiq(ip, 1, ndp->ni_cred, 0))) { + free(ndp->ni_pnbuf, M_NAMEI); ifree(ip, ip->i_number, mode); iput(ip); iput(pdir); @@ -1717,10 +1607,11 @@ maknode(mode, ndp, ipp) */ if (error = iupdat(ip, &time, &time, 1)) goto bad; - if (error = direnter(ip, ndp)) { - pdir = NULL; + if (error = direnter(ip, ndp)) goto bad; - } + if ((ndp->ni_nameiop & SAVESTART) == 0) + FREE(ndp->ni_pnbuf, M_NAMEI); + iput(pdir); *ipp = ip; return (0); @@ -1729,8 +1620,8 @@ bad: * Write error occurred trying to update the inode * or the directory so must deallocate the inode. */ - if (pdir) - iput(pdir); + free(ndp->ni_pnbuf, M_NAMEI); + iput(pdir); ip->i_nlink = 0; ip->i_flag |= ICHG; iput(ip); @@ -1823,3 +1714,124 @@ ufs_advlock(vp, id, op, fl, flags) } /* NOTREACHED */ } + +/* + * Global vfs data structures for ufs + */ +struct vnodeops ufs_vnodeops = { + ufs_lookup, /* lookup */ + ufs_create, /* create */ + ufs_mknod, /* mknod */ + ufs_open, /* open */ + ufs_close, /* close */ + ufs_access, /* access */ + ufs_getattr, /* getattr */ + ufs_setattr, /* setattr */ + ufs_read, /* read */ + ufs_write, /* write */ + ufs_ioctl, /* ioctl */ + ufs_select, /* select */ + ufs_mmap, /* mmap */ + ufs_fsync, /* fsync */ + ufs_seek, /* seek */ + ufs_remove, /* remove */ + ufs_link, /* link */ + ufs_rename, /* rename */ + ufs_mkdir, /* mkdir */ + ufs_rmdir, /* rmdir */ + ufs_symlink, /* symlink */ + ufs_readdir, /* readdir */ + ufs_readlink, /* readlink */ + ufs_abortop, /* abortop */ + ufs_inactive, /* inactive */ + ufs_reclaim, /* reclaim */ + ufs_lock, /* lock */ + ufs_unlock, /* unlock */ + ufs_bmap, /* bmap */ + ufs_strategy, /* strategy */ + ufs_print, /* print */ + ufs_islocked, /* islocked */ + ufs_advlock, /* advlock */ +}; + +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 */ +}; + +#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 */ + +enum vtype iftovt_tab[16] = { + VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON, + VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD, +}; +int vttoif_tab[9] = { + 0, IFREG, IFDIR, IFBLK, IFCHR, IFLNK, IFSOCK, IFIFO, IFMT, +};