Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

lockd: server should unlock lock if client rejects the grant

Currently lockd just dequeues the block and ignores it if the client
sends a GRANT_RES with a status of nlm_lck_denied. That status is an
indicator that the client has rejected the lock, so the right thing to
do is to unlock the lock we were trying to grant.

Reported-by: Yongcheng Yang <yoyang@redhat.com>
Link: https://bugzilla.redhat.com/show_bug.cgi?id=2063818
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>

authored by

Jeff Layton and committed by
Chuck Lever
244cc191 2005f5b9

+17 -4
+17 -4
fs/lockd/svclock.c
··· 954 954 nlmsvc_grant_reply(struct nlm_cookie *cookie, __be32 status) 955 955 { 956 956 struct nlm_block *block; 957 + struct file_lock *fl; 958 + int error; 957 959 958 960 dprintk("grant_reply: looking for cookie %x, s=%d \n", 959 961 *(unsigned int *)(cookie->data), status); 960 962 if (!(block = nlmsvc_find_block(cookie))) 961 963 return; 962 964 963 - if (status == nlm_lck_denied_grace_period) { 965 + switch (status) { 966 + case nlm_lck_denied_grace_period: 964 967 /* Try again in a couple of seconds */ 965 968 nlmsvc_insert_block(block, 10 * HZ); 966 - } else { 969 + break; 970 + case nlm_lck_denied: 971 + /* Client doesn't want it, just unlock it */ 972 + nlmsvc_unlink_block(block); 973 + fl = &block->b_call->a_args.lock.fl; 974 + fl->fl_type = F_UNLCK; 975 + error = vfs_lock_file(fl->fl_file, F_SETLK, fl, NULL); 976 + if (error) 977 + pr_warn("lockd: unable to unlock lock rejected by client!\n"); 978 + break; 979 + default: 967 980 /* 968 - * Lock is now held by client, or has been rejected. 969 - * In both cases, the block should be removed. 981 + * Either it was accepted or the status makes no sense 982 + * just unlink it either way. 970 983 */ 971 984 nlmsvc_unlink_block(block); 972 985 }