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__ 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__ 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__ 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__ 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__ 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__ 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__ 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