diff --git a/sys/nfs/nfs_vnops.c b/sys/nfs/nfs_vnops.c index 041ce493269d..3c1fa3dcdce9 100644 --- a/sys/nfs/nfs_vnops.c +++ b/sys/nfs/nfs_vnops.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)nfs_vnops.c 7.60 (Berkeley) 5/24/91 - * $Id: nfs_vnops.c,v 1.4 1993/05/21 07:38:07 cgd Exp $ + * $Id: nfs_vnops.c,v 1.5 1993/05/22 09:00:49 cgd Exp $ */ /* @@ -1709,8 +1709,9 @@ nfs_advlock(vp, id, op, fl, flags) struct flock *fl; int flags; { + register struct nfsnode *np = VTONFS(vp); - return (EOPNOTSUPP); + return (lf_advlock(&(np->n_lockf), np->n_size, id, op, fl, flags)); } /* diff --git a/sys/nfs/nfsnode.h b/sys/nfs/nfsnode.h index 85b38958cc9d..48100fef00be 100644 --- a/sys/nfs/nfsnode.h +++ b/sys/nfs/nfsnode.h @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)nfsnode.h 7.12 (Berkeley) 4/16/91 - * $Id: nfsnode.h,v 1.2 1993/05/20 03:19:11 cgd Exp $ + * $Id: nfsnode.h,v 1.3 1993/05/22 09:00:56 cgd Exp $ */ #ifndef _NFS_NFSNODE_H_ @@ -57,6 +57,7 @@ struct nfsnode { struct vattr n_vattr; /* Vnode attribute cache */ struct sillyrename *n_sillyrename; /* Ptr to silly rename struct */ u_long n_size; /* Current size of file */ + struct lockf *n_lockf; /* Locking record of file */ time_t n_mtime; /* Prev modify time to maintain data cache consistency*/ time_t n_ctime; /* Prev create time for name cache consistency*/ int n_error; /* Save write error value */ diff --git a/sys/ufs/lockf.h b/sys/ufs/lockf.h index e1fa5305beab..823e966e151c 100644 --- a/sys/ufs/lockf.h +++ b/sys/ufs/lockf.h @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)lockf.h 7.1 (Berkeley) 2/1/91 - * $Id: lockf.h,v 1.3 1993/05/20 03:53:25 cgd Exp $ + * $Id: lockf.h,v 1.4 1993/05/22 09:01:13 cgd Exp $ */ #ifndef _UFS_LOCKF_H_ @@ -52,7 +52,7 @@ struct lockf { off_t lf_start; /* The byte # of the start of the lock */ off_t lf_end; /* The byte # of the end of the lock (-1=EOF)*/ caddr_t lf_id; /* The id of the resource holding the lock */ - struct inode *lf_inode; /* Back pointer to the inode */ + struct lockf **lf_head; /* Back pointer to the head of lockf list */ struct lockf *lf_next; /* A pointer to the next lock on this inode */ struct lockf *lf_block; /* The list of blocked locks */ }; diff --git a/sys/ufs/ufs_lockf.c b/sys/ufs/ufs_lockf.c index a7a7bdda9b72..fb5894fe37e3 100644 --- a/sys/ufs/ufs_lockf.c +++ b/sys/ufs/ufs_lockf.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)ufs_lockf.c 7.7 (Berkeley) 7/2/91 - * $Id: ufs_lockf.c,v 1.3 1993/05/20 03:53:38 cgd Exp $ + * $Id: ufs_lockf.c,v 1.4 1993/05/22 09:01:16 cgd Exp $ */ #include "param.h" @@ -50,6 +50,96 @@ #include "quota.h" #include "inode.h" + + +/* + * Advisory record locking support + */ +lf_advlock(head, size, id, op, fl, flags) + struct lockf **head; + u_long size; + caddr_t id; + int op; + register struct flock *fl; + int flags; +{ + register struct lockf *lock; + off_t start, end; + int error; + + /* + * Avoid the common case of unlocking when inode has no locks. + */ + if (*head == (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 = 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_head = head; + 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 */ +} + /* * This variable controls the maximum number of processes that will * be checked in doing deadlock detection. @@ -71,7 +161,7 @@ lf_setlock(lock) register struct lockf *lock; { register struct lockf *block; - struct inode *ip = lock->lf_inode; + struct lockf **head = lock->lf_head; struct lockf **prev, *overlap, *ltmp; static char lockstr[] = "lockf"; int ovcase, priority, needtolink, error; @@ -182,8 +272,8 @@ lf_setlock(lock) * Skip over locks owned by other processes. * Handle any locks that overlap and are owned by ourselves. */ - prev = &ip->i_lockf; - block = ip->i_lockf; + prev = head; + block = *head; needtolink = 1; for (;;) { if (ovcase = lf_findoverlap(block, lock, SELF, &prev, &overlap)) @@ -306,8 +396,8 @@ lf_setlock(lock) lf_clearlock(unlock) register struct lockf *unlock; { - struct inode *ip = unlock->lf_inode; - register struct lockf *lf = ip->i_lockf; + struct lockf **head = unlock->lf_head; + register struct lockf *lf = *head; struct lockf *overlap, **prev; int ovcase; @@ -319,7 +409,7 @@ lf_clearlock(unlock) if (lockf_debug & 1) lf_print("lf_clearlock", unlock); #endif /* LOCKF_DEBUG */ - prev = &ip->i_lockf; + prev = head; while (ovcase = lf_findoverlap(lf, unlock, SELF, &prev, &overlap)) { /* * Wakeup the list of locks to be retried. @@ -409,10 +499,10 @@ struct lockf * lf_getblock(lock) register struct lockf *lock; { - struct lockf **prev, *overlap, *lf = lock->lf_inode->i_lockf; + struct lockf **prev, *overlap, *lf = *(lock->lf_head); int ovcase; - prev = &lock->lf_inode->i_lockf; + prev = lock->lf_head; while (ovcase = lf_findoverlap(lf, lock, OTHERS, &prev, &overlap)) { /* * We've found an overlap, see if it blocks us