ReactOS  0.4.12-dev-14-gd0c8636
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 */
36  struct list_entry head;
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) {
53  status = PNFSERR_RESOURCES;
54  goto out;
55  }
56 
57  memcpy(device->device.deviceid, deviceid, PNFS_DEVICEID_SIZE);
58  device->devices = devices;
60  *device_out = device;
61 out:
62  return status;
63 }
64 
65 static 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 
74 static int deviceid_compare(
75  const struct list_entry *entry,
76  const void *deviceid)
77 {
78  const pnfs_file_device *device = device_entry(entry);
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;
88  enum pnfs_status status;
89 
90  dprintf(FDLVL, "--> pnfs_file_device_find_or_create()\n");
91 
92  EnterCriticalSection(&devices->lock);
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 */
99  status = file_device_create(deviceid, devices, &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);
113  status = PNFS_SUCCESS;
114 
115  dprintf(FDLVL, "<-- pnfs_file_device_find_or_create() "
116  "returning existing device %p\n", *device_out);
117  }
118 
119  LeaveCriticalSection(&devices->lock);
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) {
132  status = PNFSERR_RESOURCES;
133  goto out;
134  }
135 
136  list_init(&devices->head);
137  InitializeCriticalSection(&devices->lock);
138 
139  *devices_out = devices;
140 out:
141  return status;
142 }
143 
146 {
147  struct list_entry *entry, *tmp;
148 
149  EnterCriticalSection(&devices->lock);
150 
151  list_for_each_tmp(entry, tmp, &devices->head)
153 
154  LeaveCriticalSection(&devices->lock);
155  DeleteCriticalSection(&devices->lock);
156  free(devices);
157 }
158 
161 {
162  struct list_entry *entry, *tmp;
164 
165  dprintf(FDLVL, "--> pnfs_file_device_list_invalidate()\n");
166 
167  EnterCriticalSection(&devices->lock);
168 
169  list_for_each_tmp(entry, tmp, &devices->head) {
170  device = device_entry(entry);
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 */
180  list_remove(entry);
181  file_device_free(device);
182  }
183  }
184 
185  LeaveCriticalSection(&devices->lock);
186 
187  dprintf(FDLVL, "<-- pnfs_file_device_list_invalidate()\n");
188 }
189 
190 
191 /* pnfs_file_device */
193  IN nfs41_session *session,
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 
204  status = file_device_find_or_create(deviceid, devices, &device);
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)
212  status = PNFSERR_NO_DEVICE;
213  else if (device->device.status & PNFS_DEVICE_GRANTED)
214  status = PNFS_SUCCESS;
215  else {
216  nfsstat = pnfs_rpc_getdeviceinfo(session, deviceid, device);
217  if (nfsstat == NFS4_OK) {
219  status = PNFS_SUCCESS;
220 
221  dprintf(FDLVL, "Received device info:\n");
222  dprint_device(FDLVL, device);
223  } else {
224  status = PNFSERR_NO_DEVICE;
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);
239 out:
240  dprintf(FDLVL, "<-- pnfs_file_device_get() returning %s\n",
241  pnfs_error_string(status));
242  return status;
243 }
244 
247 {
248  uint32_t count;
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 
261  file_device_free(device);
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;
278  status = PNFS_SUCCESS;
279  }
280  return status;
281 }
282 
284  IN nfs41_root *root,
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 */
296  AcquireSRWLockShared(&server->lock);
297  pnfsstat = data_client_status(server, client_out);
298  ReleaseSRWLockShared(&server->lock);
299 
300  if (!pnfsstat)
301  goto out;
302 
303  AcquireSRWLockExclusive(&server->lock);
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 
321  ReleaseSRWLockExclusive(&server->lock);
322 out:
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) {
339  status = PNFSERR_NOT_SUPPORTED;
340  goto out;
341  }
342 
343  EnterCriticalSection(&devices->lock);
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  }
357  status = PNFS_SUCCESS;
358  }
359 
360  LeaveCriticalSection(&devices->lock);
361 out:
362  dprintf(FDLVL, "<-- pnfs_file_device_notify() returning %s\n",
363  pnfs_error_string(status));
364  return status;
365 }
pnfs_status
Definition: pnfs.h:58
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:54
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
#define IN
Definition: typedefs.h:38
struct list_entry head
Definition: pnfs_device.c:36
static rfbScreenInfoPtr server
Definition: vnc.c:74
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
static void file_device_free(IN pnfs_file_device *device)
Definition: pnfs_device.c:65
uint32_t layout_count
Definition: pnfs.h:119
GLuint GLuint GLsizei count
Definition: gl.h:1545
#define free
Definition: debug_ros.c:5
const char * devices
Definition: diskspace.c:793
uint8_t entry
Definition: isohybrid.c:63
enum nfsstat4 pnfs_rpc_getdeviceinfo(IN nfs41_session *session, IN unsigned char *deviceid, OUT pnfs_file_device *device)
Definition: nfs41_ops.c:2109
unsigned char deviceid[PNFS_DEVICEID_SIZE]
Definition: pnfs.h:116
#define PNFS_DEVICEID_SIZE
Definition: pnfs.h:111
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
CRITICAL_SECTION lock
Definition: pnfs.h:120
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define device_entry(pos)
Definition: pnfs_device.c:40
#define FDLVL
Definition: pnfs_device.c:31
__WINE_SERVER_LIST_INLINE void list_add_tail(struct list *list, struct list *elem)
Definition: list.h:102
Definition: devices.h:39
#define dprintf
Definition: regdump.c:33
void pnfs_file_device_put(IN pnfs_file_device *device)
Definition: pnfs_device.c:245
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
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:697
smooth NULL
Definition: ftsmooth.c:416
const char * pnfs_error_string(enum pnfs_status status)
Definition: pnfs_debug.c:28
pnfs_device device
Definition: pnfs.h:140
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
__WINE_SERVER_LIST_INLINE void list_remove(struct list *elem)
Definition: list.h:108
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
static FILE * out
Definition: regtests2xml.c:44
const char * nfs_error_string(int status)
Definition: daemon_debug.c:370
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
nfsstat4
Definition: nfs41_const.h:86
VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:82
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
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
void dprint_device(int level, const struct __pnfs_file_device *device)
static enum pnfs_status data_client_status(IN pnfs_data_server *server, OUT nfs41_client **client_out)
Definition: pnfs_device.c:268
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
UINT32 uint32_t
Definition: types.h:75
enum pnfs_device_status status
Definition: pnfs.h:118
#define list_for_each_tmp(entry, tmp, head)
Definition: list.h:39
#define calloc
Definition: rosglue.h:14
#define OUT
Definition: typedefs.h:39
struct list_entry entry
Definition: pnfs.h:144
__WINE_SERVER_LIST_INLINE void list_init(struct list *list)
Definition: list.h:149
void pnfs_file_device_list_invalidate(IN struct pnfs_file_device_list *devices)
Definition: pnfs_device.c:159
CRITICAL_SECTION lock
Definition: pnfs_device.c:37
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
enum pnfs_status pnfs_file_device_list_create(OUT struct pnfs_file_device_list **devices_out)
Definition: pnfs_device.c:124
static int deviceid_compare(const struct list_entry *entry, const void *deviceid)
Definition: pnfs_device.c:74
static SERVICE_STATUS status
Definition: service.c:31
VOID WINAPI AcquireSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:61
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 WINAPI ReleaseSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:89
struct pnfs_file_device_list * devices
Definition: pnfs.h:143
Definition: ps.c:97
void pnfs_file_device_list_free(IN struct pnfs_file_device_list *devices)
Definition: pnfs_device.c:144