ReactOS 0.4.15-dev-7906-g1b85a5f
lock.c File Reference
#include <windows.h>
#include <stdio.h>
#include "daemon_debug.h"
#include "delegation.h"
#include "nfs41_ops.h"
#include "upcall.h"
#include "util.h"
Include dependency graph for lock.c:

Go to the source code of this file.

Macros

#define LKLVL   2 /* dprintf level for lock logging */
 
#define lock_entry(pos)   list_container(pos, nfs41_lock_state, open_entry)
 

Functions

static void lock_stateid_arg (IN nfs41_open_state *state, OUT stateid_arg *arg)
 
static void lock_stateid_update (OUT nfs41_open_state *state, IN const stateid4 *stateid)
 
static void open_lock_add (IN nfs41_open_state *open, IN const stateid_arg *stateid, IN nfs41_lock_state *lock)
 
static bool_t open_lock_delegate (IN nfs41_open_state *open, IN nfs41_lock_state *lock)
 
static int lock_range_cmp (const struct list_entry *entry, const void *value)
 
static int open_unlock_delegate (IN nfs41_open_state *open, IN const nfs41_lock_state *input)
 
static void open_unlock_remove (IN nfs41_open_state *open, IN const stateid_arg *stateid, IN const nfs41_lock_state *input)
 
