add Yuval Yarom's changes (originally for BSD/386) for advisory record

locking on NFS files.  Note that this DOES NOT support network locking,
only local advisory locks.
This commit is contained in:
cgd 1993-05-22 09:00:49 +00:00
parent 9899f80bab
commit d2ee066f71
4 changed files with 106 additions and 14 deletions

View File

@ -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));
}
/*

View File

@ -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 */

View File

@ -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 */
};

View File

@ -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