svn commit: r194695 - in stable/7/sys: . contrib/pf kern sys
Konstantin Belousov
kib at FreeBSD.org
Tue Jun 23 10:55:22 UTC 2009
Author: kib
Date: Tue Jun 23 10:55:21 2009
New Revision: 194695
URL: http://svn.freebsd.org/changeset/base/194695
Log:
MFC r192685:
The advisory lock may be activated or activated and removed during the
sleep waiting for conditions when the lock may be granted.
To prevent lf_setlock() from accessing possibly freed memory, add reference
counting to the struct lockf_entry. Bump refcount around the sleep.
Make lf_free_lock() return non-zero when structure was freed, and use
this after the sleep to return EINTR to the caller. The error code might
need a clarification, but we cannot return success to usermode, since
the lock is not owned anymore.
Modified:
stable/7/sys/ (props changed)
stable/7/sys/contrib/pf/ (props changed)
stable/7/sys/kern/kern_lockf.c
stable/7/sys/sys/lockf.h
Modified: stable/7/sys/kern/kern_lockf.c
==============================================================================
--- stable/7/sys/kern/kern_lockf.c Tue Jun 23 10:49:55 2009 (r194694)
+++ stable/7/sys/kern/kern_lockf.c Tue Jun 23 10:55:21 2009 (r194695)
@@ -106,7 +106,7 @@ static int lf_owner_matches(struct lock
int);
static struct lockf_entry *
lf_alloc_lock(struct lock_owner *);
-static void lf_free_lock(struct lockf_entry *);
+static int lf_free_lock(struct lockf_entry *);
static int lf_clearlock(struct lockf *, struct lockf_entry *);
static int lf_overlaps(struct lockf_entry *, struct lockf_entry *);
static int lf_blocks(struct lockf_entry *, struct lockf_entry *);
@@ -347,9 +347,13 @@ lf_alloc_lock(struct lock_owner *lo)
return (lf);
}
-static void
+static int
lf_free_lock(struct lockf_entry *lock)
{
+
+ KASSERT(lock->lf_refs > 0, ("lockf_entry negative ref count %p", lock));
+ if (--lock->lf_refs > 0)
+ return (0);
/*
* Adjust the lock_owner reference count and
* reclaim the entry if this is the last lock
@@ -394,6 +398,7 @@ lf_free_lock(struct lockf_entry *lock)
printf("Freed lock %p\n", lock);
#endif
free(lock, M_LOCKF);
+ return (1);
}
/*
@@ -540,6 +545,7 @@ lf_advlockasync(struct vop_advlockasync_
* the lf_lock_owners_lock tax twice.
*/
lock = lf_alloc_lock(NULL);
+ lock->lf_refs = 1;
lock->lf_start = start;
lock->lf_end = end;
lock->lf_owner = lo;
@@ -1450,7 +1456,13 @@ lf_setlock(struct lockf *state, struct l
goto out;
}
+ lock->lf_refs++;
error = sx_sleep(lock, &state->ls_lock, priority, lockstr, 0);
+ if (lf_free_lock(lock)) {
+ error = EINTR;
+ goto out;
+ }
+
/*
* We may have been awakened by a signal and/or by a
* debugger continuing us (in which cases we must
@@ -1812,6 +1824,7 @@ lf_split(struct lockf *state, struct loc
*/
splitlock = lf_alloc_lock(lock1->lf_owner);
memcpy(splitlock, lock1, sizeof *splitlock);
+ splitlock->lf_refs = 1;
if (splitlock->lf_flags & F_REMOTE)
vref(splitlock->lf_vnode);
Modified: stable/7/sys/sys/lockf.h
==============================================================================
--- stable/7/sys/sys/lockf.h Tue Jun 23 10:49:55 2009 (r194694)
+++ stable/7/sys/sys/lockf.h Tue Jun 23 10:55:21 2009 (r194695)
@@ -80,6 +80,7 @@ struct lockf_entry {
LIST_ENTRY(lockf_entry) lf_link; /* (s) Linkage for lock lists */
struct lockf_edge_list lf_outedges; /* (s) list of out-edges */
struct lockf_edge_list lf_inedges; /* (s) list of out-edges */
+ int lf_refs; /* (s) ref count */
};
LIST_HEAD(lockf_entry_list, lockf_entry);
More information about the svn-src-stable-7
mailing list