static int parse_lock (unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
 
static __inline uint32_t get_lock_type (BOOLEAN exclusive, BOOLEAN blocking)
 
static int handle_lock (nfs41_upcall *upcall)
 
static void cancel_lock (IN nfs41_upcall *upcall)
 
static int parse_unlock (unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
 
static int handle_unlock (nfs41_upcall *upcall)
 

Variables

const nfs41_upcall_op nfs41_op_lock
 
const nfs41_upcall_op nfs41_op_unlock
 

Macro Definition Documentation

◆ LKLVL

#define LKLVL   2 /* dprintf level for lock logging */

Definition at line 32 of file lock.c.

◆ lock_entry

Definition at line 110 of file lock.c.

Function Documentation

◆ cancel_lock()

static void cancel_lock ( IN nfs41_upcall upcall)
static

Definition at line 266 of file lock.c.

267{
268 stateid_arg stateid;
270 lock_upcall_args *args = &upcall->args.lock;
271 nfs41_open_state *state = upcall->state_ref;
272 int status = NO_ERROR;
273
274 dprintf(1, "--> cancel_lock()\n");
275
276 /* can't do 'if (upcall->status)' here, because a handle_lock() success
277 * could be overwritten by upcall_marshall() or allocation failure */
278 if (!args->acquired)
279 goto out;
280
281 input.offset = args->offset;
283
284 /* search for the range to unlock, and remove if delegated */
286 if (status != ERROR_LOCKED)
287 goto out;
288
289 EnterCriticalSection(&state->locks.lock);
290 lock_stateid_arg(state, &stateid);
291
292 status = nfs41_unlock(state->session, &state->file,
293 args->offset, args->length, &stateid);
294
295 open_unlock_remove(state, &stateid, &input);
296 LeaveCriticalSection(&state->locks.lock);
297
299out:
300 dprintf(1, "<-- cancel_lock() returning %d\n", status);
301}
static int state
Definition: maze.c:121
static int open_unlock_delegate(IN nfs41_open_state *open, IN const nfs41_lock_state *input)
Definition: lock.c:121
static void open_unlock_remove(IN nfs41_open_state *open, IN const stateid_arg *stateid, IN const nfs41_lock_state *input)
Definition: lock.c:147
static void lock_stateid_arg(IN nfs41_open_state *state, OUT stateid_arg *arg)
Definition: lock.c:35
int nfs_to_windows_error(int status, int default_error)
Definition: util.c:235
#define NO_ERROR
Definition: dderror.h:5
GLenum GLenum GLenum input
Definition: glext.h:9031
nfs41_updowncall_list upcall
Definition: nfs41_driver.c:273
int nfs41_unlock(IN nfs41_session *session, IN nfs41_path_fh *file, IN uint64_t offset, IN uint64_t length, IN OUT stateid_arg *stateid)
Definition: nfs41_ops.c:966
#define dprintf
Definition: regdump.c:33
static FILE * out
Definition: regtests2xml.c:44
Definition: match.c:390
int length
Definition: match.c:394
Definition: ps.c:97
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define ERROR_BAD_NET_RESP
Definition: winerror.h:150
#define ERROR_LOCKED
Definition: winerror.h:268

◆ get_lock_type()

static __inline uint32_t get_lock_type ( BOOLEAN  exclusive,
BOOLEAN  blocking 
)
static

Definition at line 190 of file lock.c.

191{
192 return blocking == 0
193 ? ( exclusive == 0 ? READ_LT : WRITE_LT )
194 : ( exclusive == 0 ? READW_LT : WRITEW_LT );
195}
@ READ_LT
Definition: nfs41_ops.h:399
@ READW_LT
Definition: nfs41_ops.h:401
@ WRITEW_LT
Definition: nfs41_ops.h:402
@ WRITE_LT
Definition: nfs41_ops.h:400

Referenced by handle_lock().

◆ handle_lock()

static int handle_lock ( nfs41_upcall upcall)
static

Definition at line 197 of file lock.c.

198{
199 stateid_arg stateid;
200 lock_upcall_args *args = &upcall->args.lock;
201 nfs41_open_state *state = upcall->state_ref;
203 const uint32_t type = get_lock_type(args->exclusive, args->blocking);
204 int status = NO_ERROR;
205
206 /* 18.10.3. Operation 12: LOCK - Create Lock
207 * "To lock the file from a specific offset through the end-of-file
208 * (no matter how long the file actually is) use a length field equal
209 * to NFS4_UINT64_MAX." */
210 if (args->length >= NFS4_UINT64_MAX - args->offset)
212
213 /* allocate the lock state */
214 lock = calloc(1, sizeof(nfs41_lock_state));
215 if (lock == NULL) {
217 goto out;
218 }
219 lock->offset = args->offset;
220 lock->length = args->length;
221 lock->exclusive = args->exclusive;
222
223 /* if we hold a write delegation, handle the lock locally */
225 dprintf(LKLVL, "delegated lock { %llu, %llu }\n",
226 lock->offset, lock->length);
227 args->acquired = TRUE; /* for cancel_lock() */
228 goto out;
229 }
230
231 /* open_to_lock_owner4 requires an open stateid; if we
232 * have a delegation, convert it to an open stateid */
234 if (status) {
236 goto out_free;
237 }
238
239 EnterCriticalSection(&state->locks.lock);
240
241 lock_stateid_arg(state, &stateid);
242
243 status = nfs41_lock(state->session, &state->file, &state->owner,
244 type, lock->offset, lock->length, FALSE, TRUE, &stateid);
245 if (status) {
246 dprintf(LKLVL, "nfs41_lock failed with %s\n",
249 LeaveCriticalSection(&state->locks.lock);
250 goto out_free;
251 }
252
253 /* save lock state with the open */
254 open_lock_add(state, &stateid, lock);
255 LeaveCriticalSection(&state->locks.lock);
256
257 args->acquired = TRUE; /* for cancel_lock() */
258out:
259 return status;
260
261out_free:
262 free(lock);
263 goto out;
264}
#define LKLVL
Definition: lock.c:32
static void open_lock_add(IN nfs41_open_state *open, IN const stateid_arg *stateid, IN nfs41_lock_state *lock)
Definition: lock.c:70
static __inline uint32_t get_lock_type(BOOLEAN exclusive, BOOLEAN blocking)
Definition: lock.c:190
static bool_t open_lock_delegate(IN nfs41_open_state *open, IN nfs41_lock_state *lock)
Definition: lock.c:86
const char * nfs_error_string(int status)
Definition: daemon_debug.c:370
#define free
Definition: debug_ros.c:5
int nfs41_delegation_to_open(IN nfs41_open_state *open, IN bool_t try_recovery)
Definition: delegation.c:539
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
UINT32 uint32_t
Definition: types.h:75
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
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
static const uint64_t NFS4_UINT64_MAX
Definition: nfs41_types.h:32
#define calloc
Definition: rosglue.h:14
rwlock_t lock
Definition: tcpcore.h:0
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define ERROR_FILE_INVALID
Definition: winerror.h:585

◆ handle_unlock()

static int handle_unlock ( nfs41_upcall upcall)
static

Definition at line 321 of file lock.c.

322{
324 stateid_arg stateid;
325 unlock_upcall_args *args = &upcall->args.unlock;
326 nfs41_open_state *state = upcall->state_ref;
327 unsigned char *buf = args->buf;
328 uint32_t buf_len = args->buf_len;
329 uint32_t i;
330 int status = NO_ERROR;
331
332 for (i = 0; i < args->count; i++) {
333 if (safe_read(&buf, &buf_len, &input.offset, sizeof(LONGLONG))) break;
334 if (safe_read(&buf, &buf_len, &input.length, sizeof(LONGLONG))) break;
335
336 /* do the same translation as LOCK, or the ranges won't match */
337 if (input.length >= NFS4_UINT64_MAX - input.offset)
338 input.length = NFS4_UINT64_MAX;
339
340 /* search for the range to unlock, and remove if delegated */
342 if (status != ERROR_LOCKED)
343 continue;
344
345 EnterCriticalSection(&state->locks.lock);
346 lock_stateid_arg(state, &stateid);
347
348 status = nfs41_unlock(state->session, &state->file,
349 input.offset, input.length, &stateid);
350
351 open_unlock_remove(state, &stateid, &input);
352 LeaveCriticalSection(&state->locks.lock);
353
355 }
356 return status;
357}
int safe_read(unsigned char **pos, uint32_t *remaining, void *dest, uint32_t dest_len)
Definition: util.c:33
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
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
int64_t LONGLONG
Definition: typedefs.h:68

◆ lock_range_cmp()

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

Definition at line 112 of file lock.c.

113{
114 const nfs41_lock_state *lhs = lock_entry(entry);
115 const nfs41_lock_state *rhs = (const nfs41_lock_state*)value;
116 if (lhs->offset != rhs->offset) return -1;
117 if (lhs->length != rhs->length) return -1;
118 return 0;
119}
#define lock_entry(pos)
Definition: lock.c:110
uint32_t entry
Definition: isohybrid.c:63
uint64_t length
Definition: nfs41.h:115
uint64_t offset
Definition: nfs41.h:114
Definition: pdh_main.c:94

Referenced by open_unlock_delegate(), and open_unlock_remove().

◆ lock_stateid_arg()

static void lock_stateid_arg ( IN nfs41_open_state state,
OUT stateid_arg arg 
)
static

Definition at line 35 of file lock.c.

38{
39 arg->open = state;
40 arg->delegation = NULL;
41
43 if (state->locks.stateid.seqid) {
44 memcpy(&arg->stateid, &state->locks.stateid, sizeof(stateid4));
45 arg->type = STATEID_LOCK;
46 } else if (state->do_close) {
47 memcpy(&arg->stateid, &state->stateid, sizeof(stateid4));
48 arg->type = STATEID_OPEN;
49 } else {
50 memset(&arg->stateid, 0, sizeof(stateid4));
51 arg->type = STATEID_SPECIAL;
52 }
54}
VOID WINAPI ReleaseSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:89
VOID WINAPI AcquireSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:61
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
@ STATEID_LOCK
Definition: nfs41_ops.h:277
@ STATEID_SPECIAL
Definition: nfs41_ops.h:281
@ STATEID_OPEN
Definition: nfs41_ops.h:276
#define memset(x, y, z)
Definition: compat.h:39

Referenced by cancel_lock(), handle_lock(), and handle_unlock().

◆ lock_stateid_update()

static void lock_stateid_update ( OUT nfs41_open_state state,
IN const stateid4 stateid 
)
static

Definition at line 57 of file lock.c.

60{
61 if (state->locks.stateid.seqid == 0) {
62 /* if it's a new lock stateid, copy it in */
63 memcpy(&state->locks.stateid, stateid, sizeof(stateid4));
64 } else if (stateid->seqid > state->locks.stateid.seqid) {
65 /* update the seqid if it's more recent */
66 state->locks.stateid.seqid = stateid->seqid;
67 }
68}

Referenced by open_lock_add(), and open_unlock_remove().

◆ open_lock_add()

static void open_lock_add ( IN nfs41_open_state open,
IN const stateid_arg stateid,
IN nfs41_lock_state lock 
)
static

Definition at line 70 of file lock.c.

74{
76
77 if (stateid->type == STATEID_LOCK)
78 lock_stateid_update(open, &stateid->stateid);
79
80 lock->id = open->locks.counter++;
81 list_add_tail(&open->locks.list, &lock->open_entry);
82
84}
#define open
Definition: acwin.h:95
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
static void lock_stateid_update(OUT nfs41_open_state *state, IN const stateid4 *stateid)
Definition: lock.c:57
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:54
VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:82

Referenced by handle_lock().

◆ open_lock_delegate()

static bool_t open_lock_delegate ( IN nfs41_open_state open,
IN nfs41_lock_state lock 
)
static

Definition at line 86 of file lock.c.

89{
90 bool_t delegated = FALSE;
91
93 if (open->delegation.state) {
94 nfs41_delegation_state *deleg = open->delegation.state;
96 if (deleg->state.type == OPEN_DELEGATE_WRITE
97 && deleg->status == DELEGATION_GRANTED) {
98 lock->delegated = 1;
99 lock->id = open->locks.counter++;
100 list_add_tail(&open->locks.list, &lock->open_entry);
101 delegated = TRUE;
102 }
103 ReleaseSRWLockShared(&deleg->lock);
104 }
106
107 return delegated;
108}
int32_t bool_t
Definition: types.h:101
@ DELEGATION_GRANTED
Definition: nfs41.h:90
@ OPEN_DELEGATE_WRITE
Definition: nfs41_ops.h:588
enum delegation_status status
Definition: nfs41.h:103
open_delegation4 state
Definition: nfs41.h:96
enum open_delegation_type4 type
Definition: nfs41_types.h:154

Referenced by handle_lock().

◆ open_unlock_delegate()

static int open_unlock_delegate ( IN nfs41_open_state open,
IN const nfs41_lock_state input 
)
static

Definition at line 121 of file lock.c.

124{
125 struct list_entry *entry;
127
129
130 /* find lock state that matches this range */
131 entry = list_search(&open->locks.list, input, lock_range_cmp);
132 if (entry) {
134 if (lock->delegated) {
135 /* if the lock was delegated, remove/free it and return success */
137 free(lock);
139 } else
141 }
142
144 return status;
145}
static void list_remove(struct list_entry *entry)
Definition: list.h:90
static struct list_entry * list_search(const struct list_entry *head, const void *value, list_compare_fn compare)
Definition: list.h:102
static int lock_range_cmp(const struct list_entry *entry, const void *value)
Definition: lock.c:112
Definition: list.h:27
#define ERROR_NOT_LOCKED
Definition: winerror.h:230

Referenced by cancel_lock(), and handle_unlock().

◆ open_unlock_remove()

static void open_unlock_remove ( IN nfs41_open_state open,
IN const stateid_arg stateid,
IN const nfs41_lock_state input 
)
static

Definition at line 147 of file lock.c.

151{
152 struct list_entry *entry;
153
155 if (stateid->type == STATEID_LOCK)
156 lock_stateid_update(open, &stateid->stateid);
157
158 /* find and remove the unlocked range */
159 entry = list_search(&open->locks.list, input, lock_range_cmp);
160 if (entry) {
163 }
165}

Referenced by cancel_lock(), and handle_unlock().

◆ parse_lock()

static int parse_lock ( unsigned char buffer,
uint32_t  length,
nfs41_upcall upcall 
)
static

Definition at line 169 of file lock.c.

170{
171 int status;
172 lock_upcall_args *args = &upcall->args.lock;
173
174 status = safe_read(&buffer, &length, &args->offset, sizeof(LONGLONG));
175 if (status) goto out;
176 status = safe_read(&buffer, &length, &args->length, sizeof(LONGLONG));
177 if (status) goto out;
178 status = safe_read(&buffer, &length, &args->exclusive, sizeof(BOOLEAN));
179 if (status) goto out;
180 status = safe_read(&buffer, &length, &args->blocking, sizeof(BOOLEAN));
181 if (status) goto out;
182
183 dprintf(1, "parsing NFS41_LOCK: offset=0x%llx length=0x%llx exclusive=%u "
184 "blocking=%u\n", args->offset, args->length, args->exclusive,
185 args->blocking);
186out:
187 return status;
188}
unsigned char BOOLEAN
GLuint buffer
Definition: glext.h:5915
GLuint GLsizei GLsizei * length
Definition: glext.h:6040

◆ parse_unlock()

static int parse_unlock ( unsigned char buffer,
uint32_t  length,
nfs41_upcall upcall 
)
static

Definition at line 305 of file lock.c.

306{
307 int status;
308 unlock_upcall_args *args = &upcall->args.unlock;
309
310 status = safe_read(&buffer, &length, &args->count, sizeof(ULONG));
311 if (status) goto out;
312
313 args->buf = buffer;
314 args->buf_len = length;
315
316 dprintf(1, "parsing NFS41_UNLOCK: count=%u\n", args->count);
317out:
318 return status;
319}
uint32_t ULONG
Definition: typedefs.h:59

Variable Documentation

◆ nfs41_op_lock

const nfs41_upcall_op nfs41_op_lock
Initial value:
= {
}
static void cancel_lock(IN nfs41_upcall *upcall)
Definition: lock.c:266
static int handle_lock(nfs41_upcall *upcall)
Definition: lock.c:197
static int parse_lock(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
Definition: lock.c:169

Definition at line 360 of file lock.c.

◆ nfs41_op_unlock

const nfs41_upcall_op nfs41_op_unlock
Initial value:
= {
}
static int handle_unlock(nfs41_upcall *upcall)
Definition: lock.c:321
static int parse_unlock(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
Definition: lock.c:305

Definition at line 366 of file lock.c.