mirror of
https://github.com/reactos/reactos.git
synced 2024-08-27 05:38:41 +00:00
369 lines
10 KiB
C
369 lines
10 KiB
C
![]() |
/* NFSv4.1 client for Windows
|
|||
|
* Copyright <EFBFBD> 2012 The Regents of the University of Michigan
|
|||
|
*
|
|||
|
* Olga Kornievskaia <aglo@umich.edu>
|
|||
|
* Casey Bodley <cbodley@umich.edu>
|
|||
|
*
|
|||
|
* 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__ */
|