ReactOS 0.4.15-dev-7931-gfd331f1
nfs41_session.c
Go to the documentation of this file.
1/* NFSv4.1 client for Windows
2 * Copyright © 2012 The Regents of the University of Michigan
3 *
4 * Olga Kornievskaia <aglo@umich.edu>
5 * Casey Bodley <cbodley@umich.edu>
6 *
7 * This library is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or (at
10 * your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful, but
13 * without any warranty; without even the implied warranty of merchantability
14 * or fitness for a particular purpose. See the GNU Lesser General Public
15 * License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 */
21
22#include <windows.h>
23#include <process.h>
24#include <stdio.h>
25
26#include "nfs41_ops.h"
27#include "nfs41_callback.h"
28#include "util.h"
29#include "daemon_debug.h"
30
31
32/* after a CB_RECALL_SLOT or NFS4ERR_BADSLOT, wait a short time for the
33 * SEQUENCE.target_highest_slotid to catch up before updating max_slots again */
34#define MAX_SLOTS_DELAY 2000 /* in milliseconds */
35
36
37/* predicate for nfs41_slot_table.cond */
40{
41 return table->num_used < table->max_slots;
42}
43
44/* session slot mechanism */
46{
47 uint32_t i;
49 table->max_slots = NFS41_MAX_NUM_SLOTS;
50 for (i = 0; i < NFS41_MAX_NUM_SLOTS; i++) {
51 table->seq_nums[i] = 1;
52 table->used_slots[i] = 0;
53 }
54 table->highest_used = table->num_used = 0;
55 table->target_delay = 0;
56
57 /* wake any threads waiting on a slot */
61}
62
65 IN uint32_t target_highest_slotid)
66{
67 if (target_highest_slotid >= NFS41_MAX_NUM_SLOTS)
68 target_highest_slotid = NFS41_MAX_NUM_SLOTS - 1;
69
70 if (table->max_slots != target_highest_slotid + 1) {
71 dprintf(2, "updated max_slots %u to %u\n",
72 table->max_slots, target_highest_slotid + 1);
73 table->max_slots = target_highest_slotid + 1;
74
77 }
78}
79
82 IN uint32_t slotid,
83 IN uint32_t target_highest_slotid)
84{
86
87 AcquireSRWLockShared(&session->client->session_lock);
89
90 if (slotid < NFS41_MAX_NUM_SLOTS)
91 table->seq_nums[slotid]++;
92
93 /* adjust max_slots in response to changes in target_highest_slotid,
94 * but not immediately after a CB_RECALL_SLOT or NFS4ERR_BADSLOT error */
95 if (table->target_delay <= GetTickCount64())
96 resize_slot_table(table, target_highest_slotid);
97
99 ReleaseSRWLockShared(&session->client->session_lock);
100}
101
104 IN uint32_t slotid)
105{
106 nfs41_slot_table *table = &session->table;
107
108 AcquireSRWLockShared(&session->client->session_lock);
110
111 /* flag the slot as unused */
112 if (slotid < NFS41_MAX_NUM_SLOTS && table->used_slots[slotid]) {
113 table->used_slots[slotid] = 0;
114 table->num_used--;
115 }
116 /* update highest_used if necessary */
117 if (slotid == table->highest_used) {
118 while (table->highest_used && !table->used_slots[table->highest_used])
119 table->highest_used--;
120 }
121 dprintf(3, "freeing slot#=%d used=%d highest=%d\n",
122 slotid, table->num_used, table->highest_used);
123
124 /* wake any threads waiting on a slot */
127
129 ReleaseSRWLockShared(&session->client->session_lock);
130}
131
135 OUT uint32_t *seqid,
136 OUT uint32_t *highest)
137{
138 nfs41_slot_table *table = &session->table;
139 uint32_t i;
140
141 AcquireSRWLockShared(&session->client->session_lock);
143
144 /* wait for an available slot */
145 while (!slot_table_avail(table))
147
148 for (i = 0; i < table->max_slots; i++) {
149 if (table->used_slots[i])
150 continue;
151
152 table->used_slots[i] = 1;
153 table->num_used++;
154 if (i > table->highest_used)
155 table->highest_used = i;
156
157 *slot = i;
158 *seqid = table->seq_nums[i];
159 *highest = table->highest_used;
160 break;
161 }
163 ReleaseSRWLockShared(&session->client->session_lock);
164
165 dprintf(2, "session %p: using slot#=%d with seq#=%d highest=%d\n",
166 session, *slot, *seqid, *highest);
167}
168
171 IN OUT uint32_t target_highest_slotid)
172{
173 nfs41_slot_table *table = &session->table;
174
175 AcquireSRWLockShared(&session->client->session_lock);
177 resize_slot_table(table, target_highest_slotid);
178 table->target_delay = GetTickCount64() + MAX_SLOTS_DELAY;
180 ReleaseSRWLockShared(&session->client->session_lock);
181
182 return NFS4_OK;
183}
184
188{
189 nfs41_slot_table *table = &session->table;
191
192 if (args->sa_slotid == 0) {
193 eprintf("server bug detected: NFS4ERR_BADSLOT for slotid=0\n");
194 goto out;
195 }
196
197 /* avoid using any slots >= bad_slotid */
199 if (table->max_slots > args->sa_slotid) {
200 resize_slot_table(table, args->sa_slotid);
201 table->target_delay = GetTickCount64() + MAX_SLOTS_DELAY;
202 }
204
205 /* get a new slot */
208 &args->sa_sequenceid, &args->sa_highest_slotid);
209 status = NFS4_OK;
210out:
211 return status;
212}
213
217 bool_t cachethis)
218{
219 nfs41_session_get_slot(session, &args->sa_slotid,
220 &args->sa_sequenceid, &args->sa_highest_slotid);
221 args->sa_sessionid = session->session_id;
222 args->sa_cachethis = cachethis;
223}
224
225
226/* session renewal */
227static unsigned int WINAPI renew_session(void *args)
228{
229 int status = NO_ERROR;
231 /* sleep for 2/3 of lease_time */
232 const uint32_t sleep_time = (2 * session->lease_time*1000)/3;
233
234 dprintf(1, "Creating renew_session thread: %p\n", session->renew_thread);
235 while(1) {
236 dprintf(1, "Going to sleep for %dmsecs\n", sleep_time);
237 Sleep(sleep_time);
239 if (status)
240 dprintf(1, "renewal thread: nfs41_send_sequence failed %d\n", status);
241 }
242 return status;
243}
244
245/* session creation */
246static int session_alloc(
248 OUT nfs41_session **session_out)
249{
251 int status = NO_ERROR;
252
253 session = calloc(1, sizeof(nfs41_session));
254 if (session == NULL) {
256 goto out;
257 }
258 session->client = client;
259 session->renew_thread = INVALID_HANDLE_VALUE;
260 session->isValidState = FALSE;
261
264
265 init_slot_table(&session->table);
266
267 //initialize session lock
268 InitializeSRWLock(&client->session_lock);
269
270 /* initialize the back channel */
272
273 *session_out = session;
274out:
275 return status;
276}
277
280 IN nfs41_session **session_out)
281{
283 int status;
284
286 if (status) {
287 eprintf("session_alloc() failed with %d\n", status);
288 goto out;
289 }
290
291 AcquireSRWLockShared(&client->exid_lock);
292 if (client->rpc->needcb)
295 ReleaseSRWLockShared(&client->exid_lock);
296
298 if (status) {
299 eprintf("nfs41_create_session failed %d\n", status);
301 goto out_err;
302 }
303
304 AcquireSRWLockExclusive(&session->client->session_lock);
305 client->session = session;
306 session->isValidState = TRUE;
307 ReleaseSRWLockExclusive(&session->client->session_lock);
308 *session_out = session;
309out:
310 return status;
311
312out_err:
314 goto out;
315}
316
317/* session renewal */
320{
321 int status;
322
323 AcquireSRWLockExclusive(&session->client->session_lock);
324 session->cb_session.cb_seqnum = 0;
325 init_slot_table(&session->table);
326
328 ReleaseSRWLockExclusive(&session->client->session_lock);
329 return status;
330}
331
334 IN uint32_t lease_time)
335{
336 int status = NO_ERROR;
338
339 if (valid_handle(session->renew_thread)) {
340 eprintf("nfs41_session_set_lease(): session "
341 "renewal thread already started!\n");
342 goto out;
343 }
344
345 if (lease_time == 0) {
346 eprintf("nfs41_session_set_lease(): invalid lease_time=0\n");
348 goto out;
349 }
350
351 session->lease_time = lease_time;
352 session->renew_thread = (HANDLE)_beginthreadex(NULL,
354 if (!valid_handle(session->renew_thread)) {
356 eprintf("_beginthreadex failed %d\n", status);
357 goto out;
358 }
359out:
360 return status;
361}
362
365{
366 AcquireSRWLockExclusive(&session->client->session_lock);
367 if (valid_handle(session->renew_thread)) {
368 dprintf(1, "nfs41_session_free: terminating session renewal thread\n");
369 if (!TerminateThread(session->renew_thread, NO_ERROR))
370 eprintf("failed to terminate renewal thread %p\n",
371 session->renew_thread);
372 }
373
374 if (session->isValidState) {
375 session->client->rpc->is_valid_session = FALSE;
377 }
378 DeleteCriticalSection(&session->table.lock);
379 ReleaseSRWLockExclusive(&session->client->session_lock);
380 free(session);
381}
ULONGLONG WINAPI GetTickCount64(VOID)
Definition: GetTickCount64.c:9
__inline int valid_handle(HANDLE handle)
Definition: util.h:281
void nfs41_callback_session_init(IN nfs41_session *session)
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
#define NO_ERROR
Definition: dderror.h:5
#define free
Definition: debug_ros.c:5
#define NULL
Definition: types.h:112
int32_t bool_t
Definition: types.h:101
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
UINT32 uint32_t
Definition: types.h:75
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
BOOL WINAPI TerminateThread(IN HANDLE hThread, IN DWORD dwExitCode)
Definition: thread.c:587
VOID WINAPI ReleaseSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:89
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:54
VOID WINAPI AcquireSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:61
VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:82
BOOL WINAPI SleepConditionVariableCS(PCONDITION_VARIABLE ConditionVariable, PCRITICAL_SECTION CriticalSection, DWORD Timeout)
Definition: sync.c:105
VOID WINAPI InitializeSRWLock(PSRWLOCK Lock)
Definition: sync.c:75
VOID WINAPI WakeAllConditionVariable(PCONDITION_VARIABLE ConditionVariable)
Definition: sync.c:137
VOID WINAPI InitializeConditionVariable(PCONDITION_VARIABLE ConditionVariable)
Definition: sync.c:68
#define INFINITE
Definition: serial.h:102
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static DWORD thread_id
Definition: protocol.c:159
#define NFS41_MAX_NUM_SLOTS
Definition: nfs41.h:218
#define CREATE_SESSION4_FLAG_PERSIST
Definition: nfs41_const.h:307
@ NFS4ERR_BADSLOT
Definition: nfs41_const.h:162
@ NFS4_OK
Definition: nfs41_const.h:87
#define CREATE_SESSION4_FLAG_CONN_BACK_CHAN
Definition: nfs41_const.h:308
int nfs41_send_sequence(IN nfs41_session *session)
Definition: nfs41_ops.c:1599
int nfs41_destroy_session(IN nfs41_session *session)
Definition: nfs41_ops.c:214
int nfs41_create_session(nfs41_client *clnt, nfs41_session *session, bool_t try_recovery)
Definition: nfs41_ops.c:101
void nfs41_session_get_slot(IN nfs41_session *session, OUT uint32_t *slot, OUT uint32_t *seqid, OUT uint32_t *highest)
int nfs41_session_bad_slot(IN nfs41_session *session, IN OUT nfs41_sequence_args *args)
int nfs41_session_recall_slot(IN nfs41_session *session, IN OUT uint32_t target_highest_slotid)
void nfs41_session_free_slot(IN nfs41_session *session, IN uint32_t slotid)
static int session_alloc(IN nfs41_client *client, OUT nfs41_session **session_out)
int nfs41_session_set_lease(IN nfs41_session *session, IN uint32_t lease_time)
static unsigned int WINAPI renew_session(void *args)
void nfs41_session_free(IN nfs41_session *session)
static int slot_table_avail(IN const nfs41_slot_table *table)
Definition: nfs41_session.c:38
static void init_slot_table(nfs41_slot_table *table)
Definition: nfs41_session.c:45
static void resize_slot_table(IN nfs41_slot_table *table, IN uint32_t target_highest_slotid)
Definition: nfs41_session.c:63
int nfs41_session_create(IN nfs41_client *client, IN nfs41_session **session_out)
int nfs41_session_renew(IN nfs41_session *session)
void nfs41_session_sequence(nfs41_sequence_args *args, nfs41_session *session, bool_t cachethis)
void nfs41_session_bump_seq(IN nfs41_session *session, IN uint32_t slotid, IN uint32_t target_highest_slotid)
Definition: nfs41_session.c:80
#define MAX_SLOTS_DELAY
Definition: nfs41_session.c:34
#define dprintf
Definition: regdump.c:33
static FILE * out
Definition: regtests2xml.c:44
#define calloc
Definition: rosglue.h:14
_CRTIMP uintptr_t __cdecl _beginthreadex(_In_opt_ void *_Security, _In_ unsigned _StackSize, _In_ unsigned(__stdcall *_StartAddress)(void *), _In_opt_ void *_ArgList, _In_ unsigned _InitFlag, _Out_opt_ unsigned *_ThrdAddr)
static FILE * client
Definition: client.c:41
Definition: vfat.h:185
Definition: match.c:390
Definition: ps.c:97
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
PVOID HANDLE
Definition: typedefs.h:73
#define IN
Definition: typedefs.h:39
#define OUT
Definition: typedefs.h:40
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
#define WINAPI
Definition: msvc.h:6
#define ERROR_BAD_NET_RESP
Definition: winerror.h:150