/* NFSv4.1 client for Windows * Copyright © 2012 The Regents of the University of Michigan * * Olga Kornievskaia * Casey Bodley * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, but * without any warranty; without even the implied warranty of merchantability * or fitness for a particular purpose. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA */ #ifndef __PNFS_H__ #define __PNFS_H__ #include "nfs41_types.h" #include "list.h" /* preprocessor options */ #ifndef PNFS_DISABLE # ifndef PNFS_DISABLE_READ # define PNFS_ENABLE_READ # endif # ifndef PNFS_DISABLE_WRITE # define PNFS_ENABLE_WRITE # endif # define PNFS_THREADING /* XXX: the thread-by-server model breaks down when using dense layouts, * because multiple stripes could be mapped to a single data server, and * the per-data-server thread would have to send a COMMIT for each stripe */ //# define PNFS_THREAD_BY_SERVER #endif /* forward declarations from nfs41.h */ struct __nfs41_client; struct __nfs41_session; struct __nfs41_open_state; struct __nfs41_root; struct __stateid_arg; /* pnfs error values, in order of increasing severity */ enum pnfs_status { PNFS_SUCCESS = 0, PNFS_PENDING, PNFS_READ_EOF, PNFSERR_NOT_SUPPORTED, PNFSERR_NOT_CONNECTED, PNFSERR_IO, PNFSERR_NO_DEVICE, PNFSERR_NO_LAYOUT, PNFSERR_INVALID_FH_LIST, PNFSERR_INVALID_DS_INDEX, PNFSERR_RESOURCES, PNFSERR_LAYOUT_RECALLED, PNFSERR_LAYOUT_CHANGED, }; enum pnfs_layout_type { PNFS_LAYOUTTYPE_FILE = 1, PNFS_LAYOUTTYPE_OBJECT = 2, PNFS_LAYOUTTYPE_BLOCK = 3 }; enum pnfs_iomode { PNFS_IOMODE_READ = 0x1, PNFS_IOMODE_RW = 0x2, PNFS_IOMODE_ANY = PNFS_IOMODE_READ | PNFS_IOMODE_RW }; enum pnfs_layout_status { /* a LAYOUTGET error indicated that this layout will never be granted */ PNFS_LAYOUT_UNAVAILABLE = 0x10, /* LAYOUTGET returned BADIOMODE, so a RW layout will never be granted */ PNFS_LAYOUT_NOT_RW = 0x20, }; enum pnfs_device_status { /* GETDEVICEINFO was successful */ PNFS_DEVICE_GRANTED = 0x1, /* a bulk recall or lease expiration led to device invalidation */ PNFS_DEVICE_REVOKED = 0x2, }; enum pnfs_return_type { PNFS_RETURN_FILE = 1, PNFS_RETURN_FSID = 2, PNFS_RETURN_ALL = 3 }; #define NFL4_UFLG_MASK 0x0000003F #define NFL4_UFLG_DENSE 0x00000001 #define NFL4_UFLG_COMMIT_THRU_MDS 0x00000002 #define NFL4_UFLG_STRIPE_UNIT_SIZE_MASK 0xFFFFFFC0 #define PNFS_DEVICEID_SIZE 16 /* device */ typedef struct __pnfs_device { unsigned char deviceid[PNFS_DEVICEID_SIZE]; enum pnfs_layout_type type; enum pnfs_device_status status; uint32_t layout_count; /* layouts using this device */ CRITICAL_SECTION lock; } pnfs_device; typedef struct __pnfs_stripe_indices { uint32_t count; uint32_t *arr; } pnfs_stripe_indices; typedef struct __pnfs_data_server { struct __nfs41_client *client; multi_addr4 addrs; SRWLOCK lock; } pnfs_data_server; typedef struct __pnfs_data_server_list { uint32_t count; pnfs_data_server *arr; } pnfs_data_server_list; typedef struct __pnfs_file_device { pnfs_device device; pnfs_stripe_indices stripes; pnfs_data_server_list servers; struct pnfs_file_device_list *devices; /* -> nfs41_client.devices */ struct list_entry entry; /* position in devices */ } pnfs_file_device; /* layout */ typedef struct __pnfs_layout_state { nfs41_fh meta_fh; stateid4 stateid; struct list_entry entry; /* position in nfs41_client.layouts */ struct list_entry layouts; /* list of pnfs_file_layouts */ struct list_entry recalls; /* list of pnfs_layouts */ enum pnfs_layout_status status; bool_t return_on_close; LONG open_count; /* for return on last close */ uint32_t io_count; /* number of pending io operations */ bool_t pending; /* pending LAYOUTGET/LAYOUTRETURN */ SRWLOCK lock; CONDITION_VARIABLE cond; } pnfs_layout_state; typedef struct __pnfs_layout { struct list_entry entry; uint64_t offset; uint64_t length; enum pnfs_iomode iomode; enum pnfs_layout_type type; } pnfs_layout; typedef struct __pnfs_file_layout_handles { uint32_t count; nfs41_path_fh *arr; } pnfs_file_layout_handles; typedef struct __pnfs_file_layout { pnfs_layout layout; pnfs_file_layout_handles filehandles; unsigned char deviceid[PNFS_DEVICEID_SIZE]; pnfs_file_device *device; uint64_t pattern_offset; uint32_t first_index; uint32_t util; } pnfs_file_layout; /* pnfs_layout.c */ struct pnfs_layout_list; struct cb_layoutrecall_args; enum pnfs_status pnfs_layout_list_create( OUT struct pnfs_layout_list **layouts_out); void pnfs_layout_list_free( IN struct pnfs_layout_list *layouts); enum pnfs_status pnfs_layout_state_open( IN struct __nfs41_open_state *state, OUT pnfs_layout_state **layout_out); /* expects caller to hold an exclusive lock on pnfs_layout_state */ enum pnfs_status pnfs_layout_state_prepare( IN pnfs_layout_state *state, IN struct __nfs41_session *session, IN nfs41_path_fh *meta_file, IN struct __stateid_arg *stateid, IN enum pnfs_iomode iomode, IN uint64_t offset, IN uint64_t length); void pnfs_layout_state_close( IN struct __nfs41_session *session, IN struct __nfs41_open_state *state, IN bool_t remove); enum pnfs_status pnfs_file_layout_recall( IN struct __nfs41_client *client, IN const struct cb_layoutrecall_args *recall); /* expects caller to hold a shared lock on pnfs_layout_state */ enum pnfs_status pnfs_layout_recall_status( IN const pnfs_layout_state *state, IN const pnfs_layout *layout); void pnfs_layout_recall_fenced( IN pnfs_layout_state *state, IN const pnfs_layout *layout); /* expects caller to hold an exclusive lock on pnfs_layout_state */ void pnfs_layout_io_start( IN pnfs_layout_state *state); void pnfs_layout_io_finished( IN pnfs_layout_state *state); /* pnfs_device.c */ struct pnfs_file_device_list; enum pnfs_status pnfs_file_device_list_create( OUT struct pnfs_file_device_list **devices_out); void pnfs_file_device_list_free( IN struct pnfs_file_device_list *devices); void pnfs_file_device_list_invalidate( IN struct pnfs_file_device_list *devices); enum pnfs_status pnfs_file_device_get( IN struct __nfs41_session *session, IN struct pnfs_file_device_list *devices, IN unsigned char *deviceid, OUT pnfs_file_device **device_out); void pnfs_file_device_put( IN pnfs_file_device *device); struct notify_deviceid4; /* from nfs41_callback.h */ enum notify_deviceid_type4; enum pnfs_status pnfs_file_device_notify( IN struct pnfs_file_device_list *devices, IN const struct notify_deviceid4 *change); enum pnfs_status pnfs_data_server_client( IN struct __nfs41_root *root, IN pnfs_data_server *server, IN uint32_t default_lease, OUT struct __nfs41_client **client_out); /* pnfs_io.c */ enum pnfs_status pnfs_read( IN struct __nfs41_root *root, IN struct __nfs41_open_state *state, IN struct __stateid_arg *stateid, IN pnfs_layout_state *layout, IN uint64_t offset, IN uint64_t length, OUT unsigned char *buffer_out, OUT ULONG *len_out); enum pnfs_status pnfs_write( IN struct __nfs41_root *root, IN struct __nfs41_open_state *state, IN struct __stateid_arg *stateid, IN pnfs_layout_state *layout, IN uint64_t offset, IN uint64_t length, IN unsigned char *buffer, OUT ULONG *len_out, OUT nfs41_file_info *cinfo); /* helper functions */ #ifndef __REACTOS__ __inline int is_dense( #else FORCEINLINE int is_dense( #endif IN const pnfs_file_layout *layout) { return (layout->util & NFL4_UFLG_DENSE) != 0; } #ifndef __REACTOS__ __inline int should_commit_to_mds( #else FORCEINLINE int should_commit_to_mds( #endif IN const pnfs_file_layout *layout) { return (layout->util & NFL4_UFLG_COMMIT_THRU_MDS) != 0; } #ifndef __REACTOS__ __inline uint32_t layout_unit_size( #else FORCEINLINE uint32_t layout_unit_size( #endif IN const pnfs_file_layout *layout) { return layout->util & NFL4_UFLG_STRIPE_UNIT_SIZE_MASK; } #ifndef __REACTOS__ __inline uint64_t stripe_unit_number( #else FORCEINLINE uint64_t stripe_unit_number( #endif IN const pnfs_file_layout *layout, IN uint64_t offset, IN uint32_t unit_size) { const uint64_t relative_offset = offset - layout->pattern_offset; return relative_offset / unit_size; } #ifndef __REACTOS__ __inline uint64_t stripe_unit_offset( #else FORCEINLINE uint64_t stripe_unit_offset( #endif IN const pnfs_file_layout *layout, IN uint64_t sui, IN uint32_t unit_size) { return layout->pattern_offset + unit_size * sui; } #ifndef __REACTOS__ __inline uint32_t stripe_index( #else FORCEINLINE uint32_t stripe_index( #endif IN const pnfs_file_layout *layout, IN uint64_t sui, IN uint32_t stripe_count) { return (uint32_t)((sui + layout->first_index) % stripe_count); } #ifndef __REACTOS__ __inline uint32_t data_server_index( #else FORCEINLINE uint32_t data_server_index( #endif IN const pnfs_file_device *device, IN uint32_t stripeid) { return device->stripes.arr[stripeid]; } #endif /* !__PNFS_H__ */