diff options
author | alfred <alfred@FreeBSD.org> | 2002-01-17 00:12:05 +0000 |
---|---|---|
committer | alfred <alfred@FreeBSD.org> | 2002-01-17 00:12:05 +0000 |
commit | 2b493fd00cbf2281e3d7b72202627af22d8f4349 (patch) | |
tree | ad1a151dea57dfa96b1a62cbccf811f082ecf161 /usr.sbin | |
parent | 04bc01ee42723f18483af5b6574ed87510f00ba2 (diff) | |
download | FreeBSD-src-2b493fd00cbf2281e3d7b72202627af22d8f4349.zip FreeBSD-src-2b493fd00cbf2281e3d7b72202627af22d8f4349.tar.gz |
Fix boundry condition in lock management:
Alfred, I took a look at retry_blockingfilelocklist() and the
solution seemed simple enough. Please correct me if I am wrong.
It seems said routine doesn't take into account boundary conditions
when putting back file_lock entries into the blocked lock-list.
Specifically, it fails when the file_lock being put back is the
last element in the list, and when it is the only element in the
list. I've included a patch below.
Basically, it introduces another variable: pfl, which keeps track
of the list item before ifl. That way if nfl is NULL, ifl gets
inserted after pfl. If pfl is also NULL, then it gets inserted
at the head of the list (since it was the only element in the
list).
Submitted by: Mike Makonnen <mike_makonnen@yahoo.com>
Tested by: Thomas Quinot <thomas@cuivre.fr.eu.org>
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/rpc.lockd/lockd_lock.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/usr.sbin/rpc.lockd/lockd_lock.c b/usr.sbin/rpc.lockd/lockd_lock.c index f898782..b80c243 100644 --- a/usr.sbin/rpc.lockd/lockd_lock.c +++ b/usr.sbin/rpc.lockd/lockd_lock.c @@ -1226,11 +1226,12 @@ void retry_blockingfilelocklist(void) { /* Retry all locks in the blocked list */ - struct file_lock *ifl, *nfl; /* Iterator */ + struct file_lock *ifl, *nfl, *pfl; /* Iterator */ enum partialfilelock_status pflstatus; debuglog("Entering retry_blockingfilelocklist\n"); + pfl = NULL; ifl = LIST_FIRST(&blockedlocklist_head); debuglog("Iterator choice %p\n",ifl); @@ -1241,6 +1242,7 @@ retry_blockingfilelocklist(void) */ nfl = LIST_NEXT(ifl, nfslocklist); debuglog("Iterator choice %p\n",ifl); + debuglog("Prev iterator choice %p\n",pfl); debuglog("Next iterator choice %p\n",nfl); /* @@ -1260,11 +1262,20 @@ retry_blockingfilelocklist(void) } else { /* Reinsert lock back into same place in blocked list */ debuglog("Replacing blocked lock\n"); - LIST_INSERT_BEFORE(nfl, ifl, nfslocklist); + if (pfl != NULL) + LIST_INSERT_AFTER(pfl, ifl, nfslocklist); + else + /* ifl is the only elem. in the list */ + LIST_INSERT_HEAD(&blockedlocklist_head, ifl, nfslocklist); } /* Valid increment behavior regardless of state of ifl */ ifl = nfl; + /* if a lock was granted incrementing pfl would make it nfl */ + if (pfl != NULL && (LIST_NEXT(pfl, nfslocklist) != nfl)) + pfl = LIST_NEXT(pfl, nfslocklist); + else + pfl = LIST_FIRST(&blockedlocklist_head); } debuglog("Exiting retry_blockingfilelocklist\n"); |