diff options
-rw-r--r-- | usr.sbin/rpc.lockd/lockd_lock.c | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/usr.sbin/rpc.lockd/lockd_lock.c b/usr.sbin/rpc.lockd/lockd_lock.c index cc09bcb..770cb5e 100644 --- a/usr.sbin/rpc.lockd/lockd_lock.c +++ b/usr.sbin/rpc.lockd/lockd_lock.c @@ -1195,13 +1195,54 @@ test_hwlock(fl, conflicting_fl) * if at all possible */ +int +duplicate_block(struct file_lock *fl) +{ + struct file_lock *ifl,*nfl; + int retval = 0; + + debuglog("Entering duplicate_block"); + + /* + * Is this lock request already on the blocking list? + * Condider it a dupe if the file handles, offset, length, + * exclusivity and client match. + */ + LIST_FOREACH(ifl, &blockedlocklist_head, nfslocklist) { + if (!bcmp(&fl->filehandle, &ifl->filehandle, + sizeof(fhandle_t)) && + fl->client.exclusive == ifl->client.exclusive && + fl->client.l_offset == ifl->client.l_offset && + fl->client.l_len == ifl->client.l_len && + same_filelock_identity(fl, ifl)) { + retval = 1; + break; + } + } + + debuglog("Exiting duplicate_block: %s\n", retval ? "already blocked" + : "not already blocked"); + return retval; +} + void add_blockingfilelock(struct file_lock *fl) { - debuglog("Entering add_blockingfilelock\n"); /* + * A blocking lock request _should_ never be duplicated as a client + * that is already blocked shouldn't be able to request another + * lock. Alas, there are some buggy clients that do request the same + * lock repeatedly. Make sure only unique locks are on the blocked + * lock list. + */ + if (duplicate_block(fl)) { + debuglog("Exiting add_blockingfilelock: already blocked\n"); + return; + } + + /* * Clear the blocking flag so that it can be reused without * adding it to the blocking queue a second time */ @@ -1209,7 +1250,7 @@ add_blockingfilelock(struct file_lock *fl) fl->blocking = 0; LIST_INSERT_HEAD(&blockedlocklist_head, fl, nfslocklist); - debuglog("Exiting add_blockingfilelock\n"); + debuglog("Exiting add_blockingfilelock: added blocked lock\n"); } void |