Reactos
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#ifndef __PNFS_H__
23#define __PNFS_H__
24
25#include "nfs41_types.h"
26#include "list.h"
27
28
29/* preprocessor options */
30#ifndef PNFS_DISABLE
31
32# ifndef PNFS_DISABLE_READ
33# define PNFS_ENABLE_READ
34# endif
35# ifndef PNFS_DISABLE_WRITE
36# define PNFS_ENABLE_WRITE
37# endif
38
39# define PNFS_THREADING
40
41/* XXX: the thread-by-server model breaks down when using dense layouts,
42 * because multiple stripes could be mapped to a single data server, and
43 * the per-data-server thread would have to send a COMMIT for each stripe */
44//# define PNFS_THREAD_BY_SERVER
45
46#endif
47
48
49/* forward declarations from nfs41.h */
50struct __nfs41_client;
51struct __nfs41_session;
52struct __nfs41_open_state;
53struct __nfs41_root;
54struct __stateid_arg;
55
56
57/* pnfs error values, in order of increasing severity */
58enum pnfs_status {
59 PNFS_SUCCESS = 0,
60 PNFS_PENDING,
61 PNFS_READ_EOF,
62 PNFSERR_NOT_SUPPORTED,
63 PNFSERR_NOT_CONNECTED,
64 PNFSERR_IO,
65 PNFSERR_NO_DEVICE,
66 PNFSERR_NO_LAYOUT,
67 PNFSERR_INVALID_FH_LIST,
68 PNFSERR_INVALID_DS_INDEX,
69 PNFSERR_RESOURCES,
70 PNFSERR_LAYOUT_RECALLED,
71 PNFSERR_LAYOUT_CHANGED,
72};
73
74enum pnfs_layout_type {
75 PNFS_LAYOUTTYPE_FILE = 1,
76 PNFS_LAYOUTTYPE_OBJECT = 2,
77 PNFS_LAYOUTTYPE_BLOCK = 3
78};
79
80enum pnfs_iomode {
81 PNFS_IOMODE_READ = 0x1,
82 PNFS_IOMODE_RW = 0x2,
83 PNFS_IOMODE_ANY = PNFS_IOMODE_READ | PNFS_IOMODE_RW
84};
85
86enum pnfs_layout_status {
87 /* a LAYOUTGET error indicated that this layout will never be granted */
88 PNFS_LAYOUT_UNAVAILABLE = 0x10,
89 /* LAYOUTGET returned BADIOMODE, so a RW layout will never be granted */
90 PNFS_LAYOUT_NOT_RW = 0x20,
91};
92
93enum pnfs_device_status {
94 /* GETDEVICEINFO was successful */
95 PNFS_DEVICE_GRANTED = 0x1,
96 /* a bulk recall or lease expiration led to device invalidation */
97 PNFS_DEVICE_REVOKED = 0x2,
98};
99
100enum pnfs_return_type {
101 PNFS_RETURN_FILE = 1,
102 PNFS_RETURN_FSID = 2,
103 PNFS_RETURN_ALL = 3
104};
105
106#define NFL4_UFLG_MASK 0x0000003F
107#define NFL4_UFLG_DENSE 0x00000001
108#define NFL4_UFLG_COMMIT_THRU_MDS 0x00000002
109#define NFL4_UFLG_STRIPE_UNIT_SIZE_MASK 0xFFFFFFC0
110
111#define PNFS_DEVICEID_SIZE 16
112
113
114/* device */
115typedef struct __pnfs_device {
116 unsigned char deviceid[PNFS_DEVICEID_SIZE];
117 enum pnfs_layout_type type;
118 enum pnfs_device_status status;
119 uint32_t layout_count; /* layouts using this device */
120 CRITICAL_SECTION lock;
121} pnfs_device;
122
123typedef struct __pnfs_stripe_indices {
124 uint32_t count;
125 uint32_t *arr;
126} pnfs_stripe_indices;
127
128typedef struct __pnfs_data_server {
129 struct __nfs41_client *client;
130 multi_addr4 addrs;
131 SRWLOCK lock;
132} pnfs_data_server;
133
134typedef struct __pnfs_data_server_list {
135 uint32_t count;
136 pnfs_data_server *arr;
137} pnfs_data_server_list;
138
139typedef struct __pnfs_file_device {
140 pnfs_device device;
141 pnfs_stripe_indices stripes;
142 pnfs_data_server_list servers;
143 struct pnfs_file_device_list *devices; /* -> nfs41_client.devices */
144 struct list_entry entry; /* position in devices */
145} pnfs_file_device;
146
147
148/* layout */
149typedef struct __pnfs_layout_state {
150 nfs41_fh meta_fh;
151 stateid4 stateid;
152 struct list_entry entry; /* position in nfs41_client.layouts */
153 struct list_entry layouts; /* list of pnfs_file_layouts */
154 struct list_entry recalls; /* list of pnfs_layouts */
155 enum pnfs_layout_status status;
156 bool_t return_on_close;
157 LONG open_count; /* for return on last close */
158 uint32_t io_count; /* number of pending io operations */
159 bool_t pending; /* pending LAYOUTGET/LAYOUTRETURN */
160 SRWLOCK lock;
161 CONDITION_VARIABLE cond;
162} pnfs_layout_state;
163
164typedef struct __pnfs_layout {
165 struct list_entry entry;
166 uint64_t offset;
167 uint64_t length;
168 enum pnfs_iomode iomode;
169 enum pnfs_layout_type type;
170} pnfs_layout;
171
172typedef struct __pnfs_file_layout_handles {
173 uint32_t count;
174 nfs41_path_fh *arr;
175} pnfs_file_layout_handles;
176
177typedef struct __pnfs_file_layout {
178 pnfs_layout layout;
179 pnfs_file_layout_handles filehandles;
180 unsigned char deviceid[PNFS_DEVICEID_SIZE];
181 pnfs_file_device *device;
182 uint64_t pattern_offset;
183 uint32_t first_index;
184 uint32_t util;
185} pnfs_file_layout;
186
187
188/* pnfs_layout.c */
189struct pnfs_layout_list;
190struct cb_layoutrecall_args;
191
192enum pnfs_status pnfs_layout_list_create(
193 OUT struct pnfs_layout_list **layouts_out);
194
195void pnfs_layout_list_free(
196 IN struct pnfs_layout_list *layouts);
197
198enum pnfs_status pnfs_layout_state_open(
199 IN struct __nfs41_open_state *state,
200 OUT pnfs_layout_state **layout_out);
201
202/* expects caller to hold an exclusive lock on pnfs_layout_state */
203enum pnfs_status pnfs_layout_state_prepare(
204 IN pnfs_layout_state *state,
205 IN struct __nfs41_session *session,
206 IN nfs41_path_fh *meta_file,
207 IN struct __stateid_arg *stateid,
208 IN enum pnfs_iomode iomode,
209 IN uint64_t offset,
210 IN uint64_t length);
211
212void pnfs_layout_state_close(
213 IN struct __nfs41_session *session,
214 IN struct __nfs41_open_state *state,
215 IN bool_t remove);
216
217enum pnfs_status pnfs_file_layout_recall(
218 IN struct __nfs41_client *client,
219 IN const struct cb_layoutrecall_args *recall);
220
221/* expects caller to hold a shared lock on pnfs_layout_state */
222enum pnfs_status pnfs_layout_recall_status(
223 IN const pnfs_layout_state *state,
224 IN const pnfs_layout *layout);
225
226void pnfs_layout_recall_fenced(
227 IN pnfs_layout_state *state,
228 IN const pnfs_layout *layout);
229
230/* expects caller to hold an exclusive lock on pnfs_layout_state */
231void pnfs_layout_io_start(
232 IN pnfs_layout_state *state);
233
234void pnfs_layout_io_finished(
235 IN pnfs_layout_state *state);
236
237
238/* pnfs_device.c */
239struct pnfs_file_device_list;
240
241enum pnfs_status pnfs_file_device_list_create(
242 OUT struct pnfs_file_device_list **devices_out);
243
244void pnfs_file_device_list_free(
245 IN struct pnfs_file_device_list *devices);
246
247void pnfs_file_device_list_invalidate(
248 IN struct pnfs_file_device_list *devices);
249
250enum pnfs_status pnfs_file_device_get(
251 IN struct __nfs41_session *session,
252 IN struct pnfs_file_device_list *devices,
253 IN unsigned char *deviceid,
254 OUT pnfs_file_device **device_out);
255
256void pnfs_file_device_put(
257 IN pnfs_file_device *device);
258
259struct notify_deviceid4; /* from nfs41_callback.h */
260enum notify_deviceid_type4;
261enum pnfs_status pnfs_file_device_notify(
262 IN struct pnfs_file_device_list *devices,
263 IN const struct notify_deviceid4 *change);
264
265enum pnfs_status pnfs_data_server_client(
266 IN struct __nfs41_root *root,
267 IN pnfs_data_server *server,
268 IN uint32_t default_lease,
269 OUT struct __nfs41_client **client_out);
270
271
272/* pnfs_io.c */
273enum pnfs_status pnfs_read(
274 IN struct __nfs41_root *root,
275 IN struct __nfs41_open_state *state,
276 IN struct __stateid_arg *stateid,
277 IN pnfs_layout_state *layout,
278 IN uint64_t offset,
279 IN uint64_t length,
280 OUT unsigned char *buffer_out,
281 OUT ULONG *len_out);
282
283enum pnfs_status pnfs_write(
284 IN struct __nfs41_root *root,
285 IN struct __nfs41_open_state *state,
286 IN struct __stateid_arg *stateid,
287 IN pnfs_layout_state *layout,
288 IN uint64_t offset,
289 IN uint64_t length,
290 IN unsigned char *buffer,
291 OUT ULONG *len_out,
292 OUT nfs41_file_info *cinfo);
293
294
295/* helper functions */
296#ifndef __REACTOS__
297__inline int is_dense(
298#else
299FORCEINLINE int is_dense(
300#endif
301 IN const pnfs_file_layout *layout)
302{
303 return (layout->util & NFL4_UFLG_DENSE) != 0;
304}
305#ifndef __REACTOS__
306__inline int should_commit_to_mds(
307#else
308FORCEINLINE int should_commit_to_mds(
309#endif
310 IN const pnfs_file_layout *layout)
311{
312 return (layout->util & NFL4_UFLG_COMMIT_THRU_MDS) != 0;
313}
314#ifndef __REACTOS__
315__inline uint32_t layout_unit_size(
316#else
317FORCEINLINE uint32_t layout_unit_size(
318#endif
319 IN const pnfs_file_layout *layout)
320{
321 return layout->util & NFL4_UFLG_STRIPE_UNIT_SIZE_MASK;
322}
323#ifndef __REACTOS__
324__inline uint64_t stripe_unit_number(
325#else
326FORCEINLINE uint64_t stripe_unit_number(
327#endif
328 IN const pnfs_file_layout *layout,
329 IN uint64_t offset,
330 IN uint32_t unit_size)
331{
332 const uint64_t relative_offset = offset - layout->pattern_offset;
333 return relative_offset / unit_size;
334}
335#ifndef __REACTOS__
336__inline uint64_t stripe_unit_offset(
337#else
338FORCEINLINE uint64_t stripe_unit_offset(
339#endif
340 IN const pnfs_file_layout *layout,
341 IN uint64_t sui,
342 IN uint32_t unit_size)
343{
344 return layout->pattern_offset + unit_size * sui;
345}
346#ifndef __REACTOS__
347__inline uint32_t stripe_index(
348#else
349FORCEINLINE uint32_t stripe_index(
350#endif
351 IN const pnfs_file_layout *layout,
352 IN uint64_t sui,
353 IN uint32_t stripe_count)
354{
355 return (uint32_t)((sui + layout->first_index) % stripe_count);
356}
357#ifndef __REACTOS__
358__inline uint32_t data_server_index(
359#else
360FORCEINLINE uint32_t data_server_index(
361#endif
362 IN const pnfs_file_device *device,
363 IN uint32_t stripeid)
364{
365 return device->stripes.arr[stripeid];
366}
367
368#endif /* !__PNFS_H__ */