xref: /reactos/base/services/nfsd/pnfs.h (revision c2c66aff)
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