X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/d9d75b8f74f20e0f43170b709e78e766c99adaf7..2a5d2f560769eb853f0ad5197f8828bc2c1dd4ba:/usr/src/sys/ufs/ffs/ffs_vnops.c diff --git a/usr/src/sys/ufs/ffs/ffs_vnops.c b/usr/src/sys/ufs/ffs/ffs_vnops.c index 0d3244914a..492d1f5d65 100644 --- a/usr/src/sys/ufs/ffs/ffs_vnops.c +++ b/usr/src/sys/ufs/ffs/ffs_vnops.c @@ -4,29 +4,29 @@ * * %sccs.include.redist.c% * - * @(#)ffs_vnops.c 7.51 (Berkeley) %G% + * @(#)ffs_vnops.c 7.59 (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 "malloc.h" -#include "../ufs/lockf.h" -#include "../ufs/quota.h" -#include "../ufs/inode.h" -#include "../ufs/fs.h" + +#include "lockf.h" +#include "quota.h" +#include "inode.h" +#include "fs.h" /* * Global vfs data structures for ufs @@ -112,8 +112,7 @@ int spec_lookup(), spec_select(), ufsspec_close(), spec_advlock(), - spec_badop(), - spec_nullop(); + spec_badop(); struct vnodeops spec_inodeops = { spec_lookup, /* lookup */ @@ -129,7 +128,7 @@ struct vnodeops spec_inodeops = { spec_ioctl, /* ioctl */ spec_select, /* select */ spec_badop, /* mmap */ - spec_nullop, /* fsync */ + nullop, /* fsync */ spec_badop, /* seek */ spec_badop, /* remove */ spec_badop, /* link */ @@ -162,8 +161,7 @@ int fifo_lookup(), ufsfifo_close(), fifo_print(), fifo_advlock(), - fifo_badop(), - fifo_nullop(); + fifo_badop(); struct vnodeops fifo_inodeops = { fifo_lookup, /* lookup */ @@ -179,7 +177,7 @@ struct vnodeops fifo_inodeops = { fifo_ioctl, /* ioctl */ fifo_select, /* select */ fifo_badop, /* mmap */ - fifo_nullop, /* fsync */ + nullop, /* fsync */ fifo_badop, /* seek */ fifo_badop, /* remove */ fifo_badop, /* link */ @@ -402,6 +400,7 @@ ufs_setattr(vp, vap, cred) register struct vattr *vap; register struct ucred *cred; { + struct proc *p = curproc; /* XXX */ register struct inode *ip = VTOI(vp); int error = 0; @@ -418,7 +417,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) @@ -428,7 +427,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; @@ -439,10 +438,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; @@ -459,16 +458,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)) @@ -488,13 +488,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; @@ -514,7 +515,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; @@ -657,6 +658,7 @@ ufs_write(vp, uio, ioflag, cred) int ioflag; struct ucred *cred; { + struct proc *p = curproc; /* XXX */ register struct inode *ip = VTOI(vp); register struct fs *fs; struct buf *bp; @@ -693,8 +695,8 @@ ufs_write(vp, uio, ioflag, cred) */ if (vp->v_type == VREG && 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; @@ -849,20 +851,18 @@ ufs_link(vp, ndp) register struct inode *ip = VTOI(vp); int error; + if ((unsigned short)ip->i_nlink >= LINK_MAX) + return (EMLINK); if (ndp->ni_dvp != vp) ILOCK(ip); - if (ip->i_nlink == LINK_MAX - 1) { - error = EMLINK; - goto out; - } ip->i_nlink++; ip->i_flag |= ICHG; error = iupdat(ip, &time, &time, 1); if (!error) error = direnter(ip, ndp); -out: if (ndp->ni_dvp != vp) IUNLOCK(ip); + vput(ndp->ni_dvp); if (error) { ip->i_nlink--; ip->i_flag |= ICHG; @@ -897,6 +897,7 @@ out: ufs_rename(fndp, tndp) register struct nameidata *fndp, *tndp; { + struct proc *p = curproc; /* XXX */ register struct inode *ip, *xp, *dp; struct dirtemplate dirbuf; int doingdirectory = 0, oldparent = 0, newparent = 0; @@ -965,14 +966,15 @@ ufs_rename(fndp, tndp) VOP_UNLOCK(fndp->ni_vp); if (error) goto bad; - tndp->ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE; + 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)) + if (error = namei(tndp, p)) goto out; xp = NULL; if (tndp->ni_vp) @@ -995,12 +997,24 @@ ufs_rename(fndp, tndp) * parent we don't fool with the link count. */ if (doingdirectory && newparent) { + if ((unsigned short)dp->i_nlink >= LINK_MAX) { + error = EMLINK; + goto bad; + } dp->i_nlink++; dp->i_flag |= ICHG; - error = iupdat(dp, &time, &time, 1); + if (error = iupdat(dp, &time, &time, 1)) + goto bad; + } + if (error = direnter(ip, tndp)) { + if (doingdirectory && newparent) { + dp->i_nlink--; + dp->i_flag |= ICHG; + (void) iupdat(dp, &time, &time, 1); + } + goto bad; } - if (error = direnter(ip, tndp)) - goto out; + iput(dp); } else { if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev) panic("rename: EXDEV"); @@ -1080,8 +1094,9 @@ ufs_rename(fndp, tndp) /* * 3) Unlink the source. */ - fndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; - (void)namei(fndp); + fndp->ni_nameiop &= ~(MODMASK | OPMASK); + fndp->ni_nameiop |= DELETE | LOCKPARENT | LOCKLEAF; + (void)namei(fndp, p); if (fndp->ni_vp != NULL) { xp = VTOI(fndp->ni_vp); dp = VTOI(fndp->ni_dvp); @@ -1187,6 +1202,10 @@ ufs_mkdir(ndp, vap) dvp = ndp->ni_dvp; dp = VTOI(dvp); + if ((unsigned short)dp->i_nlink >= LINK_MAX) { + iput(dp); + return (EMLINK); + } dmode = vap->va_mode&0777; dmode |= IFDIR; /* @@ -1226,7 +1245,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 "." @@ -1254,16 +1274,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 = 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: /* @@ -1277,8 +1290,7 @@ bad: iput(ip); } else ndp->ni_vp = ITOV(ip); - if (dp) - iput(dp); + iput(dp); return (error); } @@ -1709,10 +1721,9 @@ 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; - } + iput(pdir); *ipp = ip; return (0); @@ -1721,8 +1732,7 @@ bad: * Write error occurred trying to update the inode * or the directory so must deallocate the inode. */ - if (pdir) - iput(pdir); + iput(pdir); ip->i_nlink = 0; ip->i_flag |= ICHG; iput(ip); @@ -1779,7 +1789,7 @@ ufs_advlock(vp, id, op, fl, flags) if (fl->l_len == 0) end = -1; else - end = start + fl->l_len; + end = start + fl->l_len - 1; /* * Create the lockf structure */ @@ -1797,13 +1807,17 @@ ufs_advlock(vp, id, op, fl, flags) */ switch(op) { case F_SETLK: - return (ufs_setlock(lock)); + return (lf_setlock(lock)); case F_UNLCK: - return (ufs_advunlock(lock)); + error = lf_clearlock(lock); + FREE(lock, M_LOCKF); + return (error); case F_GETLK: - return (ufs_advgetlock(lock, fl)); + error = lf_getlock(lock, fl); + FREE(lock, M_LOCKF); + return (error); default: free(lock, M_LOCKF); @@ -1811,163 +1825,3 @@ ufs_advlock(vp, id, op, fl, flags) } /* NOTREACHED */ } - -/* - * This variable controls the maximum number of processes that will - * be checked in doing deadlock detection. - */ -int maxlockdepth = MAXDEPTH; - -/* - * Set a byte-range lock. - */ -ufs_setlock(lock) - register struct lockf *lock; -{ - register struct inode *ip = lock->lf_inode; - register struct lockf *block; - static char lockstr[] = "lockf"; - int priority, error; - -#ifdef LOCKF_DEBUG - if (lockf_debug & 4) - lf_print("ufs_setlock", lock); -#endif /* LOCKF_DEBUG */ - - /* - * Set the priority - */ - priority = PLOCK; - if ((lock->lf_type & F_WRLCK) == 0) - priority += 4; - priority |= PCATCH; - /* - * Scan lock list for this file looking for locks that would block us. - */ - while (block = lf_getblock(lock)) { - /* - * Free the structure and return if nonblocking. - */ - if ((lock->lf_flags & F_WAIT) == 0) { - free(lock, M_LOCKF); - return (EAGAIN); - } - /* - * We are blocked. Since flock style locks cover - * the whole file, there is no chance for deadlock. - * For byte-range locks we must check for deadlock. - * - * Deadlock detection is done by looking through the - * wait channels to see if there are any cycles that - * involve us. MAXDEPTH is set just to make sure we - * do not go off into neverland. - */ - if ((lock->lf_flags & F_POSIX) && - (block->lf_flags & F_POSIX)) { - register struct proc *wproc; - register struct lockf *waitblock; - int i = 0; - - /* The block is waiting on something */ - wproc = (struct proc *)block->lf_id; - while (wproc->p_wchan && - (wproc->p_wmesg == lockstr) && - (i++ < maxlockdepth)) { - waitblock = (struct lockf *)wproc->p_wchan; - /* Get the owner of the blocking lock */ - waitblock = waitblock->lf_next; - if ((waitblock->lf_flags & F_POSIX) == 0) - break; - wproc = (struct proc *)waitblock->lf_id; - if (wproc == (struct proc *)lock->lf_id) { - free(lock, M_LOCKF); - return (EDEADLK); - } - } - } - /* - * Add our lock to the blocked - * list and sleep until we're free. - */ -#ifdef LOCKF_DEBUG - if (lockf_debug & 4) - lf_print("ufs_advlock: blocking on", block); -#endif /* LOCKF_DEBUG */ - /* - * Remember who blocked us (for deadlock detection) - */ - lock->lf_next = block; - lf_addblock(block, lock); - if (error = tsleep((caddr_t *)lock, priority, lockstr, 0)) { - free(lock, M_LOCKF); - return (error); - } - } - /* - * No blocks!! Add the lock. Note that addlock will - * downgrade or upgrade any overlapping locks this - * process already owns. - */ -#ifdef LOCKF_DEBUG - if (lockf_debug & 4) - lf_print("ufs_advlock: got the lock", lock); -#endif /* LOCKF_DEBUG */ - lf_addlock(lock); - return (0); -} - -/* - * Remove a byte-range lock on an inode. - */ -ufs_advunlock(lock) - struct lockf *lock; -{ - struct lockf *blocklist; - - if (lock->lf_inode->i_lockf == (struct lockf *)0) - return (0); -#ifdef LOCKF_DEBUG - if (lockf_debug & 4) - lf_print("ufs_advunlock", lock); -#endif /* LOCKF_DEBUG */ - /* - * Generally, find the lock (or an overlap to that lock) - * and remove it (or shrink it), then wakeup anyone we can. - */ - blocklist = lf_remove(lock); - FREE(lock, M_LOCKF); - lf_wakelock(blocklist); - return (0); -} - -/* - * Return the blocking pid - */ -ufs_advgetlock(lock, fl) - register struct lockf *lock; - register struct flock *fl; -{ - register struct lockf *block; - off_t start, end; - -#ifdef LOCKF_DEBUG - if (lockf_debug & 4) - lf_print("ufs_advgetlock", lock); -#endif /* LOCKF_DEBUG */ - - if (block = lf_getblock(lock)) { - fl->l_type = block->lf_type; - fl->l_whence = SEEK_SET; - fl->l_start = block->lf_start; - if (block->lf_end == -1) - fl->l_len = 0; - else - fl->l_len = block->lf_end - block->lf_start; - if (block->lf_flags & F_POSIX) - fl->l_pid = ((struct proc *)(block->lf_id))->p_pid; - else - fl->l_pid = -1; - } - FREE(lock, M_LOCKF); - return (0); -}