locks: serialize lock requests

adds a critical section to nfs41_open_state.  this lock is taken before generating the stateid/seqid, and released after updated stateid is saved to nfs41_open_state

Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
Casey Bodley 2012-05-01 15:08:42 -04:00 committed by unknown
parent b9775a69e9
commit 49693532a2
3 changed files with 15 additions and 2 deletions

View file

@ -236,6 +236,8 @@ static int handle_lock(nfs41_upcall *upcall)
goto out_free; goto out_free;
} }
EnterCriticalSection(&state->locks.lock);
lock_stateid_arg(state, &stateid); lock_stateid_arg(state, &stateid);
status = nfs41_lock(state->session, &state->file, &state->owner, status = nfs41_lock(state->session, &state->file, &state->owner,
@ -244,11 +246,14 @@ static int handle_lock(nfs41_upcall *upcall)
dprintf(LKLVL, "nfs41_lock failed with %s\n", dprintf(LKLVL, "nfs41_lock failed with %s\n",
nfs_error_string(status)); nfs_error_string(status));
status = nfs_to_windows_error(status, ERROR_BAD_NET_RESP); status = nfs_to_windows_error(status, ERROR_BAD_NET_RESP);
LeaveCriticalSection(&state->locks.lock);
goto out_free; goto out_free;
} }
/* save lock state with the open */ /* save lock state with the open */
open_lock_add(state, &stateid, lock); open_lock_add(state, &stateid, lock);
LeaveCriticalSection(&state->locks.lock);
args->acquired = TRUE; /* for cancel_lock() */ args->acquired = TRUE; /* for cancel_lock() */
out: out:
return status; return status;
@ -281,12 +286,15 @@ static void cancel_lock(IN nfs41_upcall *upcall)
if (status != ERROR_LOCKED) if (status != ERROR_LOCKED)
goto out; goto out;
EnterCriticalSection(&state->locks.lock);
lock_stateid_arg(state, &stateid); lock_stateid_arg(state, &stateid);
status = nfs41_unlock(state->session, &state->file, status = nfs41_unlock(state->session, &state->file,
args->offset, args->length, &stateid); args->offset, args->length, &stateid);
open_unlock_remove(state, &stateid, &input); open_unlock_remove(state, &stateid, &input);
LeaveCriticalSection(&state->locks.lock);
status = nfs_to_windows_error(status, ERROR_BAD_NET_RESP); status = nfs_to_windows_error(status, ERROR_BAD_NET_RESP);
out: out:
dprintf(1, "<-- cancel_lock() returning %d\n", status); dprintf(1, "<-- cancel_lock() returning %d\n", status);
@ -321,8 +329,6 @@ static int handle_unlock(nfs41_upcall *upcall)
uint32_t i; uint32_t i;
int status = NO_ERROR; int status = NO_ERROR;
lock_stateid_arg(state, &stateid);
for (i = 0; i < args->count; i++) { for (i = 0; i < args->count; i++) {
if (safe_read(&buf, &buf_len, &input.offset, sizeof(LONGLONG))) break; if (safe_read(&buf, &buf_len, &input.offset, sizeof(LONGLONG))) break;
if (safe_read(&buf, &buf_len, &input.length, sizeof(LONGLONG))) break; if (safe_read(&buf, &buf_len, &input.length, sizeof(LONGLONG))) break;
@ -336,10 +342,15 @@ static int handle_unlock(nfs41_upcall *upcall)
if (status != ERROR_LOCKED) if (status != ERROR_LOCKED)
continue; continue;
EnterCriticalSection(&state->locks.lock);
lock_stateid_arg(state, &stateid);
status = nfs41_unlock(state->session, &state->file, status = nfs41_unlock(state->session, &state->file,
input.offset, input.length, &stateid); input.offset, input.length, &stateid);
open_unlock_remove(state, &stateid, &input); open_unlock_remove(state, &stateid, &input);
LeaveCriticalSection(&state->locks.lock);
status = nfs_to_windows_error(status, ERROR_BAD_NET_RESP); status = nfs_to_windows_error(status, ERROR_BAD_NET_RESP);
} }
return status; return status;

View file

@ -149,6 +149,7 @@ typedef struct __nfs41_open_state {
stateid4 stateid; stateid4 stateid;
struct list_entry list; struct list_entry list;
uint32_t counter; uint32_t counter;
CRITICAL_SECTION lock;
} locks; } locks;
HANDLE srv_open; /* for data cache invalidation */ HANDLE srv_open; /* for data cache invalidation */

View file

@ -61,6 +61,7 @@ static int create_open_state(
state->ref_count = 1; state->ref_count = 1;
list_init(&state->locks.list); list_init(&state->locks.list);
list_init(&state->client_entry); list_init(&state->client_entry);
InitializeCriticalSection(&state->locks.lock);
*state_out = state; *state_out = state;
status = NO_ERROR; status = NO_ERROR;