ReactOS  0.4.12-dev-714-gfaac916
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 */
38 static int slot_table_avail(
39  IN const nfs41_slot_table *table)
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 
63 static void resize_slot_table(
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 
81  IN nfs41_session *session,
82  IN uint32_t slotid,
83  IN uint32_t target_highest_slotid)
84 {
85  nfs41_slot_table *table = &session->table;
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 
103  IN nfs41_session *session,
104  IN uint32_t slotid)
105 {
106  nfs41_slot_table *table = &session->table;
107 
108  AcquireSRWLockShared(&session->client->session_lock);
109  EnterCriticalSection(&table->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 */
125  if (slot_table_avail(table))
127 
128  LeaveCriticalSection(&table->lock);
129  ReleaseSRWLockShared(&session->client->session_lock);
130 }
131 
133  IN nfs41_session *session,
134  OUT uint32_t *slot,
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);
142  EnterCriticalSection(&table->lock);
143 
144  /* wait for an available slot */
145  while (!slot_table_avail(table))
146  SleepConditionVariableCS(&table->cond, &table->lock, INFINITE);
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  }
162  LeaveCriticalSection(&table->lock);
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 
170  IN nfs41_session *session,
171  IN OUT uint32_t target_highest_slotid)
172 {
173  nfs41_slot_table *table = &session->table;
174 
175  AcquireSRWLockShared(&session->client->session_lock);
176  EnterCriticalSection(&table->lock);
177  resize_slot_table(table, target_highest_slotid);
178  table->target_delay = GetTickCount64() + MAX_SLOTS_DELAY;
179  LeaveCriticalSection(&table->lock);
180  ReleaseSRWLockShared(&session->client->session_lock);
181 
182  return NFS4_OK;
183 }
184 
186  IN nfs41_session *session,
188 {
189  nfs41_slot_table *table = &session->table;
190  int status = NFS4ERR_BADSLOT;
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 */
198  EnterCriticalSection(&table->lock);
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  }
203  LeaveCriticalSection(&table->lock);
204 
205  /* get a new slot */
206  nfs41_session_free_slot(session, args->sa_slotid);
207  nfs41_session_get_slot(session, &args->sa_slotid,
208  &args->sa_sequenceid, &args->sa_highest_slotid);
209  status = NFS4_OK;
210 out:
211  return status;
212 }
213 
216  nfs41_session *session,
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 */
227 static unsigned int WINAPI renew_session(void *args)
228 {
229  int status = NO_ERROR;
230  nfs41_session *session = (nfs41_session *)args;
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);
238  status = nfs41_send_sequence(session);
239  if (status)
240  dprintf(1, "renewal thread: nfs41_send_sequence failed %d\n", status);
241  }
242  return status;
243 }
244 
245 /* session creation */
246 static int session_alloc(
248  OUT nfs41_session **session_out)
249 {
250  nfs41_session *session;
251  int status = NO_ERROR;
252 
253  session = calloc(1, sizeof(nfs41_session));
254  if (session == NULL) {
255  status = GetLastError();
256  goto out;
257  }
258  session->client = client;
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;
274 out:
275  return status;
276 }
277 
280  IN nfs41_session **session_out)
281 {
282  nfs41_session *session;
283  int status;
284 
285  status = session_alloc(client, &session);
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 
297  status = nfs41_create_session(client, session, TRUE);
298  if (status) {
299  eprintf("nfs41_create_session failed %d\n", status);
301  goto out_err;
302  }
303 
305  client->session = session;
306  session->isValidState = TRUE;
308  *session_out = session;
309 out:
310  return status;
311 
312 out_err:
313  nfs41_session_free(session);
314  goto out;
315 }
316 
317 /* session renewal */
319  IN nfs41_session *session)
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 
327  status = nfs41_create_session(session->client, session, FALSE);
328  ReleaseSRWLockExclusive(&session->client->session_lock);
329  return status;
330 }
331 
333  IN nfs41_session *session,
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,
353  0, renew_session, session, 0, &thread_id);
354  if (!valid_handle(session->renew_thread)) {
355  status = GetLastError();
356  eprintf("_beginthreadex failed %d\n", status);
357  goto out;
358  }
359 out:
360  return status;
361 }
362 
364  IN nfs41_session *session)
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;
376  nfs41_destroy_session(session);
377  }
378  DeleteCriticalSection(&session->table.lock);
379  ReleaseSRWLockExclusive(&session->client->session_lock);
380  free(session);
381 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:54
#define IN
Definition: typedefs.h:38
int nfs41_session_renew(IN nfs41_session *session)
#define TRUE
Definition: types.h:120
int nfs41_send_sequence(IN nfs41_session *session)
Definition: nfs41_ops.c:1599
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:736
BOOL WINAPI TerminateThread(IN HANDLE hThread, IN DWORD dwExitCode)
Definition: thread.c:549
int32_t bool_t
Definition: types.h:101
uint32_t flags
Definition: nfs41.h:265
#define free
Definition: debug_ros.c:5
#define NFS41_MAX_NUM_SLOTS
Definition: nfs41.h:218
void nfs41_session_sequence(nfs41_sequence_args *args, nfs41_session *session, bool_t cachethis)
SRWLOCK session_lock
Definition: nfs41.h:200
void nfs41_callback_session_init(IN nfs41_session *session)
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define MAX_SLOTS_DELAY
Definition: nfs41_session.c:34
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
int nfs41_session_set_lease(IN nfs41_session *session, IN uint32_t lease_time)
static void init_slot_table(nfs41_slot_table *table)
Definition: nfs41_session.c:45
nfs41_slot_table table
Definition: nfs41.h:261
CRITICAL_SECTION lock
Definition: nfs41.h:226
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
_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)
#define NO_ERROR
Definition: dderror.h:5
Definition: match.c:390
ULONGLONG WINAPI GetTickCount64(VOID)
Definition: GetTickCount64.c:9
uint32_t lease_time
Definition: nfs41.h:260
__inline int valid_handle(HANDLE handle)
Definition: util.h:281
#define ERROR_BAD_NET_RESP
Definition: winerror.h:150
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 int slot_table_avail(IN const nfs41_slot_table *table)
Definition: nfs41_session.c:38
VOID WINAPI WakeAllConditionVariable(PCONDITION_VARIABLE ConditionVariable)
Definition: sync.c:137
int nfs41_session_bad_slot(IN nfs41_session *session, IN OUT nfs41_sequence_args *args)
nfs41_client * client
Definition: nfs41.h:256
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 dprintf
Definition: regdump.c:33
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:697
smooth NULL
Definition: ftsmooth.c:416
unsigned char session_id[NFS4_SESSIONID_SIZE]
Definition: nfs41.h:257
bool_t isValidState
Definition: nfs41.h:264
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
#define CREATE_SESSION4_FLAG_PERSIST
Definition: nfs41_const.h:307
HANDLE renew_thread
Definition: nfs41.h:263
static FILE * client
Definition: client.c:41
static FILE * out
Definition: regtests2xml.c:44
PVOID HANDLE
Definition: typedefs.h:71
void nfs41_session_get_slot(IN nfs41_session *session, OUT uint32_t *slot, OUT uint32_t *seqid, OUT uint32_t *highest)
static int session_alloc(IN nfs41_client *client, OUT nfs41_session **session_out)
VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:82
VOID WINAPI InitializeSRWLock(PSRWLOCK Lock)
Definition: sync.c:75
#define WINAPI
Definition: msvc.h:20
int nfs41_session_create(IN nfs41_client *client, IN nfs41_session **session_out)
Definition: vfat.h:184
#define CREATE_SESSION4_FLAG_CONN_BACK_CHAN
Definition: nfs41_const.h:308
BOOL WINAPI SleepConditionVariableCS(PCONDITION_VARIABLE ConditionVariable, PCRITICAL_SECTION CriticalSection, DWORD Timeout)
Definition: sync.c:105
VOID WINAPI InitializeConditionVariable(PCONDITION_VARIABLE ConditionVariable)
Definition: sync.c:68
static DWORD thread_id
Definition: protocol.c:158
int nfs41_create_session(nfs41_client *clnt, nfs41_session *session, bool_t try_recovery)
Definition: nfs41_ops.c:101
void nfs41_session_free_slot(IN nfs41_session *session, IN uint32_t slotid)
UINT32 uint32_t
Definition: types.h:75
CONDITION_VARIABLE cond
Definition: nfs41.h:227
static void resize_slot_table(IN nfs41_slot_table *table, IN uint32_t target_highest_slotid)
Definition: nfs41_session.c:63
#define calloc
Definition: rosglue.h:14
#define OUT
Definition: typedefs.h:39
int nfs41_destroy_session(IN nfs41_session *session)
Definition: nfs41_ops.c:214
static unsigned int WINAPI renew_session(void *args)
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define INFINITE
Definition: serial.h:102
void nfs41_session_free(IN nfs41_session *session)
static SERVICE_STATUS status
Definition: service.c:31
int nfs41_session_recall_slot(IN nfs41_session *session, IN OUT uint32_t target_highest_slotid)
VOID WINAPI AcquireSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:61
VOID WINAPI ReleaseSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:89
Definition: ps.c:97