lock: allocate lock state before LOCK, fail on error
now that cancel_lock() and handle_unlock() depend on finding lock state in the open, the comment /* ignore errors from open_lock_add(); they just mean we won't be able to recover the lock after reboot */ no longer applies. allocate the lock state at the top of handle_lock(), so we can bail immediately on failure Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
parent
ead5bc78a2
commit
d08d3774fd
1 changed files with 30 additions and 39 deletions
|
|
@ -72,37 +72,25 @@ static void lock_stateid_update(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int open_lock_add(
|
static void open_lock_add(
|
||||||
IN nfs41_open_state *open,
|
IN nfs41_open_state *open,
|
||||||
IN const stateid_arg *stateid,
|
IN const stateid_arg *stateid,
|
||||||
IN const nfs41_lock_state *input)
|
IN nfs41_lock_state *lock)
|
||||||
{
|
{
|
||||||
nfs41_lock_state *lock;
|
|
||||||
int status = NO_ERROR;
|
|
||||||
|
|
||||||
AcquireSRWLockExclusive(&open->lock);
|
AcquireSRWLockExclusive(&open->lock);
|
||||||
|
|
||||||
if (stateid->type == STATEID_LOCK)
|
if (stateid->type == STATEID_LOCK)
|
||||||
lock_stateid_update(open, &stateid->stateid);
|
lock_stateid_update(open, &stateid->stateid);
|
||||||
|
|
||||||
lock = calloc(1, sizeof(nfs41_lock_state));
|
|
||||||
if (lock == NULL) {
|
|
||||||
status = GetLastError();
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
lock->offset = input->offset;
|
|
||||||
lock->length = input->length;
|
|
||||||
lock->exclusive = input->exclusive;
|
|
||||||
lock->id = open->locks.counter++;
|
lock->id = open->locks.counter++;
|
||||||
|
|
||||||
list_add_tail(&open->locks.list, &lock->open_entry);
|
list_add_tail(&open->locks.list, &lock->open_entry);
|
||||||
out:
|
|
||||||
ReleaseSRWLockExclusive(&open->lock);
|
ReleaseSRWLockExclusive(&open->lock);
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool_t open_lock_delegate(
|
static bool_t open_lock_delegate(
|
||||||
IN nfs41_open_state *open,
|
IN nfs41_open_state *open,
|
||||||
IN const nfs41_lock_state *input)
|
IN nfs41_lock_state *lock)
|
||||||
{
|
{
|
||||||
bool_t delegated = FALSE;
|
bool_t delegated = FALSE;
|
||||||
|
|
||||||
|
|
@ -112,17 +100,11 @@ static bool_t open_lock_delegate(
|
||||||
AcquireSRWLockShared(&deleg->lock);
|
AcquireSRWLockShared(&deleg->lock);
|
||||||
if (deleg->state.type == OPEN_DELEGATE_WRITE
|
if (deleg->state.type == OPEN_DELEGATE_WRITE
|
||||||
&& deleg->status == DELEGATION_GRANTED) {
|
&& deleg->status == DELEGATION_GRANTED) {
|
||||||
nfs41_lock_state *lock = calloc(1, sizeof(nfs41_lock_state));
|
|
||||||
if (lock) {
|
|
||||||
lock->offset = input->offset;
|
|
||||||
lock->length = input->length;
|
|
||||||
lock->exclusive = input->exclusive;
|
|
||||||
lock->delegated = 1;
|
lock->delegated = 1;
|
||||||
lock->id = open->locks.counter++;
|
lock->id = open->locks.counter++;
|
||||||
list_add_tail(&open->locks.list, &lock->open_entry);
|
list_add_tail(&open->locks.list, &lock->open_entry);
|
||||||
delegated = TRUE;
|
delegated = TRUE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
ReleaseSRWLockShared(&deleg->lock);
|
ReleaseSRWLockShared(&deleg->lock);
|
||||||
}
|
}
|
||||||
ReleaseSRWLockExclusive(&open->lock);
|
ReleaseSRWLockExclusive(&open->lock);
|
||||||
|
|
@ -219,10 +201,10 @@ static __inline uint32_t get_lock_type(BOOLEAN exclusive, BOOLEAN blocking)
|
||||||
|
|
||||||
static int handle_lock(nfs41_upcall *upcall)
|
static int handle_lock(nfs41_upcall *upcall)
|
||||||
{
|
{
|
||||||
nfs41_lock_state input;
|
|
||||||
stateid_arg stateid;
|
stateid_arg stateid;
|
||||||
lock_upcall_args *args = &upcall->args.lock;
|
lock_upcall_args *args = &upcall->args.lock;
|
||||||
nfs41_open_state *state = upcall->state_ref;
|
nfs41_open_state *state = upcall->state_ref;
|
||||||
|
nfs41_lock_state *lock;
|
||||||
const uint32_t type = get_lock_type(args->exclusive, args->blocking);
|
const uint32_t type = get_lock_type(args->exclusive, args->blocking);
|
||||||
int status = NO_ERROR;
|
int status = NO_ERROR;
|
||||||
|
|
||||||
|
|
@ -233,14 +215,20 @@ static int handle_lock(nfs41_upcall *upcall)
|
||||||
if (args->length >= NFS4_UINT64_MAX - args->offset)
|
if (args->length >= NFS4_UINT64_MAX - args->offset)
|
||||||
args->length = NFS4_UINT64_MAX;
|
args->length = NFS4_UINT64_MAX;
|
||||||
|
|
||||||
input.offset = args->offset;
|
/* allocate the lock state */
|
||||||
input.length = args->length;
|
lock = calloc(1, sizeof(nfs41_lock_state));
|
||||||
input.exclusive = args->exclusive;
|
if (lock == NULL) {
|
||||||
|
status = GetLastError();
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
lock->offset = args->offset;
|
||||||
|
lock->length = args->length;
|
||||||
|
lock->exclusive = args->exclusive;
|
||||||
|
|
||||||
/* if we hold a write delegation, handle the lock locally */
|
/* if we hold a write delegation, handle the lock locally */
|
||||||
if (open_lock_delegate(state, &input)) {
|
if (open_lock_delegate(state, lock)) {
|
||||||
dprintf(LKLVL, "delegated lock { %llu, %llu }\n",
|
dprintf(LKLVL, "delegated lock { %llu, %llu }\n",
|
||||||
input.offset, input.length);
|
lock->offset, lock->length);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -249,25 +237,28 @@ static int handle_lock(nfs41_upcall *upcall)
|
||||||
status = nfs41_delegation_to_open(state, TRUE);
|
status = nfs41_delegation_to_open(state, TRUE);
|
||||||
if (status) {
|
if (status) {
|
||||||
status = ERROR_FILE_INVALID;
|
status = ERROR_FILE_INVALID;
|
||||||
goto out;
|
goto out_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
type, input.offset, input.length, FALSE, TRUE, &stateid);
|
type, lock->offset, lock->length, FALSE, TRUE, &stateid);
|
||||||
if (status) {
|
if (status) {
|
||||||
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);
|
||||||
goto out;
|
goto out_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ignore errors from open_lock_add(); they just mean we
|
/* save lock state with the open */
|
||||||
* won't be able to recover the lock after reboot */
|
open_lock_add(state, &stateid, lock);
|
||||||
open_lock_add(state, &stateid, &input);
|
|
||||||
out:
|
out:
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
out_free:
|
||||||
|
free(lock);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cancel_lock(IN nfs41_upcall *upcall)
|
static void cancel_lock(IN nfs41_upcall *upcall)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue