ReactOS  0.4.12-dev-43-g63b00d8
delegation.c File Reference
#include "delegation.h"
#include "nfs41_ops.h"
#include "name_cache.h"
#include "util.h"
#include "daemon_debug.h"
#include <devioctl.h>
#include "nfs41_driver.h"
Include dependency graph for delegation.c:

Go to the source code of this file.

Classes

struct  recall_thread_args
 

Macros

#define DGLVL   2 /* dprintf level for delegation logging */
 
#define open_entry(pos)   list_container(pos, nfs41_open_state, client_entry)
 
#define lock_entry(pos)   list_container(pos, nfs41_lock_state, open_entry)
 
#define deleg_entry(pos)   list_container(pos, nfs41_delegation_state, client_entry)
 

Functions

static int delegation_create (IN const nfs41_path_fh *parent, IN const nfs41_path_fh *file, IN const open_delegation4 *delegation, OUT nfs41_delegation_state **deleg_out)
 
void nfs41_delegation_ref (IN nfs41_delegation_state *state)
 
void nfs41_delegation_deref (IN nfs41_delegation_state *state)
 
static void delegation_remove (IN nfs41_client *client, IN nfs41_delegation_state *deleg)
 
static bool_t has_delegated_locks (IN nfs41_open_state *open)
 
static int open_deleg_cmp (const struct list_entry *entry, const void *value)
 
static nfs41_open_statedeleg_open_find (IN struct client_state *state, IN const nfs41_delegation_state *deleg)
 
static bool_t deleg_lock_find (IN nfs41_open_state *open, OUT nfs41_lock_state *lock_out)
 
static void deleg_lock_update (IN nfs41_open_state *open, IN const nfs41_lock_state *source)
 
static int delegation_flush_locks (IN nfs41_open_state *open, IN bool_t try_recovery)
 
static int delegation_return (IN nfs41_client *client, IN nfs41_delegation_state *deleg, IN bool_t truncate, IN bool_t try_recovery)
 
int nfs41_delegation_granted (IN nfs41_session *session, IN nfs41_path_fh *parent, IN nfs41_path_fh *file, IN open_delegation4 *delegation, IN bool_t try_recovery, OUT nfs41_delegation_state **deleg_out)
 
static int deleg_file_cmp (const struct list_entry *entry, const void *value)
 
static bool_t delegation_compatible (IN enum open_delegation_type4 type, IN uint32_t create, IN uint32_t access, IN uint32_t deny)
 
static int delegation_find (IN nfs41_client *client, IN const void *value, IN list_compare_fn cmp, OUT nfs41_delegation_state **deleg_out)
 
static int delegation_truncate (IN nfs41_delegation_state *deleg, IN nfs41_client *client, IN stateid_arg *stateid, IN nfs41_file_info *info)
 
int nfs41_delegate_open (IN nfs41_open_state *state, IN uint32_t create, IN OPTIONAL nfs41_file_info *createattrs, OUT nfs41_file_info *info)
 
int nfs41_delegation_to_open (IN nfs41_open_state *open, IN bool_t try_recovery)
 
void nfs41_delegation_remove_srvopen (IN nfs41_session *session, IN nfs41_path_fh *file)
 
int nfs41_delegation_return (IN nfs41_session *session, IN nfs41_path_fh *file, IN enum open_delegation_type4 access, IN bool_t truncate)
 
static unsigned int WINAPI delegation_recall_thread (void *args)
 
static int deleg_stateid_cmp (const struct list_entry *entry, const void *value)
 
int nfs41_delegation_recall (IN nfs41_client *client, IN nfs41_fh *fh, IN const stateid4 *stateid, IN bool_t truncate)
 
static int deleg_fh_cmp (const struct list_entry *entry, const void *value)
 
int nfs41_delegation_getattr (IN nfs41_client *client, IN const nfs41_fh *fh, IN const bitmap4 *attr_request, OUT nfs41_file_info *info)
 
void nfs41_client_delegation_free (IN nfs41_client *client)
 
static int delegation_recovery_status (IN nfs41_delegation_state *deleg)
 
int nfs41_client_delegation_recovery (IN nfs41_client *client)
 
int nfs41_client_delegation_return_lru (IN nfs41_client *client)
 

Macro Definition Documentation

◆ deleg_entry

◆ DGLVL

#define DGLVL   2 /* dprintf level for delegation logging */

◆ lock_entry

Definition at line 126 of file delegation.c.

Referenced by deleg_lock_find(), deleg_lock_update(), and has_delegated_locks().

◆ open_entry

Function Documentation

◆ deleg_fh_cmp()

static int deleg_fh_cmp ( const struct list_entry entry,
const void value 
)
static

Definition at line 775 of file delegation.c.

Referenced by nfs41_delegation_getattr().

776 {
777  const nfs41_fh *lhs = &deleg_entry(entry)->file.fh;
778  const nfs41_fh *rhs = (const nfs41_fh*)value;
779  if (lhs->len != rhs->len) return -1;
780  return memcmp(lhs->fh, rhs->fh, lhs->len);
781 }
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define deleg_entry(pos)
Definition: delegation.c:377
uint32_t len
Definition: nfs41_types.h:54
unsigned char fh[NFS4_FHSIZE]
Definition: nfs41_types.h:53

◆ deleg_file_cmp()

static int deleg_file_cmp ( const struct list_entry entry,
const void value 
)
static

Definition at line 379 of file delegation.c.

Referenced by nfs41_delegate_open(), nfs41_delegation_remove_srvopen(), and nfs41_delegation_return().

380 {
381  const nfs41_fh *lhs = &deleg_entry(entry)->file.fh;
382  const nfs41_fh *rhs = (const nfs41_fh*)value;
383  if (lhs->superblock != rhs->superblock) return -1;
384  if (lhs->fileid != rhs->fileid) return -1;
385  return 0;
386 }
uint64_t fileid
Definition: nfs41_types.h:55
struct __nfs41_superblock * superblock
Definition: nfs41_types.h:56
#define deleg_entry(pos)
Definition: delegation.c:377

◆ deleg_lock_find()

static bool_t deleg_lock_find ( IN nfs41_open_state open,
OUT nfs41_lock_state lock_out 
)
static

Definition at line 173 of file delegation.c.

Referenced by delegation_flush_locks().

176 {
177  struct list_entry *entry;
178  bool_t found = FALSE;
179 
180  AcquireSRWLockShared(&open->lock);
181  list_for_each(entry, &open->locks.list) {
182  nfs41_lock_state *lock = lock_entry(entry);
183  if (lock->delegated) {
184  /* copy offset, length, type */
185  lock_out->offset = lock->offset;
186  lock_out->length = lock->length;
187  lock_out->exclusive = lock->exclusive;
188  lock_out->id = lock->id;
189  found = TRUE;
190  break;
191  }
192  }
193  ReleaseSRWLockShared(&open->lock);
194  return found;
195 }
#define TRUE
Definition: types.h:120
uint64_t offset
Definition: nfs41.h:114
rwlock_t lock
Definition: tcpcore.h:1163
#define open
Definition: acwin.h:71
int32_t bool_t
Definition: types.h:101
uint8_t entry
Definition: isohybrid.c:63
uint32_t exclusive
Definition: nfs41.h:116
#define list_for_each(entry, head)
Definition: list.h:36
uint64_t length
Definition: nfs41.h:115
uint32_t delegated
Definition: nfs41.h:117
Definition: list.h:27
uint32_t id
Definition: nfs41.h:118
VOID WINAPI AcquireSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:61
VOID WINAPI ReleaseSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:89
#define lock_entry(pos)
Definition: delegation.c:126

◆ deleg_lock_update()

static void deleg_lock_update ( IN nfs41_open_state open,
IN const nfs41_lock_state source 
)
static

Definition at line 198 of file delegation.c.

Referenced by delegation_flush_locks().

201 {
202  struct list_entry *entry;
203 
205  list_for_each(entry, &open->locks.list) {
206  nfs41_lock_state *lock = lock_entry(entry);
207  if (lock->id == source->id) {
208  lock->delegated = FALSE;
209  break;
210  }
211  }
213 }
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:54
rwlock_t lock
Definition: tcpcore.h:1163
#define open
Definition: acwin.h:71
uint8_t entry
Definition: isohybrid.c:63
#define list_for_each(entry, head)
Definition: list.h:36
VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:82
uint32_t delegated
Definition: nfs41.h:117
Definition: list.h:27
uint32_t id
Definition: nfs41.h:118
#define lock_entry(pos)
Definition: delegation.c:126

◆ deleg_open_find()

static nfs41_open_state* deleg_open_find ( IN struct client_state state,
IN const nfs41_delegation_state deleg 
)
static

Definition at line 155 of file delegation.c.

Referenced by delegation_return().

158 {
159  struct list_entry *entry;
161 
162  EnterCriticalSection(&state->lock);
163  entry = list_search(&state->opens, deleg, open_deleg_cmp);
164  if (entry) {
165  open = open_entry(entry);
166  nfs41_open_state_ref(open); /* return a reference */
167  }
168  LeaveCriticalSection(&state->lock);
169  return open;
170 }
void nfs41_open_state_ref(IN nfs41_open_state *state)
Definition: open.c:96
#define open
Definition: acwin.h:71
static int open_deleg_cmp(const struct list_entry *entry, const void *value)
Definition: delegation.c:139
uint8_t entry
Definition: isohybrid.c:63
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
smooth NULL
Definition: ftsmooth.c:416
static int state
Definition: maze.c:121
static struct list_entry * list_search(const struct list_entry *head, const void *value, list_compare_fn compare)
Definition: list.h:102
Definition: list.h:27
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define open_entry(pos)
Definition: delegation.c:89

◆ deleg_stateid_cmp()

static int deleg_stateid_cmp ( const struct list_entry entry,
const void value 
)
static

Definition at line 696 of file delegation.c.

Referenced by nfs41_delegation_recall().

697 {
698  const stateid4 *lhs = &deleg_entry(entry)->state.stateid;
699  const stateid4 *rhs = (const stateid4*)value;
700  return memcmp(lhs->other, rhs->other, NFS4_STATEID_OTHER);
701 }
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
unsigned char other[NFS4_STATEID_OTHER]
Definition: nfs41_types.h:145
#define deleg_entry(pos)
Definition: delegation.c:377
#define NFS4_STATEID_OTHER
Definition: nfs41_const.h:33

◆ delegation_compatible()

static bool_t delegation_compatible ( IN enum open_delegation_type4  type,
IN uint32_t  create,
IN uint32_t  access,
IN uint32_t  deny 
)
static

Definition at line 388 of file delegation.c.

Referenced by nfs41_delegate_open().

393 {
394  switch (type) {
395  case OPEN_DELEGATE_WRITE:
396  /* An OPEN_DELEGATE_WRITE delegation allows the client to handle,
397  * on its own, all opens. */
398  return TRUE;
399 
400  case OPEN_DELEGATE_READ:
401  /* An OPEN_DELEGATE_READ delegation allows a client to handle,
402  * on its own, requests to open a file for reading that do not
403  * deny OPEN4_SHARE_ACCESS_READ access to others. */
404  if (create == OPEN4_CREATE)
405  return FALSE;
407  return FALSE;
408  return TRUE;
409 
410  default:
411  return FALSE;
412  }
413 }
#define TRUE
Definition: types.h:120
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
static const struct access_res create[16]
Definition: package.c:7720

◆ delegation_create()

static int delegation_create ( IN const nfs41_path_fh parent,
IN const nfs41_path_fh file,
IN const open_delegation4 delegation,
OUT nfs41_delegation_state **  deleg_out 
)
static

Definition at line 36 of file delegation.c.

Referenced by nfs41_delegation_granted().

41 {
43  int status = NO_ERROR;
44 
45  state = calloc(1, sizeof(nfs41_delegation_state));
46  if (state == NULL) {
47  status = GetLastError();
48  goto out;
49  }
50 
51  memcpy(&state->state, delegation, sizeof(open_delegation4));
52 
53  abs_path_copy(&state->path, file->path);
54  path_fh_init(&state->file, &state->path);
55  fh_copy(&state->file.fh, &file->fh);
56  path_fh_init(&state->parent, &state->path);
57  last_component(state->path.path, state->file.name.name,
58  &state->parent.name);
59  fh_copy(&state->parent.fh, &parent->fh);
60 
61  list_init(&state->client_entry);
62  state->status = DELEGATION_GRANTED;
63  InitializeSRWLock(&state->lock);
65  state->ref_count = 1;
66  *deleg_out = state;
67 out:
68  return status;
69 }
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define NO_ERROR
Definition: dderror.h:5
bool_t last_component(IN const char *path, IN const char *path_end, OUT nfs41_component *component)
Definition: util.c:317
void abs_path_copy(OUT nfs41_abs_path *dst, IN const nfs41_abs_path *src)
Definition: util.c:338
nfs41_path_fh file
Definition: nfs41.h:99
smooth NULL
Definition: ftsmooth.c:416
nfs41_path_fh parent
Definition: nfs41.h:98
void path_fh_init(OUT nfs41_path_fh *file, IN nfs41_abs_path *path)
Definition: util.c:346
open_delegation4 state
Definition: nfs41.h:96
const char * name
Definition: nfs41_types.h:48
r parent
Definition: btrfs.c:2644
struct list_entry client_entry
Definition: nfs41.h:100
static FILE * out
Definition: regtests2xml.c:44
void fh_copy(OUT nfs41_fh *dst, IN const nfs41_fh *src)
Definition: util.c:354
static int state
Definition: maze.c:121
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
VOID WINAPI InitializeSRWLock(PSRWLOCK Lock)
Definition: sync.c:75
nfs41_component name
Definition: nfs41_types.h:61
VOID WINAPI InitializeConditionVariable(PCONDITION_VARIABLE ConditionVariable)
Definition: sync.c:68
enum delegation_status status
Definition: nfs41.h:103
WCHAR * path
Definition: filesystem.c:121
#define calloc
Definition: rosglue.h:14
__WINE_SERVER_LIST_INLINE void list_init(struct list *list)
Definition: list.h:149
CONDITION_VARIABLE cond
Definition: nfs41.h:105
char path[NFS41_MAX_PATH_LEN]
Definition: nfs41_types.h:42
nfs41_abs_path path
Definition: nfs41.h:97
static SERVICE_STATUS status
Definition: service.c:31
Definition: fci.c:126
Definition: ps.c:97

◆ delegation_find()

static int delegation_find ( IN nfs41_client client,
IN const void value,
IN list_compare_fn  cmp,
OUT nfs41_delegation_state **  deleg_out 
)
static

Definition at line 415 of file delegation.c.

Referenced by nfs41_delegate_open(), nfs41_delegation_getattr(), nfs41_delegation_recall(), nfs41_delegation_remove_srvopen(), and nfs41_delegation_return().

420 {
421  struct list_entry *entry;
423 
424  EnterCriticalSection(&client->state.lock);
425  entry = list_search(&client->state.delegations, value, cmp);
426  if (entry) {
427  /* return a reference to the delegation */
428  *deleg_out = deleg_entry(entry);
429  nfs41_delegation_ref(*deleg_out);
430 
431  /* move to the 'most recently used' end of the list */
432  list_remove(entry);
433  list_add_tail(&client->state.delegations, entry);
434  status = NFS4_OK;
435  }
436  LeaveCriticalSection(&client->state.lock);
437  return status;
438 }
Definition: get.c:139
#define deleg_entry(pos)
Definition: delegation.c:377
uint8_t entry
Definition: isohybrid.c:63
#define cmp(status, error)
Definition: error.c:114
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
void nfs41_delegation_ref(IN nfs41_delegation_state *state)
Definition: delegation.c:71
__WINE_SERVER_LIST_INLINE void list_add_tail(struct list *list, struct list *elem)
Definition: list.h:102
__WINE_SERVER_LIST_INLINE void list_remove(struct list *elem)
Definition: list.h:108
static FILE * client
Definition: client.c:41
static struct list_entry * list_search(const struct list_entry *head, const void *value, list_compare_fn compare)
Definition: list.h:102
Definition: list.h:27
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
static SERVICE_STATUS status
Definition: service.c:31
Definition: ps.c:97

◆ delegation_flush_locks()

static int delegation_flush_locks ( IN nfs41_open_state open,
IN bool_t  try_recovery 
)
static

Definition at line 215 of file delegation.c.

Referenced by delegation_return().

218 {
219  stateid_arg stateid;
221  int status = NFS4_OK;
222 
223  stateid.open = open;
224  stateid.delegation = NULL;
225 
226  /* get the starting open/lock stateid */
227  AcquireSRWLockShared(&open->lock);
228  if (open->locks.stateid.seqid) {
229  memcpy(&stateid.stateid, &open->locks.stateid, sizeof(stateid4));
230  stateid.type = STATEID_LOCK;
231  } else {
232  memcpy(&stateid.stateid, &open->stateid, sizeof(stateid4));
233  stateid.type = STATEID_OPEN;
234  }
235  ReleaseSRWLockShared(&open->lock);
236 
237  /* send LOCK requests for each delegated lock range */
238  while (deleg_lock_find(open, &lock)) {
239  status = nfs41_lock(open->session, &open->file,
240  &open->owner, lock.exclusive ? WRITE_LT : READ_LT,
241  lock.offset, lock.length, FALSE, try_recovery, &stateid);
242  if (status)
243  break;
244  deleg_lock_update(open, &lock);
245  }
246 
247  /* save the updated lock stateid */
248  if (stateid.type == STATEID_LOCK) {
250  if (open->locks.stateid.seqid == 0) {
251  /* if it's a new lock stateid, copy it in */
252  memcpy(&open->locks.stateid, &stateid.stateid, sizeof(stateid4));
253  } else if (stateid.stateid.seqid > open->locks.stateid.seqid) {
254  /* update the seqid if it's more recent */
255  open->locks.stateid.seqid = stateid.stateid.seqid;
256  }
258  }
259  return status;
260 }
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:54
uint64_t offset
Definition: nfs41.h:114
rwlock_t lock
Definition: tcpcore.h:1163
#define open
Definition: acwin.h:71
static void deleg_lock_update(IN nfs41_open_state *open, IN const nfs41_lock_state *source)
Definition: delegation.c:198
uint32_t seqid
Definition: nfs41_types.h:144
uint32_t exclusive
Definition: nfs41.h:116
smooth NULL
Definition: ftsmooth.c:416
enum stateid_type type
Definition: nfs41_ops.h:285
nfs41_delegation_state * delegation
Definition: nfs41_ops.h:287
nfs41_open_state * open
Definition: nfs41_ops.h:286
uint64_t length
Definition: nfs41.h:115
static bool_t deleg_lock_find(IN nfs41_open_state *open, OUT nfs41_lock_state *lock_out)
Definition: delegation.c:173
VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:82
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
int nfs41_lock(IN nfs41_session *session, IN nfs41_path_fh *file, IN state_owner4 *owner, IN uint32_t type, IN uint64_t offset, IN uint64_t length, IN bool_t reclaim, IN bool_t try_recovery, IN OUT stateid_arg *stateid)
Definition: nfs41_ops.c:904
stateid4 stateid
Definition: nfs41_ops.h:284
static SERVICE_STATUS status
Definition: service.c:31
VOID WINAPI AcquireSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:61
VOID WINAPI ReleaseSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:89
Definition: ps.c:97

◆ delegation_recall_thread()

static unsigned int WINAPI delegation_recall_thread ( void args)
static

Definition at line 683 of file delegation.c.

Referenced by nfs41_delegation_recall().

684 {
685  struct recall_thread_args *recall = (struct recall_thread_args*)args;
686 
687  delegation_return(recall->client, recall->delegation, recall->truncate, TRUE);
688 
689  /* clean up thread arguments */
691  nfs41_root_deref(recall->client->root);
692  free(recall);
693  return 0;
694 }
#define TRUE
Definition: types.h:120
#define free
Definition: debug_ros.c:5
void nfs41_delegation_deref(IN nfs41_delegation_state *state)
Definition: delegation.c:79
nfs41_delegation_state * delegation
Definition: delegation.c:679
static int delegation_return(IN nfs41_client *client, IN nfs41_delegation_state *deleg, IN bool_t truncate, IN bool_t try_recovery)
Definition: delegation.c:264
nfs41_client * client
Definition: delegation.c:678
struct __nfs41_root * root
Definition: nfs41.h:206
void nfs41_root_deref(IN nfs41_root *root)
Definition: namespace.c:100

◆ delegation_recovery_status()

static int delegation_recovery_status ( IN nfs41_delegation_state deleg)
static

Definition at line 842 of file delegation.c.

Referenced by nfs41_client_delegation_recovery().

844 {
845  int status = NFS4_OK;
846 
847  AcquireSRWLockExclusive(&deleg->lock);
848  if (deleg->status == DELEGATION_GRANTED) {
849  if (deleg->revoked) {
850  deleg->status = DELEGATION_RETURNED;
851  status = NFS4ERR_BADHANDLE;
852  } else if (deleg->state.recalled) {
853  deleg->status = DELEGATION_RETURNING;
854  status = NFS4ERR_DELEG_REVOKED;
855  }
856  }
857  ReleaseSRWLockExclusive(&deleg->lock);
858  return status;
859 }
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:54
VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:82
static SERVICE_STATUS status
Definition: service.c:31
Definition: ps.c:97

◆ delegation_remove()

static void delegation_remove ( IN nfs41_client client,
IN nfs41_delegation_state deleg 
)
static

Definition at line 91 of file delegation.c.

Referenced by delegation_return(), and nfs41_client_delegation_recovery().

94 {
95  struct list_entry *entry;
96 
97  /* remove from the client's list */
98  EnterCriticalSection(&client->state.lock);
99  list_remove(&deleg->client_entry);
100 
101  /* remove from each associated open */
102  list_for_each(entry, &client->state.opens) {
103  nfs41_open_state *open = open_entry(entry);
105  if (open->delegation.state == deleg) {
106  /* drop the delegation reference */
107  nfs41_delegation_deref(open->delegation.state);
108  open->delegation.state = NULL;
109  }
111  }
112  LeaveCriticalSection(&client->state.lock);
113 
114  /* signal threads waiting on delegreturn */
115  AcquireSRWLockExclusive(&deleg->lock);
116  deleg->status = DELEGATION_RETURNED;
117  WakeAllConditionVariable(&deleg->cond);
118  ReleaseSRWLockExclusive(&deleg->lock);
119 
120  /* release the client's reference */
121  nfs41_delegation_deref(deleg);
122 }
SRWLOCK lock
Definition: nfs41.h:139
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:54
#define open
Definition: acwin.h:71
uint8_t entry
Definition: isohybrid.c:63
void nfs41_delegation_deref(IN nfs41_delegation_state *state)
Definition: delegation.c:79
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
VOID WINAPI WakeAllConditionVariable(PCONDITION_VARIABLE ConditionVariable)
Definition: sync.c:137
#define list_for_each(entry, head)
Definition: list.h:36
smooth NULL
Definition: ftsmooth.c:416
__WINE_SERVER_LIST_INLINE void list_remove(struct list *elem)
Definition: list.h:108
struct __nfs41_open_state::@24 delegation
static FILE * client
Definition: client.c:41
VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:82
Definition: list.h:27
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define open_entry(pos)
Definition: delegation.c:89

◆ delegation_return()

static int delegation_return ( IN nfs41_client client,
IN nfs41_delegation_state deleg,
IN bool_t  truncate,
IN bool_t  try_recovery 
)
static

Definition at line 264 of file delegation.c.

Referenced by delegation_recall_thread(), nfs41_client_delegation_recovery(), nfs41_client_delegation_return_lru(), nfs41_delegate_open(), and nfs41_delegation_return().

269 {
270  stateid_arg stateid;
272  int status;
273 
274  if (deleg->srv_open) {
275  /* make an upcall to the kernel: invalide data cache */
276  HANDLE pipe;
277  unsigned char inbuf[sizeof(HANDLE)], *buffer = inbuf;
278  DWORD inbuf_len = sizeof(HANDLE), outbuf_len, dstatus;
280  dprintf(1, "delegation_return: making a downcall for srv_open=%x\n",
281  deleg->srv_open);
284  if (pipe == INVALID_HANDLE_VALUE) {
285  eprintf("delegation_return: Unable to open downcall pipe %d\n",
286  GetLastError());
287  goto out_downcall;
288  }
289  length = inbuf_len;
290  safe_write(&buffer, &length, &deleg->srv_open, sizeof(HANDLE));
291 
292  dstatus = DeviceIoControl(pipe, IOCTL_NFS41_INVALCACHE, inbuf, inbuf_len,
293  NULL, 0, (LPDWORD)&outbuf_len, NULL);
294  if (!dstatus)
295  eprintf("IOCTL_NFS41_INVALCACHE failed %d\n", GetLastError());
296  CloseHandle(pipe);
297  }
298 out_downcall:
299 
300  /* recover opens and locks associated with the delegation */
301  while (open = deleg_open_find(&client->state, deleg)) {
302  status = nfs41_delegation_to_open(open, try_recovery);
303  if (status == NFS4_OK)
304  status = delegation_flush_locks(open, try_recovery);
306 
307  if (status)
308  break;
309  }
310 
311  /* return the delegation */
312  stateid.type = STATEID_DELEG_FILE;
313  stateid.open = NULL;
314  stateid.delegation = deleg;
315  AcquireSRWLockShared(&deleg->lock);
316  memcpy(&stateid.stateid, &deleg->state.stateid, sizeof(stateid4));
317  ReleaseSRWLockShared(&deleg->lock);
318 
319  status = nfs41_delegreturn(client->session,
320  &deleg->file, &stateid, try_recovery);
321  if (status == NFS4ERR_BADSESSION)
322  goto out;
323 
324  delegation_remove(client, deleg);
325 out:
326  return status;
327 }
void nfs41_open_state_deref(IN nfs41_open_state *state)
Definition: open.c:104
#define CloseHandle
Definition: compat.h:398
static int delegation_flush_locks(IN nfs41_open_state *open, IN bool_t try_recovery)
Definition: delegation.c:215
#define open
Definition: acwin.h:71
#define NFS41_USER_DEVICE_NAME_A
Definition: nfs41_driver.h:28
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
GLuint buffer
Definition: glext.h:5915
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
static void delegation_remove(IN nfs41_client *client, IN nfs41_delegation_state *deleg)
Definition: delegation.c:91
#define FILE_SHARE_READ
Definition: compat.h:125
#define IOCTL_NFS41_INVALCACHE
Definition: nfs41_driver.h:50
#define dprintf
Definition: regdump.c:33
#define GENERIC_WRITE
Definition: nt_native.h:90
smooth NULL
Definition: ftsmooth.c:416
#define OPEN_EXISTING
Definition: compat.h:426
static nfs41_open_state * deleg_open_find(IN struct client_state *state, IN const nfs41_delegation_state *deleg)
Definition: delegation.c:155
int nfs41_delegation_to_open(IN nfs41_open_state *open, IN bool_t try_recovery)
Definition: delegation.c:539
enum stateid_type type
Definition: nfs41_ops.h:285
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
nfs41_delegation_state * delegation
Definition: nfs41_ops.h:287
static FILE * client
Definition: client.c:41
static FILE * out
Definition: regtests2xml.c:44
unsigned long DWORD
Definition: ntddk_ex.h:95
PVOID HANDLE
Definition: typedefs.h:71
int safe_write(unsigned char **pos, uint32_t *remaining, void *src, uint32_t src_len)
Definition: util.c:44
int nfs41_delegreturn(IN nfs41_session *session, IN nfs41_path_fh *file, IN stateid_arg *stateid, IN bool_t try_recovery)
Definition: nfs41_ops.c:1693
uchar inbuf[M_BLOCK]
Definition: unzcrash.c:40
nfs41_open_state * open
Definition: nfs41_ops.h:286
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define GENERIC_READ
Definition: compat.h:124
BOOL WINAPI DeviceIoControl(IN HANDLE hDevice, IN DWORD dwIoControlCode, IN LPVOID lpInBuffer OPTIONAL, IN DWORD nInBufferSize OPTIONAL, OUT LPVOID lpOutBuffer OPTIONAL, IN DWORD nOutBufferSize OPTIONAL, OUT LPDWORD lpBytesReturned OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: deviceio.c:136
IN OUT PVCB OUT PDIRENT OUT PBCB IN BOOLEAN CreateFile
Definition: fatprocs.h:904
stateid4 stateid
Definition: nfs41_ops.h:284
UINT32 uint32_t
Definition: types.h:75
uint32_t * LPDWORD
Definition: typedefs.h:57
static SERVICE_STATUS status
Definition: service.c:31
VOID WINAPI AcquireSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:61
VOID WINAPI ReleaseSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:89

◆ delegation_truncate()

static int delegation_truncate ( IN nfs41_delegation_state deleg,
IN nfs41_client client,
IN stateid_arg stateid,
IN nfs41_file_info info 
)
static

Definition at line 440 of file delegation.c.

Referenced by nfs41_delegate_open().

445 {
446  nfs41_superblock *superblock = deleg->file.fh.superblock;
447 
448  /* use SETATTR to truncate the file */
449  info->attrmask.arr[1] |= FATTR4_WORD1_TIME_CREATE |
451 
452  get_nfs_time(&info->time_create);
453  get_nfs_time(&info->time_modify);
454  info->time_delta = &superblock->time_delta;
455 
456  /* mask out unsupported attributes */
457  nfs41_superblock_supported_attrs(superblock, &info->attrmask);
458 
459  return nfs41_setattr(client->session, &deleg->file, stateid, info);
460 }
int nfs41_setattr(IN nfs41_session *session, IN nfs41_path_fh *file, IN stateid_arg *stateid, IN nfs41_file_info *info)
Definition: nfs41_ops.c:1351
nfstime4 time_delta
Definition: nfs41.h:45
static __inline void nfs41_superblock_supported_attrs(IN const nfs41_superblock *superblock, IN OUT bitmap4 *attrs)
Definition: nfs41.h:454
static FILE * client
Definition: client.c:41
void get_nfs_time(OUT nfstime4 *nfs_time)
Definition: util.c:210

◆ has_delegated_locks()

static bool_t has_delegated_locks ( IN nfs41_open_state open)
static

Definition at line 128 of file delegation.c.

Referenced by open_deleg_cmp().

130 {
131  struct list_entry *entry;
132  list_for_each(entry, &open->locks.list) {
133  if (lock_entry(entry)->delegated)
134  return TRUE;
135  }
136  return FALSE;
137 }
#define TRUE
Definition: types.h:120
#define open
Definition: acwin.h:71
uint8_t entry
Definition: isohybrid.c:63
#define list_for_each(entry, head)
Definition: list.h:36
Definition: list.h:27
#define lock_entry(pos)
Definition: delegation.c:126

◆ nfs41_client_delegation_free()

void nfs41_client_delegation_free ( IN nfs41_client client)

Definition at line 828 of file delegation.c.

Referenced by nfs41_client_free().

830 {
831  struct list_entry *entry, *tmp;
832 
833  EnterCriticalSection(&client->state.lock);
834  list_for_each_tmp (entry, tmp, &client->state.delegations) {
835  list_remove(entry);
837  }
838  LeaveCriticalSection(&client->state.lock);
839 }
#define deleg_entry(pos)
Definition: delegation.c:377
uint8_t entry
Definition: isohybrid.c:63
void nfs41_delegation_deref(IN nfs41_delegation_state *state)
Definition: delegation.c:79
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
__WINE_SERVER_LIST_INLINE void list_remove(struct list *elem)
Definition: list.h:108
static FILE * client
Definition: client.c:41
Definition: list.h:27
#define list_for_each_tmp(entry, tmp, head)
Definition: list.h:39
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)

◆ nfs41_client_delegation_recovery()

int nfs41_client_delegation_recovery ( IN nfs41_client client)

Definition at line 861 of file delegation.c.

Referenced by nfs41_client_state_revoked(), and nfs41_recover_client_state().

863 {
864  struct list_entry *entry, *tmp;
865  nfs41_delegation_state *deleg;
866  int status = NFS4_OK;
867 
868  list_for_each_tmp(entry, tmp, &client->state.delegations) {
870 
871  status = delegation_recovery_status(deleg);
872  switch (status) {
874  /* the delegation was reclaimed, but flagged as recalled;
875  * return it with try_recovery=FALSE */
876  status = delegation_return(client, deleg, FALSE, FALSE);
877  break;
878 
879  case NFS4ERR_BADHANDLE:
880  /* reclaim failed, so we have no delegation state on the server;
881  * 'forget' the delegation without trying to return it */
882  delegation_remove(client, deleg);
883  status = NFS4_OK;
884  break;
885  }
886 
887  if (status == NFS4ERR_BADSESSION)
888  goto out;
889  }
890 
891  /* use DELEGPURGE to indicate that we're done reclaiming delegations */
892  status = nfs41_delegpurge(client->session);
893 
894  /* support for DELEGPURGE is optional; ignore any errors but BADSESSION */
895  if (status != NFS4ERR_BADSESSION)
896  status = NFS4_OK;
897 out:
898  return status;
899 }
uint8_t entry
Definition: isohybrid.c:63
int nfs41_delegpurge(IN nfs41_session *session)
Definition: nfs41_ops.c:1666
static void delegation_remove(IN nfs41_client *client, IN nfs41_delegation_state *deleg)
Definition: delegation.c:91
#define list_container(entry, type, field)
Definition: list.h:33
#define client_entry(pos)
Definition: namespace.c:33
static int delegation_return(IN nfs41_client *client, IN nfs41_delegation_state *deleg, IN bool_t truncate, IN bool_t try_recovery)
Definition: delegation.c:264
static int delegation_recovery_status(IN nfs41_delegation_state *deleg)
Definition: delegation.c:842
static FILE * client
Definition: client.c:41
static FILE * out
Definition: regtests2xml.c:44
Definition: list.h:27
#define list_for_each_tmp(entry, tmp, head)
Definition: list.h:39
static SERVICE_STATUS status
Definition: service.c:31
Definition: ps.c:97

◆ nfs41_client_delegation_return_lru()

int nfs41_client_delegation_return_lru ( IN nfs41_client client)

Definition at line 902 of file delegation.c.

Referenced by open_update_cache().

904 {
905  struct list_entry *entry;
908 
909  /* starting from the least recently opened, find and return
910  * the first delegation that's not 'in use' (currently open) */
911 
912  /* TODO: use a more robust algorithm, taking into account:
913  * -number of total opens
914  * -time since last operation on an associated open, or
915  * -number of operations/second over last n seconds */
916  EnterCriticalSection(&client->state.lock);
917  list_for_each(entry, &client->state.delegations) {
918  state = deleg_entry(entry);
919 
920  /* skip if it's currently in use for an open; note that ref_count
921  * can't go from 1 to 2 without holding client->state.lock */
922  if (state->ref_count > 1)
923  continue;
924 
925  AcquireSRWLockExclusive(&state->lock);
926  if (state->status == DELEGATION_GRANTED) {
927  /* start returning the delegation */
928  state->status = DELEGATION_RETURNING;
929  status = NFS4ERR_DELEG_REVOKED;
930  }
931  ReleaseSRWLockExclusive(&state->lock);
932 
933  if (status == NFS4ERR_DELEG_REVOKED)
934  break;
935  }
936  LeaveCriticalSection(&client->state.lock);
937 
938  if (status == NFS4ERR_DELEG_REVOKED)
939  status = delegation_return(client, state, FALSE, TRUE);
940  return status;
941 }
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:54
#define TRUE
Definition: types.h:120
#define deleg_entry(pos)
Definition: delegation.c:377
uint8_t entry
Definition: isohybrid.c:63
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define list_for_each(entry, head)
Definition: list.h:36
smooth NULL
Definition: ftsmooth.c:416
static int delegation_return(IN nfs41_client *client, IN nfs41_delegation_state *deleg, IN bool_t truncate, IN bool_t try_recovery)
Definition: delegation.c:264
static FILE * client
Definition: client.c:41
static int state
Definition: maze.c:121
VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:82
Definition: list.h:27
enum delegation_status status
Definition: nfs41.h:103
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
static SERVICE_STATUS status
Definition: service.c:31
Definition: ps.c:97

◆ nfs41_delegate_open()

int nfs41_delegate_open ( IN nfs41_open_state state,
IN uint32_t  create,
IN OPTIONAL nfs41_file_info createattrs,
OUT nfs41_file_info info 
)

Definition at line 462 of file delegation.c.

Referenced by open_or_delegate().

467 {
468  nfs41_client *client = state->session->client;
469  nfs41_path_fh *file = &state->file;
470  uint32_t access = state->share_access;
471  uint32_t deny = state->share_deny;
472  nfs41_delegation_state *deleg;
473  stateid_arg stateid;
474  int status;
475 
476  /* search for a delegation with this filehandle */
477  status = delegation_find(client, &file->fh, deleg_file_cmp, &deleg);
478  if (status)
479  goto out;
480 
481  AcquireSRWLockExclusive(&deleg->lock);
482  if (deleg->status != DELEGATION_GRANTED) {
483  /* the delegation is being returned, wait for it to finish */
484  while (deleg->status != DELEGATION_RETURNED)
485  SleepConditionVariableSRW(&deleg->cond, &deleg->lock, INFINITE, 0);
486  status = NFS4ERR_BADHANDLE;
487  }
488  else if (!delegation_compatible(deleg->state.type, create, access, deny)) {
489 #ifdef DELEGATION_RETURN_ON_CONFLICT
490  /* this open will conflict, start the delegation return */
491  deleg->status = DELEGATION_RETURNING;
492  status = NFS4ERR_DELEG_REVOKED;
493 #else
494  status = NFS4ERR_BADHANDLE;
495 #endif
496  } else if (create == OPEN4_CREATE) {
497  /* copy the stateid for SETATTR */
498  stateid.open = NULL;
499  stateid.delegation = deleg;
500  stateid.type = STATEID_DELEG_FILE;
501  memcpy(&stateid.stateid, &deleg->state.stateid, sizeof(stateid4));
502  }
503  if (!status) {
504  dprintf(1, "nfs41_delegate_open: updating srv_open from %x to %x\n",
505  deleg->srv_open, state->srv_open);
506  deleg->srv_open = state->srv_open;
507  }
508  ReleaseSRWLockExclusive(&deleg->lock);
509 
510  if (status == NFS4ERR_DELEG_REVOKED)
511  goto out_return;
512  if (status)
513  goto out_deleg;
514 
515  if (create == OPEN4_CREATE) {
516  memcpy(info, createattrs, sizeof(nfs41_file_info));
517 
518  /* write delegations allow us to simulate OPEN4_CREATE with SETATTR */
519  status = delegation_truncate(deleg, client, &stateid, info);
520  if (status)
521  goto out_deleg;
522  }
523 
524  /* TODO: check access against deleg->state.permissions or send ACCESS */
525 
526  state->delegation.state = deleg;
527  status = NFS4_OK;
528 out:
529  return status;
530 
531 out_return:
532  delegation_return(client, deleg, create == OPEN4_CREATE, TRUE);
533 
534 out_deleg:
535  nfs41_delegation_deref(deleg);
536  goto out;
537 }
static bool_t delegation_compatible(IN enum open_delegation_type4 type, IN uint32_t create, IN uint32_t access, IN uint32_t deny)
Definition: delegation.c:388
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:54
static int deleg_file_cmp(const struct list_entry *entry, const void *value)
Definition: delegation.c:379
#define TRUE
Definition: types.h:120
static int delegation_truncate(IN nfs41_delegation_state *deleg, IN nfs41_client *client, IN stateid_arg *stateid, IN nfs41_file_info *info)
Definition: delegation.c:440
void nfs41_delegation_deref(IN nfs41_delegation_state *state)
Definition: delegation.c:79
#define dprintf
Definition: regdump.c:33
smooth NULL
Definition: ftsmooth.c:416
static int delegation_return(IN nfs41_client *client, IN nfs41_delegation_state *deleg, IN bool_t truncate, IN bool_t try_recovery)
Definition: delegation.c:264
static int delegation_find(IN nfs41_client *client, IN const void *value, IN list_compare_fn cmp, OUT nfs41_delegation_state **deleg_out)
Definition: delegation.c:415
open_delegation4 state
Definition: nfs41.h:96
BOOL WINAPI SleepConditionVariableSRW(PCONDITION_VARIABLE ConditionVariable, PSRWLOCK Lock, DWORD Timeout, ULONG Flags)
Definition: sync.c:121
enum stateid_type type
Definition: nfs41_ops.h:285
nfs41_delegation_state * delegation
Definition: nfs41_ops.h:287
enum open_delegation_type4 type
Definition: nfs41_types.h:154
static FILE * client
Definition: client.c:41
static FILE * out
Definition: regtests2xml.c:44
nfs41_open_state * open
Definition: nfs41_ops.h:286
static int state
Definition: maze.c:121
VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:82
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
stateid4 stateid
Definition: nfs41_ops.h:284
UINT32 uint32_t
Definition: types.h:75
enum delegation_status status
Definition: nfs41.h:103
CONDITION_VARIABLE cond
Definition: nfs41.h:105
#define INFINITE
Definition: serial.h:102
static const struct access_res create[16]
Definition: package.c:7720
static SERVICE_STATUS status
Definition: service.c:31
Definition: fci.c:126

◆ nfs41_delegation_deref()

void nfs41_delegation_deref ( IN nfs41_delegation_state state)

Definition at line 79 of file delegation.c.

Referenced by delegation_recall_thread(), delegation_remove(), nfs41_client_delegation_free(), nfs41_delegate_open(), nfs41_delegation_getattr(), nfs41_delegation_recall(), nfs41_delegation_remove_srvopen(), nfs41_delegation_return(), and open_state_free().

81 {
82  const LONG count = InterlockedDecrement(&state->ref_count);
83  dprintf(DGLVL, "nfs41_delegation_deref(%s) count %d\n",
84  state->path.path, count);
85  if (count == 0)
86  free(state);
87 }
GLuint GLuint GLsizei count
Definition: gl.h:1545
#define free
Definition: debug_ros.c:5
long LONG
Definition: pedump.c:60
#define dprintf
Definition: regdump.c:33
#define DGLVL
Definition: delegation.c:32
#define InterlockedDecrement
Definition: armddk.h:52
static int state
Definition: maze.c:121

◆ nfs41_delegation_getattr()

int nfs41_delegation_getattr ( IN nfs41_client client,
IN const nfs41_fh fh,
IN const bitmap4 attr_request,
OUT nfs41_file_info info 
)

Definition at line 783 of file delegation.c.

Referenced by handle_cb_getattr().

788 {
789  nfs41_delegation_state *deleg;
790  uint64_t fileid;
791  int status;
792 
793  dprintf(2, "--> nfs41_delegation_getattr()\n");
794 
795  /* search for a delegation on this file handle */
796  status = delegation_find(client, fh, deleg_fh_cmp, &deleg);
797  if (status)
798  goto out;
799 
800  AcquireSRWLockShared(&deleg->lock);
801  fileid = deleg->file.fh.fileid;
802  if (deleg->status != DELEGATION_GRANTED ||
803  deleg->state.type != OPEN_DELEGATE_WRITE) {
804  status = NFS4ERR_BADHANDLE;
805  }
806  ReleaseSRWLockShared(&deleg->lock);
807  if (status)
808  goto out_deleg;
809 
810  ZeroMemory(info, sizeof(nfs41_file_info));
811 
812  /* find attributes for the given fileid */
813  status = nfs41_attr_cache_lookup(
814  client_name_cache(client), fileid, info);
815  if (status) {
816  status = NFS4ERR_BADHANDLE;
817  goto out_deleg;
818  }
819 out_deleg:
820  nfs41_delegation_deref(deleg);
821 out:
822  dprintf(DGLVL, "<-- nfs41_delegation_getattr() returning %s\n",
823  nfs_error_string(status));
824  return status;
825 }
uint64_t fileid
Definition: nfs41_types.h:55
#define ZeroMemory
Definition: winbase.h:1635
void nfs41_delegation_deref(IN nfs41_delegation_state *state)
Definition: delegation.c:79
nfs41_path_fh file
Definition: nfs41.h:99
#define dprintf
Definition: regdump.c:33
#define DGLVL
Definition: delegation.c:32
static int delegation_find(IN nfs41_client *client, IN const void *value, IN list_compare_fn cmp, OUT nfs41_delegation_state **deleg_out)
Definition: delegation.c:415
open_delegation4 state
Definition: nfs41.h:96
static __inline struct nfs41_name_cache * client_name_cache(IN nfs41_client *client)
Definition: name_cache.h:28
enum open_delegation_type4 type
Definition: nfs41_types.h:154
static FILE * client
Definition: client.c:41
static FILE * out
Definition: regtests2xml.c:44
const char * nfs_error_string(int status)
Definition: daemon_debug.c:370
static int deleg_fh_cmp(const struct list_entry *entry, const void *value)
Definition: delegation.c:775
UINT64 uint64_t
Definition: types.h:77
enum delegation_status status
Definition: nfs41.h:103
int nfs41_attr_cache_lookup(IN struct nfs41_name_cache *cache, IN uint64_t fileid, OUT nfs41_file_info *info_out)
Definition: name_cache.c:859
static SERVICE_STATUS status
Definition: service.c:31
VOID WINAPI AcquireSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:61
VOID WINAPI ReleaseSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:89

◆ nfs41_delegation_granted()

int nfs41_delegation_granted ( IN nfs41_session session,
IN nfs41_path_fh parent,
IN nfs41_path_fh file,
IN open_delegation4 delegation,
IN bool_t  try_recovery,
OUT nfs41_delegation_state **  deleg_out 
)

Definition at line 330 of file delegation.c.

Referenced by do_open(), and recover_open().

337 {
338  stateid_arg stateid;
339  nfs41_client *client = session->client;
341  int status = NO_ERROR;
342 
343  if (delegation->type != OPEN_DELEGATE_READ &&
344  delegation->type != OPEN_DELEGATE_WRITE)
345  goto out;
346 
347  if (delegation->recalled) {
348  status = NFS4ERR_DELEG_REVOKED;
349  goto out_return;
350  }
351 
352  /* allocate the delegation state */
353  status = delegation_create(parent, file, delegation, &state);
354  if (status)
355  goto out_return;
356 
357  /* register the delegation with the client */
358  EnterCriticalSection(&client->state.lock);
359  /* XXX: check for duplicates by fh and stateid? */
360  list_add_tail(&client->state.delegations, &state->client_entry);
361  LeaveCriticalSection(&client->state.lock);
362 
363  nfs41_delegation_ref(state); /* return a reference */
364  *deleg_out = state;
365 out:
366  return status;
367 
368 out_return: /* return the delegation on failure */
369  memcpy(&stateid.stateid, &delegation->stateid, sizeof(stateid4));
370  stateid.type = STATEID_DELEG_FILE;
371  stateid.open = NULL;
372  stateid.delegation = NULL;
373  nfs41_delegreturn(session, file, &stateid, try_recovery);
374  goto out;
375 }
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define NO_ERROR
Definition: dderror.h:5
void nfs41_delegation_ref(IN nfs41_delegation_state *state)
Definition: delegation.c:71
__WINE_SERVER_LIST_INLINE void list_add_tail(struct list *list, struct list *elem)
Definition: list.h:102
smooth NULL
Definition: ftsmooth.c:416
r parent
Definition: btrfs.c:2644
struct list_entry client_entry
Definition: nfs41.h:100
enum stateid_type type
Definition: nfs41_ops.h:285
nfs41_delegation_state * delegation
Definition: nfs41_ops.h:287
static FILE * client
Definition: client.c:41
static FILE * out
Definition: regtests2xml.c:44
int nfs41_delegreturn(IN nfs41_session *session, IN nfs41_path_fh *file, IN stateid_arg *stateid, IN bool_t try_recovery)
Definition: nfs41_ops.c:1693
nfs41_open_state * open
Definition: nfs41_ops.h:286
struct client_state state
Definition: nfs41.h:215
static int state
Definition: maze.c:121
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static int delegation_create(IN const nfs41_path_fh *parent, IN const nfs41_path_fh *file, IN const open_delegation4 *delegation, OUT nfs41_delegation_state **deleg_out)
Definition: delegation.c:36
stateid4 stateid
Definition: nfs41_ops.h:284
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
static SERVICE_STATUS status
Definition: service.c:31
Definition: fci.c:126
Definition: ps.c:97

◆ nfs41_delegation_recall()

int nfs41_delegation_recall ( IN nfs41_client client,
IN nfs41_fh fh,
IN const stateid4 stateid,
IN bool_t  truncate 
)

Definition at line 703 of file delegation.c.

Referenced by handle_cb_recall().

708 {
709  nfs41_delegation_state *deleg;
710  struct recall_thread_args *args;
711  int status;
712 
713  dprintf(2, "--> nfs41_delegation_recall()\n");
714 
715  /* search for the delegation by stateid instead of filehandle;
716  * deleg_file_cmp() relies on a proper superblock and fileid,
717  * which we don't get with CB_RECALL */
718  status = delegation_find(client, stateid, deleg_stateid_cmp, &deleg);
719  if (status)
720  goto out;
721 
722  AcquireSRWLockExclusive(&deleg->lock);
723  if (deleg->state.recalled) {
724  /* return BADHANDLE if we've already responded to CB_RECALL */
725  status = NFS4ERR_BADHANDLE;
726  } else {
727  deleg->state.recalled = 1;
728 
729  if (deleg->status == DELEGATION_GRANTED) {
730  /* start the delegation return */
731  deleg->status = DELEGATION_RETURNING;
732  status = NFS4ERR_DELEG_REVOKED;
733  } /* else return NFS4_OK */
734  }
735  ReleaseSRWLockExclusive(&deleg->lock);
736 
737  if (status != NFS4ERR_DELEG_REVOKED)
738  goto out_deleg;
739 
740  /* allocate thread arguments */
741  args = calloc(1, sizeof(struct recall_thread_args));
742  if (args == NULL) {
743  status = NFS4ERR_SERVERFAULT;
744  eprintf("nfs41_delegation_recall() failed to allocate arguments\n");
745  goto out_deleg;
746  }
747 
748  /* hold a reference on the root */
749  nfs41_root_ref(client->root);
750  args->client = client;
751  args->delegation = deleg;
752  args->truncate = truncate;
753 
754  /* the callback thread can't make rpc calls, so spawn a separate thread */
755  if (_beginthreadex(NULL, 0, delegation_recall_thread, args, 0, NULL) == 0) {
756  status = NFS4ERR_SERVERFAULT;
757  eprintf("nfs41_delegation_recall() failed to start thread\n");
758  goto out_args;
759  }
760  status = NFS4_OK;
761 out:
762  dprintf(DGLVL, "<-- nfs41_delegation_recall() returning %s\n",
763  nfs_error_string(status));
764  return status;
765 
766 out_args:
767  free(args);
768  nfs41_root_deref(client->root);
769 out_deleg:
770  nfs41_delegation_deref(deleg);
771  goto out;
772 }
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:54
#define free
Definition: debug_ros.c:5
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
void nfs41_delegation_deref(IN nfs41_delegation_state *state)
Definition: delegation.c:79
_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)
nfs41_delegation_state * delegation
Definition: delegation.c:679
#define dprintf
Definition: regdump.c:33
#define DGLVL
Definition: delegation.c:32
smooth NULL
Definition: ftsmooth.c:416
void nfs41_root_ref(IN nfs41_root *root)
Definition: namespace.c:92
static int delegation_find(IN nfs41_client *client, IN const void *value, IN list_compare_fn cmp, OUT nfs41_delegation_state **deleg_out)
Definition: delegation.c:415
open_delegation4 state
Definition: nfs41.h:96
static FILE * client
Definition: client.c:41
static FILE * out
Definition: regtests2xml.c:44
const char * nfs_error_string(int status)
Definition: daemon_debug.c:370
nfs41_client * client
Definition: delegation.c:678
VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:82
static int deleg_stateid_cmp(const struct list_entry *entry, const void *value)
Definition: delegation.c:696
enum delegation_status status
Definition: nfs41.h:103
#define calloc
Definition: rosglue.h:14
void nfs41_root_deref(IN nfs41_root *root)
Definition: namespace.c:100
static SERVICE_STATUS status
Definition: service.c:31
#define args
Definition: format.c:66
static unsigned int WINAPI delegation_recall_thread(void *args)
Definition: delegation.c:683

◆ nfs41_delegation_ref()

void nfs41_delegation_ref ( IN nfs41_delegation_state state)

Definition at line 71 of file delegation.c.

Referenced by delegation_find(), and nfs41_delegation_granted().

73 {
74  const LONG count = InterlockedIncrement(&state->ref_count);
75  dprintf(DGLVL, "nfs41_delegation_ref(%s) count %d\n",
76  state->path.path, count);
77 }
GLuint GLuint GLsizei count
Definition: gl.h:1545
long LONG
Definition: pedump.c:60
#define dprintf
Definition: regdump.c:33
#define DGLVL
Definition: delegation.c:32
static int state
Definition: maze.c:121
#define InterlockedIncrement
Definition: armddk.h:53

◆ nfs41_delegation_remove_srvopen()

void nfs41_delegation_remove_srvopen ( IN nfs41_session session,
IN nfs41_path_fh file 
)

Definition at line 610 of file delegation.c.

Referenced by handle_close().

613 {
614  nfs41_delegation_state *deleg = NULL;
615 
616  /* find a delegation for this file */
617  if (delegation_find(session->client, &file->fh, deleg_file_cmp, &deleg))
618  return;
619  dprintf(1, "nfs41_delegation_remove_srvopen: removing reference to "
620  "srv_open=%x\n", deleg->srv_open);
621  AcquireSRWLockExclusive(&deleg->lock);
622  deleg->srv_open = NULL;
623  ReleaseSRWLockExclusive(&deleg->lock);
624  nfs41_delegation_deref(deleg);
625 }
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:54
static int deleg_file_cmp(const struct list_entry *entry, const void *value)
Definition: delegation.c:379
void nfs41_delegation_deref(IN nfs41_delegation_state *state)
Definition: delegation.c:79
#define dprintf
Definition: regdump.c:33
smooth NULL
Definition: ftsmooth.c:416
static int delegation_find(IN nfs41_client *client, IN const void *value, IN list_compare_fn cmp, OUT nfs41_delegation_state **deleg_out)
Definition: delegation.c:415
VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:82
Definition: fci.c:126

◆ nfs41_delegation_return()

int nfs41_delegation_return ( IN nfs41_session session,
IN nfs41_path_fh file,
IN enum open_delegation_type4  access,
IN bool_t  truncate 
)

Definition at line 629 of file delegation.c.

Referenced by cancel_open(), handle_close(), handle_nfs41_remove(), handle_nfs41_set_size(), handle_open(), handle_setacl(), and handle_setexattr().

638 {
639  nfs41_client *client = session->client;
640  nfs41_delegation_state *deleg;
641  int status;
642 
643  /* find a delegation for this file */
644  status = delegation_find(client, &file->fh, deleg_file_cmp, &deleg);
645  if (status)
646  goto out;
647 
648  AcquireSRWLockExclusive(&deleg->lock);
649  if (deleg->status == DELEGATION_GRANTED) {
650  /* return unless delegation is write and access is read */
651  if (deleg->state.type != OPEN_DELEGATE_WRITE
652  || access != OPEN_DELEGATE_READ) {
653  deleg->status = DELEGATION_RETURNING;
654  status = NFS4ERR_DELEG_REVOKED;
655  }
656  } else {
657  /* the delegation is being returned, wait for it to finish */
658  while (deleg->status == DELEGATION_RETURNING)
659  SleepConditionVariableSRW(&deleg->cond, &deleg->lock, INFINITE, 0);
660  status = NFS4ERR_BADHANDLE;
661  }
662  ReleaseSRWLockExclusive(&deleg->lock);
663 
664  if (status == NFS4ERR_DELEG_REVOKED) {
665  delegation_return(client, deleg, truncate, TRUE);
666  status = NFS4_OK;
667  }
668 
669  nfs41_delegation_deref(deleg);
670 out:
671  return status;
672 }
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:54
static int deleg_file_cmp(const struct list_entry *entry, const void *value)
Definition: delegation.c:379
#define TRUE
Definition: types.h:120
void nfs41_delegation_deref(IN nfs41_delegation_state *state)
Definition: delegation.c:79
static int delegation_return(IN nfs41_client *client, IN nfs41_delegation_state *deleg, IN bool_t truncate, IN bool_t try_recovery)
Definition: delegation.c:264
static int delegation_find(IN nfs41_client *client, IN const void *value, IN list_compare_fn cmp, OUT nfs41_delegation_state **deleg_out)
Definition: delegation.c:415
open_delegation4 state
Definition: nfs41.h:96
BOOL WINAPI SleepConditionVariableSRW(PCONDITION_VARIABLE ConditionVariable, PSRWLOCK Lock, DWORD Timeout, ULONG Flags)
Definition: sync.c:121
enum open_delegation_type4 type
Definition: nfs41_types.h:154
static FILE * client
Definition: client.c:41
static FILE * out
Definition: regtests2xml.c:44
VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:82
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
enum delegation_status status
Definition: nfs41.h:103
CONDITION_VARIABLE cond
Definition: nfs41.h:105
#define INFINITE
Definition: serial.h:102
static SERVICE_STATUS status
Definition: service.c:31
Definition: fci.c:126

◆ nfs41_delegation_to_open()

int nfs41_delegation_to_open ( IN nfs41_open_state open,
IN bool_t  try_recovery 
)

Definition at line 539 of file delegation.c.

Referenced by delegation_return(), and handle_lock().

542 {
544  open_claim4 claim;
545  stateid4 open_stateid = { 0 };
546  stateid_arg deleg_stateid;
547  int status = NFS4_OK;
548 
550  if (open->delegation.state == NULL) /* no delegation to reclaim */
551  goto out_unlock;
552 
553  if (open->do_close) /* already have an open stateid */
554  goto out_unlock;
555 
556  /* if another thread is reclaiming the open stateid,
557  * wait for it to finish before returning success */
558  if (open->delegation.reclaim) {
559  do {
560  SleepConditionVariableSRW(&open->delegation.cond, &open->lock,
561  INFINITE, 0);
562  } while (open->delegation.reclaim);
563  if (open->do_close)
564  goto out_unlock;
565  }
566  open->delegation.reclaim = 1;
567 
568  AcquireSRWLockShared(&open->delegation.state->lock);
569  deleg_stateid.open = open;
570  deleg_stateid.delegation = NULL;
571  deleg_stateid.type = STATEID_DELEG_FILE;
572  memcpy(&deleg_stateid.stateid, &open->delegation.state->state.stateid,
573  sizeof(stateid4));
574  ReleaseSRWLockShared(&open->delegation.state->lock);
575 
577 
578  /* send OPEN with CLAIM_DELEGATE_CUR */
579  claim.claim = CLAIM_DELEGATE_CUR;
580  claim.u.deleg_cur.delegate_stateid = &deleg_stateid;
581  claim.u.deleg_cur.name = &open->file.name;
582 
583  status = nfs41_open(open->session, &open->parent, &open->file,
584  &open->owner, &claim, open->share_access, open->share_deny,
585  OPEN4_NOCREATE, 0, NULL, try_recovery, &open_stateid, &ignore, NULL);
586 
588  if (status == NFS4_OK) {
589  /* save the new open stateid */
590  memcpy(&open->stateid, &open_stateid, sizeof(stateid4));
591  open->do_close = 1;
592  } else if (open->do_close && (status == NFS4ERR_BAD_STATEID ||
593  status == NFS4ERR_STALE_STATEID || status == NFS4ERR_EXPIRED)) {
594  /* something triggered client state recovery, and the open stateid
595  * has already been reclaimed; see recover_stateid_delegation() */
596  status = NFS4_OK;
597  }
598  open->delegation.reclaim = 0;
599 
600  /* signal anyone waiting on the open stateid */
601  WakeAllConditionVariable(&open->delegation.cond);
602 out_unlock:
604  if (status)
605  eprintf("nfs41_delegation_to_open(%p) failed with %s\n",
606  open, nfs_error_string(status));
607  return status;
608 }
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:54
char * name
Definition: wpp.c:36
#define open
Definition: acwin.h:71
int ignore(int trapCode, ppc_trap_frame_t *trap)
Definition: mmuobject.c:296
struct __open_claim4::@40::__open_claim_deleg_cur deleg_cur
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
VOID WINAPI WakeAllConditionVariable(PCONDITION_VARIABLE ConditionVariable)
Definition: sync.c:137
smooth NULL
Definition: ftsmooth.c:416
BOOL WINAPI SleepConditionVariableSRW(PCONDITION_VARIABLE ConditionVariable, PSRWLOCK Lock, DWORD Timeout, ULONG Flags)
Definition: sync.c:121
enum stateid_type type
Definition: nfs41_ops.h:285
nfs41_delegation_state * delegation
Definition: nfs41_ops.h:287
const char * nfs_error_string(int status)
Definition: daemon_debug.c:370
union __open_claim4::@40 u
nfs41_open_state * open
Definition: nfs41_ops.h:286
int nfs41_open(IN nfs41_session *session, IN nfs41_path_fh *parent, IN nfs41_path_fh *file, IN state_owner4 *owner, IN open_claim4 *claim, IN uint32_t allow, IN uint32_t deny, IN uint32_t create, IN uint32_t how_mode, IN OPTIONAL nfs41_file_info *createattrs, IN bool_t try_recovery, OUT stateid4 *stateid, OUT open_delegation4 *delegation, OUT OPTIONAL nfs41_file_info *info)
Definition: nfs41_ops.c:366
VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:82
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
stateid4 stateid
Definition: nfs41_ops.h:284
uint32_t claim
Definition: nfs41_ops.h:615
#define INFINITE
Definition: serial.h:102
static SERVICE_STATUS status
Definition: service.c:31
VOID WINAPI AcquireSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:61
VOID WINAPI ReleaseSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:89
Definition: ps.c:97

◆ open_deleg_cmp()

static int open_deleg_cmp ( const struct list_entry entry,
const void value 
)
static

Definition at line 139 of file delegation.c.

Referenced by deleg_open_find().

140 {
141  nfs41_open_state *open = open_entry(entry);
142  int result = -1;
143 
144  /* open must match the delegation and have state to reclaim */
145  AcquireSRWLockShared(&open->lock);
146  if (open->delegation.state != value) goto out;
147  if (open->do_close && !has_delegated_locks(open)) goto out;
148  result = 0;
149 out:
150  ReleaseSRWLockShared(&open->lock);
151  return result;
152 }
SRWLOCK lock
Definition: nfs41.h:139
#define open
Definition: acwin.h:71
bool_t do_close
Definition: nfs41.h:134
struct __nfs41_open_state::@24 delegation
static FILE * out
Definition: regtests2xml.c:44
static bool_t has_delegated_locks(IN nfs41_open_state *open)
Definition: delegation.c:128
#define open_entry(pos)
Definition: delegation.c:89
GLuint64EXT * result
Definition: glext.h:11304
VOID WINAPI AcquireSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:61
VOID WINAPI ReleaseSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:89