X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/a62786b990f4e2bb099217375bb52d3ed7cfb45a..394d67a891553ad51fd85c5de35ee740601ddc5d:/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 146a105c5c..8716f219d6 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.46 (Berkeley) %G% + * @(#)ufs_vnops.c 7.56 (Berkeley) %G% */ #include "param.h" @@ -21,6 +21,9 @@ #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" @@ -60,7 +63,8 @@ int ufs_lookup(), ufs_bmap(), ufs_strategy(), ufs_print(), - ufs_islocked(); + ufs_islocked(), + ufs_advlock(); struct vnodeops ufs_vnodeops = { ufs_lookup, /* lookup */ @@ -95,6 +99,7 @@ struct vnodeops ufs_vnodeops = { ufs_strategy, /* strategy */ ufs_print, /* print */ ufs_islocked, /* islocked */ + ufs_advlock, /* advlock */ }; int spec_lookup(), @@ -106,8 +111,9 @@ int spec_lookup(), spec_ioctl(), spec_select(), ufsspec_close(), + spec_advlock(), spec_badop(), - spec_nullop(); + nullop(); struct vnodeops spec_inodeops = { spec_lookup, /* lookup */ @@ -123,7 +129,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 */ @@ -142,6 +148,7 @@ struct vnodeops spec_inodeops = { spec_strategy, /* strategy */ ufs_print, /* print */ ufs_islocked, /* islocked */ + spec_advlock, /* advlock */ }; #ifdef FIFO @@ -154,8 +161,8 @@ int fifo_lookup(), fifo_select(), ufsfifo_close(), fifo_print(), - fifo_badop(), - fifo_nullop(); + fifo_advlock(), + fifo_badop(); struct vnodeops fifo_inodeops = { fifo_lookup, /* lookup */ @@ -171,7 +178,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 */ @@ -190,6 +197,7 @@ struct vnodeops fifo_inodeops = { fifo_badop, /* strategy */ ufs_print, /* print */ ufs_islocked, /* islocked */ + fifo_advlock, /* advlock */ }; #endif /* FIFO */ @@ -461,17 +469,17 @@ chmod1(vp, mode, cred) if (cred->cr_uid != ip->i_uid && (error = suser(cred, &u.u_acflag))) return (error); - ip->i_mode &= ~07777; if (cred->cr_uid) { - if (vp->v_type != VDIR) - mode &= ~ISVTX; - if (!groupmember(ip->i_gid, cred)) - mode &= ~ISGID; + if (vp->v_type != VDIR && (mode & ISVTX)) + return (EFTYPE); + if (!groupmember(ip->i_gid, cred) && (mode & ISGID)) + return (EPERM); } + ip->i_mode &= ~07777; ip->i_mode |= mode & 07777; ip->i_flag |= ICHG; if ((vp->v_flag & VTEXT) && (ip->i_mode & ISVTX) == 0) - xrele(vp); + (void) vnode_pager_uncache(vp); return (0); } @@ -653,8 +661,8 @@ ufs_write(vp, uio, ioflag, cred) struct buf *bp; daddr_t lbn, bn; u_long osize; - int i, n, on, flags; - int count, size, resid, error = 0; + int n, on, flags; + int size, resid, error = 0; if (uio->uio_rw != UIO_WRITE) panic("ufs_write mode"); @@ -705,12 +713,12 @@ ufs_write(vp, uio, ioflag, cred) if (error = balloc(ip, lbn, (int)(on + n), &bp, flags)) break; bn = bp->b_blkno; - if (uio->uio_offset + n > ip->i_size) + if (uio->uio_offset + n > ip->i_size) { ip->i_size = uio->uio_offset + n; + vnode_pager_setsize(vp, ip->i_size); + } size = blksize(fs, ip, lbn); - count = howmany(size, CLBYTES); - for (i = 0; i < count; i++) - munhash(ip->i_devvp, bn + i * CLBYTES / DEV_BSIZE); + (void) vnode_pager_uncache(vp); n = MIN(n, size - bp->b_resid); error = uiomove(bp->b_un.b_addr + on, n, uio); if (ioflag & IO_SYNC) @@ -840,20 +848,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; @@ -956,7 +962,8 @@ 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) @@ -986,12 +993,23 @@ 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; } else { if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev) panic("rename: EXDEV"); @@ -1071,16 +1089,20 @@ ufs_rename(fndp, tndp) /* * 3) Unlink the source. */ - fndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; + fndp->ni_nameiop &= ~(MODMASK | OPMASK); + fndp->ni_nameiop |= DELETE | LOCKPARENT | LOCKLEAF; (void)namei(fndp); if (fndp->ni_vp != NULL) { xp = VTOI(fndp->ni_vp); dp = VTOI(fndp->ni_dvp); } else { - if (fndp->ni_dvp != NULL) - vput(fndp->ni_dvp); - xp = NULL; - dp = NULL; + /* + * From name has disappeared. + */ + if (doingdirectory) + panic("rename: lost dir entry"); + vrele(ITOV(ip)); + return (0); } /* * Ensure that the directory entry still exists and has not @@ -1175,6 +1197,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; /* @@ -1214,7 +1240,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 "." @@ -1242,12 +1269,12 @@ 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; + if (error = direnter(ip, ndp)) { + ndp->ni_nameiop &= ~(MODMASK | OPMASK); + ndp->ni_nameiop |= LOOKUP | LOCKLEAF | NOCACHE; error = namei(ndp); if (!error) { + iput(dp); dp = VTOI(ndp->ni_vp); dp->i_nlink--; dp->i_flag |= ICHG; @@ -1265,8 +1292,7 @@ bad: iput(ip); } else ndp->ni_vp = ITOV(ip); - if (dp) - iput(dp); + iput(dp); return (error); } @@ -1697,10 +1723,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); @@ -1709,10 +1734,96 @@ 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); return (error); } + +/* + * Advisory record locking support + */ +ufs_advlock(vp, id, op, fl, flags) + struct vnode *vp; + caddr_t id; + int op; + register struct flock *fl; + int flags; +{ + register struct inode *ip = VTOI(vp); + register struct lockf *lock; + off_t start, end; + int error; + + /* + * Avoid the common case of unlocking when inode has no locks. + */ + if (ip->i_lockf == (struct lockf *)0) { + if (op != F_SETLK) { + fl->l_type = F_UNLCK; + return (0); + } + } + /* + * Convert the flock structure into a start and end. + */ + switch (fl->l_whence) { + + case SEEK_SET: + case SEEK_CUR: + /* + * Caller is responsible for adding any necessary offset + * when SEEK_CUR is used. + */ + start = fl->l_start; + break; + + case SEEK_END: + start = ip->i_size + fl->l_start; + break; + + default: + return (EINVAL); + } + if (start < 0) + return (EINVAL); + if (fl->l_len == 0) + end = -1; + else + end = start + fl->l_len - 1; + /* + * Create the lockf structure + */ + MALLOC(lock, struct lockf *, sizeof *lock, M_LOCKF, M_WAITOK); + lock->lf_start = start; + lock->lf_end = end; + lock->lf_id = id; + lock->lf_inode = ip; + lock->lf_type = fl->l_type; + lock->lf_next = (struct lockf *)0; + lock->lf_block = (struct lockf *)0; + lock->lf_flags = flags; + /* + * Do the requested operation. + */ + switch(op) { + case F_SETLK: + return (lf_setlock(lock)); + + case F_UNLCK: + error = lf_clearlock(lock); + FREE(lock, M_LOCKF); + return (error); + + case F_GETLK: + error = lf_getlock(lock, fl); + FREE(lock, M_LOCKF); + return (error); + + default: + free(lock, M_LOCKF); + return (EINVAL); + } + /* NOTREACHED */ +}