diff options
author | mjacob <mjacob@FreeBSD.org> | 2007-01-04 20:38:50 +0000 |
---|---|---|
committer | mjacob <mjacob@FreeBSD.org> | 2007-01-04 20:38:50 +0000 |
commit | 3bc2efe5348c9a8b3576b986c86967e9c5f0c03a (patch) | |
tree | 16bda884a173caa07bac78086054302375e362a6 | |
parent | 2cd5f6bd1c305d31cb77914f9d103bfebf737dbb (diff) | |
download | FreeBSD-src-3bc2efe5348c9a8b3576b986c86967e9c5f0c03a.zip FreeBSD-src-3bc2efe5348c9a8b3576b986c86967e9c5f0c03a.tar.gz |
Add a function that checks for duplicate requests (based
on some fairly tight criteria) so we avoid having broken
clients spam rpc.lockd to death.
PR: 107530
Obtained from: Doug Rudoff
MFC after: 1 week
-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 |