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 */
50 struct __nfs41_client;
51 struct __nfs41_session;
52 struct __nfs41_open_state;
53 struct __nfs41_root;
54 struct __stateid_arg;
55
56
57 /* pnfs error values, in order of increasing severity */
58 enum 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
74 enum pnfs_layout_type {
75 PNFS_LAYOUTTYPE_FILE = 1,
76 PNFS_LAYOUTTYPE_OBJECT = 2,
77 PNFS_LAYOUTTYPE_BLOCK = 3
78 };
79
80 enum pnfs_iomode {
81 PNFS_IOMODE_READ = 0x1,
82 PNFS_IOMODE_RW = 0x2,
83 PNFS_IOMODE_ANY = PNFS_IOMODE_READ | PNFS_IOMODE_RW
84 };
85
86 enum 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
93 enum 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
100 enum 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 */
115 typedef 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
123 typedef struct __pnfs_stripe_indices {
124 uint32_t count;
125 uint32_t *arr;
126 } pnfs_stripe_indices;
127
128 typedef struct __pnfs_data_server {
129 struct __nfs41_client *client;
130 multi_addr4 addrs;
131 SRWLOCK lock;
132 } pnfs_data_server;
133
134 typedef struct __pnfs_data_server_list {
135 uint32_t count;
136 pnfs_data_server *arr;
137 } pnfs_data_server_list;
138
139 typedef 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 */
149 typedef 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
164 typedef 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
172 typedef struct __pnfs_file_layout_handles {
173 uint32_t count;
174 nfs41_path_fh *arr;
175 } pnfs_file_layout_handles;
176
177 typedef 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 */
189 struct pnfs_layout_list;
190 struct cb_layoutrecall_args;
191
192 enum pnfs_status pnfs_layout_list_create(
193 OUT struct pnfs_layout_list **layouts_out);
194
195 void pnfs_layout_list_free(
196 IN struct pnfs_layout_list *layouts);
197
198 enum 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 */
203 enum 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
212 void pnfs_layout_state_close(
213 IN struct __nfs41_session *session,
214 IN struct __nfs41_open_state *state,
215 IN bool_t remove);
216
217 enum 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 */
222 enum pnfs_status pnfs_layout_recall_status(
223 IN const pnfs_layout_state *state,
224 IN const pnfs_layout *layout);
225
226 void 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 */
231 void pnfs_layout_io_start(
232 IN pnfs_layout_state *state);
233
234 void pnfs_layout_io_finished(
235 IN pnfs_layout_state *state);
236
237
238 /* pnfs_device.c */
239 struct pnfs_file_device_list;
240
241 enum pnfs_status pnfs_file_device_list_create(
242 OUT struct pnfs_file_device_list **devices_out);
243
244 void pnfs_file_device_list_free(
245 IN struct pnfs_file_device_list *devices);
246
247 void pnfs_file_device_list_invalidate(
248 IN struct pnfs_file_device_list *devices);
249
250 enum 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
256 void pnfs_file_device_put(
257 IN pnfs_file_device *device);
258
259 struct notify_deviceid4; /* from nfs41_callback.h */
260 enum notify_deviceid_type4;
261 enum pnfs_status pnfs_file_device_notify(
262 IN struct pnfs_file_device_list *devices,
263 IN const struct notify_deviceid4 *change);
264
265 enum 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 */
273 enum 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
283 enum 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__
is_dense(IN const pnfs_file_layout * layout)297 __inline int is_dense(
298 #else
299 FORCEINLINE 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__
should_commit_to_mds(IN const pnfs_file_layout * layout)306 __inline int should_commit_to_mds(
307 #else
308 FORCEINLINE 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__
layout_unit_size(IN const pnfs_file_layout * layout)315 __inline uint32_t layout_unit_size(
316 #else
317 FORCEINLINE 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__
stripe_unit_number(IN const pnfs_file_layout * layout,IN uint64_t offset,IN uint32_t unit_size)324 __inline uint64_t stripe_unit_number(
325 #else
326 FORCEINLINE 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__
stripe_unit_offset(IN const pnfs_file_layout * layout,IN uint64_t sui,IN uint32_t unit_size)336 __inline uint64_t stripe_unit_offset(
337 #else
338 FORCEINLINE 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__
stripe_index(IN const pnfs_file_layout * layout,IN uint64_t sui,IN uint32_t stripe_count)347 __inline uint32_t stripe_index(
348 #else
349 FORCEINLINE 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__
data_server_index(IN const pnfs_file_device * device,IN uint32_t stripeid)358 __inline uint32_t data_server_index(
359 #else
360 FORCEINLINE 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__ */
369