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:
parent
9899f80bab
commit
d2ee066f71
@ -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));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
};
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user