ReactOS 0.4.16-dev-205-g7b2bb7e
pnfs_device.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 <strsafe.h>
24#include <stdio.h>
25
26#include "nfs41_ops.h"
27#include "nfs41_callback.h"
28#include "daemon_debug.h"
29
30
31#define FDLVL 2 /* dprintf level for file device logging */
32
33
34/* pnfs_file_device_list */
38};
39
40#define device_entry(pos) list_container(pos, pnfs_file_device, entry)
41
42
44 IN const unsigned char *deviceid,
46 OUT pnfs_file_device **device_out)
47{
50
51 device = calloc(1, sizeof(pnfs_file_device));
52 if (device == NULL) {
54 goto out;
55 }
56
57 memcpy(device->device.deviceid, deviceid, PNFS_DEVICEID_SIZE);
58 device->devices = devices;
59 InitializeCriticalSection(&device->device.lock);
60 *device_out = device;
61out:
62 return status;
63}
64
65static void file_device_free(
67{
68 free(device->servers.arr);
69 free(device->stripes.arr);
70 DeleteCriticalSection(&device->device.lock);
71 free(device);
72}
73
75 const struct list_entry *entry,
76 const void *deviceid)
77{
79 return memcmp(device->device.deviceid, deviceid, PNFS_DEVICEID_SIZE);
80}
81
83 IN const unsigned char *deviceid,
85 OUT pnfs_file_device **device_out)
86{
87 struct list_entry *entry;
89
90 dprintf(FDLVL, "--> pnfs_file_device_find_or_create()\n");
91
93
94 /* search for an existing device */
95 entry = list_search(&devices->head, deviceid, deviceid_compare);
96 if (entry == NULL) {
97 /* create a new device */
100 if (status == PNFS_SUCCESS) {
101 /* add it to the list */
102 list_add_tail(&devices->head, &device->entry);
103 *device_out = device;
104
105 dprintf(FDLVL, "<-- pnfs_file_device_find_or_create() "
106 "returning new device %p\n", device);
107 } else {
108 dprintf(FDLVL, "<-- pnfs_file_device_find_or_create() "
109 "returning %s\n", pnfs_error_string(status));
110 }
111 } else {
112 *device_out = device_entry(entry);
114
115 dprintf(FDLVL, "<-- pnfs_file_device_find_or_create() "
116 "returning existing device %p\n", *device_out);
117 }
118
120 return status;
121}
122
123
125 OUT struct pnfs_file_device_list **devices_out)
126{
129
130 devices = calloc(1, sizeof(struct pnfs_file_device_list));
131 if (devices == NULL) {
133 goto out;
134 }
135
136 list_init(&devices->head);
138
139 *devices_out = devices;
140out:
141 return status;
142}
143
146{
147 struct list_entry *entry, *tmp;
148
150
151 list_for_each_tmp(entry, tmp, &devices->head)
153
156 free(devices);
157}
158
161{
162 struct list_entry *entry, *tmp;
164
165 dprintf(FDLVL, "--> pnfs_file_device_list_invalidate()\n");
166
168
169 list_for_each_tmp(entry, tmp, &devices->head) {
171 EnterCriticalSection(&device->device.lock);
172 /* if there are layouts still using the device, flag it
173 * as revoked and clean up on last reference */
174 if (device->device.layout_count) {
175 device->device.status |= PNFS_DEVICE_REVOKED;
176 LeaveCriticalSection(&device->device.lock);
177 } else {
178 LeaveCriticalSection(&device->device.lock);
179 /* no layouts are using it, so it's safe to free */
182 }
183 }
184
186
187 dprintf(FDLVL, "<-- pnfs_file_device_list_invalidate()\n");
188}
189
190
191/* pnfs_file_device */
195 IN unsigned char *deviceid,
196 OUT pnfs_file_device **device_out)
197{
199 enum pnfs_status status;
200 enum nfsstat4 nfsstat;
201
202 dprintf(FDLVL, "--> pnfs_file_device_get()\n");
203
205 if (status)
206 goto out;
207
208 EnterCriticalSection(&device->device.lock);
209
210 /* don't give out a device that's been revoked */
211 if (device->device.status & PNFS_DEVICE_REVOKED)
213 else if (device->device.status & PNFS_DEVICE_GRANTED)
215 else {
216 nfsstat = pnfs_rpc_getdeviceinfo(session, deviceid, device);
217 if (nfsstat == NFS4_OK) {
218 device->device.status = PNFS_DEVICE_GRANTED;
220
221 dprintf(FDLVL, "Received device info:\n");
223 } else {
225
226 eprintf("pnfs_rpc_getdeviceinfo() failed with %s\n",
227 nfs_error_string(nfsstat));
228 }
229 }
230
231 if (status == PNFS_SUCCESS) {
232 device->device.layout_count++;
233 dprintf(FDLVL, "pnfs_file_device_get() -> %u\n",
234 device->device.layout_count);
235 *device_out = device;
236 }
237
238 LeaveCriticalSection(&device->device.lock);
239out:
240 dprintf(FDLVL, "<-- pnfs_file_device_get() returning %s\n",
242 return status;
243}
244
247{
249 EnterCriticalSection(&device->device.lock);
250 count = --device->device.layout_count;
251 dprintf(FDLVL, "pnfs_file_device_put() -> %u\n", count);
252
253 /* if the device was revoked, remove/free the device on last reference */
254 if (count == 0 && device->device.status & PNFS_DEVICE_REVOKED) {
255 EnterCriticalSection(&device->devices->lock);
256 list_remove(&device->entry);
257 LeaveCriticalSection(&device->devices->lock);
258
259 LeaveCriticalSection(&device->device.lock);
260
262 dprintf(FDLVL, "revoked file device freed after last reference\n");
263 } else {
264 LeaveCriticalSection(&device->device.lock);
265 }
266}
267
270 OUT nfs41_client **client_out)
271{
273
274 if (server->client) {
275 dprintf(FDLVL, "pnfs_data_server_client() returning "
276 "existing client %llu\n", server->client->clnt_id);
277 *client_out = server->client;
279 }
280 return status;
281}
282
286 IN uint32_t default_lease,
287 OUT nfs41_client **client_out)
288{
289 int status;
290 enum pnfs_status pnfsstat;
291
292 dprintf(FDLVL, "--> pnfs_data_server_client('%s')\n",
293 server->addrs.arr[0].uaddr);
294
295 /* if we've already created the client, return it */
297 pnfsstat = data_client_status(server, client_out);
299
300 if (!pnfsstat)
301 goto out;
302
304
305 pnfsstat = data_client_status(server, client_out);
306 if (pnfsstat) {
307 status = nfs41_root_mount_addrs(root, &server->addrs, 1, default_lease,
308 &server->client);
309 if (status) {
310 dprintf(FDLVL, "data_client_create('%s') failed with %d\n",
311 server->addrs.arr[0].uaddr, status);
312 } else {
313 *client_out = server->client;
314 pnfsstat = PNFS_SUCCESS;
315
316 dprintf(FDLVL, "pnfs_data_server_client() returning new client "
317 "%llu\n", server->client->clnt_id);
318 }
319 }
320
322out:
323 return pnfsstat;
324}
325
326
327/* CB_NOTIFY_DEVICEID */
330 IN const struct notify_deviceid4 *change)
331{
332 struct list_entry *entry;
334
335 dprintf(FDLVL, "--> pnfs_file_device_notify(%u, %0llX:%0llX)\n",
336 change->type, change->deviceid);
337
338 if (change->layouttype != PNFS_LAYOUTTYPE_FILE) {
340 goto out;
341 }
342
344
345 entry = list_search(&devices->head, change->deviceid, deviceid_compare);
346 if (entry) {
347 dprintf(FDLVL, "found file device %p\n", device_entry(entry));
348
349 if (change->type == NOTIFY_DEVICEID4_CHANGE) {
350 /* if (change->immediate) ... */
351 dprintf(FDLVL, "CHANGE (%u)\n", change->immediate);
352 } else if (change->type == NOTIFY_DEVICEID4_DELETE) {
353 /* This notification MUST NOT be sent if the client
354 * has a layout that refers to the device ID. */
355 dprintf(FDLVL, "DELETE\n");
356 }
358 }
359
361out:
362 dprintf(FDLVL, "<-- pnfs_file_device_notify() returning %s\n",
364 return status;
365}
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
static void list_remove(struct list_entry *entry)
Definition: list.h:90
#define list_for_each_tmp(entry, tmp, head)
Definition: list.h:39
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
static struct list_entry * list_search(const struct list_entry *head, const void *value, list_compare_fn compare)
Definition: list.h:102
static void list_init(struct list_entry *head)
Definition: list.h:51
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
const char * nfs_error_string(int status)
Definition: daemon_debug.c:370
void dprint_device(int level, const struct __pnfs_file_device *device)
const char * pnfs_error_string(enum pnfs_status status)
Definition: pnfs_debug.c:28
#define free
Definition: debug_ros.c:5
#define NULL
Definition: types.h:112
UINT32 uint32_t
Definition: types.h:75
VOID WINAPI ReleaseSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:43
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:8
VOID WINAPI AcquireSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:15
VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:36
static struct all_devices * devices
Definition: dsm_ctrl.c:48
GLuint GLuint GLsizei count
Definition: gl.h:1545
uint32_t entry
Definition: isohybrid.c:63
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
int nfs41_root_mount_addrs(IN nfs41_root *root, IN const multi_addr4 *addrs, IN bool_t is_data, IN OPTIONAL uint32_t lease_time, OUT nfs41_client **client_out)
Definition: namespace.c:335
@ NOTIFY_DEVICEID4_DELETE
@ NOTIFY_DEVICEID4_CHANGE
nfsstat4
Definition: nfs41_const.h:86
@ NFS4_OK
Definition: nfs41_const.h:87
enum nfsstat4 pnfs_rpc_getdeviceinfo(IN nfs41_session *session, IN unsigned char *deviceid, OUT pnfs_file_device *device)
Definition: nfs41_ops.c:2109
#define PNFS_DEVICEID_SIZE
Definition: pnfs.h:111
pnfs_status
Definition: pnfs.h:58
@ PNFSERR_NOT_SUPPORTED
Definition: pnfs.h:62
@ PNFSERR_NOT_CONNECTED
Definition: pnfs.h:63
@ PNFSERR_RESOURCES
Definition: pnfs.h:69
@ PNFSERR_NO_DEVICE
Definition: pnfs.h:65
@ PNFS_SUCCESS
Definition: pnfs.h:59
@ PNFS_DEVICE_REVOKED
Definition: pnfs.h:97
@ PNFS_DEVICE_GRANTED
Definition: pnfs.h:95
@ PNFS_LAYOUTTYPE_FILE
Definition: pnfs.h:75
static enum pnfs_status file_device_create(IN const unsigned char *deviceid, IN struct pnfs_file_device_list *devices, OUT pnfs_file_device **device_out)
Definition: pnfs_device.c:43
enum pnfs_status pnfs_file_device_notify(IN struct pnfs_file_device_list *devices, IN const struct notify_deviceid4 *change)
Definition: pnfs_device.c:328
enum pnfs_status pnfs_file_device_list_create(OUT struct pnfs_file_device_list **devices_out)
Definition: pnfs_device.c:124
#define FDLVL
Definition: pnfs_device.c:31
static enum pnfs_status data_client_status(IN pnfs_data_server *server, OUT nfs41_client **client_out)
Definition: pnfs_device.c:268
static enum pnfs_status file_device_find_or_create(IN const unsigned char *deviceid, IN struct pnfs_file_device_list *devices, OUT pnfs_file_device **device_out)
Definition: pnfs_device.c:82
enum pnfs_status pnfs_file_device_get(IN nfs41_session *session, IN struct pnfs_file_device_list *devices, IN unsigned char *deviceid, OUT pnfs_file_device **device_out)
Definition: pnfs_device.c:192
static void file_device_free(IN pnfs_file_device *device)
Definition: pnfs_device.c:65
enum pnfs_status pnfs_data_server_client(IN nfs41_root *root, IN pnfs_data_server *server, IN uint32_t default_lease, OUT nfs41_client **client_out)
Definition: pnfs_device.c:283
void pnfs_file_device_put(IN pnfs_file_device *device)
Definition: pnfs_device.c:245
static int deviceid_compare(const struct list_entry *entry, const void *deviceid)
Definition: pnfs_device.c:74
void pnfs_file_device_list_invalidate(IN struct pnfs_file_device_list *devices)
Definition: pnfs_device.c:159
void pnfs_file_device_list_free(IN struct pnfs_file_device_list *devices)
Definition: pnfs_device.c:144
#define device_entry(pos)
Definition: pnfs_device.c:40
#define dprintf
Definition: regdump.c:33
static FILE * out
Definition: regtests2xml.c:44
#define calloc
Definition: rosglue.h:14
Definition: devices.h:37
Definition: list.h:27
struct list_entry head
Definition: pnfs_device.c:36
CRITICAL_SECTION lock
Definition: pnfs_device.c:37
Definition: ps.c:97
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
#define IN
Definition: typedefs.h:39
#define OUT
Definition: typedefs.h:40
static rfbScreenInfoPtr server
Definition: vnc.c:74
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)