fresh git tree for public release
we regretfully had to remove our git history for licensing reasons Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
commit
0ad4db4fad
271 changed files with 71255 additions and 0 deletions
385
daemon/nfs41_session.c
Normal file
385
daemon/nfs41_session.c
Normal file
|
|
@ -0,0 +1,385 @@
|
|||
/* Copyright (c) 2010
|
||||
* The Regents of the University of Michigan
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Permission is granted to use, copy and redistribute this software
|
||||
* for noncommercial education and research purposes, so long as no
|
||||
* fee is charged, and so long as the name of the University of Michigan
|
||||
* is not used in any advertising or publicity pertaining to the use
|
||||
* or distribution of this software without specific, written prior
|
||||
* authorization. Permission to modify or otherwise create derivative
|
||||
* works of this software is not granted.
|
||||
*
|
||||
* This software is provided as is, without representation or warranty
|
||||
* of any kind either express or implied, including without limitation
|
||||
* the implied warranties of merchantability, fitness for a particular
|
||||
* purpose, or noninfringement. The Regents of the University of
|
||||
* Michigan shall not be liable for any damages, including special,
|
||||
* indirect, incidental, or consequential damages, with respect to any
|
||||
* claim arising out of or in connection with the use of the software,
|
||||
* even if it has been or is hereafter advised of the possibility of
|
||||
* such damages.
|
||||
*/
|
||||
|
||||
#include <Windows.h>
|
||||
#include <process.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "daemon_debug.h"
|
||||
#include "nfs41_ops.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
/* session slot mechanism */
|
||||
static int init_slot_table(nfs41_slot_table *table)
|
||||
{
|
||||
int i, status = 0;
|
||||
|
||||
//initialize slot table lock
|
||||
table->lock = CreateMutex(NULL, FALSE, "session_table_lock");
|
||||
if (table->lock == NULL) {
|
||||
status = GetLastError();
|
||||
eprintf("CreateMutext failed %d\n", status);
|
||||
goto out;
|
||||
}
|
||||
//initialize condition variable for slots
|
||||
table->cond = CreateEvent(NULL, TRUE, FALSE, "session_table_cond");
|
||||
if (table->cond == NULL) {
|
||||
status = GetLastError();
|
||||
eprintf("CreateEvent failed %d\n", status);
|
||||
goto out_mutex;
|
||||
}
|
||||
|
||||
table->max_slots = NFS41_MAX_NUM_SLOTS;
|
||||
for(i = 0; i < NFS41_MAX_NUM_SLOTS; i++) {
|
||||
table->seq_nums[i] = 1;
|
||||
table->used_slots[i] = 0;
|
||||
}
|
||||
table->highest_used = 0;
|
||||
out:
|
||||
return status;
|
||||
out_mutex:
|
||||
CloseHandle(table->lock);
|
||||
goto out;
|
||||
}
|
||||
|
||||
static int reinit_slot_table(nfs41_slot_table *table)
|
||||
{
|
||||
int i, status = 0;
|
||||
|
||||
status = WaitForSingleObject(table->lock, INFINITE);
|
||||
if (status != WAIT_OBJECT_0) {
|
||||
dprintf(1, "nfs41_session_bump_seq: WaitForSingleObject failed\n");
|
||||
print_condwait_status(1, status);
|
||||
status = ERROR_LOCK_VIOLATION;
|
||||
goto out;
|
||||
}
|
||||
|
||||
table->max_slots = NFS41_MAX_NUM_SLOTS;
|
||||
for(i = 0; i < NFS41_MAX_NUM_SLOTS; i++) {
|
||||
table->seq_nums[i] = 1;
|
||||
table->used_slots[i] = 0;
|
||||
}
|
||||
table->highest_used = 0;
|
||||
SetEvent(table->cond);
|
||||
ReleaseMutex(table->lock);
|
||||
out:
|
||||
return status;
|
||||
}
|
||||
|
||||
static void free_slot_table(nfs41_slot_table *table)
|
||||
{
|
||||
CloseHandle(table->lock);
|
||||
CloseHandle(table->cond);
|
||||
}
|
||||
|
||||
int nfs41_session_bump_seq(
|
||||
IN nfs41_session *session,
|
||||
IN uint32_t slotid)
|
||||
{
|
||||
int status;
|
||||
|
||||
AcquireSRWLockShared(&session->client->session_lock);
|
||||
status = WaitForSingleObject(session->table.lock, INFINITE);
|
||||
if (status != WAIT_OBJECT_0) {
|
||||
dprintf(1, "nfs41_session_bump_seq: WaitForSingleObject failed\n");
|
||||
print_condwait_status(1, status);
|
||||
status = ERROR_LOCK_VIOLATION;
|
||||
goto out;
|
||||
}
|
||||
session->table.seq_nums[slotid]++;
|
||||
ReleaseMutex(session->table.lock);
|
||||
out:
|
||||
ReleaseSRWLockShared(&session->client->session_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
int nfs41_session_free_slot(
|
||||
IN nfs41_session *session,
|
||||
IN uint32_t slotid)
|
||||
{
|
||||
int status, i;
|
||||
|
||||
AcquireSRWLockShared(&session->client->session_lock);
|
||||
status = WaitForSingleObject(session->table.lock, INFINITE);
|
||||
if (status != WAIT_OBJECT_0) {
|
||||
dprintf(1, "nfs41_session_free_slot: WaitForSingleObject failed\n");
|
||||
print_condwait_status(1, status);
|
||||
status = ERROR_LOCK_VIOLATION;
|
||||
goto out;
|
||||
}
|
||||
session->table.used_slots[slotid] = 0;
|
||||
if (slotid == session->table.highest_used) {
|
||||
session->table.highest_used = 0;
|
||||
for (i = slotid; i > 0; i--) {
|
||||
if (session->table.used_slots[i]) {
|
||||
session->table.highest_used = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
dprintf(3, "freeing slot#=%d highest=%d\n", slotid, session->table.highest_used);
|
||||
SetEvent(session->table.cond);
|
||||
ReleaseMutex(session->table.lock);
|
||||
out:
|
||||
ReleaseSRWLockShared(&session->client->session_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
int nfs41_session_get_slot(
|
||||
IN nfs41_session *session,
|
||||
OUT uint32_t *slot,
|
||||
OUT uint32_t *seq,
|
||||
OUT uint32_t *highest)
|
||||
{
|
||||
uint32_t status = NO_ERROR;
|
||||
uint32_t i;
|
||||
|
||||
AcquireSRWLockShared(&session->client->session_lock);
|
||||
look_for_slot:
|
||||
status = WaitForSingleObject(session->table.lock, INFINITE);
|
||||
if (status != WAIT_OBJECT_0) {
|
||||
dprintf(1, "nfs41_session_get_slot: WaitForSingleObject failed\n");
|
||||
print_condwait_status(1, status);
|
||||
status = ERROR_LOCK_VIOLATION;
|
||||
goto out;
|
||||
}
|
||||
dprintf(3, "looking for a free slot in the slot table\n");
|
||||
*highest = session->table.highest_used;
|
||||
for (i = 0; i < session->table.max_slots; i++) {
|
||||
if (!session->table.used_slots[i]) {
|
||||
session->table.used_slots[i] = 1; // mark slot used
|
||||
*slot = i; // return slot number
|
||||
*seq = session->table.seq_nums[i]; // return sequence number for the slot
|
||||
//update highest_slot_used if needed
|
||||
if (i > session->table.highest_used)
|
||||
*highest = session->table.highest_used = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == session->table.max_slots) {
|
||||
dprintf(1, "all (%d) slots are used. waiting for a free slot\n", session->table.max_slots);
|
||||
ReleaseMutex(session->table.lock);
|
||||
status = WaitForSingleObject(session->table.cond, INFINITE);
|
||||
if (status == WAIT_OBJECT_0) {
|
||||
dprintf(1, "received a signal to look for a free slot\n");
|
||||
ResetEvent(session->table.cond);
|
||||
goto look_for_slot;
|
||||
}
|
||||
}
|
||||
ReleaseMutex(session->table.lock);
|
||||
dprintf(2, "session %p: using slot#=%d with seq#=%d highest=%d\n", session, *slot, *seq, *highest);
|
||||
out:
|
||||
ReleaseSRWLockShared(&session->client->session_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
int nfs41_session_sequence(
|
||||
nfs41_sequence_args *args,
|
||||
nfs41_session *session,
|
||||
bool_t cachethis)
|
||||
{
|
||||
uint32_t status = NO_ERROR;
|
||||
|
||||
status = nfs41_session_get_slot(session, &args->sa_slotid,
|
||||
&args->sa_sequenceid, &args->sa_highest_slotid);
|
||||
if (status)
|
||||
goto out;
|
||||
args->sa_sessionid = session->session_id;
|
||||
args->sa_cachethis = cachethis;
|
||||
out:
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* session renewal */
|
||||
static unsigned int WINAPI renew_session(void *args)
|
||||
{
|
||||
int status = NO_ERROR;
|
||||
nfs41_session *session = (nfs41_session *)args;
|
||||
/* sleep for 2/3 of lease_time */
|
||||
const uint32_t sleep_time = (2 * session->lease_time*1000)/3;
|
||||
|
||||
dprintf(1, "Creating renew_session thread: %p\n", session->renew_thread);
|
||||
while(1) {
|
||||
dprintf(1, "Going to sleep for %dmsecs\n", sleep_time);
|
||||
Sleep(sleep_time);
|
||||
status = nfs41_send_sequence(session);
|
||||
if (status)
|
||||
dprintf(1, "renewal thread: nfs41_send_sequence failed %d\n", status);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/* session creation */
|
||||
static int session_alloc(
|
||||
IN nfs41_client *client,
|
||||
OUT nfs41_session **session_out)
|
||||
{
|
||||
int status;
|
||||
nfs41_session *session;
|
||||
|
||||
session = calloc(1, sizeof(nfs41_session));
|
||||
if (session == NULL) {
|
||||
status = GetLastError();
|
||||
goto out;
|
||||
}
|
||||
session->client = client;
|
||||
session->renew_thread = INVALID_HANDLE_VALUE;
|
||||
session->isValidState = FALSE;
|
||||
|
||||
status = init_slot_table(&session->table);
|
||||
if (status) {
|
||||
eprintf("init_slot_table failed %d\n", status);
|
||||
goto out_err_session;
|
||||
}
|
||||
|
||||
//initialize session lock
|
||||
InitializeSRWLock(&client->session_lock);
|
||||
|
||||
*session_out = session;
|
||||
out:
|
||||
return status;
|
||||
out_err_session:
|
||||
free(session);
|
||||
goto out;
|
||||
}
|
||||
|
||||
int nfs41_session_create(
|
||||
IN nfs41_client *client,
|
||||
IN nfs41_session **session_out)
|
||||
{
|
||||
nfs41_session *session;
|
||||
int status;
|
||||
|
||||
status = session_alloc(client, &session);
|
||||
if (status) {
|
||||
eprintf("session_alloc() failed with %d\n", status);
|
||||
goto out;
|
||||
}
|
||||
|
||||
AcquireSRWLockShared(&client->exid_lock);
|
||||
if (client->roles & (EXCHGID4_FLAG_USE_PNFS_MDS |
|
||||
EXCHGID4_FLAG_USE_NON_PNFS))
|
||||
session->flags |= CREATE_SESSION4_FLAG_CONN_BACK_CHAN;
|
||||
ReleaseSRWLockShared(&client->exid_lock);
|
||||
|
||||
status = nfs41_create_session(client, session);
|
||||
if (status) {
|
||||
eprintf("nfs41_create_session failed %d\n", status);
|
||||
status = ERROR_BAD_NET_RESP;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
AcquireSRWLockExclusive(&session->client->session_lock);
|
||||
client->session = session;
|
||||
session->isValidState = TRUE;
|
||||
ReleaseSRWLockExclusive(&session->client->session_lock);
|
||||
*session_out = session;
|
||||
out:
|
||||
return status;
|
||||
|
||||
out_err:
|
||||
nfs41_session_free(session);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* session renewal */
|
||||
int nfs41_session_renew(
|
||||
IN nfs41_session *session)
|
||||
{
|
||||
int status;
|
||||
|
||||
AcquireSRWLockExclusive(&session->client->session_lock);
|
||||
status = reinit_slot_table(&session->table);
|
||||
if (status) {
|
||||
eprintf("init_slot_table failed %d\n", status);
|
||||
goto out_err_session;
|
||||
}
|
||||
status = nfs41_create_session(session->client, session);
|
||||
if (status && status != NFS4ERR_STALE_CLIENTID) {
|
||||
eprintf("nfs41_create_session failed %d\n", status);
|
||||
status = ERROR_BAD_NET_RESP;
|
||||
goto out_err_slot;
|
||||
}
|
||||
ReleaseSRWLockExclusive(&session->client->session_lock);
|
||||
out:
|
||||
return status;
|
||||
out_err_slot:
|
||||
free_slot_table(&session->table);
|
||||
out_err_session:
|
||||
ReleaseSRWLockExclusive(&session->client->session_lock);
|
||||
free(session);
|
||||
goto out;
|
||||
}
|
||||
|
||||
int nfs41_session_set_lease(
|
||||
IN nfs41_session *session,
|
||||
IN uint32_t lease_time)
|
||||
{
|
||||
int status = NO_ERROR;
|
||||
uint32_t thread_id;
|
||||
|
||||
if (valid_handle(session->renew_thread)) {
|
||||
eprintf("nfs41_session_set_lease(): session "
|
||||
"renewal thread already started!\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (lease_time == 0) {
|
||||
eprintf("nfs41_session_set_lease(): invalid lease_time=0\n");
|
||||
status = ERROR_INVALID_PARAMETER;
|
||||
goto out;
|
||||
}
|
||||
|
||||
session->lease_time = lease_time;
|
||||
session->renew_thread = (HANDLE)_beginthreadex(NULL,
|
||||
0, renew_session, session, 0, &thread_id);
|
||||
if (!valid_handle(session->renew_thread)) {
|
||||
status = GetLastError();
|
||||
eprintf("_beginthreadex failed %d\n", status);
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
return status;
|
||||
}
|
||||
|
||||
void nfs41_session_free(
|
||||
IN nfs41_session *session)
|
||||
{
|
||||
AcquireSRWLockExclusive(&session->client->session_lock);
|
||||
if (valid_handle(session->renew_thread)) {
|
||||
dprintf(1, "nfs41_session_free: terminating session renewal thread\n");
|
||||
if (!TerminateThread(session->renew_thread, NO_ERROR))
|
||||
eprintf("failed to terminate renewal thread %p\n",
|
||||
session->renew_thread);
|
||||
}
|
||||
|
||||
if (session->isValidState) {
|
||||
session->client->rpc->is_valid_session = FALSE;
|
||||
nfs41_destroy_session(session);
|
||||
}
|
||||
free_slot_table(&session->table);
|
||||
ReleaseSRWLockExclusive(&session->client->session_lock);
|
||||
free(session);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue